aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2018-04-09 12:24:58 -0400
committerIngo Molnar <mingo@kernel.org>2018-04-09 12:24:58 -0400
commitee1400dda31814d0a61c964ad87da6880edec0e2 (patch)
treeefa8774a97234cf93b22877a51a54f71f9e979cb /tools
parent071ccc966ba5db1ac8f5c24b0faebb37698f68db (diff)
parentbc16d4052f1ae99996f3475b5a73d29c86e7ba81 (diff)
Merge branch 'linus' into x86/pti to pick up upstream changes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/arch/powerpc/include/uapi/asm/kvm.h2
-rw-r--r--tools/arch/powerpc/include/uapi/asm/unistd.h402
-rw-r--r--tools/arch/s390/include/uapi/asm/unistd.h412
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h2
-rw-r--r--tools/bpf/bpftool/common.c4
-rw-r--r--tools/bpf/bpftool/main.c2
-rw-r--r--tools/bpf/bpftool/map.c2
-rw-r--r--tools/bpf/bpftool/prog.c3
-rw-r--r--tools/build/Makefile.feature6
-rw-r--r--tools/build/feature/Makefile14
-rw-r--r--tools/cgroup/Makefile1
-rw-r--r--tools/gpio/Makefile2
-rw-r--r--tools/hv/Makefile1
-rw-r--r--tools/iio/Makefile2
-rw-r--r--tools/include/linux/bitmap.h2
-rw-r--r--tools/include/uapi/drm/i915_drm.h77
-rw-r--r--tools/include/uapi/linux/if_link.h1
-rw-r--r--tools/include/uapi/linux/kvm.h92
-rw-r--r--tools/include/uapi/linux/perf_event.h27
-rwxr-xr-xtools/kvm/kvm_stat/kvm_stat503
-rw-r--r--tools/kvm/kvm_stat/kvm_stat.txt4
-rw-r--r--tools/laptop/freefall/Makefile1
-rw-r--r--tools/leds/Makefile1
-rw-r--r--tools/lib/api/fs/fs.c44
-rw-r--r--tools/lib/api/fs/fs.h2
-rw-r--r--tools/lib/bpf/libbpf.c5
-rw-r--r--tools/lib/str_error_r.c2
-rw-r--r--tools/lib/symbol/kallsyms.c4
-rw-r--r--tools/memory-model/Documentation/cheatsheet.txt29
-rw-r--r--tools/memory-model/Documentation/explanation.txt1845
-rw-r--r--tools/memory-model/Documentation/recipes.txt570
-rw-r--r--tools/memory-model/Documentation/references.txt107
-rw-r--r--tools/memory-model/README206
-rw-r--r--tools/memory-model/linux-kernel.bell52
-rw-r--r--tools/memory-model/linux-kernel.cat121
-rw-r--r--tools/memory-model/linux-kernel.cfg21
-rw-r--r--tools/memory-model/linux-kernel.def106
-rw-r--r--tools/memory-model/litmus-tests/CoRR+poonceonce+Once.litmus26
-rw-r--r--tools/memory-model/litmus-tests/CoRW+poonceonce+Once.litmus25
-rw-r--r--tools/memory-model/litmus-tests/CoWR+poonceonce+Once.litmus25
-rw-r--r--tools/memory-model/litmus-tests/CoWW+poonceonce.litmus18
-rw-r--r--tools/memory-model/litmus-tests/IRIW+mbonceonces+OnceOnce.litmus45
-rw-r--r--tools/memory-model/litmus-tests/IRIW+poonceonces+OnceOnce.litmus43
-rw-r--r--tools/memory-model/litmus-tests/ISA2+pooncelock+pooncelock+pombonce.litmus41
-rw-r--r--tools/memory-model/litmus-tests/ISA2+poonceonces.litmus37
-rw-r--r--tools/memory-model/litmus-tests/ISA2+pooncerelease+poacquirerelease+poacquireonce.litmus39
-rw-r--r--tools/memory-model/litmus-tests/LB+ctrlonceonce+mbonceonce.litmus34
-rw-r--r--tools/memory-model/litmus-tests/LB+poacquireonce+pooncerelease.litmus29
-rw-r--r--tools/memory-model/litmus-tests/LB+poonceonces.litmus28
-rw-r--r--tools/memory-model/litmus-tests/MP+onceassign+derefonce.litmus34
-rw-r--r--tools/memory-model/litmus-tests/MP+polocks.litmus35
-rw-r--r--tools/memory-model/litmus-tests/MP+poonceonces.litmus27
-rw-r--r--tools/memory-model/litmus-tests/MP+pooncerelease+poacquireonce.litmus28
-rw-r--r--tools/memory-model/litmus-tests/MP+porevlocks.litmus35
-rw-r--r--tools/memory-model/litmus-tests/MP+wmbonceonce+rmbonceonce.litmus30
-rw-r--r--tools/memory-model/litmus-tests/R+mbonceonces.litmus30
-rw-r--r--tools/memory-model/litmus-tests/R+poonceonces.litmus27
-rw-r--r--tools/memory-model/litmus-tests/README131
-rw-r--r--tools/memory-model/litmus-tests/S+poonceonces.litmus28
-rw-r--r--tools/memory-model/litmus-tests/S+wmbonceonce+poacquireonce.litmus27
-rw-r--r--tools/memory-model/litmus-tests/SB+mbonceonces.litmus32
-rw-r--r--tools/memory-model/litmus-tests/SB+poonceonces.litmus29
-rw-r--r--tools/memory-model/litmus-tests/WRC+poonceonces+Once.litmus35
-rw-r--r--tools/memory-model/litmus-tests/WRC+pooncerelease+rmbonceonce+Once.litmus36
-rw-r--r--tools/memory-model/litmus-tests/Z6.0+pooncelock+poonceLock+pombonce.litmus42
-rw-r--r--tools/memory-model/litmus-tests/Z6.0+pooncelock+pooncelock+pombonce.litmus40
-rw-r--r--tools/memory-model/litmus-tests/Z6.0+pooncerelease+poacquirerelease+mbonceonce.litmus42
-rw-r--r--tools/memory-model/lock.cat99
-rw-r--r--tools/perf/Documentation/perf-annotate.txt11
-rw-r--r--tools/perf/Documentation/perf-c2c.txt2
-rw-r--r--tools/perf/Documentation/perf-data.txt6
-rw-r--r--tools/perf/Documentation/perf-ftrace.txt2
-rw-r--r--tools/perf/Documentation/perf-kallsyms.txt4
-rw-r--r--tools/perf/Documentation/perf-kmem.txt6
-rw-r--r--tools/perf/Documentation/perf-list.txt8
-rw-r--r--tools/perf/Documentation/perf-mem.txt4
-rw-r--r--tools/perf/Documentation/perf-record.txt15
-rw-r--r--tools/perf/Documentation/perf-report.txt8
-rw-r--r--tools/perf/Documentation/perf-sched.txt2
-rw-r--r--tools/perf/Documentation/perf-script-perl.txt2
-rw-r--r--tools/perf/Documentation/perf-script.txt3
-rw-r--r--tools/perf/Documentation/perf-stat.txt33
-rw-r--r--tools/perf/Documentation/perf-top.txt7
-rw-r--r--tools/perf/Documentation/perf-trace.txt25
-rw-r--r--tools/perf/Documentation/perf.data-file-format.txt7
-rw-r--r--tools/perf/Makefile.config27
-rw-r--r--tools/perf/Makefile.perf16
-rw-r--r--tools/perf/arch/arm/util/auxtrace.c2
-rw-r--r--tools/perf/arch/arm/util/cs-etm.c51
-rw-r--r--tools/perf/arch/arm64/include/arch-tests.h12
-rw-r--r--tools/perf/arch/arm64/tests/Build2
-rw-r--r--tools/perf/arch/arm64/tests/arch-tests.c16
-rw-r--r--tools/perf/arch/arm64/util/Build1
-rw-r--r--tools/perf/arch/arm64/util/unwind-libdw.c60
-rw-r--r--tools/perf/arch/powerpc/Makefile25
-rwxr-xr-xtools/perf/arch/powerpc/entry/syscalls/mksyscalltbl37
-rw-r--r--tools/perf/arch/s390/Makefile10
-rw-r--r--tools/perf/arch/s390/annotate/instructions.c144
-rwxr-xr-xtools/perf/arch/s390/entry/syscalls/mksyscalltbl18
-rw-r--r--tools/perf/arch/s390/entry/syscalls/syscall.tbl390
-rw-r--r--tools/perf/arch/s390/util/header.c148
-rw-r--r--tools/perf/arch/x86/tests/perf-time-to-tsc.c10
-rw-r--r--tools/perf/arch/x86/util/auxtrace.c14
-rw-r--r--tools/perf/builtin-annotate.c109
-rw-r--r--tools/perf/builtin-c2c.c251
-rw-r--r--tools/perf/builtin-ftrace.c18
-rw-r--r--tools/perf/builtin-kvm.c16
-rw-r--r--tools/perf/builtin-record.c91
-rw-r--r--tools/perf/builtin-report.c68
-rw-r--r--tools/perf/builtin-sched.c133
-rw-r--r--tools/perf/builtin-script.c39
-rw-r--r--tools/perf/builtin-stat.c118
-rw-r--r--tools/perf/builtin-top.c161
-rw-r--r--tools/perf/builtin-trace.c60
-rwxr-xr-xtools/perf/check-headers.sh3
-rw-r--r--tools/perf/perf.h4
-rw-r--r--tools/perf/pmu-events/Build2
-rw-r--r--tools/perf/pmu-events/README15
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/branch.json25
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/bus.json8
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/cache.json27
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/memory.json12
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/other.json28
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/pipeline.json52
-rw-r--r--tools/perf/pmu-events/arch/arm64/armv8-recommended.json452
-rw-r--r--tools/perf/pmu-events/arch/arm64/cavium/thunderx2-imp-def.json62
-rw-r--r--tools/perf/pmu-events/arch/arm64/cavium/thunderx2/core-imp-def.json32
-rw-r--r--tools/perf/pmu-events/arch/arm64/hisilicon/hip08/core-imp-def.json122
-rw-r--r--tools/perf/pmu-events/arch/arm64/mapfile.csv5
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/cache.json25
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/frontend.json10
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/marked.json5
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/memory.json5
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/other.json241
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/pipeline.json50
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/pmc.json5
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/translation.json10
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z10/basic.json74
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z10/crypto.json98
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z10/extended.json110
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z13/basic.json74
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z13/crypto.json98
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z13/extended.json338
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z14/basic.json50
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z14/crypto.json98
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z14/extended.json320
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z196/basic.json74
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z196/crypto.json98
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z196/extended.json146
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_zec12/basic.json74
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_zec12/crypto.json98
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_zec12/extended.json212
-rw-r--r--tools/perf/pmu-events/arch/s390/mapfile.csv6
-rw-r--r--tools/perf/pmu-events/jevents.c291
-rwxr-xr-xtools/perf/python/twatch.py8
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/Context.c34
-rw-r--r--tools/perf/tests/Build2
-rw-r--r--tools/perf/tests/attr.c4
-rw-r--r--tools/perf/tests/backward-ring-buffer.c6
-rw-r--r--tools/perf/tests/bp_account.c193
-rw-r--r--tools/perf/tests/bpf.c8
-rw-r--r--tools/perf/tests/builtin-test.c8
-rw-r--r--tools/perf/tests/code-reading.c43
-rw-r--r--tools/perf/tests/dwarf-unwind.c46
-rw-r--r--tools/perf/tests/keep-tracking.c9
-rw-r--r--tools/perf/tests/mem.c2
-rw-r--r--tools/perf/tests/mem2node.c75
-rw-r--r--tools/perf/tests/mmap-basic.c11
-rw-r--r--tools/perf/tests/openat-syscall-tp-fields.c10
-rw-r--r--tools/perf/tests/perf-record.c10
-rw-r--r--tools/perf/tests/pmu.c2
-rw-r--r--tools/perf/tests/shell/lib/probe_vfs_getname.sh2
-rwxr-xr-xtools/perf/tests/shell/record+probe_libc_inet_pton.sh (renamed from tools/perf/tests/shell/trace+probe_libc_inet_pton.sh)40
-rw-r--r--tools/perf/tests/sw-clock.c11
-rw-r--r--tools/perf/tests/switch-tracking.c10
-rw-r--r--tools/perf/tests/task-exit.c11
-rw-r--r--tools/perf/tests/tests.h2
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c4
-rw-r--r--tools/perf/ui/browser.c9
-rw-r--r--tools/perf/ui/browser.h3
-rw-r--r--tools/perf/ui/browsers/annotate.c725
-rw-r--r--tools/perf/ui/browsers/hists.c49
-rw-r--r--tools/perf/ui/browsers/hists.h3
-rw-r--r--tools/perf/ui/stdio/hist.c6
-rw-r--r--tools/perf/util/Build1
-rw-r--r--tools/perf/util/annotate.c739
-rw-r--r--tools/perf/util/annotate.h103
-rw-r--r--tools/perf/util/auxtrace.c52
-rw-r--r--tools/perf/util/auxtrace.h2
-rw-r--r--tools/perf/util/build-id.c10
-rw-r--r--tools/perf/util/cgroup.c128
-rw-r--r--tools/perf/util/cgroup.h13
-rw-r--r--tools/perf/util/cs-etm-decoder/cs-etm-decoder.c74
-rw-r--r--tools/perf/util/cs-etm-decoder/cs-etm-decoder.h2
-rw-r--r--tools/perf/util/cs-etm.c478
-rw-r--r--tools/perf/util/debug.c1
-rw-r--r--tools/perf/util/env.c4
-rw-r--r--tools/perf/util/env.h9
-rw-r--r--tools/perf/util/event.c16
-rw-r--r--tools/perf/util/evlist.c71
-rw-r--r--tools/perf/util/evlist.h8
-rw-r--r--tools/perf/util/evsel.c38
-rw-r--r--tools/perf/util/evsel.h20
-rw-r--r--tools/perf/util/header.c323
-rw-r--r--tools/perf/util/header.h2
-rw-r--r--tools/perf/util/hist.c8
-rw-r--r--tools/perf/util/hist.h7
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c64
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.h2
-rw-r--r--tools/perf/util/intel-pt.c110
-rw-r--r--tools/perf/util/llvm-utils.c14
-rw-r--r--tools/perf/util/machine.c139
-rw-r--r--tools/perf/util/machine.h6
-rw-r--r--tools/perf/util/mem2node.c134
-rw-r--r--tools/perf/util/mem2node.h19
-rw-r--r--tools/perf/util/mmap.c203
-rw-r--r--tools/perf/util/mmap.h16
-rw-r--r--tools/perf/util/parse-events.c25
-rw-r--r--tools/perf/util/parse-events.h2
-rw-r--r--tools/perf/util/parse-events.l2
-rw-r--r--tools/perf/util/parse-events.y18
-rw-r--r--tools/perf/util/pmu.c49
-rw-r--r--tools/perf/util/probe-finder.c13
-rw-r--r--tools/perf/util/python.c110
-rw-r--r--tools/perf/util/record.c51
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c147
-rw-r--r--tools/perf/util/setup.py8
-rw-r--r--tools/perf/util/sort.c7
-rw-r--r--tools/perf/util/stat.c2
-rw-r--r--tools/perf/util/stat.h4
-rw-r--r--tools/perf/util/symbol.c35
-rw-r--r--tools/perf/util/symbol.h19
-rw-r--r--tools/perf/util/syscalltbl.c8
-rw-r--r--tools/perf/util/thread.h1
-rw-r--r--tools/perf/util/thread_map.c5
-rw-r--r--tools/perf/util/thread_map.h3
-rw-r--r--tools/perf/util/trigger.h9
-rw-r--r--tools/perf/util/unwind-libdw.c5
-rw-r--r--tools/perf/util/util.c24
-rw-r--r--tools/power/acpi/Makefile.config3
-rw-r--r--tools/scripts/Makefile.include18
-rw-r--r--tools/spi/Makefile2
-rw-r--r--tools/testing/radix-tree/idr-test.c52
-rw-r--r--tools/testing/radix-tree/linux.c11
-rw-r--r--tools/testing/radix-tree/linux/compiler_types.h0
-rw-r--r--tools/testing/radix-tree/linux/gfp.h1
-rw-r--r--tools/testing/radix-tree/linux/slab.h6
-rw-r--r--tools/testing/selftests/android/Makefile8
-rw-r--r--tools/testing/selftests/bpf/.gitignore1
-rw-r--r--tools/testing/selftests/bpf/test_maps.c2
-rw-r--r--tools/testing/selftests/bpf/test_tcpbpf_kern.c1
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c84
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc46
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc97
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/probepoint.tc43
-rw-r--r--tools/testing/selftests/futex/Makefile6
-rw-r--r--tools/testing/selftests/memfd/Makefile1
-rw-r--r--tools/testing/selftests/memfd/config1
-rw-r--r--tools/testing/selftests/memory-hotplug/Makefile5
-rw-r--r--tools/testing/selftests/powerpc/mm/subpage_prot.c14
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile2
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-trap.c2
-rw-r--r--tools/testing/selftests/pstore/config1
-rw-r--r--tools/testing/selftests/rcutorture/bin/functions.sh17
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh11
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh4
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm.sh22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TASKS031
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE041
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE071
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh24
-rw-r--r--tools/testing/selftests/rcutorture/doc/rcu-test-image.txt2
-rw-r--r--tools/testing/selftests/seccomp/seccomp_bpf.c61
-rw-r--r--tools/testing/selftests/sync/Makefile2
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json2
-rw-r--r--tools/testing/selftests/vDSO/Makefile14
-rw-r--r--tools/testing/selftests/vm/.gitignore1
-rwxr-xr-xtools/testing/selftests/vm/run_vmtests25
-rw-r--r--tools/usb/Makefile1
-rw-r--r--tools/vm/Makefile1
-rw-r--r--tools/wmi/Makefile1
283 files changed, 14144 insertions, 2672 deletions
diff --git a/tools/arch/powerpc/include/uapi/asm/kvm.h b/tools/arch/powerpc/include/uapi/asm/kvm.h
index 637b7263cb86..833ed9a16adf 100644
--- a/tools/arch/powerpc/include/uapi/asm/kvm.h
+++ b/tools/arch/powerpc/include/uapi/asm/kvm.h
@@ -632,6 +632,8 @@ struct kvm_ppc_cpu_char {
632#define KVM_REG_PPC_TIDR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbc) 632#define KVM_REG_PPC_TIDR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbc)
633#define KVM_REG_PPC_PSSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbd) 633#define KVM_REG_PPC_PSSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbd)
634 634
635#define KVM_REG_PPC_DEC_EXPIRY (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbe)
636
635/* Transactional Memory checkpointed state: 637/* Transactional Memory checkpointed state:
636 * This is all GPRs, all VSX regs and a subset of SPRs 638 * This is all GPRs, all VSX regs and a subset of SPRs
637 */ 639 */
diff --git a/tools/arch/powerpc/include/uapi/asm/unistd.h b/tools/arch/powerpc/include/uapi/asm/unistd.h
new file mode 100644
index 000000000000..389c36fd8299
--- /dev/null
+++ b/tools/arch/powerpc/include/uapi/asm/unistd.h
@@ -0,0 +1,402 @@
1/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
2/*
3 * This file contains the system call numbers.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 */
10#ifndef _UAPI_ASM_POWERPC_UNISTD_H_
11#define _UAPI_ASM_POWERPC_UNISTD_H_
12
13
14#define __NR_restart_syscall 0
15#define __NR_exit 1
16#define __NR_fork 2
17#define __NR_read 3
18#define __NR_write 4
19#define __NR_open 5
20#define __NR_close 6
21#define __NR_waitpid 7
22#define __NR_creat 8
23#define __NR_link 9
24#define __NR_unlink 10
25#define __NR_execve 11
26#define __NR_chdir 12
27#define __NR_time 13
28#define __NR_mknod 14
29#define __NR_chmod 15
30#define __NR_lchown 16
31#define __NR_break 17
32#define __NR_oldstat 18
33#define __NR_lseek 19
34#define __NR_getpid 20
35#define __NR_mount 21
36#define __NR_umount 22
37#define __NR_setuid 23
38#define __NR_getuid 24
39#define __NR_stime 25
40#define __NR_ptrace 26
41#define __NR_alarm 27
42#define __NR_oldfstat 28
43#define __NR_pause 29
44#define __NR_utime 30
45#define __NR_stty 31
46#define __NR_gtty 32
47#define __NR_access 33
48#define __NR_nice 34
49#define __NR_ftime 35
50#define __NR_sync 36
51#define __NR_kill 37
52#define __NR_rename 38
53#define __NR_mkdir 39
54#define __NR_rmdir 40
55#define __NR_dup 41
56#define __NR_pipe 42
57#define __NR_times 43
58#define __NR_prof 44
59#define __NR_brk 45
60#define __NR_setgid 46
61#define __NR_getgid 47
62#define __NR_signal 48
63#define __NR_geteuid 49
64#define __NR_getegid 50
65#define __NR_acct 51
66#define __NR_umount2 52
67#define __NR_lock 53
68#define __NR_ioctl 54
69#define __NR_fcntl 55
70#define __NR_mpx 56
71#define __NR_setpgid 57
72#define __NR_ulimit 58
73#define __NR_oldolduname 59
74#define __NR_umask 60
75#define __NR_chroot 61
76#define __NR_ustat 62
77#define __NR_dup2 63
78#define __NR_getppid 64
79#define __NR_getpgrp 65
80#define __NR_setsid 66
81#define __NR_sigaction 67
82#define __NR_sgetmask 68
83#define __NR_ssetmask 69
84#define __NR_setreuid 70
85#define __NR_setregid 71
86#define __NR_sigsuspend 72
87#define __NR_sigpending 73
88#define __NR_sethostname 74
89#define __NR_setrlimit 75
90#define __NR_getrlimit 76
91#define __NR_getrusage 77
92#define __NR_gettimeofday 78
93#define __NR_settimeofday 79
94#define __NR_getgroups 80
95#define __NR_setgroups 81
96#define __NR_select 82
97#define __NR_symlink 83
98#define __NR_oldlstat 84
99#define __NR_readlink 85
100#define __NR_uselib 86
101#define __NR_swapon 87
102#define __NR_reboot 88
103#define __NR_readdir 89
104#define __NR_mmap 90
105#define __NR_munmap 91
106#define __NR_truncate 92
107#define __NR_ftruncate 93
108#define __NR_fchmod 94
109#define __NR_fchown 95
110#define __NR_getpriority 96
111#define __NR_setpriority 97
112#define __NR_profil 98
113#define __NR_statfs 99
114#define __NR_fstatfs 100
115#define __NR_ioperm 101
116#define __NR_socketcall 102
117#define __NR_syslog 103
118#define __NR_setitimer 104
119#define __NR_getitimer 105
120#define __NR_stat 106
121#define __NR_lstat 107
122#define __NR_fstat 108
123#define __NR_olduname 109
124#define __NR_iopl 110
125#define __NR_vhangup 111
126#define __NR_idle 112
127#define __NR_vm86 113
128#define __NR_wait4 114
129#define __NR_swapoff 115
130#define __NR_sysinfo 116
131#define __NR_ipc 117
132#define __NR_fsync 118
133#define __NR_sigreturn 119
134#define __NR_clone 120
135#define __NR_setdomainname 121
136#define __NR_uname 122
137#define __NR_modify_ldt 123
138#define __NR_adjtimex 124
139#define __NR_mprotect 125
140#define __NR_sigprocmask 126
141#define __NR_create_module 127
142#define __NR_init_module 128
143#define __NR_delete_module 129
144#define __NR_get_kernel_syms 130
145#define __NR_quotactl 131
146#define __NR_getpgid 132
147#define __NR_fchdir 133
148#define __NR_bdflush 134
149#define __NR_sysfs 135
150#define __NR_personality 136
151#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
152#define __NR_setfsuid 138
153#define __NR_setfsgid 139
154#define __NR__llseek 140
155#define __NR_getdents 141
156#define __NR__newselect 142
157#define __NR_flock 143
158#define __NR_msync 144
159#define __NR_readv 145
160#define __NR_writev 146
161#define __NR_getsid 147
162#define __NR_fdatasync 148
163#define __NR__sysctl 149
164#define __NR_mlock 150
165#define __NR_munlock 151
166#define __NR_mlockall 152
167#define __NR_munlockall 153
168#define __NR_sched_setparam 154
169#define __NR_sched_getparam 155
170#define __NR_sched_setscheduler 156
171#define __NR_sched_getscheduler 157
172#define __NR_sched_yield 158
173#define __NR_sched_get_priority_max 159
174#define __NR_sched_get_priority_min 160
175#define __NR_sched_rr_get_interval 161
176#define __NR_nanosleep 162
177#define __NR_mremap 163
178#define __NR_setresuid 164
179#define __NR_getresuid 165
180#define __NR_query_module 166
181#define __NR_poll 167
182#define __NR_nfsservctl 168
183#define __NR_setresgid 169
184#define __NR_getresgid 170
185#define __NR_prctl 171
186#define __NR_rt_sigreturn 172
187#define __NR_rt_sigaction 173
188#define __NR_rt_sigprocmask 174
189#define __NR_rt_sigpending 175
190#define __NR_rt_sigtimedwait 176
191#define __NR_rt_sigqueueinfo 177
192#define __NR_rt_sigsuspend 178
193#define __NR_pread64 179
194#define __NR_pwrite64 180
195#define __NR_chown 181
196#define __NR_getcwd 182
197#define __NR_capget 183
198#define __NR_capset 184
199#define __NR_sigaltstack 185
200#define __NR_sendfile 186
201#define __NR_getpmsg 187 /* some people actually want streams */
202#define __NR_putpmsg 188 /* some people actually want streams */
203#define __NR_vfork 189
204#define __NR_ugetrlimit 190 /* SuS compliant getrlimit */
205#define __NR_readahead 191
206#ifndef __powerpc64__ /* these are 32-bit only */
207#define __NR_mmap2 192
208#define __NR_truncate64 193
209#define __NR_ftruncate64 194
210#define __NR_stat64 195
211#define __NR_lstat64 196
212#define __NR_fstat64 197
213#endif
214#define __NR_pciconfig_read 198
215#define __NR_pciconfig_write 199
216#define __NR_pciconfig_iobase 200
217#define __NR_multiplexer 201
218#define __NR_getdents64 202
219#define __NR_pivot_root 203
220#ifndef __powerpc64__
221#define __NR_fcntl64 204
222#endif
223#define __NR_madvise 205
224#define __NR_mincore 206
225#define __NR_gettid 207
226#define __NR_tkill 208
227#define __NR_setxattr 209
228#define __NR_lsetxattr 210
229#define __NR_fsetxattr 211
230#define __NR_getxattr 212
231#define __NR_lgetxattr 213
232#define __NR_fgetxattr 214
233#define __NR_listxattr 215
234#define __NR_llistxattr 216
235#define __NR_flistxattr 217
236#define __NR_removexattr 218
237#define __NR_lremovexattr 219
238#define __NR_fremovexattr 220
239#define __NR_futex 221
240#define __NR_sched_setaffinity 222
241#define __NR_sched_getaffinity 223
242/* 224 currently unused */
243#define __NR_tuxcall 225
244#ifndef __powerpc64__
245#define __NR_sendfile64 226
246#endif
247#define __NR_io_setup 227
248#define __NR_io_destroy 228
249#define __NR_io_getevents 229
250#define __NR_io_submit 230
251#define __NR_io_cancel 231
252#define __NR_set_tid_address 232
253#define __NR_fadvise64 233
254#define __NR_exit_group 234
255#define __NR_lookup_dcookie 235
256#define __NR_epoll_create 236
257#define __NR_epoll_ctl 237
258#define __NR_epoll_wait 238
259#define __NR_remap_file_pages 239
260#define __NR_timer_create 240
261#define __NR_timer_settime 241
262#define __NR_timer_gettime 242
263#define __NR_timer_getoverrun 243
264#define __NR_timer_delete 244
265#define __NR_clock_settime 245
266#define __NR_clock_gettime 246
267#define __NR_clock_getres 247
268#define __NR_clock_nanosleep 248
269#define __NR_swapcontext 249
270#define __NR_tgkill 250
271#define __NR_utimes 251
272#define __NR_statfs64 252
273#define __NR_fstatfs64 253
274#ifndef __powerpc64__
275#define __NR_fadvise64_64 254
276#endif
277#define __NR_rtas 255
278#define __NR_sys_debug_setcontext 256
279/* Number 257 is reserved for vserver */
280#define __NR_migrate_pages 258
281#define __NR_mbind 259
282#define __NR_get_mempolicy 260
283#define __NR_set_mempolicy 261
284#define __NR_mq_open 262
285#define __NR_mq_unlink 263
286#define __NR_mq_timedsend 264
287#define __NR_mq_timedreceive 265
288#define __NR_mq_notify 266
289#define __NR_mq_getsetattr 267
290#define __NR_kexec_load 268
291#define __NR_add_key 269
292#define __NR_request_key 270
293#define __NR_keyctl 271
294#define __NR_waitid 272
295#define __NR_ioprio_set 273
296#define __NR_ioprio_get 274
297#define __NR_inotify_init 275
298#define __NR_inotify_add_watch 276
299#define __NR_inotify_rm_watch 277
300#define __NR_spu_run 278
301#define __NR_spu_create 279
302#define __NR_pselect6 280
303#define __NR_ppoll 281
304#define __NR_unshare 282
305#define __NR_splice 283
306#define __NR_tee 284
307#define __NR_vmsplice 285
308#define __NR_openat 286
309#define __NR_mkdirat 287
310#define __NR_mknodat 288
311#define __NR_fchownat 289
312#define __NR_futimesat 290
313#ifdef __powerpc64__
314#define __NR_newfstatat 291
315#else
316#define __NR_fstatat64 291
317#endif
318#define __NR_unlinkat 292
319#define __NR_renameat 293
320#define __NR_linkat 294
321#define __NR_symlinkat 295
322#define __NR_readlinkat 296
323#define __NR_fchmodat 297
324#define __NR_faccessat 298
325#define __NR_get_robust_list 299
326#define __NR_set_robust_list 300
327#define __NR_move_pages 301
328#define __NR_getcpu 302
329#define __NR_epoll_pwait 303
330#define __NR_utimensat 304
331#define __NR_signalfd 305
332#define __NR_timerfd_create 306
333#define __NR_eventfd 307
334#define __NR_sync_file_range2 308
335#define __NR_fallocate 309
336#define __NR_subpage_prot 310
337#define __NR_timerfd_settime 311
338#define __NR_timerfd_gettime 312
339#define __NR_signalfd4 313
340#define __NR_eventfd2 314
341#define __NR_epoll_create1 315
342#define __NR_dup3 316
343#define __NR_pipe2 317
344#define __NR_inotify_init1 318
345#define __NR_perf_event_open 319
346#define __NR_preadv 320
347#define __NR_pwritev 321
348#define __NR_rt_tgsigqueueinfo 322
349#define __NR_fanotify_init 323
350#define __NR_fanotify_mark 324
351#define __NR_prlimit64 325
352#define __NR_socket 326
353#define __NR_bind 327
354#define __NR_connect 328
355#define __NR_listen 329
356#define __NR_accept 330
357#define __NR_getsockname 331
358#define __NR_getpeername 332
359#define __NR_socketpair 333
360#define __NR_send 334
361#define __NR_sendto 335
362#define __NR_recv 336
363#define __NR_recvfrom 337
364#define __NR_shutdown 338
365#define __NR_setsockopt 339
366#define __NR_getsockopt 340
367#define __NR_sendmsg 341
368#define __NR_recvmsg 342
369#define __NR_recvmmsg 343
370#define __NR_accept4 344
371#define __NR_name_to_handle_at 345
372#define __NR_open_by_handle_at 346
373#define __NR_clock_adjtime 347
374#define __NR_syncfs 348
375#define __NR_sendmmsg 349
376#define __NR_setns 350
377#define __NR_process_vm_readv 351
378#define __NR_process_vm_writev 352
379#define __NR_finit_module 353
380#define __NR_kcmp 354
381#define __NR_sched_setattr 355
382#define __NR_sched_getattr 356
383#define __NR_renameat2 357
384#define __NR_seccomp 358
385#define __NR_getrandom 359
386#define __NR_memfd_create 360
387#define __NR_bpf 361
388#define __NR_execveat 362
389#define __NR_switch_endian 363
390#define __NR_userfaultfd 364
391#define __NR_membarrier 365
392#define __NR_mlock2 378
393#define __NR_copy_file_range 379
394#define __NR_preadv2 380
395#define __NR_pwritev2 381
396#define __NR_kexec_file_load 382
397#define __NR_statx 383
398#define __NR_pkey_alloc 384
399#define __NR_pkey_free 385
400#define __NR_pkey_mprotect 386
401
402#endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
diff --git a/tools/arch/s390/include/uapi/asm/unistd.h b/tools/arch/s390/include/uapi/asm/unistd.h
deleted file mode 100644
index 725120939051..000000000000
--- a/tools/arch/s390/include/uapi/asm/unistd.h
+++ /dev/null
@@ -1,412 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2/*
3 * S390 version
4 *
5 * Derived from "include/asm-i386/unistd.h"
6 */
7
8#ifndef _UAPI_ASM_S390_UNISTD_H_
9#define _UAPI_ASM_S390_UNISTD_H_
10
11/*
12 * This file contains the system call numbers.
13 */
14
15#define __NR_exit 1
16#define __NR_fork 2
17#define __NR_read 3
18#define __NR_write 4
19#define __NR_open 5
20#define __NR_close 6
21#define __NR_restart_syscall 7
22#define __NR_creat 8
23#define __NR_link 9
24#define __NR_unlink 10
25#define __NR_execve 11
26#define __NR_chdir 12
27#define __NR_mknod 14
28#define __NR_chmod 15
29#define __NR_lseek 19
30#define __NR_getpid 20
31#define __NR_mount 21
32#define __NR_umount 22
33#define __NR_ptrace 26
34#define __NR_alarm 27
35#define __NR_pause 29
36#define __NR_utime 30
37#define __NR_access 33
38#define __NR_nice 34
39#define __NR_sync 36
40#define __NR_kill 37
41#define __NR_rename 38
42#define __NR_mkdir 39
43#define __NR_rmdir 40
44#define __NR_dup 41
45#define __NR_pipe 42
46#define __NR_times 43
47#define __NR_brk 45
48#define __NR_signal 48
49#define __NR_acct 51
50#define __NR_umount2 52
51#define __NR_ioctl 54
52#define __NR_fcntl 55
53#define __NR_setpgid 57
54#define __NR_umask 60
55#define __NR_chroot 61
56#define __NR_ustat 62
57#define __NR_dup2 63
58#define __NR_getppid 64
59#define __NR_getpgrp 65
60#define __NR_setsid 66
61#define __NR_sigaction 67
62#define __NR_sigsuspend 72
63#define __NR_sigpending 73
64#define __NR_sethostname 74
65#define __NR_setrlimit 75
66#define __NR_getrusage 77
67#define __NR_gettimeofday 78
68#define __NR_settimeofday 79
69#define __NR_symlink 83
70#define __NR_readlink 85
71#define __NR_uselib 86
72#define __NR_swapon 87
73#define __NR_reboot 88
74#define __NR_readdir 89
75#define __NR_mmap 90
76#define __NR_munmap 91
77#define __NR_truncate 92
78#define __NR_ftruncate 93
79#define __NR_fchmod 94
80#define __NR_getpriority 96
81#define __NR_setpriority 97
82#define __NR_statfs 99
83#define __NR_fstatfs 100
84#define __NR_socketcall 102
85#define __NR_syslog 103
86#define __NR_setitimer 104
87#define __NR_getitimer 105
88#define __NR_stat 106
89#define __NR_lstat 107
90#define __NR_fstat 108
91#define __NR_lookup_dcookie 110
92#define __NR_vhangup 111
93#define __NR_idle 112
94#define __NR_wait4 114
95#define __NR_swapoff 115
96#define __NR_sysinfo 116
97#define __NR_ipc 117
98#define __NR_fsync 118
99#define __NR_sigreturn 119
100#define __NR_clone 120
101#define __NR_setdomainname 121
102#define __NR_uname 122
103#define __NR_adjtimex 124
104#define __NR_mprotect 125
105#define __NR_sigprocmask 126
106#define __NR_create_module 127
107#define __NR_init_module 128
108#define __NR_delete_module 129
109#define __NR_get_kernel_syms 130
110#define __NR_quotactl 131
111#define __NR_getpgid 132
112#define __NR_fchdir 133
113#define __NR_bdflush 134
114#define __NR_sysfs 135
115#define __NR_personality 136
116#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
117#define __NR_getdents 141
118#define __NR_flock 143
119#define __NR_msync 144
120#define __NR_readv 145
121#define __NR_writev 146
122#define __NR_getsid 147
123#define __NR_fdatasync 148
124#define __NR__sysctl 149
125#define __NR_mlock 150
126#define __NR_munlock 151
127#define __NR_mlockall 152
128#define __NR_munlockall 153
129#define __NR_sched_setparam 154
130#define __NR_sched_getparam 155
131#define __NR_sched_setscheduler 156
132#define __NR_sched_getscheduler 157
133#define __NR_sched_yield 158
134#define __NR_sched_get_priority_max 159
135#define __NR_sched_get_priority_min 160
136#define __NR_sched_rr_get_interval 161
137#define __NR_nanosleep 162
138#define __NR_mremap 163
139#define __NR_query_module 167
140#define __NR_poll 168
141#define __NR_nfsservctl 169
142#define __NR_prctl 172
143#define __NR_rt_sigreturn 173
144#define __NR_rt_sigaction 174
145#define __NR_rt_sigprocmask 175
146#define __NR_rt_sigpending 176
147#define __NR_rt_sigtimedwait 177
148#define __NR_rt_sigqueueinfo 178
149#define __NR_rt_sigsuspend 179
150#define __NR_pread64 180
151#define __NR_pwrite64 181
152#define __NR_getcwd 183
153#define __NR_capget 184
154#define __NR_capset 185
155#define __NR_sigaltstack 186
156#define __NR_sendfile 187
157#define __NR_getpmsg 188
158#define __NR_putpmsg 189
159#define __NR_vfork 190
160#define __NR_pivot_root 217
161#define __NR_mincore 218
162#define __NR_madvise 219
163#define __NR_getdents64 220
164#define __NR_readahead 222
165#define __NR_setxattr 224
166#define __NR_lsetxattr 225
167#define __NR_fsetxattr 226
168#define __NR_getxattr 227
169#define __NR_lgetxattr 228
170#define __NR_fgetxattr 229
171#define __NR_listxattr 230
172#define __NR_llistxattr 231
173#define __NR_flistxattr 232
174#define __NR_removexattr 233
175#define __NR_lremovexattr 234
176#define __NR_fremovexattr 235
177#define __NR_gettid 236
178#define __NR_tkill 237
179#define __NR_futex 238
180#define __NR_sched_setaffinity 239
181#define __NR_sched_getaffinity 240
182#define __NR_tgkill 241
183/* Number 242 is reserved for tux */
184#define __NR_io_setup 243
185#define __NR_io_destroy 244
186#define __NR_io_getevents 245
187#define __NR_io_submit 246
188#define __NR_io_cancel 247
189#define __NR_exit_group 248
190#define __NR_epoll_create 249
191#define __NR_epoll_ctl 250
192#define __NR_epoll_wait 251
193#define __NR_set_tid_address 252
194#define __NR_fadvise64 253
195#define __NR_timer_create 254
196#define __NR_timer_settime 255
197#define __NR_timer_gettime 256
198#define __NR_timer_getoverrun 257
199#define __NR_timer_delete 258
200#define __NR_clock_settime 259
201#define __NR_clock_gettime 260
202#define __NR_clock_getres 261
203#define __NR_clock_nanosleep 262
204/* Number 263 is reserved for vserver */
205#define __NR_statfs64 265
206#define __NR_fstatfs64 266
207#define __NR_remap_file_pages 267
208#define __NR_mbind 268
209#define __NR_get_mempolicy 269
210#define __NR_set_mempolicy 270
211#define __NR_mq_open 271
212#define __NR_mq_unlink 272
213#define __NR_mq_timedsend 273
214#define __NR_mq_timedreceive 274
215#define __NR_mq_notify 275
216#define __NR_mq_getsetattr 276
217#define __NR_kexec_load 277
218#define __NR_add_key 278
219#define __NR_request_key 279
220#define __NR_keyctl 280
221#define __NR_waitid 281
222#define __NR_ioprio_set 282
223#define __NR_ioprio_get 283
224#define __NR_inotify_init 284
225#define __NR_inotify_add_watch 285
226#define __NR_inotify_rm_watch 286
227#define __NR_migrate_pages 287
228#define __NR_openat 288
229#define __NR_mkdirat 289
230#define __NR_mknodat 290
231#define __NR_fchownat 291
232#define __NR_futimesat 292
233#define __NR_unlinkat 294
234#define __NR_renameat 295
235#define __NR_linkat 296
236#define __NR_symlinkat 297
237#define __NR_readlinkat 298
238#define __NR_fchmodat 299
239#define __NR_faccessat 300
240#define __NR_pselect6 301
241#define __NR_ppoll 302
242#define __NR_unshare 303
243#define __NR_set_robust_list 304
244#define __NR_get_robust_list 305
245#define __NR_splice 306
246#define __NR_sync_file_range 307
247#define __NR_tee 308
248#define __NR_vmsplice 309
249#define __NR_move_pages 310
250#define __NR_getcpu 311
251#define __NR_epoll_pwait 312
252#define __NR_utimes 313
253#define __NR_fallocate 314
254#define __NR_utimensat 315
255#define __NR_signalfd 316
256#define __NR_timerfd 317
257#define __NR_eventfd 318
258#define __NR_timerfd_create 319
259#define __NR_timerfd_settime 320
260#define __NR_timerfd_gettime 321
261#define __NR_signalfd4 322
262#define __NR_eventfd2 323
263#define __NR_inotify_init1 324
264#define __NR_pipe2 325
265#define __NR_dup3 326
266#define __NR_epoll_create1 327
267#define __NR_preadv 328
268#define __NR_pwritev 329
269#define __NR_rt_tgsigqueueinfo 330
270#define __NR_perf_event_open 331
271#define __NR_fanotify_init 332
272#define __NR_fanotify_mark 333
273#define __NR_prlimit64 334
274#define __NR_name_to_handle_at 335
275#define __NR_open_by_handle_at 336
276#define __NR_clock_adjtime 337
277#define __NR_syncfs 338
278#define __NR_setns 339
279#define __NR_process_vm_readv 340
280#define __NR_process_vm_writev 341
281#define __NR_s390_runtime_instr 342
282#define __NR_kcmp 343
283#define __NR_finit_module 344
284#define __NR_sched_setattr 345
285#define __NR_sched_getattr 346
286#define __NR_renameat2 347
287#define __NR_seccomp 348
288#define __NR_getrandom 349
289#define __NR_memfd_create 350
290#define __NR_bpf 351
291#define __NR_s390_pci_mmio_write 352
292#define __NR_s390_pci_mmio_read 353
293#define __NR_execveat 354
294#define __NR_userfaultfd 355
295#define __NR_membarrier 356
296#define __NR_recvmmsg 357
297#define __NR_sendmmsg 358
298#define __NR_socket 359
299#define __NR_socketpair 360
300#define __NR_bind 361
301#define __NR_connect 362
302#define __NR_listen 363
303#define __NR_accept4 364
304#define __NR_getsockopt 365
305#define __NR_setsockopt 366
306#define __NR_getsockname 367
307#define __NR_getpeername 368
308#define __NR_sendto 369
309#define __NR_sendmsg 370
310#define __NR_recvfrom 371
311#define __NR_recvmsg 372
312#define __NR_shutdown 373
313#define __NR_mlock2 374
314#define __NR_copy_file_range 375
315#define __NR_preadv2 376
316#define __NR_pwritev2 377
317#define __NR_s390_guarded_storage 378
318#define __NR_statx 379
319#define __NR_s390_sthyi 380
320#define NR_syscalls 381
321
322/*
323 * There are some system calls that are not present on 64 bit, some
324 * have a different name although they do the same (e.g. __NR_chown32
325 * is __NR_chown on 64 bit).
326 */
327#ifndef __s390x__
328
329#define __NR_time 13
330#define __NR_lchown 16
331#define __NR_setuid 23
332#define __NR_getuid 24
333#define __NR_stime 25
334#define __NR_setgid 46
335#define __NR_getgid 47
336#define __NR_geteuid 49
337#define __NR_getegid 50
338#define __NR_setreuid 70
339#define __NR_setregid 71
340#define __NR_getrlimit 76
341#define __NR_getgroups 80
342#define __NR_setgroups 81
343#define __NR_fchown 95
344#define __NR_ioperm 101
345#define __NR_setfsuid 138
346#define __NR_setfsgid 139
347#define __NR__llseek 140
348#define __NR__newselect 142
349#define __NR_setresuid 164
350#define __NR_getresuid 165
351#define __NR_setresgid 170
352#define __NR_getresgid 171
353#define __NR_chown 182
354#define __NR_ugetrlimit 191 /* SuS compliant getrlimit */
355#define __NR_mmap2 192
356#define __NR_truncate64 193
357#define __NR_ftruncate64 194
358#define __NR_stat64 195
359#define __NR_lstat64 196
360#define __NR_fstat64 197
361#define __NR_lchown32 198
362#define __NR_getuid32 199
363#define __NR_getgid32 200
364#define __NR_geteuid32 201
365#define __NR_getegid32 202
366#define __NR_setreuid32 203
367#define __NR_setregid32 204
368#define __NR_getgroups32 205
369#define __NR_setgroups32 206
370#define __NR_fchown32 207
371#define __NR_setresuid32 208
372#define __NR_getresuid32 209
373#define __NR_setresgid32 210
374#define __NR_getresgid32 211
375#define __NR_chown32 212
376#define __NR_setuid32 213
377#define __NR_setgid32 214
378#define __NR_setfsuid32 215
379#define __NR_setfsgid32 216
380#define __NR_fcntl64 221
381#define __NR_sendfile64 223
382#define __NR_fadvise64_64 264
383#define __NR_fstatat64 293
384
385#else
386
387#define __NR_select 142
388#define __NR_getrlimit 191 /* SuS compliant getrlimit */
389#define __NR_lchown 198
390#define __NR_getuid 199
391#define __NR_getgid 200
392#define __NR_geteuid 201
393#define __NR_getegid 202
394#define __NR_setreuid 203
395#define __NR_setregid 204
396#define __NR_getgroups 205
397#define __NR_setgroups 206
398#define __NR_fchown 207
399#define __NR_setresuid 208
400#define __NR_getresuid 209
401#define __NR_setresgid 210
402#define __NR_getresgid 211
403#define __NR_chown 212
404#define __NR_setuid 213
405#define __NR_setgid 214
406#define __NR_setfsuid 215
407#define __NR_setfsgid 216
408#define __NR_newfstatat 293
409
410#endif
411
412#endif /* _UAPI_ASM_S390_UNISTD_H_ */
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
index 1d9199e1c2ad..f41079da38c5 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -210,8 +210,10 @@
210 210
211#define X86_FEATURE_MBA ( 7*32+18) /* Memory Bandwidth Allocation */ 211#define X86_FEATURE_MBA ( 7*32+18) /* Memory Bandwidth Allocation */
212#define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* "" Fill RSB on context switches */ 212#define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* "" Fill RSB on context switches */
213#define X86_FEATURE_SEV ( 7*32+20) /* AMD Secure Encrypted Virtualization */
213 214
214#define X86_FEATURE_USE_IBPB ( 7*32+21) /* "" Indirect Branch Prediction Barrier enabled */ 215#define X86_FEATURE_USE_IBPB ( 7*32+21) /* "" Indirect Branch Prediction Barrier enabled */
216#define X86_FEATURE_USE_IBRS_FW ( 7*32+22) /* "" Use IBRS during runtime firmware calls */
215 217
216/* Virtualization flags: Linux defined, word 8 */ 218/* Virtualization flags: Linux defined, word 8 */
217#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ 219#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
index 0b482c0070e0..465995281dcd 100644
--- a/tools/bpf/bpftool/common.c
+++ b/tools/bpf/bpftool/common.c
@@ -55,6 +55,10 @@
55 55
56#include "main.h" 56#include "main.h"
57 57
58#ifndef BPF_FS_MAGIC
59#define BPF_FS_MAGIC 0xcafe4a11
60#endif
61
58void p_err(const char *fmt, ...) 62void p_err(const char *fmt, ...)
59{ 63{
60 va_list ap; 64 va_list ap;
diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
index 3a0396d87c42..185acfa229b5 100644
--- a/tools/bpf/bpftool/main.c
+++ b/tools/bpf/bpftool/main.c
@@ -244,7 +244,7 @@ static int do_batch(int argc, char **argv)
244 } 244 }
245 245
246 if (errno && errno != ENOENT) { 246 if (errno && errno != ENOENT) {
247 perror("reading batch file failed"); 247 p_err("reading batch file failed: %s", strerror(errno));
248 err = -1; 248 err = -1;
249 } else { 249 } else {
250 p_info("processed %d lines", lines); 250 p_info("processed %d lines", lines);
diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
index f95fa67bb498..f509c86faede 100644
--- a/tools/bpf/bpftool/map.c
+++ b/tools/bpf/bpftool/map.c
@@ -428,7 +428,7 @@ static int show_map_close_json(int fd, struct bpf_map_info *info)
428 jsonw_string_field(json_wtr, "name", info->name); 428 jsonw_string_field(json_wtr, "name", info->name);
429 429
430 jsonw_name(json_wtr, "flags"); 430 jsonw_name(json_wtr, "flags");
431 jsonw_printf(json_wtr, "%#x", info->map_flags); 431 jsonw_printf(json_wtr, "%d", info->map_flags);
432 432
433 print_dev_json(info->ifindex, info->netns_dev, info->netns_ino); 433 print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
434 434
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index e8e2baaf93c2..e549e329be82 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -774,6 +774,9 @@ static int do_dump(int argc, char **argv)
774 n < 0 ? strerror(errno) : "short write"); 774 n < 0 ? strerror(errno) : "short write");
775 goto err_free; 775 goto err_free;
776 } 776 }
777
778 if (json_output)
779 jsonw_null(json_wtr);
777 } else { 780 } else {
778 if (member_len == &info.jited_prog_len) { 781 if (member_len == &info.jited_prog_len) {
779 const char *name = NULL; 782 const char *name = NULL;
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index c378f003b007..5b6dda3b1ca8 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -82,7 +82,11 @@ FEATURE_TESTS_EXTRA := \
82 liberty-z \ 82 liberty-z \
83 libunwind-debug-frame \ 83 libunwind-debug-frame \
84 libunwind-debug-frame-arm \ 84 libunwind-debug-frame-arm \
85 libunwind-debug-frame-aarch64 85 libunwind-debug-frame-aarch64 \
86 cxx \
87 llvm \
88 llvm-version \
89 clang
86 90
87FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC) 91FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)
88 92
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index 0a490cb15149..dac9563b5470 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -54,7 +54,10 @@ FILES= \
54 test-jvmti.bin \ 54 test-jvmti.bin \
55 test-sched_getcpu.bin \ 55 test-sched_getcpu.bin \
56 test-setns.bin \ 56 test-setns.bin \
57 test-libopencsd.bin 57 test-libopencsd.bin \
58 test-clang.bin \
59 test-llvm.bin \
60 test-llvm-version.bin
58 61
59FILES := $(addprefix $(OUTPUT),$(FILES)) 62FILES := $(addprefix $(OUTPUT),$(FILES))
60 63
@@ -257,11 +260,13 @@ $(OUTPUT)test-llvm.bin:
257 -I$(shell $(LLVM_CONFIG) --includedir) \ 260 -I$(shell $(LLVM_CONFIG) --includedir) \
258 -L$(shell $(LLVM_CONFIG) --libdir) \ 261 -L$(shell $(LLVM_CONFIG) --libdir) \
259 $(shell $(LLVM_CONFIG) --libs Core BPF) \ 262 $(shell $(LLVM_CONFIG) --libs Core BPF) \
260 $(shell $(LLVM_CONFIG) --system-libs) 263 $(shell $(LLVM_CONFIG) --system-libs) \
264 > $(@:.bin=.make.output) 2>&1
261 265
262$(OUTPUT)test-llvm-version.bin: 266$(OUTPUT)test-llvm-version.bin:
263 $(BUILDXX) -std=gnu++11 \ 267 $(BUILDXX) -std=gnu++11 \
264 -I$(shell $(LLVM_CONFIG) --includedir) 268 -I$(shell $(LLVM_CONFIG) --includedir) \
269 > $(@:.bin=.make.output) 2>&1
265 270
266$(OUTPUT)test-clang.bin: 271$(OUTPUT)test-clang.bin:
267 $(BUILDXX) -std=gnu++11 \ 272 $(BUILDXX) -std=gnu++11 \
@@ -271,7 +276,8 @@ $(OUTPUT)test-clang.bin:
271 -lclangFrontend -lclangEdit -lclangLex \ 276 -lclangFrontend -lclangEdit -lclangLex \
272 -lclangAST -Wl,--end-group \ 277 -lclangAST -Wl,--end-group \
273 $(shell $(LLVM_CONFIG) --libs Core option) \ 278 $(shell $(LLVM_CONFIG) --libs Core option) \
274 $(shell $(LLVM_CONFIG) --system-libs) 279 $(shell $(LLVM_CONFIG) --system-libs) \
280 > $(@:.bin=.make.output) 2>&1
275 281
276-include $(OUTPUT)*.d 282-include $(OUTPUT)*.d
277 283
diff --git a/tools/cgroup/Makefile b/tools/cgroup/Makefile
index 860fa151640a..ffca068e4a76 100644
--- a/tools/cgroup/Makefile
+++ b/tools/cgroup/Makefile
@@ -1,7 +1,6 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2# Makefile for cgroup tools 2# Makefile for cgroup tools
3 3
4CC = $(CROSS_COMPILE)gcc
5CFLAGS = -Wall -Wextra 4CFLAGS = -Wall -Wextra
6 5
7all: cgroup_event_listener 6all: cgroup_event_listener
diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile
index 805a2c0cf4cd..240eda014b37 100644
--- a/tools/gpio/Makefile
+++ b/tools/gpio/Makefile
@@ -12,8 +12,6 @@ endif
12# (this improves performance and avoids hard-to-debug behaviour); 12# (this improves performance and avoids hard-to-debug behaviour);
13MAKEFLAGS += -r 13MAKEFLAGS += -r
14 14
15CC = $(CROSS_COMPILE)gcc
16LD = $(CROSS_COMPILE)ld
17CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include 15CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
18 16
19ALL_TARGETS := lsgpio gpio-hammer gpio-event-mon 17ALL_TARGETS := lsgpio gpio-hammer gpio-event-mon
diff --git a/tools/hv/Makefile b/tools/hv/Makefile
index 1139d71fa0cf..5db5e62cebda 100644
--- a/tools/hv/Makefile
+++ b/tools/hv/Makefile
@@ -1,7 +1,6 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2# Makefile for Hyper-V tools 2# Makefile for Hyper-V tools
3 3
4CC = $(CROSS_COMPILE)gcc
5WARNINGS = -Wall -Wextra 4WARNINGS = -Wall -Wextra
6CFLAGS = $(WARNINGS) -g $(shell getconf LFS_CFLAGS) 5CFLAGS = $(WARNINGS) -g $(shell getconf LFS_CFLAGS)
7 6
diff --git a/tools/iio/Makefile b/tools/iio/Makefile
index a08e7a47d6a3..332ed2f6c2c2 100644
--- a/tools/iio/Makefile
+++ b/tools/iio/Makefile
@@ -12,8 +12,6 @@ endif
12# (this improves performance and avoids hard-to-debug behaviour); 12# (this improves performance and avoids hard-to-debug behaviour);
13MAKEFLAGS += -r 13MAKEFLAGS += -r
14 14
15CC = $(CROSS_COMPILE)gcc
16LD = $(CROSS_COMPILE)ld
17CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include 15CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
18 16
19ALL_TARGETS := iio_event_monitor lsiio iio_generic_buffer 17ALL_TARGETS := iio_event_monitor lsiio iio_generic_buffer
diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index ca160270fdfa..63440cc8d618 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -98,7 +98,7 @@ static inline int test_and_set_bit(int nr, unsigned long *addr)
98 98
99/** 99/**
100 * bitmap_alloc - Allocate bitmap 100 * bitmap_alloc - Allocate bitmap
101 * @nr: Bit to set 101 * @nbits: Number of bits
102 */ 102 */
103static inline unsigned long *bitmap_alloc(int nbits) 103static inline unsigned long *bitmap_alloc(int nbits)
104{ 104{
diff --git a/tools/include/uapi/drm/i915_drm.h b/tools/include/uapi/drm/i915_drm.h
index ac3c6503ca27..536ee4febd74 100644
--- a/tools/include/uapi/drm/i915_drm.h
+++ b/tools/include/uapi/drm/i915_drm.h
@@ -86,6 +86,62 @@ enum i915_mocs_table_index {
86 I915_MOCS_CACHED, 86 I915_MOCS_CACHED,
87}; 87};
88 88
89/*
90 * Different engines serve different roles, and there may be more than one
91 * engine serving each role. enum drm_i915_gem_engine_class provides a
92 * classification of the role of the engine, which may be used when requesting
93 * operations to be performed on a certain subset of engines, or for providing
94 * information about that group.
95 */
96enum drm_i915_gem_engine_class {
97 I915_ENGINE_CLASS_RENDER = 0,
98 I915_ENGINE_CLASS_COPY = 1,
99 I915_ENGINE_CLASS_VIDEO = 2,
100 I915_ENGINE_CLASS_VIDEO_ENHANCE = 3,
101
102 I915_ENGINE_CLASS_INVALID = -1
103};
104
105/**
106 * DOC: perf_events exposed by i915 through /sys/bus/event_sources/drivers/i915
107 *
108 */
109
110enum drm_i915_pmu_engine_sample {
111 I915_SAMPLE_BUSY = 0,
112 I915_SAMPLE_WAIT = 1,
113 I915_SAMPLE_SEMA = 2
114};
115
116#define I915_PMU_SAMPLE_BITS (4)
117#define I915_PMU_SAMPLE_MASK (0xf)
118#define I915_PMU_SAMPLE_INSTANCE_BITS (8)
119#define I915_PMU_CLASS_SHIFT \
120 (I915_PMU_SAMPLE_BITS + I915_PMU_SAMPLE_INSTANCE_BITS)
121
122#define __I915_PMU_ENGINE(class, instance, sample) \
123 ((class) << I915_PMU_CLASS_SHIFT | \
124 (instance) << I915_PMU_SAMPLE_BITS | \
125 (sample))
126
127#define I915_PMU_ENGINE_BUSY(class, instance) \
128 __I915_PMU_ENGINE(class, instance, I915_SAMPLE_BUSY)
129
130#define I915_PMU_ENGINE_WAIT(class, instance) \
131 __I915_PMU_ENGINE(class, instance, I915_SAMPLE_WAIT)
132
133#define I915_PMU_ENGINE_SEMA(class, instance) \
134 __I915_PMU_ENGINE(class, instance, I915_SAMPLE_SEMA)
135
136#define __I915_PMU_OTHER(x) (__I915_PMU_ENGINE(0xff, 0xff, 0xf) + 1 + (x))
137
138#define I915_PMU_ACTUAL_FREQUENCY __I915_PMU_OTHER(0)
139#define I915_PMU_REQUESTED_FREQUENCY __I915_PMU_OTHER(1)
140#define I915_PMU_INTERRUPTS __I915_PMU_OTHER(2)
141#define I915_PMU_RC6_RESIDENCY __I915_PMU_OTHER(3)
142
143#define I915_PMU_LAST I915_PMU_RC6_RESIDENCY
144
89/* Each region is a minimum of 16k, and there are at most 255 of them. 145/* Each region is a minimum of 16k, and there are at most 255 of them.
90 */ 146 */
91#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use 147#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use
@@ -450,6 +506,27 @@ typedef struct drm_i915_irq_wait {
450 */ 506 */
451#define I915_PARAM_HAS_EXEC_FENCE_ARRAY 49 507#define I915_PARAM_HAS_EXEC_FENCE_ARRAY 49
452 508
509/*
510 * Query whether every context (both per-file default and user created) is
511 * isolated (insofar as HW supports). If this parameter is not true, then
512 * freshly created contexts may inherit values from an existing context,
513 * rather than default HW values. If true, it also ensures (insofar as HW
514 * supports) that all state set by this context will not leak to any other
515 * context.
516 *
517 * As not every engine across every gen support contexts, the returned
518 * value reports the support of context isolation for individual engines by
519 * returning a bitmask of each engine class set to true if that class supports
520 * isolation.
521 */
522#define I915_PARAM_HAS_CONTEXT_ISOLATION 50
523
524/* Frequency of the command streamer timestamps given by the *_TIMESTAMP
525 * registers. This used to be fixed per platform but from CNL onwards, this
526 * might vary depending on the parts.
527 */
528#define I915_PARAM_CS_TIMESTAMP_FREQUENCY 51
529
453typedef struct drm_i915_getparam { 530typedef struct drm_i915_getparam {
454 __s32 param; 531 __s32 param;
455 /* 532 /*
diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/if_link.h
index 8616131e2c61..6d9447700e18 100644
--- a/tools/include/uapi/linux/if_link.h
+++ b/tools/include/uapi/linux/if_link.h
@@ -163,6 +163,7 @@ enum {
163 IFLA_IF_NETNSID, 163 IFLA_IF_NETNSID,
164 IFLA_CARRIER_UP_COUNT, 164 IFLA_CARRIER_UP_COUNT,
165 IFLA_CARRIER_DOWN_COUNT, 165 IFLA_CARRIER_DOWN_COUNT,
166 IFLA_NEW_IFINDEX,
166 __IFLA_MAX 167 __IFLA_MAX
167}; 168};
168 169
diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h
index 8fb90a0819c3..7b26d4b0b052 100644
--- a/tools/include/uapi/linux/kvm.h
+++ b/tools/include/uapi/linux/kvm.h
@@ -761,6 +761,7 @@ struct kvm_ppc_resize_hpt {
761#define KVM_TRACE_PAUSE __KVM_DEPRECATED_MAIN_0x07 761#define KVM_TRACE_PAUSE __KVM_DEPRECATED_MAIN_0x07
762#define KVM_TRACE_DISABLE __KVM_DEPRECATED_MAIN_0x08 762#define KVM_TRACE_DISABLE __KVM_DEPRECATED_MAIN_0x08
763#define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2) 763#define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2)
764#define KVM_GET_MSR_FEATURE_INDEX_LIST _IOWR(KVMIO, 0x0a, struct kvm_msr_list)
764 765
765/* 766/*
766 * Extension capability list. 767 * Extension capability list.
@@ -934,6 +935,7 @@ struct kvm_ppc_resize_hpt {
934#define KVM_CAP_S390_AIS_MIGRATION 150 935#define KVM_CAP_S390_AIS_MIGRATION 150
935#define KVM_CAP_PPC_GET_CPU_CHAR 151 936#define KVM_CAP_PPC_GET_CPU_CHAR 151
936#define KVM_CAP_S390_BPB 152 937#define KVM_CAP_S390_BPB 152
938#define KVM_CAP_GET_MSR_FEATURES 153
937 939
938#ifdef KVM_CAP_IRQ_ROUTING 940#ifdef KVM_CAP_IRQ_ROUTING
939 941
@@ -1362,6 +1364,96 @@ struct kvm_s390_ucas_mapping {
1362/* Available with KVM_CAP_S390_CMMA_MIGRATION */ 1364/* Available with KVM_CAP_S390_CMMA_MIGRATION */
1363#define KVM_S390_GET_CMMA_BITS _IOWR(KVMIO, 0xb8, struct kvm_s390_cmma_log) 1365#define KVM_S390_GET_CMMA_BITS _IOWR(KVMIO, 0xb8, struct kvm_s390_cmma_log)
1364#define KVM_S390_SET_CMMA_BITS _IOW(KVMIO, 0xb9, struct kvm_s390_cmma_log) 1366#define KVM_S390_SET_CMMA_BITS _IOW(KVMIO, 0xb9, struct kvm_s390_cmma_log)
1367/* Memory Encryption Commands */
1368#define KVM_MEMORY_ENCRYPT_OP _IOWR(KVMIO, 0xba, unsigned long)
1369
1370struct kvm_enc_region {
1371 __u64 addr;
1372 __u64 size;
1373};
1374
1375#define KVM_MEMORY_ENCRYPT_REG_REGION _IOR(KVMIO, 0xbb, struct kvm_enc_region)
1376#define KVM_MEMORY_ENCRYPT_UNREG_REGION _IOR(KVMIO, 0xbc, struct kvm_enc_region)
1377
1378/* Secure Encrypted Virtualization command */
1379enum sev_cmd_id {
1380 /* Guest initialization commands */
1381 KVM_SEV_INIT = 0,
1382 KVM_SEV_ES_INIT,
1383 /* Guest launch commands */
1384 KVM_SEV_LAUNCH_START,
1385 KVM_SEV_LAUNCH_UPDATE_DATA,
1386 KVM_SEV_LAUNCH_UPDATE_VMSA,
1387 KVM_SEV_LAUNCH_SECRET,
1388 KVM_SEV_LAUNCH_MEASURE,
1389 KVM_SEV_LAUNCH_FINISH,
1390 /* Guest migration commands (outgoing) */
1391 KVM_SEV_SEND_START,
1392 KVM_SEV_SEND_UPDATE_DATA,
1393 KVM_SEV_SEND_UPDATE_VMSA,
1394 KVM_SEV_SEND_FINISH,
1395 /* Guest migration commands (incoming) */
1396 KVM_SEV_RECEIVE_START,
1397 KVM_SEV_RECEIVE_UPDATE_DATA,
1398 KVM_SEV_RECEIVE_UPDATE_VMSA,
1399 KVM_SEV_RECEIVE_FINISH,
1400 /* Guest status and debug commands */
1401 KVM_SEV_GUEST_STATUS,
1402 KVM_SEV_DBG_DECRYPT,
1403 KVM_SEV_DBG_ENCRYPT,
1404 /* Guest certificates commands */
1405 KVM_SEV_CERT_EXPORT,
1406
1407 KVM_SEV_NR_MAX,
1408};
1409
1410struct kvm_sev_cmd {
1411 __u32 id;
1412 __u64 data;
1413 __u32 error;
1414 __u32 sev_fd;
1415};
1416
1417struct kvm_sev_launch_start {
1418 __u32 handle;
1419 __u32 policy;
1420 __u64 dh_uaddr;
1421 __u32 dh_len;
1422 __u64 session_uaddr;
1423 __u32 session_len;
1424};
1425
1426struct kvm_sev_launch_update_data {
1427 __u64 uaddr;
1428 __u32 len;
1429};
1430
1431
1432struct kvm_sev_launch_secret {
1433 __u64 hdr_uaddr;
1434 __u32 hdr_len;
1435 __u64 guest_uaddr;
1436 __u32 guest_len;
1437 __u64 trans_uaddr;
1438 __u32 trans_len;
1439};
1440
1441struct kvm_sev_launch_measure {
1442 __u64 uaddr;
1443 __u32 len;
1444};
1445
1446struct kvm_sev_guest_status {
1447 __u32 handle;
1448 __u32 policy;
1449 __u32 state;
1450};
1451
1452struct kvm_sev_dbg {
1453 __u64 src_uaddr;
1454 __u64 dst_uaddr;
1455 __u32 len;
1456};
1365 1457
1366#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) 1458#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
1367#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1) 1459#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index e0739a1aa4b2..912b85b52344 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -380,10 +380,14 @@ struct perf_event_attr {
380 __u32 bp_type; 380 __u32 bp_type;
381 union { 381 union {
382 __u64 bp_addr; 382 __u64 bp_addr;
383 __u64 kprobe_func; /* for perf_kprobe */
384 __u64 uprobe_path; /* for perf_uprobe */
383 __u64 config1; /* extension of config */ 385 __u64 config1; /* extension of config */
384 }; 386 };
385 union { 387 union {
386 __u64 bp_len; 388 __u64 bp_len;
389 __u64 kprobe_addr; /* when kprobe_func == NULL */
390 __u64 probe_offset; /* for perf_[k,u]probe */
387 __u64 config2; /* extension of config1 */ 391 __u64 config2; /* extension of config1 */
388 }; 392 };
389 __u64 branch_sample_type; /* enum perf_branch_sample_type */ 393 __u64 branch_sample_type; /* enum perf_branch_sample_type */
@@ -444,17 +448,18 @@ struct perf_event_query_bpf {
444/* 448/*
445 * Ioctls that can be done on a perf event fd: 449 * Ioctls that can be done on a perf event fd:
446 */ 450 */
447#define PERF_EVENT_IOC_ENABLE _IO ('$', 0) 451#define PERF_EVENT_IOC_ENABLE _IO ('$', 0)
448#define PERF_EVENT_IOC_DISABLE _IO ('$', 1) 452#define PERF_EVENT_IOC_DISABLE _IO ('$', 1)
449#define PERF_EVENT_IOC_REFRESH _IO ('$', 2) 453#define PERF_EVENT_IOC_REFRESH _IO ('$', 2)
450#define PERF_EVENT_IOC_RESET _IO ('$', 3) 454#define PERF_EVENT_IOC_RESET _IO ('$', 3)
451#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, __u64) 455#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, __u64)
452#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5) 456#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5)
453#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *) 457#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *)
454#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *) 458#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *)
455#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32) 459#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32)
456#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32) 460#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32)
457#define PERF_EVENT_IOC_QUERY_BPF _IOWR('$', 10, struct perf_event_query_bpf *) 461#define PERF_EVENT_IOC_QUERY_BPF _IOWR('$', 10, struct perf_event_query_bpf *)
462#define PERF_EVENT_IOC_MODIFY_ATTRIBUTES _IOW('$', 11, struct perf_event_attr *)
458 463
459enum perf_event_ioc_flags { 464enum perf_event_ioc_flags {
460 PERF_IOC_FLAG_GROUP = 1U << 0, 465 PERF_IOC_FLAG_GROUP = 1U << 0,
diff --git a/tools/kvm/kvm_stat/kvm_stat b/tools/kvm/kvm_stat/kvm_stat
index a5684d0968b4..5898c22ba310 100755
--- a/tools/kvm/kvm_stat/kvm_stat
+++ b/tools/kvm/kvm_stat/kvm_stat
@@ -33,7 +33,7 @@ import resource
33import struct 33import struct
34import re 34import re
35import subprocess 35import subprocess
36from collections import defaultdict 36from collections import defaultdict, namedtuple
37 37
38VMX_EXIT_REASONS = { 38VMX_EXIT_REASONS = {
39 'EXCEPTION_NMI': 0, 39 'EXCEPTION_NMI': 0,
@@ -228,6 +228,7 @@ IOCTL_NUMBERS = {
228} 228}
229 229
230ENCODING = locale.getpreferredencoding(False) 230ENCODING = locale.getpreferredencoding(False)
231TRACE_FILTER = re.compile(r'^[^\(]*$')
231 232
232 233
233class Arch(object): 234class Arch(object):
@@ -260,6 +261,11 @@ class Arch(object):
260 return ArchX86(SVM_EXIT_REASONS) 261 return ArchX86(SVM_EXIT_REASONS)
261 return 262 return
262 263
264 def tracepoint_is_child(self, field):
265 if (TRACE_FILTER.match(field)):
266 return None
267 return field.split('(', 1)[0]
268
263 269
264class ArchX86(Arch): 270class ArchX86(Arch):
265 def __init__(self, exit_reasons): 271 def __init__(self, exit_reasons):
@@ -267,6 +273,10 @@ class ArchX86(Arch):
267 self.ioctl_numbers = IOCTL_NUMBERS 273 self.ioctl_numbers = IOCTL_NUMBERS
268 self.exit_reasons = exit_reasons 274 self.exit_reasons = exit_reasons
269 275
276 def debugfs_is_child(self, field):
277 """ Returns name of parent if 'field' is a child, None otherwise """
278 return None
279
270 280
271class ArchPPC(Arch): 281class ArchPPC(Arch):
272 def __init__(self): 282 def __init__(self):
@@ -282,6 +292,10 @@ class ArchPPC(Arch):
282 self.ioctl_numbers['SET_FILTER'] = 0x80002406 | char_ptr_size << 16 292 self.ioctl_numbers['SET_FILTER'] = 0x80002406 | char_ptr_size << 16
283 self.exit_reasons = {} 293 self.exit_reasons = {}
284 294
295 def debugfs_is_child(self, field):
296 """ Returns name of parent if 'field' is a child, None otherwise """
297 return None
298
285 299
286class ArchA64(Arch): 300class ArchA64(Arch):
287 def __init__(self): 301 def __init__(self):
@@ -289,6 +303,10 @@ class ArchA64(Arch):
289 self.ioctl_numbers = IOCTL_NUMBERS 303 self.ioctl_numbers = IOCTL_NUMBERS
290 self.exit_reasons = AARCH64_EXIT_REASONS 304 self.exit_reasons = AARCH64_EXIT_REASONS
291 305
306 def debugfs_is_child(self, field):
307 """ Returns name of parent if 'field' is a child, None otherwise """
308 return None
309
292 310
293class ArchS390(Arch): 311class ArchS390(Arch):
294 def __init__(self): 312 def __init__(self):
@@ -296,6 +314,12 @@ class ArchS390(Arch):
296 self.ioctl_numbers = IOCTL_NUMBERS 314 self.ioctl_numbers = IOCTL_NUMBERS
297 self.exit_reasons = None 315 self.exit_reasons = None
298 316
317 def debugfs_is_child(self, field):
318 """ Returns name of parent if 'field' is a child, None otherwise """
319 if field.startswith('instruction_'):
320 return 'exit_instruction'
321
322
299ARCH = Arch.get_arch() 323ARCH = Arch.get_arch()
300 324
301 325
@@ -331,9 +355,6 @@ class perf_event_attr(ctypes.Structure):
331PERF_TYPE_TRACEPOINT = 2 355PERF_TYPE_TRACEPOINT = 2
332PERF_FORMAT_GROUP = 1 << 3 356PERF_FORMAT_GROUP = 1 << 3
333 357
334PATH_DEBUGFS_TRACING = '/sys/kernel/debug/tracing'
335PATH_DEBUGFS_KVM = '/sys/kernel/debug/kvm'
336
337 358
338class Group(object): 359class Group(object):
339 """Represents a perf event group.""" 360 """Represents a perf event group."""
@@ -376,8 +397,8 @@ class Event(object):
376 self.syscall = self.libc.syscall 397 self.syscall = self.libc.syscall
377 self.name = name 398 self.name = name
378 self.fd = None 399 self.fd = None
379 self.setup_event(group, trace_cpu, trace_pid, trace_point, 400 self._setup_event(group, trace_cpu, trace_pid, trace_point,
380 trace_filter, trace_set) 401 trace_filter, trace_set)
381 402
382 def __del__(self): 403 def __del__(self):
383 """Closes the event's file descriptor. 404 """Closes the event's file descriptor.
@@ -390,7 +411,7 @@ class Event(object):
390 if self.fd: 411 if self.fd:
391 os.close(self.fd) 412 os.close(self.fd)
392 413
393 def perf_event_open(self, attr, pid, cpu, group_fd, flags): 414 def _perf_event_open(self, attr, pid, cpu, group_fd, flags):
394 """Wrapper for the sys_perf_evt_open() syscall. 415 """Wrapper for the sys_perf_evt_open() syscall.
395 416
396 Used to set up performance events, returns a file descriptor or -1 417 Used to set up performance events, returns a file descriptor or -1
@@ -409,7 +430,7 @@ class Event(object):
409 ctypes.c_int(pid), ctypes.c_int(cpu), 430 ctypes.c_int(pid), ctypes.c_int(cpu),
410 ctypes.c_int(group_fd), ctypes.c_long(flags)) 431 ctypes.c_int(group_fd), ctypes.c_long(flags))
411 432
412 def setup_event_attribute(self, trace_set, trace_point): 433 def _setup_event_attribute(self, trace_set, trace_point):
413 """Returns an initialized ctype perf_event_attr struct.""" 434 """Returns an initialized ctype perf_event_attr struct."""
414 435
415 id_path = os.path.join(PATH_DEBUGFS_TRACING, 'events', trace_set, 436 id_path = os.path.join(PATH_DEBUGFS_TRACING, 'events', trace_set,
@@ -419,8 +440,8 @@ class Event(object):
419 event_attr.config = int(open(id_path).read()) 440 event_attr.config = int(open(id_path).read())
420 return event_attr 441 return event_attr
421 442
422 def setup_event(self, group, trace_cpu, trace_pid, trace_point, 443 def _setup_event(self, group, trace_cpu, trace_pid, trace_point,
423 trace_filter, trace_set): 444 trace_filter, trace_set):
424 """Sets up the perf event in Linux. 445 """Sets up the perf event in Linux.
425 446
426 Issues the syscall to register the event in the kernel and 447 Issues the syscall to register the event in the kernel and
@@ -428,7 +449,7 @@ class Event(object):
428 449
429 """ 450 """
430 451
431 event_attr = self.setup_event_attribute(trace_set, trace_point) 452 event_attr = self._setup_event_attribute(trace_set, trace_point)
432 453
433 # First event will be group leader. 454 # First event will be group leader.
434 group_leader = -1 455 group_leader = -1
@@ -437,8 +458,8 @@ class Event(object):
437 if group.events: 458 if group.events:
438 group_leader = group.events[0].fd 459 group_leader = group.events[0].fd
439 460
440 fd = self.perf_event_open(event_attr, trace_pid, 461 fd = self._perf_event_open(event_attr, trace_pid,
441 trace_cpu, group_leader, 0) 462 trace_cpu, group_leader, 0)
442 if fd == -1: 463 if fd == -1:
443 err = ctypes.get_errno() 464 err = ctypes.get_errno()
444 raise OSError(err, os.strerror(err), 465 raise OSError(err, os.strerror(err),
@@ -475,6 +496,10 @@ class Event(object):
475 496
476class Provider(object): 497class Provider(object):
477 """Encapsulates functionalities used by all providers.""" 498 """Encapsulates functionalities used by all providers."""
499 def __init__(self, pid):
500 self.child_events = False
501 self.pid = pid
502
478 @staticmethod 503 @staticmethod
479 def is_field_wanted(fields_filter, field): 504 def is_field_wanted(fields_filter, field):
480 """Indicate whether field is valid according to fields_filter.""" 505 """Indicate whether field is valid according to fields_filter."""
@@ -500,12 +525,12 @@ class TracepointProvider(Provider):
500 """ 525 """
501 def __init__(self, pid, fields_filter): 526 def __init__(self, pid, fields_filter):
502 self.group_leaders = [] 527 self.group_leaders = []
503 self.filters = self.get_filters() 528 self.filters = self._get_filters()
504 self.update_fields(fields_filter) 529 self.update_fields(fields_filter)
505 self.pid = pid 530 super(TracepointProvider, self).__init__(pid)
506 531
507 @staticmethod 532 @staticmethod
508 def get_filters(): 533 def _get_filters():
509 """Returns a dict of trace events, their filter ids and 534 """Returns a dict of trace events, their filter ids and
510 the values that can be filtered. 535 the values that can be filtered.
511 536
@@ -521,8 +546,8 @@ class TracepointProvider(Provider):
521 filters['kvm_exit'] = ('exit_reason', ARCH.exit_reasons) 546 filters['kvm_exit'] = ('exit_reason', ARCH.exit_reasons)
522 return filters 547 return filters
523 548
524 def get_available_fields(self): 549 def _get_available_fields(self):
525 """Returns a list of available event's of format 'event name(filter 550 """Returns a list of available events of format 'event name(filter
526 name)'. 551 name)'.
527 552
528 All available events have directories under 553 All available events have directories under
@@ -549,11 +574,12 @@ class TracepointProvider(Provider):
549 574
550 def update_fields(self, fields_filter): 575 def update_fields(self, fields_filter):
551 """Refresh fields, applying fields_filter""" 576 """Refresh fields, applying fields_filter"""
552 self.fields = [field for field in self.get_available_fields() 577 self.fields = [field for field in self._get_available_fields()
553 if self.is_field_wanted(fields_filter, field)] 578 if self.is_field_wanted(fields_filter, field) or
579 ARCH.tracepoint_is_child(field)]
554 580
555 @staticmethod 581 @staticmethod
556 def get_online_cpus(): 582 def _get_online_cpus():
557 """Returns a list of cpu id integers.""" 583 """Returns a list of cpu id integers."""
558 def parse_int_list(list_string): 584 def parse_int_list(list_string):
559 """Returns an int list from a string of comma separated integers and 585 """Returns an int list from a string of comma separated integers and
@@ -575,17 +601,17 @@ class TracepointProvider(Provider):
575 cpu_string = cpu_list.readline() 601 cpu_string = cpu_list.readline()
576 return parse_int_list(cpu_string) 602 return parse_int_list(cpu_string)
577 603
578 def setup_traces(self): 604 def _setup_traces(self):
579 """Creates all event and group objects needed to be able to retrieve 605 """Creates all event and group objects needed to be able to retrieve
580 data.""" 606 data."""
581 fields = self.get_available_fields() 607 fields = self._get_available_fields()
582 if self._pid > 0: 608 if self._pid > 0:
583 # Fetch list of all threads of the monitored pid, as qemu 609 # Fetch list of all threads of the monitored pid, as qemu
584 # starts a thread for each vcpu. 610 # starts a thread for each vcpu.
585 path = os.path.join('/proc', str(self._pid), 'task') 611 path = os.path.join('/proc', str(self._pid), 'task')
586 groupids = self.walkdir(path)[1] 612 groupids = self.walkdir(path)[1]
587 else: 613 else:
588 groupids = self.get_online_cpus() 614 groupids = self._get_online_cpus()
589 615
590 # The constant is needed as a buffer for python libs, std 616 # The constant is needed as a buffer for python libs, std
591 # streams and other files that the script opens. 617 # streams and other files that the script opens.
@@ -663,7 +689,7 @@ class TracepointProvider(Provider):
663 # The garbage collector will get rid of all Event/Group 689 # The garbage collector will get rid of all Event/Group
664 # objects and open files after removing the references. 690 # objects and open files after removing the references.
665 self.group_leaders = [] 691 self.group_leaders = []
666 self.setup_traces() 692 self._setup_traces()
667 self.fields = self._fields 693 self.fields = self._fields
668 694
669 def read(self, by_guest=0): 695 def read(self, by_guest=0):
@@ -671,8 +697,12 @@ class TracepointProvider(Provider):
671 ret = defaultdict(int) 697 ret = defaultdict(int)
672 for group in self.group_leaders: 698 for group in self.group_leaders:
673 for name, val in group.read().items(): 699 for name, val in group.read().items():
674 if name in self._fields: 700 if name not in self._fields:
675 ret[name] += val 701 continue
702 parent = ARCH.tracepoint_is_child(name)
703 if parent:
704 name += ' ' + parent
705 ret[name] += val
676 return ret 706 return ret
677 707
678 def reset(self): 708 def reset(self):
@@ -690,11 +720,11 @@ class DebugfsProvider(Provider):
690 self._baseline = {} 720 self._baseline = {}
691 self.do_read = True 721 self.do_read = True
692 self.paths = [] 722 self.paths = []
693 self.pid = pid 723 super(DebugfsProvider, self).__init__(pid)
694 if include_past: 724 if include_past:
695 self.restore() 725 self._restore()
696 726
697 def get_available_fields(self): 727 def _get_available_fields(self):
698 """"Returns a list of available fields. 728 """"Returns a list of available fields.
699 729
700 The fields are all available KVM debugfs files 730 The fields are all available KVM debugfs files
@@ -704,8 +734,9 @@ class DebugfsProvider(Provider):
704 734
705 def update_fields(self, fields_filter): 735 def update_fields(self, fields_filter):
706 """Refresh fields, applying fields_filter""" 736 """Refresh fields, applying fields_filter"""
707 self._fields = [field for field in self.get_available_fields() 737 self._fields = [field for field in self._get_available_fields()
708 if self.is_field_wanted(fields_filter, field)] 738 if self.is_field_wanted(fields_filter, field) or
739 ARCH.debugfs_is_child(field)]
709 740
710 @property 741 @property
711 def fields(self): 742 def fields(self):
@@ -758,7 +789,7 @@ class DebugfsProvider(Provider):
758 paths.append(dir) 789 paths.append(dir)
759 for path in paths: 790 for path in paths:
760 for field in self._fields: 791 for field in self._fields:
761 value = self.read_field(field, path) 792 value = self._read_field(field, path)
762 key = path + field 793 key = path + field
763 if reset == 1: 794 if reset == 1:
764 self._baseline[key] = value 795 self._baseline[key] = value
@@ -766,20 +797,21 @@ class DebugfsProvider(Provider):
766 self._baseline[key] = 0 797 self._baseline[key] = 0
767 if self._baseline.get(key, -1) == -1: 798 if self._baseline.get(key, -1) == -1:
768 self._baseline[key] = value 799 self._baseline[key] = value
769 increment = (results.get(field, 0) + value - 800 parent = ARCH.debugfs_is_child(field)
770 self._baseline.get(key, 0)) 801 if parent:
771 if by_guest: 802 field = field + ' ' + parent
772 pid = key.split('-')[0] 803 else:
773 if pid in results: 804 if by_guest:
774 results[pid] += increment 805 field = key.split('-')[0] # set 'field' to 'pid'
775 else: 806 increment = value - self._baseline.get(key, 0)
776 results[pid] = increment 807 if field in results:
808 results[field] += increment
777 else: 809 else:
778 results[field] = increment 810 results[field] = increment
779 811
780 return results 812 return results
781 813
782 def read_field(self, field, path): 814 def _read_field(self, field, path):
783 """Returns the value of a single field from a specific VM.""" 815 """Returns the value of a single field from a specific VM."""
784 try: 816 try:
785 return int(open(os.path.join(PATH_DEBUGFS_KVM, 817 return int(open(os.path.join(PATH_DEBUGFS_KVM,
@@ -794,12 +826,15 @@ class DebugfsProvider(Provider):
794 self._baseline = {} 826 self._baseline = {}
795 self.read(1) 827 self.read(1)
796 828
797 def restore(self): 829 def _restore(self):
798 """Reset field counters""" 830 """Reset field counters"""
799 self._baseline = {} 831 self._baseline = {}
800 self.read(2) 832 self.read(2)
801 833
802 834
835EventStat = namedtuple('EventStat', ['value', 'delta'])
836
837
803class Stats(object): 838class Stats(object):
804 """Manages the data providers and the data they provide. 839 """Manages the data providers and the data they provide.
805 840
@@ -808,13 +843,13 @@ class Stats(object):
808 843
809 """ 844 """
810 def __init__(self, options): 845 def __init__(self, options):
811 self.providers = self.get_providers(options) 846 self.providers = self._get_providers(options)
812 self._pid_filter = options.pid 847 self._pid_filter = options.pid
813 self._fields_filter = options.fields 848 self._fields_filter = options.fields
814 self.values = {} 849 self.values = {}
850 self._child_events = False
815 851
816 @staticmethod 852 def _get_providers(self, options):
817 def get_providers(options):
818 """Returns a list of data providers depending on the passed options.""" 853 """Returns a list of data providers depending on the passed options."""
819 providers = [] 854 providers = []
820 855
@@ -826,7 +861,7 @@ class Stats(object):
826 861
827 return providers 862 return providers
828 863
829 def update_provider_filters(self): 864 def _update_provider_filters(self):
830 """Propagates fields filters to providers.""" 865 """Propagates fields filters to providers."""
831 # As we reset the counters when updating the fields we can 866 # As we reset the counters when updating the fields we can
832 # also clear the cache of old values. 867 # also clear the cache of old values.
@@ -847,7 +882,7 @@ class Stats(object):
847 def fields_filter(self, fields_filter): 882 def fields_filter(self, fields_filter):
848 if fields_filter != self._fields_filter: 883 if fields_filter != self._fields_filter:
849 self._fields_filter = fields_filter 884 self._fields_filter = fields_filter
850 self.update_provider_filters() 885 self._update_provider_filters()
851 886
852 @property 887 @property
853 def pid_filter(self): 888 def pid_filter(self):
@@ -861,16 +896,33 @@ class Stats(object):
861 for provider in self.providers: 896 for provider in self.providers:
862 provider.pid = self._pid_filter 897 provider.pid = self._pid_filter
863 898
899 @property
900 def child_events(self):
901 return self._child_events
902
903 @child_events.setter
904 def child_events(self, val):
905 self._child_events = val
906 for provider in self.providers:
907 provider.child_events = val
908
864 def get(self, by_guest=0): 909 def get(self, by_guest=0):
865 """Returns a dict with field -> (value, delta to last value) of all 910 """Returns a dict with field -> (value, delta to last value) of all
866 provider data.""" 911 provider data.
912 Key formats:
913 * plain: 'key' is event name
914 * child-parent: 'key' is in format '<child> <parent>'
915 * pid: 'key' is the pid of the guest, and the record contains the
916 aggregated event data
917 These formats are generated by the providers, and handled in class TUI.
918 """
867 for provider in self.providers: 919 for provider in self.providers:
868 new = provider.read(by_guest=by_guest) 920 new = provider.read(by_guest=by_guest)
869 for key in new if by_guest else provider.fields: 921 for key in new:
870 oldval = self.values.get(key, (0, 0))[0] 922 oldval = self.values.get(key, EventStat(0, 0)).value
871 newval = new.get(key, 0) 923 newval = new.get(key, 0)
872 newdelta = newval - oldval 924 newdelta = newval - oldval
873 self.values[key] = (newval, newdelta) 925 self.values[key] = EventStat(newval, newdelta)
874 return self.values 926 return self.values
875 927
876 def toggle_display_guests(self, to_pid): 928 def toggle_display_guests(self, to_pid):
@@ -899,10 +951,10 @@ class Stats(object):
899 self.get(to_pid) 951 self.get(to_pid)
900 return 0 952 return 0
901 953
954
902DELAY_DEFAULT = 3.0 955DELAY_DEFAULT = 3.0
903MAX_GUEST_NAME_LEN = 48 956MAX_GUEST_NAME_LEN = 48
904MAX_REGEX_LEN = 44 957MAX_REGEX_LEN = 44
905DEFAULT_REGEX = r'^[^\(]*$'
906SORT_DEFAULT = 0 958SORT_DEFAULT = 0
907 959
908 960
@@ -969,7 +1021,7 @@ class Tui(object):
969 1021
970 return res 1022 return res
971 1023
972 def print_all_gnames(self, row): 1024 def _print_all_gnames(self, row):
973 """Print a list of all running guests along with their pids.""" 1025 """Print a list of all running guests along with their pids."""
974 self.screen.addstr(row, 2, '%8s %-60s' % 1026 self.screen.addstr(row, 2, '%8s %-60s' %
975 ('Pid', 'Guest Name (fuzzy list, might be ' 1027 ('Pid', 'Guest Name (fuzzy list, might be '
@@ -1032,19 +1084,13 @@ class Tui(object):
1032 1084
1033 return name 1085 return name
1034 1086
1035 def update_drilldown(self): 1087 def _update_pid(self, pid):
1036 """Sets or removes a filter that only allows fields without braces."""
1037 if not self.stats.fields_filter:
1038 self.stats.fields_filter = DEFAULT_REGEX
1039
1040 elif self.stats.fields_filter == DEFAULT_REGEX:
1041 self.stats.fields_filter = None
1042
1043 def update_pid(self, pid):
1044 """Propagates pid selection to stats object.""" 1088 """Propagates pid selection to stats object."""
1089 self.screen.addstr(4, 1, 'Updating pid filter...')
1090 self.screen.refresh()
1045 self.stats.pid_filter = pid 1091 self.stats.pid_filter = pid
1046 1092
1047 def refresh_header(self, pid=None): 1093 def _refresh_header(self, pid=None):
1048 """Refreshes the header.""" 1094 """Refreshes the header."""
1049 if pid is None: 1095 if pid is None:
1050 pid = self.stats.pid_filter 1096 pid = self.stats.pid_filter
@@ -1059,8 +1105,7 @@ class Tui(object):
1059 .format(pid, gname), curses.A_BOLD) 1105 .format(pid, gname), curses.A_BOLD)
1060 else: 1106 else:
1061 self.screen.addstr(0, 0, 'kvm statistics - summary', curses.A_BOLD) 1107 self.screen.addstr(0, 0, 'kvm statistics - summary', curses.A_BOLD)
1062 if self.stats.fields_filter and self.stats.fields_filter \ 1108 if self.stats.fields_filter:
1063 != DEFAULT_REGEX:
1064 regex = self.stats.fields_filter 1109 regex = self.stats.fields_filter
1065 if len(regex) > MAX_REGEX_LEN: 1110 if len(regex) > MAX_REGEX_LEN:
1066 regex = regex[:MAX_REGEX_LEN] + '...' 1111 regex = regex[:MAX_REGEX_LEN] + '...'
@@ -1075,56 +1120,99 @@ class Tui(object):
1075 self.screen.addstr(4, 1, 'Collecting data...') 1120 self.screen.addstr(4, 1, 'Collecting data...')
1076 self.screen.refresh() 1121 self.screen.refresh()
1077 1122
1078 def refresh_body(self, sleeptime): 1123 def _refresh_body(self, sleeptime):
1124 def is_child_field(field):
1125 return field.find('(') != -1
1126
1127 def insert_child(sorted_items, child, values, parent):
1128 num = len(sorted_items)
1129 for i in range(0, num):
1130 # only add child if parent is present
1131 if parent.startswith(sorted_items[i][0]):
1132 sorted_items.insert(i + 1, (' ' + child, values))
1133
1134 def get_sorted_events(self, stats):
1135 """ separate parent and child events """
1136 if self._sorting == SORT_DEFAULT:
1137 def sortkey((_k, v)):
1138 # sort by (delta value, overall value)
1139 return (v.delta, v.value)
1140 else:
1141 def sortkey((_k, v)):
1142 # sort by overall value
1143 return v.value
1144
1145 childs = []
1146 sorted_items = []
1147 # we can't rule out child events to appear prior to parents even
1148 # when sorted - separate out all children first, and add in later
1149 for key, values in sorted(stats.items(), key=sortkey,
1150 reverse=True):
1151 if values == (0, 0):
1152 continue
1153 if key.find(' ') != -1:
1154 if not self.stats.child_events:
1155 continue
1156 childs.insert(0, (key, values))
1157 else:
1158 sorted_items.append((key, values))
1159 if self.stats.child_events:
1160 for key, values in childs:
1161 (child, parent) = key.split(' ')
1162 insert_child(sorted_items, child, values, parent)
1163
1164 return sorted_items
1165
1079 row = 3 1166 row = 3
1080 self.screen.move(row, 0) 1167 self.screen.move(row, 0)
1081 self.screen.clrtobot() 1168 self.screen.clrtobot()
1082 stats = self.stats.get(self._display_guests) 1169 stats = self.stats.get(self._display_guests)
1083 1170 total = 0.
1084 def sortCurAvg(x): 1171 ctotal = 0.
1085 # sort by current events if available 1172 for key, values in stats.items():
1086 if stats[x][1]: 1173 if self._display_guests:
1087 return (-stats[x][1], -stats[x][0]) 1174 if self.get_gname_from_pid(key):
1175 total += values.value
1176 continue
1177 if not key.find(' ') != -1:
1178 total += values.value
1088 else: 1179 else:
1089 return (0, -stats[x][0]) 1180 ctotal += values.value
1181 if total == 0.:
1182 # we don't have any fields, or all non-child events are filtered
1183 total = ctotal
1090 1184
1091 def sortTotal(x): 1185 # print events
1092 # sort by totals
1093 return (0, -stats[x][0])
1094 total = 0.
1095 for key in stats.keys():
1096 if key.find('(') is -1:
1097 total += stats[key][0]
1098 if self._sorting == SORT_DEFAULT:
1099 sortkey = sortCurAvg
1100 else:
1101 sortkey = sortTotal
1102 tavg = 0 1186 tavg = 0
1103 for key in sorted(stats.keys(), key=sortkey): 1187 tcur = 0
1104 if row >= self.screen.getmaxyx()[0] - 1: 1188 for key, values in get_sorted_events(self, stats):
1105 break 1189 if row >= self.screen.getmaxyx()[0] - 1 or values == (0, 0):
1106 values = stats[key]
1107 if not values[0] and not values[1]:
1108 break 1190 break
1109 if values[0] is not None: 1191 if self._display_guests:
1110 cur = int(round(values[1] / sleeptime)) if values[1] else '' 1192 key = self.get_gname_from_pid(key)
1111 if self._display_guests: 1193 if not key:
1112 key = self.get_gname_from_pid(key) 1194 continue
1113 self.screen.addstr(row, 1, '%-40s %10d%7.1f %8s' % 1195 cur = int(round(values.delta / sleeptime)) if values.delta else ''
1114 (key, values[0], values[0] * 100 / total, 1196 if key[0] != ' ':
1115 cur)) 1197 if values.delta:
1116 if cur is not '' and key.find('(') is -1: 1198 tcur += values.delta
1117 tavg += cur 1199 ptotal = values.value
1200 ltotal = total
1201 else:
1202 ltotal = ptotal
1203 self.screen.addstr(row, 1, '%-40s %10d%7.1f %8s' % (key,
1204 values.value,
1205 values.value * 100 / float(ltotal), cur))
1118 row += 1 1206 row += 1
1119 if row == 3: 1207 if row == 3:
1120 self.screen.addstr(4, 1, 'No matching events reported yet') 1208 self.screen.addstr(4, 1, 'No matching events reported yet')
1121 else: 1209 if row > 4:
1210 tavg = int(round(tcur / sleeptime)) if tcur > 0 else ''
1122 self.screen.addstr(row, 1, '%-40s %10d %8s' % 1211 self.screen.addstr(row, 1, '%-40s %10d %8s' %
1123 ('Total', total, tavg if tavg else ''), 1212 ('Total', total, tavg), curses.A_BOLD)
1124 curses.A_BOLD)
1125 self.screen.refresh() 1213 self.screen.refresh()
1126 1214
1127 def show_msg(self, text): 1215 def _show_msg(self, text):
1128 """Display message centered text and exit on key press""" 1216 """Display message centered text and exit on key press"""
1129 hint = 'Press any key to continue' 1217 hint = 'Press any key to continue'
1130 curses.cbreak() 1218 curses.cbreak()
@@ -1139,16 +1227,16 @@ class Tui(object):
1139 curses.A_STANDOUT) 1227 curses.A_STANDOUT)
1140 self.screen.getkey() 1228 self.screen.getkey()
1141 1229
1142 def show_help_interactive(self): 1230 def _show_help_interactive(self):
1143 """Display help with list of interactive commands""" 1231 """Display help with list of interactive commands"""
1144 msg = (' b toggle events by guests (debugfs only, honors' 1232 msg = (' b toggle events by guests (debugfs only, honors'
1145 ' filters)', 1233 ' filters)',
1146 ' c clear filter', 1234 ' c clear filter',
1147 ' f filter by regular expression', 1235 ' f filter by regular expression',
1148 ' g filter by guest name', 1236 ' g filter by guest name/PID',
1149 ' h display interactive commands reference', 1237 ' h display interactive commands reference',
1150 ' o toggle sorting order (Total vs CurAvg/s)', 1238 ' o toggle sorting order (Total vs CurAvg/s)',
1151 ' p filter by PID', 1239 ' p filter by guest name/PID',
1152 ' q quit', 1240 ' q quit',
1153 ' r reset stats', 1241 ' r reset stats',
1154 ' s set update interval', 1242 ' s set update interval',
@@ -1165,14 +1253,15 @@ class Tui(object):
1165 self.screen.addstr(row, 0, line) 1253 self.screen.addstr(row, 0, line)
1166 row += 1 1254 row += 1
1167 self.screen.getkey() 1255 self.screen.getkey()
1168 self.refresh_header() 1256 self._refresh_header()
1169 1257
1170 def show_filter_selection(self): 1258 def _show_filter_selection(self):
1171 """Draws filter selection mask. 1259 """Draws filter selection mask.
1172 1260
1173 Asks for a valid regex and sets the fields filter accordingly. 1261 Asks for a valid regex and sets the fields filter accordingly.
1174 1262
1175 """ 1263 """
1264 msg = ''
1176 while True: 1265 while True:
1177 self.screen.erase() 1266 self.screen.erase()
1178 self.screen.addstr(0, 0, 1267 self.screen.addstr(0, 0,
@@ -1181,61 +1270,25 @@ class Tui(object):
1181 self.screen.addstr(2, 0, 1270 self.screen.addstr(2, 0,
1182 "Current regex: {0}" 1271 "Current regex: {0}"
1183 .format(self.stats.fields_filter)) 1272 .format(self.stats.fields_filter))
1273 self.screen.addstr(5, 0, msg)
1184 self.screen.addstr(3, 0, "New regex: ") 1274 self.screen.addstr(3, 0, "New regex: ")
1185 curses.echo() 1275 curses.echo()
1186 regex = self.screen.getstr().decode(ENCODING) 1276 regex = self.screen.getstr().decode(ENCODING)
1187 curses.noecho() 1277 curses.noecho()
1188 if len(regex) == 0: 1278 if len(regex) == 0:
1189 self.stats.fields_filter = DEFAULT_REGEX 1279 self.stats.fields_filter = ''
1190 self.refresh_header() 1280 self._refresh_header()
1191 return 1281 return
1192 try: 1282 try:
1193 re.compile(regex) 1283 re.compile(regex)
1194 self.stats.fields_filter = regex 1284 self.stats.fields_filter = regex
1195 self.refresh_header() 1285 self._refresh_header()
1196 return 1286 return
1197 except re.error: 1287 except re.error:
1288 msg = '"' + regex + '": Not a valid regular expression'
1198 continue 1289 continue
1199 1290
1200 def show_vm_selection_by_pid(self): 1291 def _show_set_update_interval(self):
1201 """Draws PID selection mask.
1202
1203 Asks for a pid until a valid pid or 0 has been entered.
1204
1205 """
1206 msg = ''
1207 while True:
1208 self.screen.erase()
1209 self.screen.addstr(0, 0,
1210 'Show statistics for specific pid.',
1211 curses.A_BOLD)
1212 self.screen.addstr(1, 0,
1213 'This might limit the shown data to the trace '
1214 'statistics.')
1215 self.screen.addstr(5, 0, msg)
1216 self.print_all_gnames(7)
1217
1218 curses.echo()
1219 self.screen.addstr(3, 0, "Pid [0 or pid]: ")
1220 pid = self.screen.getstr().decode(ENCODING)
1221 curses.noecho()
1222
1223 try:
1224 if len(pid) > 0:
1225 pid = int(pid)
1226 if pid != 0 and not os.path.isdir(os.path.join('/proc/',
1227 str(pid))):
1228 msg = '"' + str(pid) + '": Not a running process'
1229 continue
1230 else:
1231 pid = 0
1232 self.refresh_header(pid)
1233 self.update_pid(pid)
1234 break
1235 except ValueError:
1236 msg = '"' + str(pid) + '": Not a valid pid'
1237
1238 def show_set_update_interval(self):
1239 """Draws update interval selection mask.""" 1292 """Draws update interval selection mask."""
1240 msg = '' 1293 msg = ''
1241 while True: 1294 while True:
@@ -1265,60 +1318,67 @@ class Tui(object):
1265 1318
1266 except ValueError: 1319 except ValueError:
1267 msg = '"' + str(val) + '": Invalid value' 1320 msg = '"' + str(val) + '": Invalid value'
1268 self.refresh_header() 1321 self._refresh_header()
1269 1322
1270 def show_vm_selection_by_guest_name(self): 1323 def _show_vm_selection_by_guest(self):
1271 """Draws guest selection mask. 1324 """Draws guest selection mask.
1272 1325
1273 Asks for a guest name until a valid guest name or '' is entered. 1326 Asks for a guest name or pid until a valid guest name or '' is entered.
1274 1327
1275 """ 1328 """
1276 msg = '' 1329 msg = ''
1277 while True: 1330 while True:
1278 self.screen.erase() 1331 self.screen.erase()
1279 self.screen.addstr(0, 0, 1332 self.screen.addstr(0, 0,
1280 'Show statistics for specific guest.', 1333 'Show statistics for specific guest or pid.',
1281 curses.A_BOLD) 1334 curses.A_BOLD)
1282 self.screen.addstr(1, 0, 1335 self.screen.addstr(1, 0,
1283 'This might limit the shown data to the trace ' 1336 'This might limit the shown data to the trace '
1284 'statistics.') 1337 'statistics.')
1285 self.screen.addstr(5, 0, msg) 1338 self.screen.addstr(5, 0, msg)
1286 self.print_all_gnames(7) 1339 self._print_all_gnames(7)
1287 curses.echo() 1340 curses.echo()
1288 self.screen.addstr(3, 0, "Guest [ENTER or guest]: ") 1341 curses.curs_set(1)
1289 gname = self.screen.getstr().decode(ENCODING) 1342 self.screen.addstr(3, 0, "Guest or pid [ENTER exits]: ")
1343 guest = self.screen.getstr().decode(ENCODING)
1290 curses.noecho() 1344 curses.noecho()
1291 1345
1292 if not gname: 1346 pid = 0
1293 self.refresh_header(0) 1347 if not guest or guest == '0':
1294 self.update_pid(0)
1295 break 1348 break
1296 else: 1349 if guest.isdigit():
1297 pids = [] 1350 if not os.path.isdir(os.path.join('/proc/', guest)):
1298 try: 1351 msg = '"' + guest + '": Not a running process'
1299 pids = self.get_pid_from_gname(gname)
1300 except:
1301 msg = '"' + gname + '": Internal error while searching, ' \
1302 'use pid filter instead'
1303 continue
1304 if len(pids) == 0:
1305 msg = '"' + gname + '": Not an active guest'
1306 continue 1352 continue
1307 if len(pids) > 1: 1353 pid = int(guest)
1308 msg = '"' + gname + '": Multiple matches found, use pid ' \
1309 'filter instead'
1310 continue
1311 self.refresh_header(pids[0])
1312 self.update_pid(pids[0])
1313 break 1354 break
1355 pids = []
1356 try:
1357 pids = self.get_pid_from_gname(guest)
1358 except:
1359 msg = '"' + guest + '": Internal error while searching, ' \
1360 'use pid filter instead'
1361 continue
1362 if len(pids) == 0:
1363 msg = '"' + guest + '": Not an active guest'
1364 continue
1365 if len(pids) > 1:
1366 msg = '"' + guest + '": Multiple matches found, use pid ' \
1367 'filter instead'
1368 continue
1369 pid = pids[0]
1370 break
1371 curses.curs_set(0)
1372 self._refresh_header(pid)
1373 self._update_pid(pid)
1314 1374
1315 def show_stats(self): 1375 def show_stats(self):
1316 """Refreshes the screen and processes user input.""" 1376 """Refreshes the screen and processes user input."""
1317 sleeptime = self._delay_initial 1377 sleeptime = self._delay_initial
1318 self.refresh_header() 1378 self._refresh_header()
1319 start = 0.0 # result based on init value never appears on screen 1379 start = 0.0 # result based on init value never appears on screen
1320 while True: 1380 while True:
1321 self.refresh_body(time.time() - start) 1381 self._refresh_body(time.time() - start)
1322 curses.halfdelay(int(sleeptime * 10)) 1382 curses.halfdelay(int(sleeptime * 10))
1323 start = time.time() 1383 start = time.time()
1324 sleeptime = self._delay_regular 1384 sleeptime = self._delay_regular
@@ -1327,47 +1387,39 @@ class Tui(object):
1327 if char == 'b': 1387 if char == 'b':
1328 self._display_guests = not self._display_guests 1388 self._display_guests = not self._display_guests
1329 if self.stats.toggle_display_guests(self._display_guests): 1389 if self.stats.toggle_display_guests(self._display_guests):
1330 self.show_msg(['Command not available with tracepoints' 1390 self._show_msg(['Command not available with '
1331 ' enabled', 'Restart with debugfs only ' 1391 'tracepoints enabled', 'Restart with '
1332 '(see option \'-d\') and try again!']) 1392 'debugfs only (see option \'-d\') and '
1393 'try again!'])
1333 self._display_guests = not self._display_guests 1394 self._display_guests = not self._display_guests
1334 self.refresh_header() 1395 self._refresh_header()
1335 if char == 'c': 1396 if char == 'c':
1336 self.stats.fields_filter = DEFAULT_REGEX 1397 self.stats.fields_filter = ''
1337 self.refresh_header(0) 1398 self._refresh_header(0)
1338 self.update_pid(0) 1399 self._update_pid(0)
1339 if char == 'f': 1400 if char == 'f':
1340 curses.curs_set(1) 1401 curses.curs_set(1)
1341 self.show_filter_selection() 1402 self._show_filter_selection()
1342 curses.curs_set(0) 1403 curses.curs_set(0)
1343 sleeptime = self._delay_initial 1404 sleeptime = self._delay_initial
1344 if char == 'g': 1405 if char == 'g' or char == 'p':
1345 curses.curs_set(1) 1406 self._show_vm_selection_by_guest()
1346 self.show_vm_selection_by_guest_name()
1347 curses.curs_set(0)
1348 sleeptime = self._delay_initial 1407 sleeptime = self._delay_initial
1349 if char == 'h': 1408 if char == 'h':
1350 self.show_help_interactive() 1409 self._show_help_interactive()
1351 if char == 'o': 1410 if char == 'o':
1352 self._sorting = not self._sorting 1411 self._sorting = not self._sorting
1353 if char == 'p':
1354 curses.curs_set(1)
1355 self.show_vm_selection_by_pid()
1356 curses.curs_set(0)
1357 sleeptime = self._delay_initial
1358 if char == 'q': 1412 if char == 'q':
1359 break 1413 break
1360 if char == 'r': 1414 if char == 'r':
1361 self.stats.reset() 1415 self.stats.reset()
1362 if char == 's': 1416 if char == 's':
1363 curses.curs_set(1) 1417 curses.curs_set(1)
1364 self.show_set_update_interval() 1418 self._show_set_update_interval()
1365 curses.curs_set(0) 1419 curses.curs_set(0)
1366 sleeptime = self._delay_initial 1420 sleeptime = self._delay_initial
1367 if char == 'x': 1421 if char == 'x':
1368 self.update_drilldown() 1422 self.stats.child_events = not self.stats.child_events
1369 # prevents display of current values on next refresh
1370 self.stats.get(self._display_guests)
1371 except KeyboardInterrupt: 1423 except KeyboardInterrupt:
1372 break 1424 break
1373 except curses.error: 1425 except curses.error:
@@ -1380,9 +1432,9 @@ def batch(stats):
1380 s = stats.get() 1432 s = stats.get()
1381 time.sleep(1) 1433 time.sleep(1)
1382 s = stats.get() 1434 s = stats.get()
1383 for key in sorted(s.keys()): 1435 for key, values in sorted(s.items()):
1384 values = s[key] 1436 print('%-42s%10d%10d' % (key.split(' ')[0], values.value,
1385 print('%-42s%10d%10d' % (key, values[0], values[1])) 1437 values.delta))
1386 except KeyboardInterrupt: 1438 except KeyboardInterrupt:
1387 pass 1439 pass
1388 1440
@@ -1392,14 +1444,14 @@ def log(stats):
1392 keys = sorted(stats.get().keys()) 1444 keys = sorted(stats.get().keys())
1393 1445
1394 def banner(): 1446 def banner():
1395 for k in keys: 1447 for key in keys:
1396 print(k, end=' ') 1448 print(key.split(' ')[0], end=' ')
1397 print() 1449 print()
1398 1450
1399 def statline(): 1451 def statline():
1400 s = stats.get() 1452 s = stats.get()
1401 for k in keys: 1453 for key in keys:
1402 print(' %9d' % s[k][1], end=' ') 1454 print(' %9d' % s[key].delta, end=' ')
1403 print() 1455 print()
1404 line = 0 1456 line = 0
1405 banner_repeat = 20 1457 banner_repeat = 20
@@ -1504,7 +1556,7 @@ Press any other key to refresh statistics immediately.
1504 ) 1556 )
1505 optparser.add_option('-f', '--fields', 1557 optparser.add_option('-f', '--fields',
1506 action='store', 1558 action='store',
1507 default=DEFAULT_REGEX, 1559 default='',
1508 dest='fields', 1560 dest='fields',
1509 help='''fields to display (regex) 1561 help='''fields to display (regex)
1510 "-f help" for a list of available events''', 1562 "-f help" for a list of available events''',
@@ -1539,17 +1591,6 @@ Press any other key to refresh statistics immediately.
1539 1591
1540def check_access(options): 1592def check_access(options):
1541 """Exits if the current user can't access all needed directories.""" 1593 """Exits if the current user can't access all needed directories."""
1542 if not os.path.exists('/sys/kernel/debug'):
1543 sys.stderr.write('Please enable CONFIG_DEBUG_FS in your kernel.')
1544 sys.exit(1)
1545
1546 if not os.path.exists(PATH_DEBUGFS_KVM):
1547 sys.stderr.write("Please make sure, that debugfs is mounted and "
1548 "readable by the current user:\n"
1549 "('mount -t debugfs debugfs /sys/kernel/debug')\n"
1550 "Also ensure, that the kvm modules are loaded.\n")
1551 sys.exit(1)
1552
1553 if not os.path.exists(PATH_DEBUGFS_TRACING) and (options.tracepoints or 1594 if not os.path.exists(PATH_DEBUGFS_TRACING) and (options.tracepoints or
1554 not options.debugfs): 1595 not options.debugfs):
1555 sys.stderr.write("Please enable CONFIG_TRACING in your kernel " 1596 sys.stderr.write("Please enable CONFIG_TRACING in your kernel "
@@ -1567,7 +1608,33 @@ def check_access(options):
1567 return options 1608 return options
1568 1609
1569 1610
1611def assign_globals():
1612 global PATH_DEBUGFS_KVM
1613 global PATH_DEBUGFS_TRACING
1614
1615 debugfs = ''
1616 for line in file('/proc/mounts'):
1617 if line.split(' ')[0] == 'debugfs':
1618 debugfs = line.split(' ')[1]
1619 break
1620 if debugfs == '':
1621 sys.stderr.write("Please make sure that CONFIG_DEBUG_FS is enabled in "
1622 "your kernel, mounted and\nreadable by the current "
1623 "user:\n"
1624 "('mount -t debugfs debugfs /sys/kernel/debug')\n")
1625 sys.exit(1)
1626
1627 PATH_DEBUGFS_KVM = os.path.join(debugfs, 'kvm')
1628 PATH_DEBUGFS_TRACING = os.path.join(debugfs, 'tracing')
1629
1630 if not os.path.exists(PATH_DEBUGFS_KVM):
1631 sys.stderr.write("Please make sure that CONFIG_KVM is enabled in "
1632 "your kernel and that the modules are loaded.\n")
1633 sys.exit(1)
1634
1635
1570def main(): 1636def main():
1637 assign_globals()
1571 options = get_options() 1638 options = get_options()
1572 options = check_access(options) 1639 options = check_access(options)
1573 1640
diff --git a/tools/kvm/kvm_stat/kvm_stat.txt b/tools/kvm/kvm_stat/kvm_stat.txt
index b5b3810c9e94..0811d860fe75 100644
--- a/tools/kvm/kvm_stat/kvm_stat.txt
+++ b/tools/kvm/kvm_stat/kvm_stat.txt
@@ -35,13 +35,13 @@ INTERACTIVE COMMANDS
35 35
36*f*:: filter by regular expression 36*f*:: filter by regular expression
37 37
38*g*:: filter by guest name 38*g*:: filter by guest name/PID
39 39
40*h*:: display interactive commands reference 40*h*:: display interactive commands reference
41 41
42*o*:: toggle sorting order (Total vs CurAvg/s) 42*o*:: toggle sorting order (Total vs CurAvg/s)
43 43
44*p*:: filter by PID 44*p*:: filter by guest name/PID
45 45
46*q*:: quit 46*q*:: quit
47 47
diff --git a/tools/laptop/freefall/Makefile b/tools/laptop/freefall/Makefile
index 5f758c489a20..b572d94255f6 100644
--- a/tools/laptop/freefall/Makefile
+++ b/tools/laptop/freefall/Makefile
@@ -2,7 +2,6 @@
2PREFIX ?= /usr 2PREFIX ?= /usr
3SBINDIR ?= sbin 3SBINDIR ?= sbin
4INSTALL ?= install 4INSTALL ?= install
5CC = $(CROSS_COMPILE)gcc
6 5
7TARGET = freefall 6TARGET = freefall
8 7
diff --git a/tools/leds/Makefile b/tools/leds/Makefile
index c379af003807..7b6bed13daaa 100644
--- a/tools/leds/Makefile
+++ b/tools/leds/Makefile
@@ -1,7 +1,6 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2# Makefile for LEDs tools 2# Makefile for LEDs tools
3 3
4CC = $(CROSS_COMPILE)gcc
5CFLAGS = -Wall -Wextra -g -I../../include/uapi 4CFLAGS = -Wall -Wextra -g -I../../include/uapi
6 5
7all: uledmon led_hw_brightness_mon 6all: uledmon led_hw_brightness_mon
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c
index b24afc0e6e81..6a12bbf39f7b 100644
--- a/tools/lib/api/fs/fs.c
+++ b/tools/lib/api/fs/fs.c
@@ -315,12 +315,8 @@ int filename__read_int(const char *filename, int *value)
315 return err; 315 return err;
316} 316}
317 317
318/* 318static int filename__read_ull_base(const char *filename,
319 * Parses @value out of @filename with strtoull. 319 unsigned long long *value, int base)
320 * By using 0 for base, the strtoull detects the
321 * base automatically (see man strtoull).
322 */
323int filename__read_ull(const char *filename, unsigned long long *value)
324{ 320{
325 char line[64]; 321 char line[64];
326 int fd = open(filename, O_RDONLY), err = -1; 322 int fd = open(filename, O_RDONLY), err = -1;
@@ -329,7 +325,7 @@ int filename__read_ull(const char *filename, unsigned long long *value)
329 return -1; 325 return -1;
330 326
331 if (read(fd, line, sizeof(line)) > 0) { 327 if (read(fd, line, sizeof(line)) > 0) {
332 *value = strtoull(line, NULL, 0); 328 *value = strtoull(line, NULL, base);
333 if (*value != ULLONG_MAX) 329 if (*value != ULLONG_MAX)
334 err = 0; 330 err = 0;
335 } 331 }
@@ -338,6 +334,25 @@ int filename__read_ull(const char *filename, unsigned long long *value)
338 return err; 334 return err;
339} 335}
340 336
337/*
338 * Parses @value out of @filename with strtoull.
339 * By using 16 for base to treat the number as hex.
340 */
341int filename__read_xll(const char *filename, unsigned long long *value)
342{
343 return filename__read_ull_base(filename, value, 16);
344}
345
346/*
347 * Parses @value out of @filename with strtoull.
348 * By using 0 for base, the strtoull detects the
349 * base automatically (see man strtoull).
350 */
351int filename__read_ull(const char *filename, unsigned long long *value)
352{
353 return filename__read_ull_base(filename, value, 0);
354}
355
341#define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */ 356#define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */
342 357
343int filename__read_str(const char *filename, char **buf, size_t *sizep) 358int filename__read_str(const char *filename, char **buf, size_t *sizep)
@@ -417,7 +432,8 @@ int procfs__read_str(const char *entry, char **buf, size_t *sizep)
417 return filename__read_str(path, buf, sizep); 432 return filename__read_str(path, buf, sizep);
418} 433}
419 434
420int sysfs__read_ull(const char *entry, unsigned long long *value) 435static int sysfs__read_ull_base(const char *entry,
436 unsigned long long *value, int base)
421{ 437{
422 char path[PATH_MAX]; 438 char path[PATH_MAX];
423 const char *sysfs = sysfs__mountpoint(); 439 const char *sysfs = sysfs__mountpoint();
@@ -427,7 +443,17 @@ int sysfs__read_ull(const char *entry, unsigned long long *value)
427 443
428 snprintf(path, sizeof(path), "%s/%s", sysfs, entry); 444 snprintf(path, sizeof(path), "%s/%s", sysfs, entry);
429 445
430 return filename__read_ull(path, value); 446 return filename__read_ull_base(path, value, base);
447}
448
449int sysfs__read_xll(const char *entry, unsigned long long *value)
450{
451 return sysfs__read_ull_base(entry, value, 16);
452}
453
454int sysfs__read_ull(const char *entry, unsigned long long *value)
455{
456 return sysfs__read_ull_base(entry, value, 0);
431} 457}
432 458
433int sysfs__read_int(const char *entry, int *value) 459int sysfs__read_int(const char *entry, int *value)
diff --git a/tools/lib/api/fs/fs.h b/tools/lib/api/fs/fs.h
index dda49deefb52..92d03b8396b1 100644
--- a/tools/lib/api/fs/fs.h
+++ b/tools/lib/api/fs/fs.h
@@ -30,6 +30,7 @@ FS(bpf_fs)
30 30
31int filename__read_int(const char *filename, int *value); 31int filename__read_int(const char *filename, int *value);
32int filename__read_ull(const char *filename, unsigned long long *value); 32int filename__read_ull(const char *filename, unsigned long long *value);
33int filename__read_xll(const char *filename, unsigned long long *value);
33int filename__read_str(const char *filename, char **buf, size_t *sizep); 34int filename__read_str(const char *filename, char **buf, size_t *sizep);
34 35
35int filename__write_int(const char *filename, int value); 36int filename__write_int(const char *filename, int value);
@@ -39,6 +40,7 @@ int procfs__read_str(const char *entry, char **buf, size_t *sizep);
39int sysctl__read_int(const char *sysctl, int *value); 40int sysctl__read_int(const char *sysctl, int *value);
40int sysfs__read_int(const char *entry, int *value); 41int sysfs__read_int(const char *entry, int *value);
41int sysfs__read_ull(const char *entry, unsigned long long *value); 42int sysfs__read_ull(const char *entry, unsigned long long *value);
43int sysfs__read_xll(const char *entry, unsigned long long *value);
42int sysfs__read_str(const char *entry, char **buf, size_t *sizep); 44int sysfs__read_str(const char *entry, char **buf, size_t *sizep);
43int sysfs__read_bool(const char *entry, bool *value); 45int sysfs__read_bool(const char *entry, bool *value);
44 46
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 97073d649c1a..5bbbf285af74 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1060,11 +1060,12 @@ bpf_program__reloc_text(struct bpf_program *prog, struct bpf_object *obj,
1060 prog->insns = new_insn; 1060 prog->insns = new_insn;
1061 prog->main_prog_cnt = prog->insns_cnt; 1061 prog->main_prog_cnt = prog->insns_cnt;
1062 prog->insns_cnt = new_cnt; 1062 prog->insns_cnt = new_cnt;
1063 pr_debug("added %zd insn from %s to prog %s\n",
1064 text->insns_cnt, text->section_name,
1065 prog->section_name);
1063 } 1066 }
1064 insn = &prog->insns[relo->insn_idx]; 1067 insn = &prog->insns[relo->insn_idx];
1065 insn->imm += prog->main_prog_cnt - relo->insn_idx; 1068 insn->imm += prog->main_prog_cnt - relo->insn_idx;
1066 pr_debug("added %zd insn from %s to prog %s\n",
1067 text->insns_cnt, text->section_name, prog->section_name);
1068 return 0; 1069 return 0;
1069} 1070}
1070 1071
diff --git a/tools/lib/str_error_r.c b/tools/lib/str_error_r.c
index d6d65537b0d9..6aad8308a0ac 100644
--- a/tools/lib/str_error_r.c
+++ b/tools/lib/str_error_r.c
@@ -22,6 +22,6 @@ char *str_error_r(int errnum, char *buf, size_t buflen)
22{ 22{
23 int err = strerror_r(errnum, buf, buflen); 23 int err = strerror_r(errnum, buf, buflen);
24 if (err) 24 if (err)
25 snprintf(buf, buflen, "INTERNAL ERROR: strerror_r(%d, %p, %zd)=%d", errnum, buf, buflen, err); 25 snprintf(buf, buflen, "INTERNAL ERROR: strerror_r(%d, [buf], %zd)=%d", errnum, buflen, err);
26 return buf; 26 return buf;
27} 27}
diff --git a/tools/lib/symbol/kallsyms.c b/tools/lib/symbol/kallsyms.c
index 914cb8e3d40b..689b6a130dd7 100644
--- a/tools/lib/symbol/kallsyms.c
+++ b/tools/lib/symbol/kallsyms.c
@@ -38,6 +38,10 @@ int kallsyms__parse(const char *filename, void *arg,
38 38
39 len = hex2u64(line, &start); 39 len = hex2u64(line, &start);
40 40
41 /* Skip the line if we failed to parse the address. */
42 if (!len)
43 continue;
44
41 len++; 45 len++;
42 if (len + 2 >= line_len) 46 if (len + 2 >= line_len)
43 continue; 47 continue;
diff --git a/tools/memory-model/Documentation/cheatsheet.txt b/tools/memory-model/Documentation/cheatsheet.txt
new file mode 100644
index 000000000000..956b1ae4aafb
--- /dev/null
+++ b/tools/memory-model/Documentation/cheatsheet.txt
@@ -0,0 +1,29 @@
1 Prior Operation Subsequent Operation
2 --------------- ---------------------------
3 C Self R W RWM Self R W DR DW RMW SV
4 -- ---- - - --- ---- - - -- -- --- --
5
6Store, e.g., WRITE_ONCE() Y Y
7Load, e.g., READ_ONCE() Y Y Y Y
8Unsuccessful RMW operation Y Y Y Y
9rcu_dereference() Y Y Y Y
10Successful *_acquire() R Y Y Y Y Y Y
11Successful *_release() C Y Y Y W Y
12smp_rmb() Y R Y Y R
13smp_wmb() Y W Y Y W
14smp_mb() & synchronize_rcu() CP Y Y Y Y Y Y Y Y
15Successful full non-void RMW CP Y Y Y Y Y Y Y Y Y Y Y
16smp_mb__before_atomic() CP Y Y Y a a a a Y
17smp_mb__after_atomic() CP a a Y Y Y Y Y
18
19
20Key: C: Ordering is cumulative
21 P: Ordering propagates
22 R: Read, for example, READ_ONCE(), or read portion of RMW
23 W: Write, for example, WRITE_ONCE(), or write portion of RMW
24 Y: Provides ordering
25 a: Provides ordering given intervening RMW atomic operation
26 DR: Dependent read (address dependency)
27 DW: Dependent write (address, data, or control dependency)
28 RMW: Atomic read-modify-write operation
29 SV Same-variable access
diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt
new file mode 100644
index 000000000000..a727c82bd434
--- /dev/null
+++ b/tools/memory-model/Documentation/explanation.txt
@@ -0,0 +1,1845 @@
1Explanation of the Linux-Kernel Memory Consistency Model
2~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
4:Author: Alan Stern <stern@rowland.harvard.edu>
5:Created: October 2017
6
7.. Contents
8
9 1. INTRODUCTION
10 2. BACKGROUND
11 3. A SIMPLE EXAMPLE
12 4. A SELECTION OF MEMORY MODELS
13 5. ORDERING AND CYCLES
14 6. EVENTS
15 7. THE PROGRAM ORDER RELATION: po AND po-loc
16 8. A WARNING
17 9. DEPENDENCY RELATIONS: data, addr, and ctrl
18 10. THE READS-FROM RELATION: rf, rfi, and rfe
19 11. CACHE COHERENCE AND THE COHERENCE ORDER RELATION: co, coi, and coe
20 12. THE FROM-READS RELATION: fr, fri, and fre
21 13. AN OPERATIONAL MODEL
22 14. PROPAGATION ORDER RELATION: cumul-fence
23 15. DERIVATION OF THE LKMM FROM THE OPERATIONAL MODEL
24 16. SEQUENTIAL CONSISTENCY PER VARIABLE
25 17. ATOMIC UPDATES: rmw
26 18. THE PRESERVED PROGRAM ORDER RELATION: ppo
27 19. AND THEN THERE WAS ALPHA
28 20. THE HAPPENS-BEFORE RELATION: hb
29 21. THE PROPAGATES-BEFORE RELATION: pb
30 22. RCU RELATIONS: link, gp-link, rscs-link, and rcu-path
31 23. ODDS AND ENDS
32
33
34
35INTRODUCTION
36------------
37
38The Linux-kernel memory consistency model (LKMM) is rather complex and
39obscure. This is particularly evident if you read through the
40linux-kernel.bell and linux-kernel.cat files that make up the formal
41version of the model; they are extremely terse and their meanings are
42far from clear.
43
44This document describes the ideas underlying the LKMM. It is meant
45for people who want to understand how the model was designed. It does
46not go into the details of the code in the .bell and .cat files;
47rather, it explains in English what the code expresses symbolically.
48
49Sections 2 (BACKGROUND) through 5 (ORDERING AND CYCLES) are aimed
50toward beginners; they explain what memory consistency models are and
51the basic notions shared by all such models. People already familiar
52with these concepts can skim or skip over them. Sections 6 (EVENTS)
53through 12 (THE FROM_READS RELATION) describe the fundamental
54relations used in many models. Starting in Section 13 (AN OPERATIONAL
55MODEL), the workings of the LKMM itself are covered.
56
57Warning: The code examples in this document are not written in the
58proper format for litmus tests. They don't include a header line, the
59initializations are not enclosed in braces, the global variables are
60not passed by pointers, and they don't have an "exists" clause at the
61end. Converting them to the right format is left as an exercise for
62the reader.
63
64
65BACKGROUND
66----------
67
68A memory consistency model (or just memory model, for short) is
69something which predicts, given a piece of computer code running on a
70particular kind of system, what values may be obtained by the code's
71load instructions. The LKMM makes these predictions for code running
72as part of the Linux kernel.
73
74In practice, people tend to use memory models the other way around.
75That is, given a piece of code and a collection of values specified
76for the loads, the model will predict whether it is possible for the
77code to run in such a way that the loads will indeed obtain the
78specified values. Of course, this is just another way of expressing
79the same idea.
80
81For code running on a uniprocessor system, the predictions are easy:
82Each load instruction must obtain the value written by the most recent
83store instruction accessing the same location (we ignore complicating
84factors such as DMA and mixed-size accesses.) But on multiprocessor
85systems, with multiple CPUs making concurrent accesses to shared
86memory locations, things aren't so simple.
87
88Different architectures have differing memory models, and the Linux
89kernel supports a variety of architectures. The LKMM has to be fairly
90permissive, in the sense that any behavior allowed by one of these
91architectures also has to be allowed by the LKMM.
92
93
94A SIMPLE EXAMPLE
95----------------
96
97Here is a simple example to illustrate the basic concepts. Consider
98some code running as part of a device driver for an input device. The
99driver might contain an interrupt handler which collects data from the
100device, stores it in a buffer, and sets a flag to indicate the buffer
101is full. Running concurrently on a different CPU might be a part of
102the driver code being executed by a process in the midst of a read(2)
103system call. This code tests the flag to see whether the buffer is
104ready, and if it is, copies the data back to userspace. The buffer
105and the flag are memory locations shared between the two CPUs.
106
107We can abstract out the important pieces of the driver code as follows
108(the reason for using WRITE_ONCE() and READ_ONCE() instead of simple
109assignment statements is discussed later):
110
111 int buf = 0, flag = 0;
112
113 P0()
114 {
115 WRITE_ONCE(buf, 1);
116 WRITE_ONCE(flag, 1);
117 }
118
119 P1()
120 {
121 int r1;
122 int r2 = 0;
123
124 r1 = READ_ONCE(flag);
125 if (r1)
126 r2 = READ_ONCE(buf);
127 }
128
129Here the P0() function represents the interrupt handler running on one
130CPU and P1() represents the read() routine running on another. The
131value 1 stored in buf represents input data collected from the device.
132Thus, P0 stores the data in buf and then sets flag. Meanwhile, P1
133reads flag into the private variable r1, and if it is set, reads the
134data from buf into a second private variable r2 for copying to
135userspace. (Presumably if flag is not set then the driver will wait a
136while and try again.)
137
138This pattern of memory accesses, where one CPU stores values to two
139shared memory locations and another CPU loads from those locations in
140the opposite order, is widely known as the "Message Passing" or MP
141pattern. It is typical of memory access patterns in the kernel.
142
143Please note that this example code is a simplified abstraction. Real
144buffers are usually larger than a single integer, real device drivers
145usually use sleep and wakeup mechanisms rather than polling for I/O
146completion, and real code generally doesn't bother to copy values into
147private variables before using them. All that is beside the point;
148the idea here is simply to illustrate the overall pattern of memory
149accesses by the CPUs.
150
151A memory model will predict what values P1 might obtain for its loads
152from flag and buf, or equivalently, what values r1 and r2 might end up
153with after the code has finished running.
154
155Some predictions are trivial. For instance, no sane memory model would
156predict that r1 = 42 or r2 = -7, because neither of those values ever
157gets stored in flag or buf.
158
159Some nontrivial predictions are nonetheless quite simple. For
160instance, P1 might run entirely before P0 begins, in which case r1 and
161r2 will both be 0 at the end. Or P0 might run entirely before P1
162begins, in which case r1 and r2 will both be 1.
163
164The interesting predictions concern what might happen when the two
165routines run concurrently. One possibility is that P1 runs after P0's
166store to buf but before the store to flag. In this case, r1 and r2
167will again both be 0. (If P1 had been designed to read buf
168unconditionally then we would instead have r1 = 0 and r2 = 1.)
169
170However, the most interesting possibility is where r1 = 1 and r2 = 0.
171If this were to occur it would mean the driver contains a bug, because
172incorrect data would get sent to the user: 0 instead of 1. As it
173happens, the LKMM does predict this outcome can occur, and the example
174driver code shown above is indeed buggy.
175
176
177A SELECTION OF MEMORY MODELS
178----------------------------
179
180The first widely cited memory model, and the simplest to understand,
181is Sequential Consistency. According to this model, systems behave as
182if each CPU executed its instructions in order but with unspecified
183timing. In other words, the instructions from the various CPUs get
184interleaved in a nondeterministic way, always according to some single
185global order that agrees with the order of the instructions in the
186program source for each CPU. The model says that the value obtained
187by each load is simply the value written by the most recently executed
188store to the same memory location, from any CPU.
189
190For the MP example code shown above, Sequential Consistency predicts
191that the undesired result r1 = 1, r2 = 0 cannot occur. The reasoning
192goes like this:
193
194 Since r1 = 1, P0 must store 1 to flag before P1 loads 1 from
195 it, as loads can obtain values only from earlier stores.
196
197 P1 loads from flag before loading from buf, since CPUs execute
198 their instructions in order.
199
200 P1 must load 0 from buf before P0 stores 1 to it; otherwise r2
201 would be 1 since a load obtains its value from the most recent
202 store to the same address.
203
204 P0 stores 1 to buf before storing 1 to flag, since it executes
205 its instructions in order.
206
207 Since an instruction (in this case, P1's store to flag) cannot
208 execute before itself, the specified outcome is impossible.
209
210However, real computer hardware almost never follows the Sequential
211Consistency memory model; doing so would rule out too many valuable
212performance optimizations. On ARM and PowerPC architectures, for
213instance, the MP example code really does sometimes yield r1 = 1 and
214r2 = 0.
215
216x86 and SPARC follow yet a different memory model: TSO (Total Store
217Ordering). This model predicts that the undesired outcome for the MP
218pattern cannot occur, but in other respects it differs from Sequential
219Consistency. One example is the Store Buffer (SB) pattern, in which
220each CPU stores to its own shared location and then loads from the
221other CPU's location:
222
223 int x = 0, y = 0;
224
225 P0()
226 {
227 int r0;
228
229 WRITE_ONCE(x, 1);
230 r0 = READ_ONCE(y);
231 }
232
233 P1()
234 {
235 int r1;
236
237 WRITE_ONCE(y, 1);
238 r1 = READ_ONCE(x);
239 }
240
241Sequential Consistency predicts that the outcome r0 = 0, r1 = 0 is
242impossible. (Exercise: Figure out the reasoning.) But TSO allows
243this outcome to occur, and in fact it does sometimes occur on x86 and
244SPARC systems.
245
246The LKMM was inspired by the memory models followed by PowerPC, ARM,
247x86, Alpha, and other architectures. However, it is different in
248detail from each of them.
249
250
251ORDERING AND CYCLES
252-------------------
253
254Memory models are all about ordering. Often this is temporal ordering
255(i.e., the order in which certain events occur) but it doesn't have to
256be; consider for example the order of instructions in a program's
257source code. We saw above that Sequential Consistency makes an
258important assumption that CPUs execute instructions in the same order
259as those instructions occur in the code, and there are many other
260instances of ordering playing central roles in memory models.
261
262The counterpart to ordering is a cycle. Ordering rules out cycles:
263It's not possible to have X ordered before Y, Y ordered before Z, and
264Z ordered before X, because this would mean that X is ordered before
265itself. The analysis of the MP example under Sequential Consistency
266involved just such an impossible cycle:
267
268 W: P0 stores 1 to flag executes before
269 X: P1 loads 1 from flag executes before
270 Y: P1 loads 0 from buf executes before
271 Z: P0 stores 1 to buf executes before
272 W: P0 stores 1 to flag.
273
274In short, if a memory model requires certain accesses to be ordered,
275and a certain outcome for the loads in a piece of code can happen only
276if those accesses would form a cycle, then the memory model predicts
277that outcome cannot occur.
278
279The LKMM is defined largely in terms of cycles, as we will see.
280
281
282EVENTS
283------
284
285The LKMM does not work directly with the C statements that make up
286kernel source code. Instead it considers the effects of those
287statements in a more abstract form, namely, events. The model
288includes three types of events:
289
290 Read events correspond to loads from shared memory, such as
291 calls to READ_ONCE(), smp_load_acquire(), or
292 rcu_dereference().
293
294 Write events correspond to stores to shared memory, such as
295 calls to WRITE_ONCE(), smp_store_release(), or atomic_set().
296
297 Fence events correspond to memory barriers (also known as
298 fences), such as calls to smp_rmb() or rcu_read_lock().
299
300These categories are not exclusive; a read or write event can also be
301a fence. This happens with functions like smp_load_acquire() or
302spin_lock(). However, no single event can be both a read and a write.
303Atomic read-modify-write accesses, such as atomic_inc() or xchg(),
304correspond to a pair of events: a read followed by a write. (The
305write event is omitted for executions where it doesn't occur, such as
306a cmpxchg() where the comparison fails.)
307
308Other parts of the code, those which do not involve interaction with
309shared memory, do not give rise to events. Thus, arithmetic and
310logical computations, control-flow instructions, or accesses to
311private memory or CPU registers are not of central interest to the
312memory model. They only affect the model's predictions indirectly.
313For example, an arithmetic computation might determine the value that
314gets stored to a shared memory location (or in the case of an array
315index, the address where the value gets stored), but the memory model
316is concerned only with the store itself -- its value and its address
317-- not the computation leading up to it.
318
319Events in the LKMM can be linked by various relations, which we will
320describe in the following sections. The memory model requires certain
321of these relations to be orderings, that is, it requires them not to
322have any cycles.
323
324
325THE PROGRAM ORDER RELATION: po AND po-loc
326-----------------------------------------
327
328The most important relation between events is program order (po). You
329can think of it as the order in which statements occur in the source
330code after branches are taken into account and loops have been
331unrolled. A better description might be the order in which
332instructions are presented to a CPU's execution unit. Thus, we say
333that X is po-before Y (written as "X ->po Y" in formulas) if X occurs
334before Y in the instruction stream.
335
336This is inherently a single-CPU relation; two instructions executing
337on different CPUs are never linked by po. Also, it is by definition
338an ordering so it cannot have any cycles.
339
340po-loc is a sub-relation of po. It links two memory accesses when the
341first comes before the second in program order and they access the
342same memory location (the "-loc" suffix).
343
344Although this may seem straightforward, there is one subtle aspect to
345program order we need to explain. The LKMM was inspired by low-level
346architectural memory models which describe the behavior of machine
347code, and it retains their outlook to a considerable extent. The
348read, write, and fence events used by the model are close in spirit to
349individual machine instructions. Nevertheless, the LKMM describes
350kernel code written in C, and the mapping from C to machine code can
351be extremely complex.
352
353Optimizing compilers have great freedom in the way they translate
354source code to object code. They are allowed to apply transformations
355that add memory accesses, eliminate accesses, combine them, split them
356into pieces, or move them around. Faced with all these possibilities,
357the LKMM basically gives up. It insists that the code it analyzes
358must contain no ordinary accesses to shared memory; all accesses must
359be performed using READ_ONCE(), WRITE_ONCE(), or one of the other
360atomic or synchronization primitives. These primitives prevent a
361large number of compiler optimizations. In particular, it is
362guaranteed that the compiler will not remove such accesses from the
363generated code (unless it can prove the accesses will never be
364executed), it will not change the order in which they occur in the
365code (within limits imposed by the C standard), and it will not
366introduce extraneous accesses.
367
368This explains why the MP and SB examples above used READ_ONCE() and
369WRITE_ONCE() rather than ordinary memory accesses. Thanks to this
370usage, we can be certain that in the MP example, P0's write event to
371buf really is po-before its write event to flag, and similarly for the
372other shared memory accesses in the examples.
373
374Private variables are not subject to this restriction. Since they are
375not shared between CPUs, they can be accessed normally without
376READ_ONCE() or WRITE_ONCE(), and there will be no ill effects. In
377fact, they need not even be stored in normal memory at all -- in
378principle a private variable could be stored in a CPU register (hence
379the convention that these variables have names starting with the
380letter 'r').
381
382
383A WARNING
384---------
385
386The protections provided by READ_ONCE(), WRITE_ONCE(), and others are
387not perfect; and under some circumstances it is possible for the
388compiler to undermine the memory model. Here is an example. Suppose
389both branches of an "if" statement store the same value to the same
390location:
391
392 r1 = READ_ONCE(x);
393 if (r1) {
394 WRITE_ONCE(y, 2);
395 ... /* do something */
396 } else {
397 WRITE_ONCE(y, 2);
398 ... /* do something else */
399 }
400
401For this code, the LKMM predicts that the load from x will always be
402executed before either of the stores to y. However, a compiler could
403lift the stores out of the conditional, transforming the code into
404something resembling:
405
406 r1 = READ_ONCE(x);
407 WRITE_ONCE(y, 2);
408 if (r1) {
409 ... /* do something */
410 } else {
411 ... /* do something else */
412 }
413
414Given this version of the code, the LKMM would predict that the load
415from x could be executed after the store to y. Thus, the memory
416model's original prediction could be invalidated by the compiler.
417
418Another issue arises from the fact that in C, arguments to many
419operators and function calls can be evaluated in any order. For
420example:
421
422 r1 = f(5) + g(6);
423
424The object code might call f(5) either before or after g(6); the
425memory model cannot assume there is a fixed program order relation
426between them. (In fact, if the functions are inlined then the
427compiler might even interleave their object code.)
428
429
430DEPENDENCY RELATIONS: data, addr, and ctrl
431------------------------------------------
432
433We say that two events are linked by a dependency relation when the
434execution of the second event depends in some way on a value obtained
435from memory by the first. The first event must be a read, and the
436value it obtains must somehow affect what the second event does.
437There are three kinds of dependencies: data, address (addr), and
438control (ctrl).
439
440A read and a write event are linked by a data dependency if the value
441obtained by the read affects the value stored by the write. As a very
442simple example:
443
444 int x, y;
445
446 r1 = READ_ONCE(x);
447 WRITE_ONCE(y, r1 + 5);
448
449The value stored by the WRITE_ONCE obviously depends on the value
450loaded by the READ_ONCE. Such dependencies can wind through
451arbitrarily complicated computations, and a write can depend on the
452values of multiple reads.
453
454A read event and another memory access event are linked by an address
455dependency if the value obtained by the read affects the location
456accessed by the other event. The second event can be either a read or
457a write. Here's another simple example:
458
459 int a[20];
460 int i;
461
462 r1 = READ_ONCE(i);
463 r2 = READ_ONCE(a[r1]);
464
465Here the location accessed by the second READ_ONCE() depends on the
466index value loaded by the first. Pointer indirection also gives rise
467to address dependencies, since the address of a location accessed
468through a pointer will depend on the value read earlier from that
469pointer.
470
471Finally, a read event and another memory access event are linked by a
472control dependency if the value obtained by the read affects whether
473the second event is executed at all. Simple example:
474
475 int x, y;
476
477 r1 = READ_ONCE(x);
478 if (r1)
479 WRITE_ONCE(y, 1984);
480
481Execution of the WRITE_ONCE() is controlled by a conditional expression
482which depends on the value obtained by the READ_ONCE(); hence there is
483a control dependency from the load to the store.
484
485It should be pretty obvious that events can only depend on reads that
486come earlier in program order. Symbolically, if we have R ->data X,
487R ->addr X, or R ->ctrl X (where R is a read event), then we must also
488have R ->po X. It wouldn't make sense for a computation to depend
489somehow on a value that doesn't get loaded from shared memory until
490later in the code!
491
492
493THE READS-FROM RELATION: rf, rfi, and rfe
494-----------------------------------------
495
496The reads-from relation (rf) links a write event to a read event when
497the value loaded by the read is the value that was stored by the
498write. In colloquial terms, the load "reads from" the store. We
499write W ->rf R to indicate that the load R reads from the store W. We
500further distinguish the cases where the load and the store occur on
501the same CPU (internal reads-from, or rfi) and where they occur on
502different CPUs (external reads-from, or rfe).
503
504For our purposes, a memory location's initial value is treated as
505though it had been written there by an imaginary initial store that
506executes on a separate CPU before the program runs.
507
508Usage of the rf relation implicitly assumes that loads will always
509read from a single store. It doesn't apply properly in the presence
510of load-tearing, where a load obtains some of its bits from one store
511and some of them from another store. Fortunately, use of READ_ONCE()
512and WRITE_ONCE() will prevent load-tearing; it's not possible to have:
513
514 int x = 0;
515
516 P0()
517 {
518 WRITE_ONCE(x, 0x1234);
519 }
520
521 P1()
522 {
523 int r1;
524
525 r1 = READ_ONCE(x);
526 }
527
528and end up with r1 = 0x1200 (partly from x's initial value and partly
529from the value stored by P0).
530
531On the other hand, load-tearing is unavoidable when mixed-size
532accesses are used. Consider this example:
533
534 union {
535 u32 w;
536 u16 h[2];
537 } x;
538
539 P0()
540 {
541 WRITE_ONCE(x.h[0], 0x1234);
542 WRITE_ONCE(x.h[1], 0x5678);
543 }
544
545 P1()
546 {
547 int r1;
548
549 r1 = READ_ONCE(x.w);
550 }
551
552If r1 = 0x56781234 (little-endian!) at the end, then P1 must have read
553from both of P0's stores. It is possible to handle mixed-size and
554unaligned accesses in a memory model, but the LKMM currently does not
555attempt to do so. It requires all accesses to be properly aligned and
556of the location's actual size.
557
558
559CACHE COHERENCE AND THE COHERENCE ORDER RELATION: co, coi, and coe
560------------------------------------------------------------------
561
562Cache coherence is a general principle requiring that in a
563multi-processor system, the CPUs must share a consistent view of the
564memory contents. Specifically, it requires that for each location in
565shared memory, the stores to that location must form a single global
566ordering which all the CPUs agree on (the coherence order), and this
567ordering must be consistent with the program order for accesses to
568that location.
569
570To put it another way, for any variable x, the coherence order (co) of
571the stores to x is simply the order in which the stores overwrite one
572another. The imaginary store which establishes x's initial value
573comes first in the coherence order; the store which directly
574overwrites the initial value comes second; the store which overwrites
575that value comes third, and so on.
576
577You can think of the coherence order as being the order in which the
578stores reach x's location in memory (or if you prefer a more
579hardware-centric view, the order in which the stores get written to
580x's cache line). We write W ->co W' if W comes before W' in the
581coherence order, that is, if the value stored by W gets overwritten,
582directly or indirectly, by the value stored by W'.
583
584Coherence order is required to be consistent with program order. This
585requirement takes the form of four coherency rules:
586
587 Write-write coherence: If W ->po-loc W' (i.e., W comes before
588 W' in program order and they access the same location), where W
589 and W' are two stores, then W ->co W'.
590
591 Write-read coherence: If W ->po-loc R, where W is a store and R
592 is a load, then R must read from W or from some other store
593 which comes after W in the coherence order.
594
595 Read-write coherence: If R ->po-loc W, where R is a load and W
596 is a store, then the store which R reads from must come before
597 W in the coherence order.
598
599 Read-read coherence: If R ->po-loc R', where R and R' are two
600 loads, then either they read from the same store or else the
601 store read by R comes before the store read by R' in the
602 coherence order.
603
604This is sometimes referred to as sequential consistency per variable,
605because it means that the accesses to any single memory location obey
606the rules of the Sequential Consistency memory model. (According to
607Wikipedia, sequential consistency per variable and cache coherence
608mean the same thing except that cache coherence includes an extra
609requirement that every store eventually becomes visible to every CPU.)
610
611Any reasonable memory model will include cache coherence. Indeed, our
612expectation of cache coherence is so deeply ingrained that violations
613of its requirements look more like hardware bugs than programming
614errors:
615
616 int x;
617
618 P0()
619 {
620 WRITE_ONCE(x, 17);
621 WRITE_ONCE(x, 23);
622 }
623
624If the final value stored in x after this code ran was 17, you would
625think your computer was broken. It would be a violation of the
626write-write coherence rule: Since the store of 23 comes later in
627program order, it must also come later in x's coherence order and
628thus must overwrite the store of 17.
629
630 int x = 0;
631
632 P0()
633 {
634 int r1;
635
636 r1 = READ_ONCE(x);
637 WRITE_ONCE(x, 666);
638 }
639
640If r1 = 666 at the end, this would violate the read-write coherence
641rule: The READ_ONCE() load comes before the WRITE_ONCE() store in
642program order, so it must not read from that store but rather from one
643coming earlier in the coherence order (in this case, x's initial
644value).
645
646 int x = 0;
647
648 P0()
649 {
650 WRITE_ONCE(x, 5);
651 }
652
653 P1()
654 {
655 int r1, r2;
656
657 r1 = READ_ONCE(x);
658 r2 = READ_ONCE(x);
659 }
660
661If r1 = 5 (reading from P0's store) and r2 = 0 (reading from the
662imaginary store which establishes x's initial value) at the end, this
663would violate the read-read coherence rule: The r1 load comes before
664the r2 load in program order, so it must not read from a store that
665comes later in the coherence order.
666
667(As a minor curiosity, if this code had used normal loads instead of
668READ_ONCE() in P1, on Itanium it sometimes could end up with r1 = 5
669and r2 = 0! This results from parallel execution of the operations
670encoded in Itanium's Very-Long-Instruction-Word format, and it is yet
671another motivation for using READ_ONCE() when accessing shared memory
672locations.)
673
674Just like the po relation, co is inherently an ordering -- it is not
675possible for a store to directly or indirectly overwrite itself! And
676just like with the rf relation, we distinguish between stores that
677occur on the same CPU (internal coherence order, or coi) and stores
678that occur on different CPUs (external coherence order, or coe).
679
680On the other hand, stores to different memory locations are never
681related by co, just as instructions on different CPUs are never
682related by po. Coherence order is strictly per-location, or if you
683prefer, each location has its own independent coherence order.
684
685
686THE FROM-READS RELATION: fr, fri, and fre
687-----------------------------------------
688
689The from-reads relation (fr) can be a little difficult for people to
690grok. It describes the situation where a load reads a value that gets
691overwritten by a store. In other words, we have R ->fr W when the
692value that R reads is overwritten (directly or indirectly) by W, or
693equivalently, when R reads from a store which comes earlier than W in
694the coherence order.
695
696For example:
697
698 int x = 0;
699
700 P0()
701 {
702 int r1;
703
704 r1 = READ_ONCE(x);
705 WRITE_ONCE(x, 2);
706 }
707
708The value loaded from x will be 0 (assuming cache coherence!), and it
709gets overwritten by the value 2. Thus there is an fr link from the
710READ_ONCE() to the WRITE_ONCE(). If the code contained any later
711stores to x, there would also be fr links from the READ_ONCE() to
712them.
713
714As with rf, rfi, and rfe, we subdivide the fr relation into fri (when
715the load and the store are on the same CPU) and fre (when they are on
716different CPUs).
717
718Note that the fr relation is determined entirely by the rf and co
719relations; it is not independent. Given a read event R and a write
720event W for the same location, we will have R ->fr W if and only if
721the write which R reads from is co-before W. In symbols,
722
723 (R ->fr W) := (there exists W' with W' ->rf R and W' ->co W).
724
725
726AN OPERATIONAL MODEL
727--------------------
728
729The LKMM is based on various operational memory models, meaning that
730the models arise from an abstract view of how a computer system
731operates. Here are the main ideas, as incorporated into the LKMM.
732
733The system as a whole is divided into the CPUs and a memory subsystem.
734The CPUs are responsible for executing instructions (not necessarily
735in program order), and they communicate with the memory subsystem.
736For the most part, executing an instruction requires a CPU to perform
737only internal operations. However, loads, stores, and fences involve
738more.
739
740When CPU C executes a store instruction, it tells the memory subsystem
741to store a certain value at a certain location. The memory subsystem
742propagates the store to all the other CPUs as well as to RAM. (As a
743special case, we say that the store propagates to its own CPU at the
744time it is executed.) The memory subsystem also determines where the
745store falls in the location's coherence order. In particular, it must
746arrange for the store to be co-later than (i.e., to overwrite) any
747other store to the same location which has already propagated to CPU C.
748
749When a CPU executes a load instruction R, it first checks to see
750whether there are any as-yet unexecuted store instructions, for the
751same location, that come before R in program order. If there are, it
752uses the value of the po-latest such store as the value obtained by R,
753and we say that the store's value is forwarded to R. Otherwise, the
754CPU asks the memory subsystem for the value to load and we say that R
755is satisfied from memory. The memory subsystem hands back the value
756of the co-latest store to the location in question which has already
757propagated to that CPU.
758
759(In fact, the picture needs to be a little more complicated than this.
760CPUs have local caches, and propagating a store to a CPU really means
761propagating it to the CPU's local cache. A local cache can take some
762time to process the stores that it receives, and a store can't be used
763to satisfy one of the CPU's loads until it has been processed. On
764most architectures, the local caches process stores in
765First-In-First-Out order, and consequently the processing delay
766doesn't matter for the memory model. But on Alpha, the local caches
767have a partitioned design that results in non-FIFO behavior. We will
768discuss this in more detail later.)
769
770Note that load instructions may be executed speculatively and may be
771restarted under certain circumstances. The memory model ignores these
772premature executions; we simply say that the load executes at the
773final time it is forwarded or satisfied.
774
775Executing a fence (or memory barrier) instruction doesn't require a
776CPU to do anything special other than informing the memory subsystem
777about the fence. However, fences do constrain the way CPUs and the
778memory subsystem handle other instructions, in two respects.
779
780First, a fence forces the CPU to execute various instructions in
781program order. Exactly which instructions are ordered depends on the
782type of fence:
783
784 Strong fences, including smp_mb() and synchronize_rcu(), force
785 the CPU to execute all po-earlier instructions before any
786 po-later instructions;
787
788 smp_rmb() forces the CPU to execute all po-earlier loads
789 before any po-later loads;
790
791 smp_wmb() forces the CPU to execute all po-earlier stores
792 before any po-later stores;
793
794 Acquire fences, such as smp_load_acquire(), force the CPU to
795 execute the load associated with the fence (e.g., the load
796 part of an smp_load_acquire()) before any po-later
797 instructions;
798
799 Release fences, such as smp_store_release(), force the CPU to
800 execute all po-earlier instructions before the store
801 associated with the fence (e.g., the store part of an
802 smp_store_release()).
803
804Second, some types of fence affect the way the memory subsystem
805propagates stores. When a fence instruction is executed on CPU C:
806
807 For each other CPU C', smb_wmb() forces all po-earlier stores
808 on C to propagate to C' before any po-later stores do.
809
810 For each other CPU C', any store which propagates to C before
811 a release fence is executed (including all po-earlier
812 stores executed on C) is forced to propagate to C' before the
813 store associated with the release fence does.
814
815 Any store which propagates to C before a strong fence is
816 executed (including all po-earlier stores on C) is forced to
817 propagate to all other CPUs before any instructions po-after
818 the strong fence are executed on C.
819
820The propagation ordering enforced by release fences and strong fences
821affects stores from other CPUs that propagate to CPU C before the
822fence is executed, as well as stores that are executed on C before the
823fence. We describe this property by saying that release fences and
824strong fences are A-cumulative. By contrast, smp_wmb() fences are not
825A-cumulative; they only affect the propagation of stores that are
826executed on C before the fence (i.e., those which precede the fence in
827program order).
828
829rcu_read_lock(), rcu_read_unlock(), and synchronize_rcu() fences have
830other properties which we discuss later.
831
832
833PROPAGATION ORDER RELATION: cumul-fence
834---------------------------------------
835
836The fences which affect propagation order (i.e., strong, release, and
837smp_wmb() fences) are collectively referred to as cumul-fences, even
838though smp_wmb() isn't A-cumulative. The cumul-fence relation is
839defined to link memory access events E and F whenever:
840
841 E and F are both stores on the same CPU and an smp_wmb() fence
842 event occurs between them in program order; or
843
844 F is a release fence and some X comes before F in program order,
845 where either X = E or else E ->rf X; or
846
847 A strong fence event occurs between some X and F in program
848 order, where either X = E or else E ->rf X.
849
850The operational model requires that whenever W and W' are both stores
851and W ->cumul-fence W', then W must propagate to any given CPU
852before W' does. However, for different CPUs C and C', it does not
853require W to propagate to C before W' propagates to C'.
854
855
856DERIVATION OF THE LKMM FROM THE OPERATIONAL MODEL
857-------------------------------------------------
858
859The LKMM is derived from the restrictions imposed by the design
860outlined above. These restrictions involve the necessity of
861maintaining cache coherence and the fact that a CPU can't operate on a
862value before it knows what that value is, among other things.
863
864The formal version of the LKMM is defined by five requirements, or
865axioms:
866
867 Sequential consistency per variable: This requires that the
868 system obey the four coherency rules.
869
870 Atomicity: This requires that atomic read-modify-write
871 operations really are atomic, that is, no other stores can
872 sneak into the middle of such an update.
873
874 Happens-before: This requires that certain instructions are
875 executed in a specific order.
876
877 Propagation: This requires that certain stores propagate to
878 CPUs and to RAM in a specific order.
879
880 Rcu: This requires that RCU read-side critical sections and
881 grace periods obey the rules of RCU, in particular, the
882 Grace-Period Guarantee.
883
884The first and second are quite common; they can be found in many
885memory models (such as those for C11/C++11). The "happens-before" and
886"propagation" axioms have analogs in other memory models as well. The
887"rcu" axiom is specific to the LKMM.
888
889Each of these axioms is discussed below.
890
891
892SEQUENTIAL CONSISTENCY PER VARIABLE
893-----------------------------------
894
895According to the principle of cache coherence, the stores to any fixed
896shared location in memory form a global ordering. We can imagine
897inserting the loads from that location into this ordering, by placing
898each load between the store that it reads from and the following
899store. This leaves the relative positions of loads that read from the
900same store unspecified; let's say they are inserted in program order,
901first for CPU 0, then CPU 1, etc.
902
903You can check that the four coherency rules imply that the rf, co, fr,
904and po-loc relations agree with this global ordering; in other words,
905whenever we have X ->rf Y or X ->co Y or X ->fr Y or X ->po-loc Y, the
906X event comes before the Y event in the global ordering. The LKMM's
907"coherence" axiom expresses this by requiring the union of these
908relations not to have any cycles. This means it must not be possible
909to find events
910
911 X0 -> X1 -> X2 -> ... -> Xn -> X0,
912
913where each of the links is either rf, co, fr, or po-loc. This has to
914hold if the accesses to the fixed memory location can be ordered as
915cache coherence demands.
916
917Although it is not obvious, it can be shown that the converse is also
918true: This LKMM axiom implies that the four coherency rules are
919obeyed.
920
921
922ATOMIC UPDATES: rmw
923-------------------
924
925What does it mean to say that a read-modify-write (rmw) update, such
926as atomic_inc(&x), is atomic? It means that the memory location (x in
927this case) does not get altered between the read and the write events
928making up the atomic operation. In particular, if two CPUs perform
929atomic_inc(&x) concurrently, it must be guaranteed that the final
930value of x will be the initial value plus two. We should never have
931the following sequence of events:
932
933 CPU 0 loads x obtaining 13;
934 CPU 1 loads x obtaining 13;
935 CPU 0 stores 14 to x;
936 CPU 1 stores 14 to x;
937
938where the final value of x is wrong (14 rather than 15).
939
940In this example, CPU 0's increment effectively gets lost because it
941occurs in between CPU 1's load and store. To put it another way, the
942problem is that the position of CPU 0's store in x's coherence order
943is between the store that CPU 1 reads from and the store that CPU 1
944performs.
945
946The same analysis applies to all atomic update operations. Therefore,
947to enforce atomicity the LKMM requires that atomic updates follow this
948rule: Whenever R and W are the read and write events composing an
949atomic read-modify-write and W' is the write event which R reads from,
950there must not be any stores coming between W' and W in the coherence
951order. Equivalently,
952
953 (R ->rmw W) implies (there is no X with R ->fr X and X ->co W),
954
955where the rmw relation links the read and write events making up each
956atomic update. This is what the LKMM's "atomic" axiom says.
957
958
959THE PRESERVED PROGRAM ORDER RELATION: ppo
960-----------------------------------------
961
962There are many situations where a CPU is obligated to execute two
963instructions in program order. We amalgamate them into the ppo (for
964"preserved program order") relation, which links the po-earlier
965instruction to the po-later instruction and is thus a sub-relation of
966po.
967
968The operational model already includes a description of one such
969situation: Fences are a source of ppo links. Suppose X and Y are
970memory accesses with X ->po Y; then the CPU must execute X before Y if
971any of the following hold:
972
973 A strong (smp_mb() or synchronize_rcu()) fence occurs between
974 X and Y;
975
976 X and Y are both stores and an smp_wmb() fence occurs between
977 them;
978
979 X and Y are both loads and an smp_rmb() fence occurs between
980 them;
981
982 X is also an acquire fence, such as smp_load_acquire();
983
984 Y is also a release fence, such as smp_store_release().
985
986Another possibility, not mentioned earlier but discussed in the next
987section, is:
988
989 X and Y are both loads, X ->addr Y (i.e., there is an address
990 dependency from X to Y), and X is a READ_ONCE() or an atomic
991 access.
992
993Dependencies can also cause instructions to be executed in program
994order. This is uncontroversial when the second instruction is a
995store; either a data, address, or control dependency from a load R to
996a store W will force the CPU to execute R before W. This is very
997simply because the CPU cannot tell the memory subsystem about W's
998store before it knows what value should be stored (in the case of a
999data dependency), what location it should be stored into (in the case
1000of an address dependency), or whether the store should actually take
1001place (in the case of a control dependency).
1002
1003Dependencies to load instructions are more problematic. To begin with,
1004there is no such thing as a data dependency to a load. Next, a CPU
1005has no reason to respect a control dependency to a load, because it
1006can always satisfy the second load speculatively before the first, and
1007then ignore the result if it turns out that the second load shouldn't
1008be executed after all. And lastly, the real difficulties begin when
1009we consider address dependencies to loads.
1010
1011To be fair about it, all Linux-supported architectures do execute
1012loads in program order if there is an address dependency between them.
1013After all, a CPU cannot ask the memory subsystem to load a value from
1014a particular location before it knows what that location is. However,
1015the split-cache design used by Alpha can cause it to behave in a way
1016that looks as if the loads were executed out of order (see the next
1017section for more details). The kernel includes a workaround for this
1018problem when the loads come from READ_ONCE(), and therefore the LKMM
1019includes address dependencies to loads in the ppo relation.
1020
1021On the other hand, dependencies can indirectly affect the ordering of
1022two loads. This happens when there is a dependency from a load to a
1023store and a second, po-later load reads from that store:
1024
1025 R ->dep W ->rfi R',
1026
1027where the dep link can be either an address or a data dependency. In
1028this situation we know it is possible for the CPU to execute R' before
1029W, because it can forward the value that W will store to R'. But it
1030cannot execute R' before R, because it cannot forward the value before
1031it knows what that value is, or that W and R' do access the same
1032location. However, if there is merely a control dependency between R
1033and W then the CPU can speculatively forward W to R' before executing
1034R; if the speculation turns out to be wrong then the CPU merely has to
1035restart or abandon R'.
1036
1037(In theory, a CPU might forward a store to a load when it runs across
1038an address dependency like this:
1039
1040 r1 = READ_ONCE(ptr);
1041 WRITE_ONCE(*r1, 17);
1042 r2 = READ_ONCE(*r1);
1043
1044because it could tell that the store and the second load access the
1045same location even before it knows what the location's address is.
1046However, none of the architectures supported by the Linux kernel do
1047this.)
1048
1049Two memory accesses of the same location must always be executed in
1050program order if the second access is a store. Thus, if we have
1051
1052 R ->po-loc W
1053
1054(the po-loc link says that R comes before W in program order and they
1055access the same location), the CPU is obliged to execute W after R.
1056If it executed W first then the memory subsystem would respond to R's
1057read request with the value stored by W (or an even later store), in
1058violation of the read-write coherence rule. Similarly, if we had
1059
1060 W ->po-loc W'
1061
1062and the CPU executed W' before W, then the memory subsystem would put
1063W' before W in the coherence order. It would effectively cause W to
1064overwrite W', in violation of the write-write coherence rule.
1065(Interestingly, an early ARMv8 memory model, now obsolete, proposed
1066allowing out-of-order writes like this to occur. The model avoided
1067violating the write-write coherence rule by requiring the CPU not to
1068send the W write to the memory subsystem at all!)
1069
1070There is one last example of preserved program order in the LKMM: when
1071a load-acquire reads from an earlier store-release. For example:
1072
1073 smp_store_release(&x, 123);
1074 r1 = smp_load_acquire(&x);
1075
1076If the smp_load_acquire() ends up obtaining the 123 value that was
1077stored by the smp_store_release(), the LKMM says that the load must be
1078executed after the store; the store cannot be forwarded to the load.
1079This requirement does not arise from the operational model, but it
1080yields correct predictions on all architectures supported by the Linux
1081kernel, although for differing reasons.
1082
1083On some architectures, including x86 and ARMv8, it is true that the
1084store cannot be forwarded to the load. On others, including PowerPC
1085and ARMv7, smp_store_release() generates object code that starts with
1086a fence and smp_load_acquire() generates object code that ends with a
1087fence. The upshot is that even though the store may be forwarded to
1088the load, it is still true that any instruction preceding the store
1089will be executed before the load or any following instructions, and
1090the store will be executed before any instruction following the load.
1091
1092
1093AND THEN THERE WAS ALPHA
1094------------------------
1095
1096As mentioned above, the Alpha architecture is unique in that it does
1097not appear to respect address dependencies to loads. This means that
1098code such as the following:
1099
1100 int x = 0;
1101 int y = -1;
1102 int *ptr = &y;
1103
1104 P0()
1105 {
1106 WRITE_ONCE(x, 1);
1107 smp_wmb();
1108 WRITE_ONCE(ptr, &x);
1109 }
1110
1111 P1()
1112 {
1113 int *r1;
1114 int r2;
1115
1116 r1 = ptr;
1117 r2 = READ_ONCE(*r1);
1118 }
1119
1120can malfunction on Alpha systems (notice that P1 uses an ordinary load
1121to read ptr instead of READ_ONCE()). It is quite possible that r1 = &x
1122and r2 = 0 at the end, in spite of the address dependency.
1123
1124At first glance this doesn't seem to make sense. We know that the
1125smp_wmb() forces P0's store to x to propagate to P1 before the store
1126to ptr does. And since P1 can't execute its second load
1127until it knows what location to load from, i.e., after executing its
1128first load, the value x = 1 must have propagated to P1 before the
1129second load executed. So why doesn't r2 end up equal to 1?
1130
1131The answer lies in the Alpha's split local caches. Although the two
1132stores do reach P1's local cache in the proper order, it can happen
1133that the first store is processed by a busy part of the cache while
1134the second store is processed by an idle part. As a result, the x = 1
1135value may not become available for P1's CPU to read until after the
1136ptr = &x value does, leading to the undesirable result above. The
1137final effect is that even though the two loads really are executed in
1138program order, it appears that they aren't.
1139
1140This could not have happened if the local cache had processed the
1141incoming stores in FIFO order. By contrast, other architectures
1142maintain at least the appearance of FIFO order.
1143
1144In practice, this difficulty is solved by inserting a special fence
1145between P1's two loads when the kernel is compiled for the Alpha
1146architecture. In fact, as of version 4.15, the kernel automatically
1147adds this fence (called smp_read_barrier_depends() and defined as
1148nothing at all on non-Alpha builds) after every READ_ONCE() and atomic
1149load. The effect of the fence is to cause the CPU not to execute any
1150po-later instructions until after the local cache has finished
1151processing all the stores it has already received. Thus, if the code
1152was changed to:
1153
1154 P1()
1155 {
1156 int *r1;
1157 int r2;
1158
1159 r1 = READ_ONCE(ptr);
1160 r2 = READ_ONCE(*r1);
1161 }
1162
1163then we would never get r1 = &x and r2 = 0. By the time P1 executed
1164its second load, the x = 1 store would already be fully processed by
1165the local cache and available for satisfying the read request. Thus
1166we have yet another reason why shared data should always be read with
1167READ_ONCE() or another synchronization primitive rather than accessed
1168directly.
1169
1170The LKMM requires that smp_rmb(), acquire fences, and strong fences
1171share this property with smp_read_barrier_depends(): They do not allow
1172the CPU to execute any po-later instructions (or po-later loads in the
1173case of smp_rmb()) until all outstanding stores have been processed by
1174the local cache. In the case of a strong fence, the CPU first has to
1175wait for all of its po-earlier stores to propagate to every other CPU
1176in the system; then it has to wait for the local cache to process all
1177the stores received as of that time -- not just the stores received
1178when the strong fence began.
1179
1180And of course, none of this matters for any architecture other than
1181Alpha.
1182
1183
1184THE HAPPENS-BEFORE RELATION: hb
1185-------------------------------
1186
1187The happens-before relation (hb) links memory accesses that have to
1188execute in a certain order. hb includes the ppo relation and two
1189others, one of which is rfe.
1190
1191W ->rfe R implies that W and R are on different CPUs. It also means
1192that W's store must have propagated to R's CPU before R executed;
1193otherwise R could not have read the value stored by W. Therefore W
1194must have executed before R, and so we have W ->hb R.
1195
1196The equivalent fact need not hold if W ->rfi R (i.e., W and R are on
1197the same CPU). As we have already seen, the operational model allows
1198W's value to be forwarded to R in such cases, meaning that R may well
1199execute before W does.
1200
1201It's important to understand that neither coe nor fre is included in
1202hb, despite their similarities to rfe. For example, suppose we have
1203W ->coe W'. This means that W and W' are stores to the same location,
1204they execute on different CPUs, and W comes before W' in the coherence
1205order (i.e., W' overwrites W). Nevertheless, it is possible for W' to
1206execute before W, because the decision as to which store overwrites
1207the other is made later by the memory subsystem. When the stores are
1208nearly simultaneous, either one can come out on top. Similarly,
1209R ->fre W means that W overwrites the value which R reads, but it
1210doesn't mean that W has to execute after R. All that's necessary is
1211for the memory subsystem not to propagate W to R's CPU until after R
1212has executed, which is possible if W executes shortly before R.
1213
1214The third relation included in hb is like ppo, in that it only links
1215events that are on the same CPU. However it is more difficult to
1216explain, because it arises only indirectly from the requirement of
1217cache coherence. The relation is called prop, and it links two events
1218on CPU C in situations where a store from some other CPU comes after
1219the first event in the coherence order and propagates to C before the
1220second event executes.
1221
1222This is best explained with some examples. The simplest case looks
1223like this:
1224
1225 int x;
1226
1227 P0()
1228 {
1229 int r1;
1230
1231 WRITE_ONCE(x, 1);
1232 r1 = READ_ONCE(x);
1233 }
1234
1235 P1()
1236 {
1237 WRITE_ONCE(x, 8);
1238 }
1239
1240If r1 = 8 at the end then P0's accesses must have executed in program
1241order. We can deduce this from the operational model; if P0's load
1242had executed before its store then the value of the store would have
1243been forwarded to the load, so r1 would have ended up equal to 1, not
12448. In this case there is a prop link from P0's write event to its read
1245event, because P1's store came after P0's store in x's coherence
1246order, and P1's store propagated to P0 before P0's load executed.
1247
1248An equally simple case involves two loads of the same location that
1249read from different stores:
1250
1251 int x = 0;
1252
1253 P0()
1254 {
1255 int r1, r2;
1256
1257 r1 = READ_ONCE(x);
1258 r2 = READ_ONCE(x);
1259 }
1260
1261 P1()
1262 {
1263 WRITE_ONCE(x, 9);
1264 }
1265
1266If r1 = 0 and r2 = 9 at the end then P0's accesses must have executed
1267in program order. If the second load had executed before the first
1268then the x = 9 store must have been propagated to P0 before the first
1269load executed, and so r1 would have been 9 rather than 0. In this
1270case there is a prop link from P0's first read event to its second,
1271because P1's store overwrote the value read by P0's first load, and
1272P1's store propagated to P0 before P0's second load executed.
1273
1274Less trivial examples of prop all involve fences. Unlike the simple
1275examples above, they can require that some instructions are executed
1276out of program order. This next one should look familiar:
1277
1278 int buf = 0, flag = 0;
1279
1280 P0()
1281 {
1282 WRITE_ONCE(buf, 1);
1283 smp_wmb();
1284 WRITE_ONCE(flag, 1);
1285 }
1286
1287 P1()
1288 {
1289 int r1;
1290 int r2;
1291
1292 r1 = READ_ONCE(flag);
1293 r2 = READ_ONCE(buf);
1294 }
1295
1296This is the MP pattern again, with an smp_wmb() fence between the two
1297stores. If r1 = 1 and r2 = 0 at the end then there is a prop link
1298from P1's second load to its first (backwards!). The reason is
1299similar to the previous examples: The value P1 loads from buf gets
1300overwritten by P0's store to buf, the fence guarantees that the store
1301to buf will propagate to P1 before the store to flag does, and the
1302store to flag propagates to P1 before P1 reads flag.
1303
1304The prop link says that in order to obtain the r1 = 1, r2 = 0 result,
1305P1 must execute its second load before the first. Indeed, if the load
1306from flag were executed first, then the buf = 1 store would already
1307have propagated to P1 by the time P1's load from buf executed, so r2
1308would have been 1 at the end, not 0. (The reasoning holds even for
1309Alpha, although the details are more complicated and we will not go
1310into them.)
1311
1312But what if we put an smp_rmb() fence between P1's loads? The fence
1313would force the two loads to be executed in program order, and it
1314would generate a cycle in the hb relation: The fence would create a ppo
1315link (hence an hb link) from the first load to the second, and the
1316prop relation would give an hb link from the second load to the first.
1317Since an instruction can't execute before itself, we are forced to
1318conclude that if an smp_rmb() fence is added, the r1 = 1, r2 = 0
1319outcome is impossible -- as it should be.
1320
1321The formal definition of the prop relation involves a coe or fre link,
1322followed by an arbitrary number of cumul-fence links, ending with an
1323rfe link. You can concoct more exotic examples, containing more than
1324one fence, although this quickly leads to diminishing returns in terms
1325of complexity. For instance, here's an example containing a coe link
1326followed by two fences and an rfe link, utilizing the fact that
1327release fences are A-cumulative:
1328
1329 int x, y, z;
1330
1331 P0()
1332 {
1333 int r0;
1334
1335 WRITE_ONCE(x, 1);
1336 r0 = READ_ONCE(z);
1337 }
1338
1339 P1()
1340 {
1341 WRITE_ONCE(x, 2);
1342 smp_wmb();
1343 WRITE_ONCE(y, 1);
1344 }
1345
1346 P2()
1347 {
1348 int r2;
1349
1350 r2 = READ_ONCE(y);
1351 smp_store_release(&z, 1);
1352 }
1353
1354If x = 2, r0 = 1, and r2 = 1 after this code runs then there is a prop
1355link from P0's store to its load. This is because P0's store gets
1356overwritten by P1's store since x = 2 at the end (a coe link), the
1357smp_wmb() ensures that P1's store to x propagates to P2 before the
1358store to y does (the first fence), the store to y propagates to P2
1359before P2's load and store execute, P2's smp_store_release()
1360guarantees that the stores to x and y both propagate to P0 before the
1361store to z does (the second fence), and P0's load executes after the
1362store to z has propagated to P0 (an rfe link).
1363
1364In summary, the fact that the hb relation links memory access events
1365in the order they execute means that it must not have cycles. This
1366requirement is the content of the LKMM's "happens-before" axiom.
1367
1368The LKMM defines yet another relation connected to times of
1369instruction execution, but it is not included in hb. It relies on the
1370particular properties of strong fences, which we cover in the next
1371section.
1372
1373
1374THE PROPAGATES-BEFORE RELATION: pb
1375----------------------------------
1376
1377The propagates-before (pb) relation capitalizes on the special
1378features of strong fences. It links two events E and F whenever some
1379store is coherence-later than E and propagates to every CPU and to RAM
1380before F executes. The formal definition requires that E be linked to
1381F via a coe or fre link, an arbitrary number of cumul-fences, an
1382optional rfe link, a strong fence, and an arbitrary number of hb
1383links. Let's see how this definition works out.
1384
1385Consider first the case where E is a store (implying that the sequence
1386of links begins with coe). Then there are events W, X, Y, and Z such
1387that:
1388
1389 E ->coe W ->cumul-fence* X ->rfe? Y ->strong-fence Z ->hb* F,
1390
1391where the * suffix indicates an arbitrary number of links of the
1392specified type, and the ? suffix indicates the link is optional (Y may
1393be equal to X). Because of the cumul-fence links, we know that W will
1394propagate to Y's CPU before X does, hence before Y executes and hence
1395before the strong fence executes. Because this fence is strong, we
1396know that W will propagate to every CPU and to RAM before Z executes.
1397And because of the hb links, we know that Z will execute before F.
1398Thus W, which comes later than E in the coherence order, will
1399propagate to every CPU and to RAM before F executes.
1400
1401The case where E is a load is exactly the same, except that the first
1402link in the sequence is fre instead of coe.
1403
1404The existence of a pb link from E to F implies that E must execute
1405before F. To see why, suppose that F executed first. Then W would
1406have propagated to E's CPU before E executed. If E was a store, the
1407memory subsystem would then be forced to make E come after W in the
1408coherence order, contradicting the fact that E ->coe W. If E was a
1409load, the memory subsystem would then be forced to satisfy E's read
1410request with the value stored by W or an even later store,
1411contradicting the fact that E ->fre W.
1412
1413A good example illustrating how pb works is the SB pattern with strong
1414fences:
1415
1416 int x = 0, y = 0;
1417
1418 P0()
1419 {
1420 int r0;
1421
1422 WRITE_ONCE(x, 1);
1423 smp_mb();
1424 r0 = READ_ONCE(y);
1425 }
1426
1427 P1()
1428 {
1429 int r1;
1430
1431 WRITE_ONCE(y, 1);
1432 smp_mb();
1433 r1 = READ_ONCE(x);
1434 }
1435
1436If r0 = 0 at the end then there is a pb link from P0's load to P1's
1437load: an fre link from P0's load to P1's store (which overwrites the
1438value read by P0), and a strong fence between P1's store and its load.
1439In this example, the sequences of cumul-fence and hb links are empty.
1440Note that this pb link is not included in hb as an instance of prop,
1441because it does not start and end on the same CPU.
1442
1443Similarly, if r1 = 0 at the end then there is a pb link from P1's load
1444to P0's. This means that if both r1 and r2 were 0 there would be a
1445cycle in pb, which is not possible since an instruction cannot execute
1446before itself. Thus, adding smp_mb() fences to the SB pattern
1447prevents the r0 = 0, r1 = 0 outcome.
1448
1449In summary, the fact that the pb relation links events in the order
1450they execute means that it cannot have cycles. This requirement is
1451the content of the LKMM's "propagation" axiom.
1452
1453
1454RCU RELATIONS: link, gp-link, rscs-link, and rcu-path
1455-----------------------------------------------------
1456
1457RCU (Read-Copy-Update) is a powerful synchronization mechanism. It
1458rests on two concepts: grace periods and read-side critical sections.
1459
1460A grace period is the span of time occupied by a call to
1461synchronize_rcu(). A read-side critical section (or just critical
1462section, for short) is a region of code delimited by rcu_read_lock()
1463at the start and rcu_read_unlock() at the end. Critical sections can
1464be nested, although we won't make use of this fact.
1465
1466As far as memory models are concerned, RCU's main feature is its
1467Grace-Period Guarantee, which states that a critical section can never
1468span a full grace period. In more detail, the Guarantee says:
1469
1470 If a critical section starts before a grace period then it
1471 must end before the grace period does. In addition, every
1472 store that propagates to the critical section's CPU before the
1473 end of the critical section must propagate to every CPU before
1474 the end of the grace period.
1475
1476 If a critical section ends after a grace period ends then it
1477 must start after the grace period does. In addition, every
1478 store that propagates to the grace period's CPU before the
1479 start of the grace period must propagate to every CPU before
1480 the start of the critical section.
1481
1482Here is a simple example of RCU in action:
1483
1484 int x, y;
1485
1486 P0()
1487 {
1488 rcu_read_lock();
1489 WRITE_ONCE(x, 1);
1490 WRITE_ONCE(y, 1);
1491 rcu_read_unlock();
1492 }
1493
1494 P1()
1495 {
1496 int r1, r2;
1497
1498 r1 = READ_ONCE(x);
1499 synchronize_rcu();
1500 r2 = READ_ONCE(y);
1501 }
1502
1503The Grace Period Guarantee tells us that when this code runs, it will
1504never end with r1 = 1 and r2 = 0. The reasoning is as follows. r1 = 1
1505means that P0's store to x propagated to P1 before P1 called
1506synchronize_rcu(), so P0's critical section must have started before
1507P1's grace period. On the other hand, r2 = 0 means that P0's store to
1508y, which occurs before the end of the critical section, did not
1509propagate to P1 before the end of the grace period, violating the
1510Guarantee.
1511
1512In the kernel's implementations of RCU, the business about stores
1513propagating to every CPU is realized by placing strong fences at
1514suitable places in the RCU-related code. Thus, if a critical section
1515starts before a grace period does then the critical section's CPU will
1516execute an smp_mb() fence after the end of the critical section and
1517some time before the grace period's synchronize_rcu() call returns.
1518And if a critical section ends after a grace period does then the
1519synchronize_rcu() routine will execute an smp_mb() fence at its start
1520and some time before the critical section's opening rcu_read_lock()
1521executes.
1522
1523What exactly do we mean by saying that a critical section "starts
1524before" or "ends after" a grace period? Some aspects of the meaning
1525are pretty obvious, as in the example above, but the details aren't
1526entirely clear. The LKMM formalizes this notion by means of a
1527relation with the unfortunately generic name "link". It is a very
1528general relation; among other things, X ->link Z includes cases where
1529X happens-before or is equal to some event Y which is equal to or
1530comes before Z in the coherence order. Taking Y = Z, this says that
1531X ->rfe Z implies X ->link Z, and taking Y = X, it says that X ->fr Z
1532and X ->co Z each imply X ->link Z.
1533
1534The formal definition of the link relation is more than a little
1535obscure, and we won't give it here. It is closely related to the pb
1536relation, and the details don't matter unless you want to comb through
1537a somewhat lengthy formal proof. Pretty much all you need to know
1538about link is the information in the preceding paragraph.
1539
1540The LKMM goes on to define the gp-link and rscs-link relations. They
1541bring grace periods and read-side critical sections into the picture,
1542in the following way:
1543
1544 E ->gp-link F means there is a synchronize_rcu() fence event S
1545 and an event X such that E ->po S, either S ->po X or S = X,
1546 and X ->link F. In other words, E and F are connected by a
1547 grace period followed by an instance of link.
1548
1549 E ->rscs-link F means there is a critical section delimited by
1550 an rcu_read_lock() fence L and an rcu_read_unlock() fence U,
1551 and an event X such that E ->po U, either L ->po X or L = X,
1552 and X ->link F. Roughly speaking, this says that some event
1553 in the same critical section as E is connected by link to F.
1554
1555If we think of the link relation as standing for an extended "before",
1556then E ->gp-link F says that E executes before a grace period which
1557ends before F executes. (In fact it says more than this, because it
1558includes cases where E executes before a grace period and some store
1559propagates to F's CPU before F executes and doesn't propagate to some
1560other CPU until after the grace period ends.) Similarly,
1561E ->rscs-link F says that E is part of (or before the start of) a
1562critical section which starts before F executes.
1563
1564Putting this all together, the LKMM expresses the Grace Period
1565Guarantee by requiring that there are no cycles consisting of gp-link
1566and rscs-link connections in which the number of gp-link instances is
1567>= the number of rscs-link instances. It does this by defining the
1568rcu-path relation to link events E and F whenever it is possible to
1569pass from E to F by a sequence of gp-link and rscs-link connections
1570with at least as many of the former as the latter. The LKMM's "rcu"
1571axiom then says that there are no events E such that E ->rcu-path E.
1572
1573Justifying this axiom takes some intellectual effort, but it is in
1574fact a valid formalization of the Grace Period Guarantee. We won't
1575attempt to go through the detailed argument, but the following
1576analysis gives a taste of what is involved. Suppose we have a
1577violation of the first part of the Guarantee: A critical section
1578starts before a grace period, and some store propagates to the
1579critical section's CPU before the end of the critical section but
1580doesn't propagate to some other CPU until after the end of the grace
1581period.
1582
1583Putting symbols to these ideas, let L and U be the rcu_read_lock() and
1584rcu_read_unlock() fence events delimiting the critical section in
1585question, and let S be the synchronize_rcu() fence event for the grace
1586period. Saying that the critical section starts before S means there
1587are events E and F where E is po-after L (which marks the start of the
1588critical section), E is "before" F in the sense of the link relation,
1589and F is po-before the grace period S:
1590
1591 L ->po E ->link F ->po S.
1592
1593Let W be the store mentioned above, let Z come before the end of the
1594critical section and witness that W propagates to the critical
1595section's CPU by reading from W, and let Y on some arbitrary CPU be a
1596witness that W has not propagated to that CPU, where Y happens after
1597some event X which is po-after S. Symbolically, this amounts to:
1598
1599 S ->po X ->hb* Y ->fr W ->rf Z ->po U.
1600
1601The fr link from Y to W indicates that W has not propagated to Y's CPU
1602at the time that Y executes. From this, it can be shown (see the
1603discussion of the link relation earlier) that X and Z are connected by
1604link, yielding:
1605
1606 S ->po X ->link Z ->po U.
1607
1608These formulas say that S is po-between F and X, hence F ->gp-link Z
1609via X. They also say that Z comes before the end of the critical
1610section and E comes after its start, hence Z ->rscs-link F via E. But
1611now we have a forbidden cycle: F ->gp-link Z ->rscs-link F. Thus the
1612"rcu" axiom rules out this violation of the Grace Period Guarantee.
1613
1614For something a little more down-to-earth, let's see how the axiom
1615works out in practice. Consider the RCU code example from above, this
1616time with statement labels added to the memory access instructions:
1617
1618 int x, y;
1619
1620 P0()
1621 {
1622 rcu_read_lock();
1623 W: WRITE_ONCE(x, 1);
1624 X: WRITE_ONCE(y, 1);
1625 rcu_read_unlock();
1626 }
1627
1628 P1()
1629 {
1630 int r1, r2;
1631
1632 Y: r1 = READ_ONCE(x);
1633 synchronize_rcu();
1634 Z: r2 = READ_ONCE(y);
1635 }
1636
1637
1638If r2 = 0 at the end then P0's store at X overwrites the value
1639that P1's load at Z reads from, so we have Z ->fre X and thus
1640Z ->link X. In addition, there is a synchronize_rcu() between Y and
1641Z, so therefore we have Y ->gp-link X.
1642
1643If r1 = 1 at the end then P1's load at Y reads from P0's store at W,
1644so we have W ->link Y. In addition, W and X are in the same critical
1645section, so therefore we have X ->rscs-link Y.
1646
1647This gives us a cycle, Y ->gp-link X ->rscs-link Y, with one gp-link
1648and one rscs-link, violating the "rcu" axiom. Hence the outcome is
1649not allowed by the LKMM, as we would expect.
1650
1651For contrast, let's see what can happen in a more complicated example:
1652
1653 int x, y, z;
1654
1655 P0()
1656 {
1657 int r0;
1658
1659 rcu_read_lock();
1660 W: r0 = READ_ONCE(x);
1661 X: WRITE_ONCE(y, 1);
1662 rcu_read_unlock();
1663 }
1664
1665 P1()
1666 {
1667 int r1;
1668
1669 Y: r1 = READ_ONCE(y);
1670 synchronize_rcu();
1671 Z: WRITE_ONCE(z, 1);
1672 }
1673
1674 P2()
1675 {
1676 int r2;
1677
1678 rcu_read_lock();
1679 U: r2 = READ_ONCE(z);
1680 V: WRITE_ONCE(x, 1);
1681 rcu_read_unlock();
1682 }
1683
1684If r0 = r1 = r2 = 1 at the end, then similar reasoning to before shows
1685that W ->rscs-link Y via X, Y ->gp-link U via Z, and U ->rscs-link W
1686via V. And just as before, this gives a cycle:
1687
1688 W ->rscs-link Y ->gp-link U ->rscs-link W.
1689
1690However, this cycle has fewer gp-link instances than rscs-link
1691instances, and consequently the outcome is not forbidden by the LKMM.
1692The following instruction timing diagram shows how it might actually
1693occur:
1694
1695P0 P1 P2
1696-------------------- -------------------- --------------------
1697rcu_read_lock()
1698X: WRITE_ONCE(y, 1)
1699 Y: r1 = READ_ONCE(y)
1700 synchronize_rcu() starts
1701 . rcu_read_lock()
1702 . V: WRITE_ONCE(x, 1)
1703W: r0 = READ_ONCE(x) .
1704rcu_read_unlock() .
1705 synchronize_rcu() ends
1706 Z: WRITE_ONCE(z, 1)
1707 U: r2 = READ_ONCE(z)
1708 rcu_read_unlock()
1709
1710This requires P0 and P2 to execute their loads and stores out of
1711program order, but of course they are allowed to do so. And as you
1712can see, the Grace Period Guarantee is not violated: The critical
1713section in P0 both starts before P1's grace period does and ends
1714before it does, and the critical section in P2 both starts after P1's
1715grace period does and ends after it does.
1716
1717
1718ODDS AND ENDS
1719-------------
1720
1721This section covers material that didn't quite fit anywhere in the
1722earlier sections.
1723
1724The descriptions in this document don't always match the formal
1725version of the LKMM exactly. For example, the actual formal
1726definition of the prop relation makes the initial coe or fre part
1727optional, and it doesn't require the events linked by the relation to
1728be on the same CPU. These differences are very unimportant; indeed,
1729instances where the coe/fre part of prop is missing are of no interest
1730because all the other parts (fences and rfe) are already included in
1731hb anyway, and where the formal model adds prop into hb, it includes
1732an explicit requirement that the events being linked are on the same
1733CPU.
1734
1735Another minor difference has to do with events that are both memory
1736accesses and fences, such as those corresponding to smp_load_acquire()
1737calls. In the formal model, these events aren't actually both reads
1738and fences; rather, they are read events with an annotation marking
1739them as acquires. (Or write events annotated as releases, in the case
1740smp_store_release().) The final effect is the same.
1741
1742Although we didn't mention it above, the instruction execution
1743ordering provided by the smp_rmb() fence doesn't apply to read events
1744that are part of a non-value-returning atomic update. For instance,
1745given:
1746
1747 atomic_inc(&x);
1748 smp_rmb();
1749 r1 = READ_ONCE(y);
1750
1751it is not guaranteed that the load from y will execute after the
1752update to x. This is because the ARMv8 architecture allows
1753non-value-returning atomic operations effectively to be executed off
1754the CPU. Basically, the CPU tells the memory subsystem to increment
1755x, and then the increment is carried out by the memory hardware with
1756no further involvement from the CPU. Since the CPU doesn't ever read
1757the value of x, there is nothing for the smp_rmb() fence to act on.
1758
1759The LKMM defines a few extra synchronization operations in terms of
1760things we have already covered. In particular, rcu_dereference() is
1761treated as READ_ONCE() and rcu_assign_pointer() is treated as
1762smp_store_release() -- which is basically how the Linux kernel treats
1763them.
1764
1765There are a few oddball fences which need special treatment:
1766smp_mb__before_atomic(), smp_mb__after_atomic(), and
1767smp_mb__after_spinlock(). The LKMM uses fence events with special
1768annotations for them; they act as strong fences just like smp_mb()
1769except for the sets of events that they order. Instead of ordering
1770all po-earlier events against all po-later events, as smp_mb() does,
1771they behave as follows:
1772
1773 smp_mb__before_atomic() orders all po-earlier events against
1774 po-later atomic updates and the events following them;
1775
1776 smp_mb__after_atomic() orders po-earlier atomic updates and
1777 the events preceding them against all po-later events;
1778
1779 smp_mb_after_spinlock() orders po-earlier lock acquisition
1780 events and the events preceding them against all po-later
1781 events.
1782
1783The LKMM includes locking. In fact, there is special code for locking
1784in the formal model, added in order to make tools run faster.
1785However, this special code is intended to be exactly equivalent to
1786concepts we have already covered. A spinlock_t variable is treated
1787the same as an int, and spin_lock(&s) is treated the same as:
1788
1789 while (cmpxchg_acquire(&s, 0, 1) != 0)
1790 cpu_relax();
1791
1792which waits until s is equal to 0 and then atomically sets it to 1,
1793and where the read part of the atomic update is also an acquire fence.
1794An alternate way to express the same thing would be:
1795
1796 r = xchg_acquire(&s, 1);
1797
1798along with a requirement that at the end, r = 0. spin_unlock(&s) is
1799treated the same as:
1800
1801 smp_store_release(&s, 0);
1802
1803Interestingly, RCU and locking each introduce the possibility of
1804deadlock. When faced with code sequences such as:
1805
1806 spin_lock(&s);
1807 spin_lock(&s);
1808 spin_unlock(&s);
1809 spin_unlock(&s);
1810
1811or:
1812
1813 rcu_read_lock();
1814 synchronize_rcu();
1815 rcu_read_unlock();
1816
1817what does the LKMM have to say? Answer: It says there are no allowed
1818executions at all, which makes sense. But this can also lead to
1819misleading results, because if a piece of code has multiple possible
1820executions, some of which deadlock, the model will report only on the
1821non-deadlocking executions. For example:
1822
1823 int x, y;
1824
1825 P0()
1826 {
1827 int r0;
1828
1829 WRITE_ONCE(x, 1);
1830 r0 = READ_ONCE(y);
1831 }
1832
1833 P1()
1834 {
1835 rcu_read_lock();
1836 if (READ_ONCE(x) > 0) {
1837 WRITE_ONCE(y, 36);
1838 synchronize_rcu();
1839 }
1840 rcu_read_unlock();
1841 }
1842
1843Is it possible to end up with r0 = 36 at the end? The LKMM will tell
1844you it is not, but the model won't mention that this is because P1
1845will self-deadlock in the executions where it stores 36 in y.
diff --git a/tools/memory-model/Documentation/recipes.txt b/tools/memory-model/Documentation/recipes.txt
new file mode 100644
index 000000000000..ee4309a87fc4
--- /dev/null
+++ b/tools/memory-model/Documentation/recipes.txt
@@ -0,0 +1,570 @@
1This document provides "recipes", that is, litmus tests for commonly
2occurring situations, as well as a few that illustrate subtly broken but
3attractive nuisances. Many of these recipes include example code from
4v4.13 of the Linux kernel.
5
6The first section covers simple special cases, the second section
7takes off the training wheels to cover more involved examples,
8and the third section provides a few rules of thumb.
9
10
11Simple special cases
12====================
13
14This section presents two simple special cases, the first being where
15there is only one CPU or only one memory location is accessed, and the
16second being use of that old concurrency workhorse, locking.
17
18
19Single CPU or single memory location
20------------------------------------
21
22If there is only one CPU on the one hand or only one variable
23on the other, the code will execute in order. There are (as
24usual) some things to be careful of:
25
261. Some aspects of the C language are unordered. For example,
27 in the expression "f(x) + g(y)", the order in which f and g are
28 called is not defined; the object code is allowed to use either
29 order or even to interleave the computations.
30
312. Compilers are permitted to use the "as-if" rule. That is, a
32 compiler can emit whatever code it likes for normal accesses,
33 as long as the results of a single-threaded execution appear
34 just as if the compiler had followed all the relevant rules.
35 To see this, compile with a high level of optimization and run
36 the debugger on the resulting binary.
37
383. If there is only one variable but multiple CPUs, that variable
39 must be properly aligned and all accesses to that variable must
40 be full sized. Variables that straddle cachelines or pages void
41 your full-ordering warranty, as do undersized accesses that load
42 from or store to only part of the variable.
43
444. If there are multiple CPUs, accesses to shared variables should
45 use READ_ONCE() and WRITE_ONCE() or stronger to prevent load/store
46 tearing, load/store fusing, and invented loads and stores.
47 There are exceptions to this rule, including:
48
49 i. When there is no possibility of a given shared variable
50 being updated by some other CPU, for example, while
51 holding the update-side lock, reads from that variable
52 need not use READ_ONCE().
53
54 ii. When there is no possibility of a given shared variable
55 being either read or updated by other CPUs, for example,
56 when running during early boot, reads from that variable
57 need not use READ_ONCE() and writes to that variable
58 need not use WRITE_ONCE().
59
60
61Locking
62-------
63
64Locking is well-known and straightforward, at least if you don't think
65about it too hard. And the basic rule is indeed quite simple: Any CPU that
66has acquired a given lock sees any changes previously seen or made by any
67CPU before it released that same lock. Note that this statement is a bit
68stronger than "Any CPU holding a given lock sees all changes made by any
69CPU during the time that CPU was holding this same lock". For example,
70consider the following pair of code fragments:
71
72 /* See MP+polocks.litmus. */
73 void CPU0(void)
74 {
75 WRITE_ONCE(x, 1);
76 spin_lock(&mylock);
77 WRITE_ONCE(y, 1);
78 spin_unlock(&mylock);
79 }
80
81 void CPU1(void)
82 {
83 spin_lock(&mylock);
84 r0 = READ_ONCE(y);
85 spin_unlock(&mylock);
86 r1 = READ_ONCE(x);
87 }
88
89The basic rule guarantees that if CPU0() acquires mylock before CPU1(),
90then both r0 and r1 must be set to the value 1. This also has the
91consequence that if the final value of r0 is equal to 1, then the final
92value of r1 must also be equal to 1. In contrast, the weaker rule would
93say nothing about the final value of r1.
94
95The converse to the basic rule also holds, as illustrated by the
96following litmus test:
97
98 /* See MP+porevlocks.litmus. */
99 void CPU0(void)
100 {
101 r0 = READ_ONCE(y);
102 spin_lock(&mylock);
103 r1 = READ_ONCE(x);
104 spin_unlock(&mylock);
105 }
106
107 void CPU1(void)
108 {
109 spin_lock(&mylock);
110 WRITE_ONCE(x, 1);
111 spin_unlock(&mylock);
112 WRITE_ONCE(y, 1);
113 }
114
115This converse to the basic rule guarantees that if CPU0() acquires
116mylock before CPU1(), then both r0 and r1 must be set to the value 0.
117This also has the consequence that if the final value of r1 is equal
118to 0, then the final value of r0 must also be equal to 0. In contrast,
119the weaker rule would say nothing about the final value of r0.
120
121These examples show only a single pair of CPUs, but the effects of the
122locking basic rule extend across multiple acquisitions of a given lock
123across multiple CPUs.
124
125However, it is not necessarily the case that accesses ordered by
126locking will be seen as ordered by CPUs not holding that lock.
127Consider this example:
128
129 /* See Z6.0+pooncelock+pooncelock+pombonce.litmus. */
130 void CPU0(void)
131 {
132 spin_lock(&mylock);
133 WRITE_ONCE(x, 1);
134 WRITE_ONCE(y, 1);
135 spin_unlock(&mylock);
136 }
137
138 void CPU1(void)
139 {
140 spin_lock(&mylock);
141 r0 = READ_ONCE(y);
142 WRITE_ONCE(z, 1);
143 spin_unlock(&mylock);
144 }
145
146 void CPU2(void)
147 {
148 WRITE_ONCE(z, 2);
149 smp_mb();
150 r1 = READ_ONCE(x);
151 }
152
153Counter-intuitive though it might be, it is quite possible to have
154the final value of r0 be 1, the final value of z be 2, and the final
155value of r1 be 0. The reason for this surprising outcome is that
156CPU2() never acquired the lock, and thus did not benefit from the
157lock's ordering properties.
158
159Ordering can be extended to CPUs not holding the lock by careful use
160of smp_mb__after_spinlock():
161
162 /* See Z6.0+pooncelock+poonceLock+pombonce.litmus. */
163 void CPU0(void)
164 {
165 spin_lock(&mylock);
166 WRITE_ONCE(x, 1);
167 WRITE_ONCE(y, 1);
168 spin_unlock(&mylock);
169 }
170
171 void CPU1(void)
172 {
173 spin_lock(&mylock);
174 smp_mb__after_spinlock();
175 r0 = READ_ONCE(y);
176 WRITE_ONCE(z, 1);
177 spin_unlock(&mylock);
178 }
179
180 void CPU2(void)
181 {
182 WRITE_ONCE(z, 2);
183 smp_mb();
184 r1 = READ_ONCE(x);
185 }
186
187This addition of smp_mb__after_spinlock() strengthens the lock acquisition
188sufficiently to rule out the counter-intuitive outcome.
189
190
191Taking off the training wheels
192==============================
193
194This section looks at more complex examples, including message passing,
195load buffering, release-acquire chains, store buffering.
196Many classes of litmus tests have abbreviated names, which may be found
197here: https://www.cl.cam.ac.uk/~pes20/ppc-supplemental/test6.pdf
198
199
200Message passing (MP)
201--------------------
202
203The MP pattern has one CPU execute a pair of stores to a pair of variables
204and another CPU execute a pair of loads from this same pair of variables,
205but in the opposite order. The goal is to avoid the counter-intuitive
206outcome in which the first load sees the value written by the second store
207but the second load does not see the value written by the first store.
208In the absence of any ordering, this goal may not be met, as can be seen
209in the MP+poonceonces.litmus litmus test. This section therefore looks at
210a number of ways of meeting this goal.
211
212
213Release and acquire
214~~~~~~~~~~~~~~~~~~~
215
216Use of smp_store_release() and smp_load_acquire() is one way to force
217the desired MP ordering. The general approach is shown below:
218
219 /* See MP+pooncerelease+poacquireonce.litmus. */
220 void CPU0(void)
221 {
222 WRITE_ONCE(x, 1);
223 smp_store_release(&y, 1);
224 }
225
226 void CPU1(void)
227 {
228 r0 = smp_load_acquire(&y);
229 r1 = READ_ONCE(x);
230 }
231
232The smp_store_release() macro orders any prior accesses against the
233store, while the smp_load_acquire macro orders the load against any
234subsequent accesses. Therefore, if the final value of r0 is the value 1,
235the final value of r1 must also be the value 1.
236
237The init_stack_slab() function in lib/stackdepot.c uses release-acquire
238in this way to safely initialize of a slab of the stack. Working out
239the mutual-exclusion design is left as an exercise for the reader.
240
241
242Assign and dereference
243~~~~~~~~~~~~~~~~~~~~~~
244
245Use of rcu_assign_pointer() and rcu_dereference() is quite similar to the
246use of smp_store_release() and smp_load_acquire(), except that both
247rcu_assign_pointer() and rcu_dereference() operate on RCU-protected
248pointers. The general approach is shown below:
249
250 /* See MP+onceassign+derefonce.litmus. */
251 int z;
252 int *y = &z;
253 int x;
254
255 void CPU0(void)
256 {
257 WRITE_ONCE(x, 1);
258 rcu_assign_pointer(y, &x);
259 }
260
261 void CPU1(void)
262 {
263 rcu_read_lock();
264 r0 = rcu_dereference(y);
265 r1 = READ_ONCE(*r0);
266 rcu_read_unlock();
267 }
268
269In this example, if the final value of r0 is &x then the final value of
270r1 must be 1.
271
272The rcu_assign_pointer() macro has the same ordering properties as does
273smp_store_release(), but the rcu_dereference() macro orders the load only
274against later accesses that depend on the value loaded. A dependency
275is present if the value loaded determines the address of a later access
276(address dependency, as shown above), the value written by a later store
277(data dependency), or whether or not a later store is executed in the
278first place (control dependency). Note that the term "data dependency"
279is sometimes casually used to cover both address and data dependencies.
280
281In lib/prime_numbers.c, the expand_to_next_prime() function invokes
282rcu_assign_pointer(), and the next_prime_number() function invokes
283rcu_dereference(). This combination mediates access to a bit vector
284that is expanded as additional primes are needed.
285
286
287Write and read memory barriers
288~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
289
290It is usually better to use smp_store_release() instead of smp_wmb()
291and to use smp_load_acquire() instead of smp_rmb(). However, the older
292smp_wmb() and smp_rmb() APIs are still heavily used, so it is important
293to understand their use cases. The general approach is shown below:
294
295 /* See MP+wmbonceonce+rmbonceonce.litmus. */
296 void CPU0(void)
297 {
298 WRITE_ONCE(x, 1);
299 smp_wmb();
300 WRITE_ONCE(y, 1);
301 }
302
303 void CPU1(void)
304 {
305 r0 = READ_ONCE(y);
306 smp_rmb();
307 r1 = READ_ONCE(x);
308 }
309
310The smp_wmb() macro orders prior stores against later stores, and the
311smp_rmb() macro orders prior loads against later loads. Therefore, if
312the final value of r0 is 1, the final value of r1 must also be 1.
313
314The the xlog_state_switch_iclogs() function in fs/xfs/xfs_log.c contains
315the following write-side code fragment:
316
317 log->l_curr_block -= log->l_logBBsize;
318 ASSERT(log->l_curr_block >= 0);
319 smp_wmb();
320 log->l_curr_cycle++;
321
322And the xlog_valid_lsn() function in fs/xfs/xfs_log_priv.h contains
323the corresponding read-side code fragment:
324
325 cur_cycle = ACCESS_ONCE(log->l_curr_cycle);
326 smp_rmb();
327 cur_block = ACCESS_ONCE(log->l_curr_block);
328
329Alternatively, consider the following comment in function
330perf_output_put_handle() in kernel/events/ring_buffer.c:
331
332 * kernel user
333 *
334 * if (LOAD ->data_tail) { LOAD ->data_head
335 * (A) smp_rmb() (C)
336 * STORE $data LOAD $data
337 * smp_wmb() (B) smp_mb() (D)
338 * STORE ->data_head STORE ->data_tail
339 * }
340
341The B/C pairing is an example of the MP pattern using smp_wmb() on the
342write side and smp_rmb() on the read side.
343
344Of course, given that smp_mb() is strictly stronger than either smp_wmb()
345or smp_rmb(), any code fragment that would work with smp_rmb() and
346smp_wmb() would also work with smp_mb() replacing either or both of the
347weaker barriers.
348
349
350Load buffering (LB)
351-------------------
352
353The LB pattern has one CPU load from one variable and then store to a
354second, while another CPU loads from the second variable and then stores
355to the first. The goal is to avoid the counter-intuitive situation where
356each load reads the value written by the other CPU's store. In the
357absence of any ordering it is quite possible that this may happen, as
358can be seen in the LB+poonceonces.litmus litmus test.
359
360One way of avoiding the counter-intuitive outcome is through the use of a
361control dependency paired with a full memory barrier:
362
363 /* See LB+ctrlonceonce+mbonceonce.litmus. */
364 void CPU0(void)
365 {
366 r0 = READ_ONCE(x);
367 if (r0)
368 WRITE_ONCE(y, 1);
369 }
370
371 void CPU1(void)
372 {
373 r1 = READ_ONCE(y);
374 smp_mb();
375 WRITE_ONCE(x, 1);
376 }
377
378This pairing of a control dependency in CPU0() with a full memory
379barrier in CPU1() prevents r0 and r1 from both ending up equal to 1.
380
381The A/D pairing from the ring-buffer use case shown earlier also
382illustrates LB. Here is a repeat of the comment in
383perf_output_put_handle() in kernel/events/ring_buffer.c, showing a
384control dependency on the kernel side and a full memory barrier on
385the user side:
386
387 * kernel user
388 *
389 * if (LOAD ->data_tail) { LOAD ->data_head
390 * (A) smp_rmb() (C)
391 * STORE $data LOAD $data
392 * smp_wmb() (B) smp_mb() (D)
393 * STORE ->data_head STORE ->data_tail
394 * }
395 *
396 * Where A pairs with D, and B pairs with C.
397
398The kernel's control dependency between the load from ->data_tail
399and the store to data combined with the user's full memory barrier
400between the load from data and the store to ->data_tail prevents
401the counter-intuitive outcome where the kernel overwrites the data
402before the user gets done loading it.
403
404
405Release-acquire chains
406----------------------
407
408Release-acquire chains are a low-overhead, flexible, and easy-to-use
409method of maintaining order. However, they do have some limitations that
410need to be fully understood. Here is an example that maintains order:
411
412 /* See ISA2+pooncerelease+poacquirerelease+poacquireonce.litmus. */
413 void CPU0(void)
414 {
415 WRITE_ONCE(x, 1);
416 smp_store_release(&y, 1);
417 }
418
419 void CPU1(void)
420 {
421 r0 = smp_load_acquire(y);
422 smp_store_release(&z, 1);
423 }
424
425 void CPU2(void)
426 {
427 r1 = smp_load_acquire(z);
428 r2 = READ_ONCE(x);
429 }
430
431In this case, if r0 and r1 both have final values of 1, then r2 must
432also have a final value of 1.
433
434The ordering in this example is stronger than it needs to be. For
435example, ordering would still be preserved if CPU1()'s smp_load_acquire()
436invocation was replaced with READ_ONCE().
437
438It is tempting to assume that CPU0()'s store to x is globally ordered
439before CPU1()'s store to z, but this is not the case:
440
441 /* See Z6.0+pooncerelease+poacquirerelease+mbonceonce.litmus. */
442 void CPU0(void)
443 {
444 WRITE_ONCE(x, 1);
445 smp_store_release(&y, 1);
446 }
447
448 void CPU1(void)
449 {
450 r0 = smp_load_acquire(y);
451 smp_store_release(&z, 1);
452 }
453
454 void CPU2(void)
455 {
456 WRITE_ONCE(z, 2);
457 smp_mb();
458 r1 = READ_ONCE(x);
459 }
460
461One might hope that if the final value of r0 is 1 and the final value
462of z is 2, then the final value of r1 must also be 1, but it really is
463possible for r1 to have the final value of 0. The reason, of course,
464is that in this version, CPU2() is not part of the release-acquire chain.
465This situation is accounted for in the rules of thumb below.
466
467Despite this limitation, release-acquire chains are low-overhead as
468well as simple and powerful, at least as memory-ordering mechanisms go.
469
470
471Store buffering
472---------------
473
474Store buffering can be thought of as upside-down load buffering, so
475that one CPU first stores to one variable and then loads from a second,
476while another CPU stores to the second variable and then loads from the
477first. Preserving order requires nothing less than full barriers:
478
479 /* See SB+mbonceonces.litmus. */
480 void CPU0(void)
481 {
482 WRITE_ONCE(x, 1);
483 smp_mb();
484 r0 = READ_ONCE(y);
485 }
486
487 void CPU1(void)
488 {
489 WRITE_ONCE(y, 1);
490 smp_mb();
491 r1 = READ_ONCE(x);
492 }
493
494Omitting either smp_mb() will allow both r0 and r1 to have final
495values of 0, but providing both full barriers as shown above prevents
496this counter-intuitive outcome.
497
498This pattern most famously appears as part of Dekker's locking
499algorithm, but it has a much more practical use within the Linux kernel
500of ordering wakeups. The following comment taken from waitqueue_active()
501in include/linux/wait.h shows the canonical pattern:
502
503 * CPU0 - waker CPU1 - waiter
504 *
505 * for (;;) {
506 * @cond = true; prepare_to_wait(&wq_head, &wait, state);
507 * smp_mb(); // smp_mb() from set_current_state()
508 * if (waitqueue_active(wq_head)) if (@cond)
509 * wake_up(wq_head); break;
510 * schedule();
511 * }
512 * finish_wait(&wq_head, &wait);
513
514On CPU0, the store is to @cond and the load is in waitqueue_active().
515On CPU1, prepare_to_wait() contains both a store to wq_head and a call
516to set_current_state(), which contains an smp_mb() barrier; the load is
517"if (@cond)". The full barriers prevent the undesirable outcome where
518CPU1 puts the waiting task to sleep and CPU0 fails to wake it up.
519
520Note that use of locking can greatly simplify this pattern.
521
522
523Rules of thumb
524==============
525
526There might seem to be no pattern governing what ordering primitives are
527needed in which situations, but this is not the case. There is a pattern
528based on the relation between the accesses linking successive CPUs in a
529given litmus test. There are three types of linkage:
530
5311. Write-to-read, where the next CPU reads the value that the
532 previous CPU wrote. The LB litmus-test patterns contain only
533 this type of relation. In formal memory-modeling texts, this
534 relation is called "reads-from" and is usually abbreviated "rf".
535
5362. Read-to-write, where the next CPU overwrites the value that the
537 previous CPU read. The SB litmus test contains only this type
538 of relation. In formal memory-modeling texts, this relation is
539 often called "from-reads" and is sometimes abbreviated "fr".
540
5413. Write-to-write, where the next CPU overwrites the value written
542 by the previous CPU. The Z6.0 litmus test pattern contains a
543 write-to-write relation between the last access of CPU1() and
544 the first access of CPU2(). In formal memory-modeling texts,
545 this relation is often called "coherence order" and is sometimes
546 abbreviated "co". In the C++ standard, it is instead called
547 "modification order" and often abbreviated "mo".
548
549The strength of memory ordering required for a given litmus test to
550avoid a counter-intuitive outcome depends on the types of relations
551linking the memory accesses for the outcome in question:
552
553o If all links are write-to-read links, then the weakest
554 possible ordering within each CPU suffices. For example, in
555 the LB litmus test, a control dependency was enough to do the
556 job.
557
558o If all but one of the links are write-to-read links, then a
559 release-acquire chain suffices. Both the MP and the ISA2
560 litmus tests illustrate this case.
561
562o If more than one of the links are something other than
563 write-to-read links, then a full memory barrier is required
564 between each successive pair of non-write-to-read links. This
565 case is illustrated by the Z6.0 litmus tests, both in the
566 locking and in the release-acquire sections.
567
568However, if you find yourself having to stretch these rules of thumb
569to fit your situation, you should consider creating a litmus test and
570running it on the model.
diff --git a/tools/memory-model/Documentation/references.txt b/tools/memory-model/Documentation/references.txt
new file mode 100644
index 000000000000..ba2e34c2ec3f
--- /dev/null
+++ b/tools/memory-model/Documentation/references.txt
@@ -0,0 +1,107 @@
1This document provides background reading for memory models and related
2tools. These documents are aimed at kernel hackers who are interested
3in memory models.
4
5
6Hardware manuals and models
7===========================
8
9o SPARC International Inc. (Ed.). 1994. "The SPARC Architecture
10 Reference Manual Version 9". SPARC International Inc.
11
12o Compaq Computer Corporation (Ed.). 2002. "Alpha Architecture
13 Reference Manual". Compaq Computer Corporation.
14
15o Intel Corporation (Ed.). 2002. "A Formal Specification of Intel
16 Itanium Processor Family Memory Ordering". Intel Corporation.
17
18o Intel Corporation (Ed.). 2002. "Intel 64 and IA-32 Architectures
19 Software Developer’s Manual". Intel Corporation.
20
21o Peter Sewell, Susmit Sarkar, Scott Owens, Francesco Zappa Nardelli,
22 and Magnus O. Myreen. 2010. "x86-TSO: A Rigorous and Usable
23 Programmer's Model for x86 Multiprocessors". Commun. ACM 53, 7
24 (July, 2010), 89-97. http://doi.acm.org/10.1145/1785414.1785443
25
26o IBM Corporation (Ed.). 2009. "Power ISA Version 2.06". IBM
27 Corporation.
28
29o ARM Ltd. (Ed.). 2009. "ARM Barrier Litmus Tests and Cookbook".
30 ARM Ltd.
31
32o Susmit Sarkar, Peter Sewell, Jade Alglave, Luc Maranget, and
33 Derek Williams. 2011. "Understanding POWER Multiprocessors". In
34 Proceedings of the 32Nd ACM SIGPLAN Conference on Programming
35 Language Design and Implementation (PLDI ’11). ACM, New York,
36 NY, USA, 175–186.
37
38o Susmit Sarkar, Kayvan Memarian, Scott Owens, Mark Batty,
39 Peter Sewell, Luc Maranget, Jade Alglave, and Derek Williams.
40 2012. "Synchronising C/C++ and POWER". In Proceedings of the 33rd
41 ACM SIGPLAN Conference on Programming Language Design and
42 Implementation (PLDI '12). ACM, New York, NY, USA, 311-322.
43
44o ARM Ltd. (Ed.). 2014. "ARM Architecture Reference Manual (ARMv8,
45 for ARMv8-A architecture profile)". ARM Ltd.
46
47o Imagination Technologies, LTD. 2015. "MIPS(R) Architecture
48 For Programmers, Volume II-A: The MIPS64(R) Instruction,
49 Set Reference Manual". Imagination Technologies,
50 LTD. https://imgtec.com/?do-download=4302.
51
52o Shaked Flur, Kathryn E. Gray, Christopher Pulte, Susmit
53 Sarkar, Ali Sezgin, Luc Maranget, Will Deacon, and Peter
54 Sewell. 2016. "Modelling the ARMv8 Architecture, Operationally:
55 Concurrency and ISA". In Proceedings of the 43rd Annual ACM
56 SIGPLAN-SIGACT Symposium on Principles of Programming Languages
57 (POPL ’16). ACM, New York, NY, USA, 608–621.
58
59o Shaked Flur, Susmit Sarkar, Christopher Pulte, Kyndylan Nienhuis,
60 Luc Maranget, Kathryn E. Gray, Ali Sezgin, Mark Batty, and Peter
61 Sewell. 2017. "Mixed-size Concurrency: ARM, POWER, C/C++11,
62 and SC". In Proceedings of the 44th ACM SIGPLAN Symposium on
63 Principles of Programming Languages (POPL 2017). ACM, New York,
64 NY, USA, 429–442.
65
66
67Linux-kernel memory model
68=========================
69
70o Andrea Parri, Alan Stern, Luc Maranget, Paul E. McKenney,
71 and Jade Alglave. 2017. "A formal model of
72 Linux-kernel memory ordering - companion webpage".
73 http://moscova.inria.fr/∼maranget/cats7/linux/. (2017). [Online;
74 accessed 30-January-2017].
75
76o Jade Alglave, Luc Maranget, Paul E. McKenney, Andrea Parri, and
77 Alan Stern. 2017. "A formal kernel memory-ordering model (part 1)"
78 Linux Weekly News. https://lwn.net/Articles/718628/
79
80o Jade Alglave, Luc Maranget, Paul E. McKenney, Andrea Parri, and
81 Alan Stern. 2017. "A formal kernel memory-ordering model (part 2)"
82 Linux Weekly News. https://lwn.net/Articles/720550/
83
84
85Memory-model tooling
86====================
87
88o Daniel Jackson. 2002. "Alloy: A Lightweight Object Modelling
89 Notation". ACM Trans. Softw. Eng. Methodol. 11, 2 (April 2002),
90 256–290. http://doi.acm.org/10.1145/505145.505149
91
92o Jade Alglave, Luc Maranget, and Michael Tautschnig. 2014. "Herding
93 Cats: Modelling, Simulation, Testing, and Data Mining for Weak
94 Memory". ACM Trans. Program. Lang. Syst. 36, 2, Article 7 (July
95 2014), 7:1–7:74 pages.
96
97o Jade Alglave, Patrick Cousot, and Luc Maranget. 2016. "Syntax and
98 semantics of the weak consistency model specification language
99 cat". CoRR abs/1608.07531 (2016). http://arxiv.org/abs/1608.07531
100
101
102Memory-model comparisons
103========================
104
105o Paul E. McKenney, Ulrich Weigand, Andrea Parri, and Boqun
106 Feng. 2016. "Linux-Kernel Memory Model". (6 June 2016).
107 http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0124r2.html.
diff --git a/tools/memory-model/README b/tools/memory-model/README
new file mode 100644
index 000000000000..0b3a5f3c9ccd
--- /dev/null
+++ b/tools/memory-model/README
@@ -0,0 +1,206 @@
1 =====================================
2 LINUX KERNEL MEMORY CONSISTENCY MODEL
3 =====================================
4
5============
6INTRODUCTION
7============
8
9This directory contains the memory consistency model (memory model, for
10short) of the Linux kernel, written in the "cat" language and executable
11by the externally provided "herd7" simulator, which exhaustively explores
12the state space of small litmus tests.
13
14In addition, the "klitmus7" tool (also externally provided) may be used
15to convert a litmus test to a Linux kernel module, which in turn allows
16that litmus test to be exercised within the Linux kernel.
17
18
19============
20REQUIREMENTS
21============
22
23Version 7.48 of the "herd7" and "klitmus7" tools must be downloaded
24separately:
25
26 https://github.com/herd/herdtools7
27
28See "herdtools7/INSTALL.md" for installation instructions.
29
30
31==================
32BASIC USAGE: HERD7
33==================
34
35The memory model is used, in conjunction with "herd7", to exhaustively
36explore the state space of small litmus tests.
37
38For example, to run SB+mbonceonces.litmus against the memory model:
39
40 $ herd7 -conf linux-kernel.cfg litmus-tests/SB+mbonceonces.litmus
41
42Here is the corresponding output:
43
44 Test SB+mbonceonces Allowed
45 States 3
46 0:r0=0; 1:r0=1;
47 0:r0=1; 1:r0=0;
48 0:r0=1; 1:r0=1;
49 No
50 Witnesses
51 Positive: 0 Negative: 3
52 Condition exists (0:r0=0 /\ 1:r0=0)
53 Observation SB+mbonceonces Never 0 3
54 Time SB+mbonceonces 0.01
55 Hash=d66d99523e2cac6b06e66f4c995ebb48
56
57The "Positive: 0 Negative: 3" and the "Never 0 3" each indicate that
58this litmus test's "exists" clause can not be satisfied.
59
60See "herd7 -help" or "herdtools7/doc/" for more information.
61
62
63=====================
64BASIC USAGE: KLITMUS7
65=====================
66
67The "klitmus7" tool converts a litmus test into a Linux kernel module,
68which may then be loaded and run.
69
70For example, to run SB+mbonceonces.litmus against hardware:
71
72 $ mkdir mymodules
73 $ klitmus7 -o mymodules litmus-tests/SB+mbonceonces.litmus
74 $ cd mymodules ; make
75 $ sudo sh run.sh
76
77The corresponding output includes:
78
79 Test SB+mbonceonces Allowed
80 Histogram (3 states)
81 644580 :>0:r0=1; 1:r0=0;
82 644328 :>0:r0=0; 1:r0=1;
83 711092 :>0:r0=1; 1:r0=1;
84 No
85 Witnesses
86 Positive: 0, Negative: 2000000
87 Condition exists (0:r0=0 /\ 1:r0=0) is NOT validated
88 Hash=d66d99523e2cac6b06e66f4c995ebb48
89 Observation SB+mbonceonces Never 0 2000000
90 Time SB+mbonceonces 0.16
91
92The "Positive: 0 Negative: 2000000" and the "Never 0 2000000" indicate
93that during two million trials, the state specified in this litmus
94test's "exists" clause was not reached.
95
96And, as with "herd7", please see "klitmus7 -help" or "herdtools7/doc/"
97for more information.
98
99
100====================
101DESCRIPTION OF FILES
102====================
103
104Documentation/cheatsheet.txt
105 Quick-reference guide to the Linux-kernel memory model.
106
107Documentation/explanation.txt
108 Describes the memory model in detail.
109
110Documentation/recipes.txt
111 Lists common memory-ordering patterns.
112
113Documentation/references.txt
114 Provides background reading.
115
116linux-kernel.bell
117 Categorizes the relevant instructions, including memory
118 references, memory barriers, atomic read-modify-write operations,
119 lock acquisition/release, and RCU operations.
120
121 More formally, this file (1) lists the subtypes of the various
122 event types used by the memory model and (2) performs RCU
123 read-side critical section nesting analysis.
124
125linux-kernel.cat
126 Specifies what reorderings are forbidden by memory references,
127 memory barriers, atomic read-modify-write operations, and RCU.
128
129 More formally, this file specifies what executions are forbidden
130 by the memory model. Allowed executions are those which
131 satisfy the model's "coherence", "atomic", "happens-before",
132 "propagation", and "rcu" axioms, which are defined in the file.
133
134linux-kernel.cfg
135 Convenience file that gathers the common-case herd7 command-line
136 arguments.
137
138linux-kernel.def
139 Maps from C-like syntax to herd7's internal litmus-test
140 instruction-set architecture.
141
142litmus-tests
143 Directory containing a few representative litmus tests, which
144 are listed in litmus-tests/README. A great deal more litmus
145 tests are available at https://github.com/paulmckrcu/litmus.
146
147lock.cat
148 Provides a front-end analysis of lock acquisition and release,
149 for example, associating a lock acquisition with the preceding
150 and following releases and checking for self-deadlock.
151
152 More formally, this file defines a performance-enhanced scheme
153 for generation of the possible reads-from and coherence order
154 relations on the locking primitives.
155
156README
157 This file.
158
159
160===========
161LIMITATIONS
162===========
163
164The Linux-kernel memory model has the following limitations:
165
1661. Compiler optimizations are not modeled. Of course, the use
167 of READ_ONCE() and WRITE_ONCE() limits the compiler's ability
168 to optimize, but there is Linux-kernel code that uses bare C
169 memory accesses. Handling this code is on the to-do list.
170 For more information, see Documentation/explanation.txt (in
171 particular, the "THE PROGRAM ORDER RELATION: po AND po-loc"
172 and "A WARNING" sections).
173
1742. Multiple access sizes for a single variable are not supported,
175 and neither are misaligned or partially overlapping accesses.
176
1773. Exceptions and interrupts are not modeled. In some cases,
178 this limitation can be overcome by modeling the interrupt or
179 exception with an additional process.
180
1814. I/O such as MMIO or DMA is not supported.
182
1835. Self-modifying code (such as that found in the kernel's
184 alternatives mechanism, function tracer, Berkeley Packet Filter
185 JIT compiler, and module loader) is not supported.
186
1876. Complete modeling of all variants of atomic read-modify-write
188 operations, locking primitives, and RCU is not provided.
189 For example, call_rcu() and rcu_barrier() are not supported.
190 However, a substantial amount of support is provided for these
191 operations, as shown in the linux-kernel.def file.
192
193The "herd7" tool has some additional limitations of its own, apart from
194the memory model:
195
1961. Non-trivial data structures such as arrays or structures are
197 not supported. However, pointers are supported, allowing trivial
198 linked lists to be constructed.
199
2002. Dynamic memory allocation is not supported, although this can
201 be worked around in some cases by supplying multiple statically
202 allocated variables.
203
204Some of these limitations may be overcome in the future, but others are
205more likely to be addressed by incorporating the Linux-kernel memory model
206into other tools.
diff --git a/tools/memory-model/linux-kernel.bell b/tools/memory-model/linux-kernel.bell
new file mode 100644
index 000000000000..432c7cf71b23
--- /dev/null
+++ b/tools/memory-model/linux-kernel.bell
@@ -0,0 +1,52 @@
1// SPDX-License-Identifier: GPL-2.0+
2(*
3 * Copyright (C) 2015 Jade Alglave <j.alglave@ucl.ac.uk>,
4 * Copyright (C) 2016 Luc Maranget <luc.maranget@inria.fr> for Inria
5 * Copyright (C) 2017 Alan Stern <stern@rowland.harvard.edu>,
6 * Andrea Parri <parri.andrea@gmail.com>
7 *
8 * An earlier version of this file appears in the companion webpage for
9 * "Frightening small children and disconcerting grown-ups: Concurrency
10 * in the Linux kernel" by Alglave, Maranget, McKenney, Parri, and Stern,
11 * which is to appear in ASPLOS 2018.
12 *)
13
14"Linux-kernel memory consistency model"
15
16enum Accesses = 'once (*READ_ONCE,WRITE_ONCE,ACCESS_ONCE*) ||
17 'release (*smp_store_release*) ||
18 'acquire (*smp_load_acquire*) ||
19 'noreturn (* R of non-return RMW *)
20instructions R[{'once,'acquire,'noreturn}]
21instructions W[{'once,'release}]
22instructions RMW[{'once,'acquire,'release}]
23
24enum Barriers = 'wmb (*smp_wmb*) ||
25 'rmb (*smp_rmb*) ||
26 'mb (*smp_mb*) ||
27 'rcu-lock (*rcu_read_lock*) ||
28 'rcu-unlock (*rcu_read_unlock*) ||
29 'sync-rcu (*synchronize_rcu*) ||
30 'before-atomic (*smp_mb__before_atomic*) ||
31 'after-atomic (*smp_mb__after_atomic*) ||
32 'after-spinlock (*smp_mb__after_spinlock*)
33instructions F[Barriers]
34
35(* Compute matching pairs of nested Rcu-lock and Rcu-unlock *)
36let matched = let rec
37 unmatched-locks = Rcu-lock \ domain(matched)
38 and unmatched-unlocks = Rcu-unlock \ range(matched)
39 and unmatched = unmatched-locks | unmatched-unlocks
40 and unmatched-po = [unmatched] ; po ; [unmatched]
41 and unmatched-locks-to-unlocks =
42 [unmatched-locks] ; po ; [unmatched-unlocks]
43 and matched = matched | (unmatched-locks-to-unlocks \
44 (unmatched-po ; unmatched-po))
45 in matched
46
47(* Validate nesting *)
48flag ~empty Rcu-lock \ domain(matched) as unbalanced-rcu-locking
49flag ~empty Rcu-unlock \ range(matched) as unbalanced-rcu-locking
50
51(* Outermost level of nesting only *)
52let crit = matched \ (po^-1 ; matched ; po^-1)
diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
new file mode 100644
index 000000000000..df97db03b6c2
--- /dev/null
+++ b/tools/memory-model/linux-kernel.cat
@@ -0,0 +1,121 @@
1// SPDX-License-Identifier: GPL-2.0+
2(*
3 * Copyright (C) 2015 Jade Alglave <j.alglave@ucl.ac.uk>,
4 * Copyright (C) 2016 Luc Maranget <luc.maranget@inria.fr> for Inria
5 * Copyright (C) 2017 Alan Stern <stern@rowland.harvard.edu>,
6 * Andrea Parri <parri.andrea@gmail.com>
7 *
8 * An earlier version of this file appears in the companion webpage for
9 * "Frightening small children and disconcerting grown-ups: Concurrency
10 * in the Linux kernel" by Alglave, Maranget, McKenney, Parri, and Stern,
11 * which is to appear in ASPLOS 2018.
12 *)
13
14"Linux-kernel memory consistency model"
15
16(*
17 * File "lock.cat" handles locks and is experimental.
18 * It can be replaced by include "cos.cat" for tests that do not use locks.
19 *)
20
21include "lock.cat"
22
23(*******************)
24(* Basic relations *)
25(*******************)
26
27(* Fences *)
28let rmb = [R \ Noreturn] ; fencerel(Rmb) ; [R \ Noreturn]
29let wmb = [W] ; fencerel(Wmb) ; [W]
30let mb = ([M] ; fencerel(Mb) ; [M]) |
31 ([M] ; fencerel(Before-atomic) ; [RMW] ; po? ; [M]) |
32 ([M] ; po? ; [RMW] ; fencerel(After-atomic) ; [M]) |
33 ([M] ; po? ; [LKW] ; fencerel(After-spinlock) ; [M])
34let gp = po ; [Sync-rcu] ; po?
35
36let strong-fence = mb | gp
37
38(* Release Acquire *)
39let acq-po = [Acquire] ; po ; [M]
40let po-rel = [M] ; po ; [Release]
41let rfi-rel-acq = [Release] ; rfi ; [Acquire]
42
43(**********************************)
44(* Fundamental coherence ordering *)
45(**********************************)
46
47(* Sequential Consistency Per Variable *)
48let com = rf | co | fr
49acyclic po-loc | com as coherence
50
51(* Atomic Read-Modify-Write *)
52empty rmw & (fre ; coe) as atomic
53
54(**********************************)
55(* Instruction execution ordering *)
56(**********************************)
57
58(* Preserved Program Order *)
59let dep = addr | data
60let rwdep = (dep | ctrl) ; [W]
61let overwrite = co | fr
62let to-w = rwdep | (overwrite & int)
63let to-r = addr | (dep ; rfi) | rfi-rel-acq
64let fence = strong-fence | wmb | po-rel | rmb | acq-po
65let ppo = to-r | to-w | fence
66
67(* Propagation: Ordering from release operations and strong fences. *)
68let A-cumul(r) = rfe? ; r
69let cumul-fence = A-cumul(strong-fence | po-rel) | wmb
70let prop = (overwrite & ext)? ; cumul-fence* ; rfe?
71
72(*
73 * Happens Before: Ordering from the passage of time.
74 * No fences needed here for prop because relation confined to one process.
75 *)
76let hb = ppo | rfe | ((prop \ id) & int)
77acyclic hb as happens-before
78
79(****************************************)
80(* Write and fence propagation ordering *)
81(****************************************)
82
83(* Propagation: Each non-rf link needs a strong fence. *)
84let pb = prop ; strong-fence ; hb*
85acyclic pb as propagation
86
87(*******)
88(* RCU *)
89(*******)
90
91(*
92 * Effect of read-side critical section proceeds from the rcu_read_lock()
93 * onward on the one hand and from the rcu_read_unlock() backwards on the
94 * other hand.
95 *)
96let rscs = po ; crit^-1 ; po?
97
98(*
99 * The synchronize_rcu() strong fence is special in that it can order not
100 * one but two non-rf relations, but only in conjunction with an RCU
101 * read-side critical section.
102 *)
103let link = hb* ; pb* ; prop
104
105(* Chains that affect the RCU grace-period guarantee *)
106let gp-link = gp ; link
107let rscs-link = rscs ; link
108
109(*
110 * A cycle containing at least as many grace periods as RCU read-side
111 * critical sections is forbidden.
112 *)
113let rec rcu-path =
114 gp-link |
115 (gp-link ; rscs-link) |
116 (rscs-link ; gp-link) |
117 (rcu-path ; rcu-path) |
118 (gp-link ; rcu-path ; rscs-link) |
119 (rscs-link ; rcu-path ; gp-link)
120
121irreflexive rcu-path as rcu
diff --git a/tools/memory-model/linux-kernel.cfg b/tools/memory-model/linux-kernel.cfg
new file mode 100644
index 000000000000..3c8098e99f41
--- /dev/null
+++ b/tools/memory-model/linux-kernel.cfg
@@ -0,0 +1,21 @@
1macros linux-kernel.def
2bell linux-kernel.bell
3model linux-kernel.cat
4graph columns
5squished true
6showevents noregs
7movelabel true
8fontsize 8
9xscale 2.0
10yscale 1.5
11arrowsize 0.8
12showinitrf false
13showfinalrf false
14showinitwrites false
15splines spline
16pad 0.1
17edgeattr hb,color,indigo
18edgeattr co,color,blue
19edgeattr mb,color,darkgreen
20edgeattr wmb,color,darkgreen
21edgeattr rmb,color,darkgreen
diff --git a/tools/memory-model/linux-kernel.def b/tools/memory-model/linux-kernel.def
new file mode 100644
index 000000000000..397e4e67e8c8
--- /dev/null
+++ b/tools/memory-model/linux-kernel.def
@@ -0,0 +1,106 @@
1// SPDX-License-Identifier: GPL-2.0+
2//
3// An earlier version of this file appears in the companion webpage for
4// "Frightening small children and disconcerting grown-ups: Concurrency
5// in the Linux kernel" by Alglave, Maranget, McKenney, Parri, and Stern,
6// which is to appear in ASPLOS 2018.
7
8// ONCE
9READ_ONCE(X) __load{once}(X)
10WRITE_ONCE(X,V) { __store{once}(X,V); }
11
12// Release Acquire and friends
13smp_store_release(X,V) { __store{release}(*X,V); }
14smp_load_acquire(X) __load{acquire}(*X)
15rcu_assign_pointer(X,V) { __store{release}(X,V); }
16rcu_dereference(X) __load{once}(X)
17
18// Fences
19smp_mb() { __fence{mb} ; }
20smp_rmb() { __fence{rmb} ; }
21smp_wmb() { __fence{wmb} ; }
22smp_mb__before_atomic() { __fence{before-atomic} ; }
23smp_mb__after_atomic() { __fence{after-atomic} ; }
24smp_mb__after_spinlock() { __fence{after-spinlock} ; }
25
26// Exchange
27xchg(X,V) __xchg{mb}(X,V)
28xchg_relaxed(X,V) __xchg{once}(X,V)
29xchg_release(X,V) __xchg{release}(X,V)
30xchg_acquire(X,V) __xchg{acquire}(X,V)
31cmpxchg(X,V,W) __cmpxchg{mb}(X,V,W)
32cmpxchg_relaxed(X,V,W) __cmpxchg{once}(X,V,W)
33cmpxchg_acquire(X,V,W) __cmpxchg{acquire}(X,V,W)
34cmpxchg_release(X,V,W) __cmpxchg{release}(X,V,W)
35
36// Spinlocks
37spin_lock(X) { __lock(X) ; }
38spin_unlock(X) { __unlock(X) ; }
39spin_trylock(X) __trylock(X)
40
41// RCU
42rcu_read_lock() { __fence{rcu-lock}; }
43rcu_read_unlock() { __fence{rcu-unlock};}
44synchronize_rcu() { __fence{sync-rcu}; }
45synchronize_rcu_expedited() { __fence{sync-rcu}; }
46
47// Atomic
48atomic_read(X) READ_ONCE(*X)
49atomic_set(X,V) { WRITE_ONCE(*X,V) ; }
50atomic_read_acquire(X) smp_load_acquire(X)
51atomic_set_release(X,V) { smp_store_release(X,V); }
52
53atomic_add(V,X) { __atomic_op(X,+,V) ; }
54atomic_sub(V,X) { __atomic_op(X,-,V) ; }
55atomic_inc(X) { __atomic_op(X,+,1) ; }
56atomic_dec(X) { __atomic_op(X,-,1) ; }
57
58atomic_add_return(V,X) __atomic_op_return{mb}(X,+,V)
59atomic_add_return_relaxed(V,X) __atomic_op_return{once}(X,+,V)
60atomic_add_return_acquire(V,X) __atomic_op_return{acquire}(X,+,V)
61atomic_add_return_release(V,X) __atomic_op_return{release}(X,+,V)
62atomic_fetch_add(V,X) __atomic_fetch_op{mb}(X,+,V)
63atomic_fetch_add_relaxed(V,X) __atomic_fetch_op{once}(X,+,V)
64atomic_fetch_add_acquire(V,X) __atomic_fetch_op{acquire}(X,+,V)
65atomic_fetch_add_release(V,X) __atomic_fetch_op{release}(X,+,V)
66
67atomic_inc_return(X) __atomic_op_return{mb}(X,+,1)
68atomic_inc_return_relaxed(X) __atomic_op_return{once}(X,+,1)
69atomic_inc_return_acquire(X) __atomic_op_return{acquire}(X,+,1)
70atomic_inc_return_release(X) __atomic_op_return{release}(X,+,1)
71atomic_fetch_inc(X) __atomic_fetch_op{mb}(X,+,1)
72atomic_fetch_inc_relaxed(X) __atomic_fetch_op{once}(X,+,1)
73atomic_fetch_inc_acquire(X) __atomic_fetch_op{acquire}(X,+,1)
74atomic_fetch_inc_release(X) __atomic_fetch_op{release}(X,+,1)
75
76atomic_sub_return(V,X) __atomic_op_return{mb}(X,-,V)
77atomic_sub_return_relaxed(V,X) __atomic_op_return{once}(X,-,V)
78atomic_sub_return_acquire(V,X) __atomic_op_return{acquire}(X,-,V)
79atomic_sub_return_release(V,X) __atomic_op_return{release}(X,-,V)
80atomic_fetch_sub(V,X) __atomic_fetch_op{mb}(X,-,V)
81atomic_fetch_sub_relaxed(V,X) __atomic_fetch_op{once}(X,-,V)
82atomic_fetch_sub_acquire(V,X) __atomic_fetch_op{acquire}(X,-,V)
83atomic_fetch_sub_release(V,X) __atomic_fetch_op{release}(X,-,V)
84
85atomic_dec_return(X) __atomic_op_return{mb}(X,-,1)
86atomic_dec_return_relaxed(X) __atomic_op_return{once}(X,-,1)
87atomic_dec_return_acquire(X) __atomic_op_return{acquire}(X,-,1)
88atomic_dec_return_release(X) __atomic_op_return{release}(X,-,1)
89atomic_fetch_dec(X) __atomic_fetch_op{mb}(X,-,1)
90atomic_fetch_dec_relaxed(X) __atomic_fetch_op{once}(X,-,1)
91atomic_fetch_dec_acquire(X) __atomic_fetch_op{acquire}(X,-,1)
92atomic_fetch_dec_release(X) __atomic_fetch_op{release}(X,-,1)
93
94atomic_xchg(X,V) __xchg{mb}(X,V)
95atomic_xchg_relaxed(X,V) __xchg{once}(X,V)
96atomic_xchg_release(X,V) __xchg{release}(X,V)
97atomic_xchg_acquire(X,V) __xchg{acquire}(X,V)
98atomic_cmpxchg(X,V,W) __cmpxchg{mb}(X,V,W)
99atomic_cmpxchg_relaxed(X,V,W) __cmpxchg{once}(X,V,W)
100atomic_cmpxchg_acquire(X,V,W) __cmpxchg{acquire}(X,V,W)
101atomic_cmpxchg_release(X,V,W) __cmpxchg{release}(X,V,W)
102
103atomic_sub_and_test(V,X) __atomic_op_return{mb}(X,-,V) == 0
104atomic_dec_and_test(X) __atomic_op_return{mb}(X,-,1) == 0
105atomic_inc_and_test(X) __atomic_op_return{mb}(X,+,1) == 0
106atomic_add_negative(V,X) __atomic_op_return{mb}(X,+,V) < 0
diff --git a/tools/memory-model/litmus-tests/CoRR+poonceonce+Once.litmus b/tools/memory-model/litmus-tests/CoRR+poonceonce+Once.litmus
new file mode 100644
index 000000000000..967f9f2a6226
--- /dev/null
+++ b/tools/memory-model/litmus-tests/CoRR+poonceonce+Once.litmus
@@ -0,0 +1,26 @@
1C CoRR+poonceonce+Once
2
3(*
4 * Result: Never
5 *
6 * Test of read-read coherence, that is, whether or not two successive
7 * reads from the same variable are ordered.
8 *)
9
10{}
11
12P0(int *x)
13{
14 WRITE_ONCE(*x, 1);
15}
16
17P1(int *x)
18{
19 int r0;
20 int r1;
21
22 r0 = READ_ONCE(*x);
23 r1 = READ_ONCE(*x);
24}
25
26exists (1:r0=1 /\ 1:r1=0)
diff --git a/tools/memory-model/litmus-tests/CoRW+poonceonce+Once.litmus b/tools/memory-model/litmus-tests/CoRW+poonceonce+Once.litmus
new file mode 100644
index 000000000000..4635739f3974
--- /dev/null
+++ b/tools/memory-model/litmus-tests/CoRW+poonceonce+Once.litmus
@@ -0,0 +1,25 @@
1C CoRW+poonceonce+Once
2
3(*
4 * Result: Never
5 *
6 * Test of read-write coherence, that is, whether or not a read from
7 * a given variable and a later write to that same variable are ordered.
8 *)
9
10{}
11
12P0(int *x)
13{
14 int r0;
15
16 r0 = READ_ONCE(*x);
17 WRITE_ONCE(*x, 1);
18}
19
20P1(int *x)
21{
22 WRITE_ONCE(*x, 2);
23}
24
25exists (x=2 /\ 0:r0=2)
diff --git a/tools/memory-model/litmus-tests/CoWR+poonceonce+Once.litmus b/tools/memory-model/litmus-tests/CoWR+poonceonce+Once.litmus
new file mode 100644
index 000000000000..bb068c92d8da
--- /dev/null
+++ b/tools/memory-model/litmus-tests/CoWR+poonceonce+Once.litmus
@@ -0,0 +1,25 @@
1C CoWR+poonceonce+Once
2
3(*
4 * Result: Never
5 *
6 * Test of write-read coherence, that is, whether or not a write to a
7 * given variable and a later read from that same variable are ordered.
8 *)
9
10{}
11
12P0(int *x)
13{
14 int r0;
15
16 WRITE_ONCE(*x, 1);
17 r0 = READ_ONCE(*x);
18}
19
20P1(int *x)
21{
22 WRITE_ONCE(*x, 2);
23}
24
25exists (x=1 /\ 0:r0=2)
diff --git a/tools/memory-model/litmus-tests/CoWW+poonceonce.litmus b/tools/memory-model/litmus-tests/CoWW+poonceonce.litmus
new file mode 100644
index 000000000000..0d9f0a958799
--- /dev/null
+++ b/tools/memory-model/litmus-tests/CoWW+poonceonce.litmus
@@ -0,0 +1,18 @@
1C CoWW+poonceonce
2
3(*
4 * Result: Never
5 *
6 * Test of write-write coherence, that is, whether or not two successive
7 * writes to the same variable are ordered.
8 *)
9
10{}
11
12P0(int *x)
13{
14 WRITE_ONCE(*x, 1);
15 WRITE_ONCE(*x, 2);
16}
17
18exists (x=1)
diff --git a/tools/memory-model/litmus-tests/IRIW+mbonceonces+OnceOnce.litmus b/tools/memory-model/litmus-tests/IRIW+mbonceonces+OnceOnce.litmus
new file mode 100644
index 000000000000..50d5db9ea983
--- /dev/null
+++ b/tools/memory-model/litmus-tests/IRIW+mbonceonces+OnceOnce.litmus
@@ -0,0 +1,45 @@
1C IRIW+mbonceonces+OnceOnce
2
3(*
4 * Result: Never
5 *
6 * Test of independent reads from independent writes with smp_mb()
7 * between each pairs of reads. In other words, is smp_mb() sufficient to
8 * cause two different reading processes to agree on the order of a pair
9 * of writes, where each write is to a different variable by a different
10 * process?
11 *)
12
13{}
14
15P0(int *x)
16{
17 WRITE_ONCE(*x, 1);
18}
19
20P1(int *x, int *y)
21{
22 int r0;
23 int r1;
24
25 r0 = READ_ONCE(*x);
26 smp_mb();
27 r1 = READ_ONCE(*y);
28}
29
30P2(int *y)
31{
32 WRITE_ONCE(*y, 1);
33}
34
35P3(int *x, int *y)
36{
37 int r0;
38 int r1;
39
40 r0 = READ_ONCE(*y);
41 smp_mb();
42 r1 = READ_ONCE(*x);
43}
44
45exists (1:r0=1 /\ 1:r1=0 /\ 3:r0=1 /\ 3:r1=0)
diff --git a/tools/memory-model/litmus-tests/IRIW+poonceonces+OnceOnce.litmus b/tools/memory-model/litmus-tests/IRIW+poonceonces+OnceOnce.litmus
new file mode 100644
index 000000000000..4b54dd6a6cd9
--- /dev/null
+++ b/tools/memory-model/litmus-tests/IRIW+poonceonces+OnceOnce.litmus
@@ -0,0 +1,43 @@
1C IRIW+poonceonces+OnceOnce
2
3(*
4 * Result: Sometimes
5 *
6 * Test of independent reads from independent writes with nothing
7 * between each pairs of reads. In other words, is anything at all
8 * needed to cause two different reading processes to agree on the order
9 * of a pair of writes, where each write is to a different variable by a
10 * different process?
11 *)
12
13{}
14
15P0(int *x)
16{
17 WRITE_ONCE(*x, 1);
18}
19
20P1(int *x, int *y)
21{
22 int r0;
23 int r1;
24
25 r0 = READ_ONCE(*x);
26 r1 = READ_ONCE(*y);
27}
28
29P2(int *y)
30{
31 WRITE_ONCE(*y, 1);
32}
33
34P3(int *x, int *y)
35{
36 int r0;
37 int r1;
38
39 r0 = READ_ONCE(*y);
40 r1 = READ_ONCE(*x);
41}
42
43exists (1:r0=1 /\ 1:r1=0 /\ 3:r0=1 /\ 3:r1=0)
diff --git a/tools/memory-model/litmus-tests/ISA2+pooncelock+pooncelock+pombonce.litmus b/tools/memory-model/litmus-tests/ISA2+pooncelock+pooncelock+pombonce.litmus
new file mode 100644
index 000000000000..7a39a0aaa976
--- /dev/null
+++ b/tools/memory-model/litmus-tests/ISA2+pooncelock+pooncelock+pombonce.litmus
@@ -0,0 +1,41 @@
1C ISA2+pooncelock+pooncelock+pombonce.litmus
2
3(*
4 * Result: Sometimes
5 *
6 * This test shows that the ordering provided by a lock-protected S
7 * litmus test (P0() and P1()) are not visible to external process P2().
8 * This is likely to change soon.
9 *)
10
11{}
12
13P0(int *x, int *y, spinlock_t *mylock)
14{
15 spin_lock(mylock);
16 WRITE_ONCE(*x, 1);
17 WRITE_ONCE(*y, 1);
18 spin_unlock(mylock);
19}
20
21P1(int *y, int *z, spinlock_t *mylock)
22{
23 int r0;
24
25 spin_lock(mylock);
26 r0 = READ_ONCE(*y);
27 WRITE_ONCE(*z, 1);
28 spin_unlock(mylock);
29}
30
31P2(int *x, int *z)
32{
33 int r1;
34 int r2;
35
36 r2 = READ_ONCE(*z);
37 smp_mb();
38 r1 = READ_ONCE(*x);
39}
40
41exists (1:r0=1 /\ 2:r2=1 /\ 2:r1=0)
diff --git a/tools/memory-model/litmus-tests/ISA2+poonceonces.litmus b/tools/memory-model/litmus-tests/ISA2+poonceonces.litmus
new file mode 100644
index 000000000000..b321aa6f4ea5
--- /dev/null
+++ b/tools/memory-model/litmus-tests/ISA2+poonceonces.litmus
@@ -0,0 +1,37 @@
1C ISA2+poonceonces
2
3(*
4 * Result: Sometimes
5 *
6 * Given a release-acquire chain ordering the first process's store
7 * against the last process's load, is ordering preserved if all of the
8 * smp_store_release() invocations are replaced by WRITE_ONCE() and all
9 * of the smp_load_acquire() invocations are replaced by READ_ONCE()?
10 *)
11
12{}
13
14P0(int *x, int *y)
15{
16 WRITE_ONCE(*x, 1);
17 WRITE_ONCE(*y, 1);
18}
19
20P1(int *y, int *z)
21{
22 int r0;
23
24 r0 = READ_ONCE(*y);
25 WRITE_ONCE(*z, 1);
26}
27
28P2(int *x, int *z)
29{
30 int r0;
31 int r1;
32
33 r0 = READ_ONCE(*z);
34 r1 = READ_ONCE(*x);
35}
36
37exists (1:r0=1 /\ 2:r0=1 /\ 2:r1=0)
diff --git a/tools/memory-model/litmus-tests/ISA2+pooncerelease+poacquirerelease+poacquireonce.litmus b/tools/memory-model/litmus-tests/ISA2+pooncerelease+poacquirerelease+poacquireonce.litmus
new file mode 100644
index 000000000000..025b0462ec9b
--- /dev/null
+++ b/tools/memory-model/litmus-tests/ISA2+pooncerelease+poacquirerelease+poacquireonce.litmus
@@ -0,0 +1,39 @@
1C ISA2+pooncerelease+poacquirerelease+poacquireonce
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates that a release-acquire chain suffices
7 * to order P0()'s initial write against P2()'s final read. The reason
8 * that the release-acquire chain suffices is because in all but one
9 * case (P2() to P0()), each process reads from the preceding process's
10 * write. In memory-model-speak, there is only one non-reads-from
11 * (AKA non-rf) link, so release-acquire is all that is needed.
12 *)
13
14{}
15
16P0(int *x, int *y)
17{
18 WRITE_ONCE(*x, 1);
19 smp_store_release(y, 1);
20}
21
22P1(int *y, int *z)
23{
24 int r0;
25
26 r0 = smp_load_acquire(y);
27 smp_store_release(z, 1);
28}
29
30P2(int *x, int *z)
31{
32 int r0;
33 int r1;
34
35 r0 = smp_load_acquire(z);
36 r1 = READ_ONCE(*x);
37}
38
39exists (1:r0=1 /\ 2:r0=1 /\ 2:r1=0)
diff --git a/tools/memory-model/litmus-tests/LB+ctrlonceonce+mbonceonce.litmus b/tools/memory-model/litmus-tests/LB+ctrlonceonce+mbonceonce.litmus
new file mode 100644
index 000000000000..de6708229dd1
--- /dev/null
+++ b/tools/memory-model/litmus-tests/LB+ctrlonceonce+mbonceonce.litmus
@@ -0,0 +1,34 @@
1C LB+ctrlonceonce+mbonceonce
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates that lightweight ordering suffices for
7 * the load-buffering pattern, in other words, preventing all processes
8 * reading from the preceding process's write. In this example, the
9 * combination of a control dependency and a full memory barrier are enough
10 * to do the trick. (But the full memory barrier could be replaced with
11 * another control dependency and order would still be maintained.)
12 *)
13
14{}
15
16P0(int *x, int *y)
17{
18 int r0;
19
20 r0 = READ_ONCE(*x);
21 if (r0)
22 WRITE_ONCE(*y, 1);
23}
24
25P1(int *x, int *y)
26{
27 int r0;
28
29 r0 = READ_ONCE(*y);
30 smp_mb();
31 WRITE_ONCE(*x, 1);
32}
33
34exists (0:r0=1 /\ 1:r0=1)
diff --git a/tools/memory-model/litmus-tests/LB+poacquireonce+pooncerelease.litmus b/tools/memory-model/litmus-tests/LB+poacquireonce+pooncerelease.litmus
new file mode 100644
index 000000000000..07b9904b0e49
--- /dev/null
+++ b/tools/memory-model/litmus-tests/LB+poacquireonce+pooncerelease.litmus
@@ -0,0 +1,29 @@
1C LB+poacquireonce+pooncerelease
2
3(*
4 * Result: Never
5 *
6 * Does a release-acquire pair suffice for the load-buffering litmus
7 * test, where each process reads from one of two variables then writes
8 * to the other?
9 *)
10
11{}
12
13P0(int *x, int *y)
14{
15 int r0;
16
17 r0 = READ_ONCE(*x);
18 smp_store_release(y, 1);
19}
20
21P1(int *x, int *y)
22{
23 int r0;
24
25 r0 = smp_load_acquire(y);
26 WRITE_ONCE(*x, 1);
27}
28
29exists (0:r0=1 /\ 1:r0=1)
diff --git a/tools/memory-model/litmus-tests/LB+poonceonces.litmus b/tools/memory-model/litmus-tests/LB+poonceonces.litmus
new file mode 100644
index 000000000000..74c49cb3c37b
--- /dev/null
+++ b/tools/memory-model/litmus-tests/LB+poonceonces.litmus
@@ -0,0 +1,28 @@
1C LB+poonceonces
2
3(*
4 * Result: Sometimes
5 *
6 * Can the counter-intuitive outcome for the load-buffering pattern
7 * be prevented even with no explicit ordering?
8 *)
9
10{}
11
12P0(int *x, int *y)
13{
14 int r0;
15
16 r0 = READ_ONCE(*x);
17 WRITE_ONCE(*y, 1);
18}
19
20P1(int *x, int *y)
21{
22 int r0;
23
24 r0 = READ_ONCE(*y);
25 WRITE_ONCE(*x, 1);
26}
27
28exists (0:r0=1 /\ 1:r0=1)
diff --git a/tools/memory-model/litmus-tests/MP+onceassign+derefonce.litmus b/tools/memory-model/litmus-tests/MP+onceassign+derefonce.litmus
new file mode 100644
index 000000000000..97731b4bbdd8
--- /dev/null
+++ b/tools/memory-model/litmus-tests/MP+onceassign+derefonce.litmus
@@ -0,0 +1,34 @@
1C MP+onceassign+derefonce
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates that rcu_assign_pointer() and
7 * rcu_dereference() suffice to ensure that an RCU reader will not see
8 * pre-initialization garbage when it traverses an RCU-protected data
9 * structure containing a newly inserted element.
10 *)
11
12{
13y=z;
14z=0;
15}
16
17P0(int *x, int **y)
18{
19 WRITE_ONCE(*x, 1);
20 rcu_assign_pointer(*y, x);
21}
22
23P1(int *x, int **y)
24{
25 int *r0;
26 int r1;
27
28 rcu_read_lock();
29 r0 = rcu_dereference(*y);
30 r1 = READ_ONCE(*r0);
31 rcu_read_unlock();
32}
33
34exists (1:r0=x /\ 1:r1=0)
diff --git a/tools/memory-model/litmus-tests/MP+polocks.litmus b/tools/memory-model/litmus-tests/MP+polocks.litmus
new file mode 100644
index 000000000000..712a4fcdf6ce
--- /dev/null
+++ b/tools/memory-model/litmus-tests/MP+polocks.litmus
@@ -0,0 +1,35 @@
1C MP+polocks
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates how lock acquisitions and releases can
7 * stand in for smp_load_acquire() and smp_store_release(), respectively.
8 * In other words, when holding a given lock (or indeed after releasing a
9 * given lock), a CPU is not only guaranteed to see the accesses that other
10 * CPUs made while previously holding that lock, it is also guaranteed
11 * to see all prior accesses by those other CPUs.
12 *)
13
14{}
15
16P0(int *x, int *y, spinlock_t *mylock)
17{
18 WRITE_ONCE(*x, 1);
19 spin_lock(mylock);
20 WRITE_ONCE(*y, 1);
21 spin_unlock(mylock);
22}
23
24P1(int *x, int *y, spinlock_t *mylock)
25{
26 int r0;
27 int r1;
28
29 spin_lock(mylock);
30 r0 = READ_ONCE(*y);
31 spin_unlock(mylock);
32 r1 = READ_ONCE(*x);
33}
34
35exists (1:r0=1 /\ 1:r1=0)
diff --git a/tools/memory-model/litmus-tests/MP+poonceonces.litmus b/tools/memory-model/litmus-tests/MP+poonceonces.litmus
new file mode 100644
index 000000000000..b2b60b84fb9d
--- /dev/null
+++ b/tools/memory-model/litmus-tests/MP+poonceonces.litmus
@@ -0,0 +1,27 @@
1C MP+poonceonces
2
3(*
4 * Result: Maybe
5 *
6 * Can the counter-intuitive message-passing outcome be prevented with
7 * no ordering at all?
8 *)
9
10{}
11
12P0(int *x, int *y)
13{
14 WRITE_ONCE(*x, 1);
15 WRITE_ONCE(*y, 1);
16}
17
18P1(int *x, int *y)
19{
20 int r0;
21 int r1;
22
23 r0 = READ_ONCE(*y);
24 r1 = READ_ONCE(*x);
25}
26
27exists (1:r0=1 /\ 1:r1=0)
diff --git a/tools/memory-model/litmus-tests/MP+pooncerelease+poacquireonce.litmus b/tools/memory-model/litmus-tests/MP+pooncerelease+poacquireonce.litmus
new file mode 100644
index 000000000000..d52c68429722
--- /dev/null
+++ b/tools/memory-model/litmus-tests/MP+pooncerelease+poacquireonce.litmus
@@ -0,0 +1,28 @@
1C MP+pooncerelease+poacquireonce
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates that smp_store_release() and
7 * smp_load_acquire() provide sufficient ordering for the message-passing
8 * pattern.
9 *)
10
11{}
12
13P0(int *x, int *y)
14{
15 WRITE_ONCE(*x, 1);
16 smp_store_release(y, 1);
17}
18
19P1(int *x, int *y)
20{
21 int r0;
22 int r1;
23
24 r0 = smp_load_acquire(y);
25 r1 = READ_ONCE(*x);
26}
27
28exists (1:r0=1 /\ 1:r1=0)
diff --git a/tools/memory-model/litmus-tests/MP+porevlocks.litmus b/tools/memory-model/litmus-tests/MP+porevlocks.litmus
new file mode 100644
index 000000000000..72c9276b363e
--- /dev/null
+++ b/tools/memory-model/litmus-tests/MP+porevlocks.litmus
@@ -0,0 +1,35 @@
1C MP+porevlocks
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates how lock acquisitions and releases can
7 * stand in for smp_load_acquire() and smp_store_release(), respectively.
8 * In other words, when holding a given lock (or indeed after releasing a
9 * given lock), a CPU is not only guaranteed to see the accesses that other
10 * CPUs made while previously holding that lock, it is also guaranteed to
11 * see all prior accesses by those other CPUs.
12 *)
13
14{}
15
16P0(int *x, int *y, spinlock_t *mylock)
17{
18 int r0;
19 int r1;
20
21 r0 = READ_ONCE(*y);
22 spin_lock(mylock);
23 r1 = READ_ONCE(*x);
24 spin_unlock(mylock);
25}
26
27P1(int *x, int *y, spinlock_t *mylock)
28{
29 spin_lock(mylock);
30 WRITE_ONCE(*x, 1);
31 spin_unlock(mylock);
32 WRITE_ONCE(*y, 1);
33}
34
35exists (0:r0=1 /\ 0:r1=0)
diff --git a/tools/memory-model/litmus-tests/MP+wmbonceonce+rmbonceonce.litmus b/tools/memory-model/litmus-tests/MP+wmbonceonce+rmbonceonce.litmus
new file mode 100644
index 000000000000..c078f38ff27a
--- /dev/null
+++ b/tools/memory-model/litmus-tests/MP+wmbonceonce+rmbonceonce.litmus
@@ -0,0 +1,30 @@
1C MP+wmbonceonce+rmbonceonce
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates that smp_wmb() and smp_rmb() provide
7 * sufficient ordering for the message-passing pattern. However, it
8 * is usually better to use smp_store_release() and smp_load_acquire().
9 *)
10
11{}
12
13P0(int *x, int *y)
14{
15 WRITE_ONCE(*x, 1);
16 smp_wmb();
17 WRITE_ONCE(*y, 1);
18}
19
20P1(int *x, int *y)
21{
22 int r0;
23 int r1;
24
25 r0 = READ_ONCE(*y);
26 smp_rmb();
27 r1 = READ_ONCE(*x);
28}
29
30exists (1:r0=1 /\ 1:r1=0)
diff --git a/tools/memory-model/litmus-tests/R+mbonceonces.litmus b/tools/memory-model/litmus-tests/R+mbonceonces.litmus
new file mode 100644
index 000000000000..a0e884ad2132
--- /dev/null
+++ b/tools/memory-model/litmus-tests/R+mbonceonces.litmus
@@ -0,0 +1,30 @@
1C R+mbonceonces
2
3(*
4 * Result: Never
5 *
6 * This is the fully ordered (via smp_mb()) version of one of the classic
7 * counterintuitive litmus tests that illustrates the effects of store
8 * propagation delays. Note that weakening either of the barriers would
9 * cause the resulting test to be allowed.
10 *)
11
12{}
13
14P0(int *x, int *y)
15{
16 WRITE_ONCE(*x, 1);
17 smp_mb();
18 WRITE_ONCE(*y, 1);
19}
20
21P1(int *x, int *y)
22{
23 int r0;
24
25 WRITE_ONCE(*y, 2);
26 smp_mb();
27 r0 = READ_ONCE(*x);
28}
29
30exists (y=2 /\ 1:r0=0)
diff --git a/tools/memory-model/litmus-tests/R+poonceonces.litmus b/tools/memory-model/litmus-tests/R+poonceonces.litmus
new file mode 100644
index 000000000000..5386f128a131
--- /dev/null
+++ b/tools/memory-model/litmus-tests/R+poonceonces.litmus
@@ -0,0 +1,27 @@
1C R+poonceonces
2
3(*
4 * Result: Sometimes
5 *
6 * This is the unordered (thus lacking smp_mb()) version of one of the
7 * classic counterintuitive litmus tests that illustrates the effects of
8 * store propagation delays.
9 *)
10
11{}
12
13P0(int *x, int *y)
14{
15 WRITE_ONCE(*x, 1);
16 WRITE_ONCE(*y, 1);
17}
18
19P1(int *x, int *y)
20{
21 int r0;
22
23 WRITE_ONCE(*y, 2);
24 r0 = READ_ONCE(*x);
25}
26
27exists (y=2 /\ 1:r0=0)
diff --git a/tools/memory-model/litmus-tests/README b/tools/memory-model/litmus-tests/README
new file mode 100644
index 000000000000..04096fb8b8d9
--- /dev/null
+++ b/tools/memory-model/litmus-tests/README
@@ -0,0 +1,131 @@
1This directory contains the following litmus tests:
2
3CoRR+poonceonce+Once.litmus
4 Test of read-read coherence, that is, whether or not two
5 successive reads from the same variable are ordered.
6
7CoRW+poonceonce+Once.litmus
8 Test of read-write coherence, that is, whether or not a read
9 from a given variable followed by a write to that same variable
10 are ordered.
11
12CoWR+poonceonce+Once.litmus
13 Test of write-read coherence, that is, whether or not a write
14 to a given variable followed by a read from that same variable
15 are ordered.
16
17CoWW+poonceonce.litmus
18 Test of write-write coherence, that is, whether or not two
19 successive writes to the same variable are ordered.
20
21IRIW+mbonceonces+OnceOnce.litmus
22 Test of independent reads from independent writes with smp_mb()
23 between each pairs of reads. In other words, is smp_mb()
24 sufficient to cause two different reading processes to agree on
25 the order of a pair of writes, where each write is to a different
26 variable by a different process?
27
28IRIW+poonceonces+OnceOnce.litmus
29 Test of independent reads from independent writes with nothing
30 between each pairs of reads. In other words, is anything at all
31 needed to cause two different reading processes to agree on the
32 order of a pair of writes, where each write is to a different
33 variable by a different process?
34
35ISA2+pooncelock+pooncelock+pombonce.litmus
36 Tests whether the ordering provided by a lock-protected S
37 litmus test is visible to an external process whose accesses are
38 separated by smp_mb(). This addition of an external process to
39 S is otherwise known as ISA2.
40
41ISA2+poonceonces.litmus
42 As below, but with store-release replaced with WRITE_ONCE()
43 and load-acquire replaced with READ_ONCE().
44
45ISA2+pooncerelease+poacquirerelease+poacquireonce.litmus
46 Can a release-acquire chain order a prior store against
47 a later load?
48
49LB+ctrlonceonce+mbonceonce.litmus
50 Does a control dependency and an smp_mb() suffice for the
51 load-buffering litmus test, where each process reads from one
52 of two variables then writes to the other?
53
54LB+poacquireonce+pooncerelease.litmus
55 Does a release-acquire pair suffice for the load-buffering
56 litmus test, where each process reads from one of two variables then
57 writes to the other?
58
59LB+poonceonces.litmus
60 As above, but with store-release replaced with WRITE_ONCE()
61 and load-acquire replaced with READ_ONCE().
62
63MP+onceassign+derefonce.litmus
64 As below, but with rcu_assign_pointer() and an rcu_dereference().
65
66MP+polocks.litmus
67 As below, but with the second access of the writer process
68 and the first access of reader process protected by a lock.
69
70MP+poonceonces.litmus
71 As below, but without the smp_rmb() and smp_wmb().
72
73MP+pooncerelease+poacquireonce.litmus
74 As below, but with a release-acquire chain.
75
76MP+porevlocks.litmus
77 As below, but with the first access of the writer process
78 and the second access of reader process protected by a lock.
79
80MP+wmbonceonce+rmbonceonce.litmus
81 Does a smp_wmb() (between the stores) and an smp_rmb() (between
82 the loads) suffice for the message-passing litmus test, where one
83 process writes data and then a flag, and the other process reads
84 the flag and then the data. (This is similar to the ISA2 tests,
85 but with two processes instead of three.)
86
87R+mbonceonces.litmus
88 This is the fully ordered (via smp_mb()) version of one of
89 the classic counterintuitive litmus tests that illustrates the
90 effects of store propagation delays.
91
92R+poonceonces.litmus
93 As above, but without the smp_mb() invocations.
94
95SB+mbonceonces.litmus
96 This is the fully ordered (again, via smp_mb() version of store
97 buffering, which forms the core of Dekker's mutual-exclusion
98 algorithm.
99
100SB+poonceonces.litmus
101 As above, but without the smp_mb() invocations.
102
103S+poonceonces.litmus
104 As below, but without the smp_wmb() and acquire load.
105
106S+wmbonceonce+poacquireonce.litmus
107 Can a smp_wmb(), instead of a release, and an acquire order
108 a prior store against a subsequent store?
109
110WRC+poonceonces+Once.litmus
111WRC+pooncerelease+rmbonceonce+Once.litmus
112 These two are members of an extension of the MP litmus-test class
113 in which the first write is moved to a separate process.
114
115Z6.0+pooncelock+pooncelock+pombonce.litmus
116 Is the ordering provided by a spin_unlock() and a subsequent
117 spin_lock() sufficient to make ordering apparent to accesses
118 by a process not holding the lock?
119
120Z6.0+pooncelock+poonceLock+pombonce.litmus
121 As above, but with smp_mb__after_spinlock() immediately
122 following the spin_lock().
123
124Z6.0+pooncerelease+poacquirerelease+mbonceonce.litmus
125 Is the ordering provided by a release-acquire chain sufficient
126 to make ordering apparent to accesses by a process that does
127 not participate in that release-acquire chain?
128
129A great many more litmus tests are available here:
130
131 https://github.com/paulmckrcu/litmus
diff --git a/tools/memory-model/litmus-tests/S+poonceonces.litmus b/tools/memory-model/litmus-tests/S+poonceonces.litmus
new file mode 100644
index 000000000000..8c9c2f81a580
--- /dev/null
+++ b/tools/memory-model/litmus-tests/S+poonceonces.litmus
@@ -0,0 +1,28 @@
1C S+poonceonces
2
3(*
4 * Result: Sometimes
5 *
6 * Starting with a two-process release-acquire chain ordering P0()'s
7 * first store against P1()'s final load, if the smp_store_release()
8 * is replaced by WRITE_ONCE() and the smp_load_acquire() replaced by
9 * READ_ONCE(), is ordering preserved?
10 *)
11
12{}
13
14P0(int *x, int *y)
15{
16 WRITE_ONCE(*x, 2);
17 WRITE_ONCE(*y, 1);
18}
19
20P1(int *x, int *y)
21{
22 int r0;
23
24 r0 = READ_ONCE(*y);
25 WRITE_ONCE(*x, 1);
26}
27
28exists (x=2 /\ 1:r0=1)
diff --git a/tools/memory-model/litmus-tests/S+wmbonceonce+poacquireonce.litmus b/tools/memory-model/litmus-tests/S+wmbonceonce+poacquireonce.litmus
new file mode 100644
index 000000000000..c53350205d28
--- /dev/null
+++ b/tools/memory-model/litmus-tests/S+wmbonceonce+poacquireonce.litmus
@@ -0,0 +1,27 @@
1C S+wmbonceonce+poacquireonce
2
3(*
4 * Result: Never
5 *
6 * Can a smp_wmb(), instead of a release, and an acquire order a prior
7 * store against a subsequent store?
8 *)
9
10{}
11
12P0(int *x, int *y)
13{
14 WRITE_ONCE(*x, 2);
15 smp_wmb();
16 WRITE_ONCE(*y, 1);
17}
18
19P1(int *x, int *y)
20{
21 int r0;
22
23 r0 = smp_load_acquire(y);
24 WRITE_ONCE(*x, 1);
25}
26
27exists (x=2 /\ 1:r0=1)
diff --git a/tools/memory-model/litmus-tests/SB+mbonceonces.litmus b/tools/memory-model/litmus-tests/SB+mbonceonces.litmus
new file mode 100644
index 000000000000..74b874ffa8da
--- /dev/null
+++ b/tools/memory-model/litmus-tests/SB+mbonceonces.litmus
@@ -0,0 +1,32 @@
1C SB+mbonceonces
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates that full memory barriers suffice to
7 * order the store-buffering pattern, where each process writes to the
8 * variable that the preceding process reads. (Locking and RCU can also
9 * suffice, but not much else.)
10 *)
11
12{}
13
14P0(int *x, int *y)
15{
16 int r0;
17
18 WRITE_ONCE(*x, 1);
19 smp_mb();
20 r0 = READ_ONCE(*y);
21}
22
23P1(int *x, int *y)
24{
25 int r0;
26
27 WRITE_ONCE(*y, 1);
28 smp_mb();
29 r0 = READ_ONCE(*x);
30}
31
32exists (0:r0=0 /\ 1:r0=0)
diff --git a/tools/memory-model/litmus-tests/SB+poonceonces.litmus b/tools/memory-model/litmus-tests/SB+poonceonces.litmus
new file mode 100644
index 000000000000..10d550730b25
--- /dev/null
+++ b/tools/memory-model/litmus-tests/SB+poonceonces.litmus
@@ -0,0 +1,29 @@
1C SB+poonceonces
2
3(*
4 * Result: Sometimes
5 *
6 * This litmus test demonstrates that at least some ordering is required
7 * to order the store-buffering pattern, where each process writes to the
8 * variable that the preceding process reads.
9 *)
10
11{}
12
13P0(int *x, int *y)
14{
15 int r0;
16
17 WRITE_ONCE(*x, 1);
18 r0 = READ_ONCE(*y);
19}
20
21P1(int *x, int *y)
22{
23 int r0;
24
25 WRITE_ONCE(*y, 1);
26 r0 = READ_ONCE(*x);
27}
28
29exists (0:r0=0 /\ 1:r0=0)
diff --git a/tools/memory-model/litmus-tests/WRC+poonceonces+Once.litmus b/tools/memory-model/litmus-tests/WRC+poonceonces+Once.litmus
new file mode 100644
index 000000000000..6a2bc12a1af1
--- /dev/null
+++ b/tools/memory-model/litmus-tests/WRC+poonceonces+Once.litmus
@@ -0,0 +1,35 @@
1C WRC+poonceonces+Once
2
3(*
4 * Result: Sometimes
5 *
6 * This litmus test is an extension of the message-passing pattern,
7 * where the first write is moved to a separate process. Note that this
8 * test has no ordering at all.
9 *)
10
11{}
12
13P0(int *x)
14{
15 WRITE_ONCE(*x, 1);
16}
17
18P1(int *x, int *y)
19{
20 int r0;
21
22 r0 = READ_ONCE(*x);
23 WRITE_ONCE(*y, 1);
24}
25
26P2(int *x, int *y)
27{
28 int r0;
29 int r1;
30
31 r0 = READ_ONCE(*y);
32 r1 = READ_ONCE(*x);
33}
34
35exists (1:r0=1 /\ 2:r0=1 /\ 2:r1=0)
diff --git a/tools/memory-model/litmus-tests/WRC+pooncerelease+rmbonceonce+Once.litmus b/tools/memory-model/litmus-tests/WRC+pooncerelease+rmbonceonce+Once.litmus
new file mode 100644
index 000000000000..97fcbffde9a0
--- /dev/null
+++ b/tools/memory-model/litmus-tests/WRC+pooncerelease+rmbonceonce+Once.litmus
@@ -0,0 +1,36 @@
1C WRC+pooncerelease+rmbonceonce+Once
2
3(*
4 * Result: Never
5 *
6 * This litmus test is an extension of the message-passing pattern, where
7 * the first write is moved to a separate process. Because it features
8 * a release and a read memory barrier, it should be forbidden.
9 *)
10
11{}
12
13P0(int *x)
14{
15 WRITE_ONCE(*x, 1);
16}
17
18P1(int *x, int *y)
19{
20 int r0;
21
22 r0 = READ_ONCE(*x);
23 smp_store_release(y, 1);
24}
25
26P2(int *x, int *y)
27{
28 int r0;
29 int r1;
30
31 r0 = READ_ONCE(*y);
32 smp_rmb();
33 r1 = READ_ONCE(*x);
34}
35
36exists (1:r0=1 /\ 2:r0=1 /\ 2:r1=0)
diff --git a/tools/memory-model/litmus-tests/Z6.0+pooncelock+poonceLock+pombonce.litmus b/tools/memory-model/litmus-tests/Z6.0+pooncelock+poonceLock+pombonce.litmus
new file mode 100644
index 000000000000..415248fb6699
--- /dev/null
+++ b/tools/memory-model/litmus-tests/Z6.0+pooncelock+poonceLock+pombonce.litmus
@@ -0,0 +1,42 @@
1C Z6.0+pooncelock+poonceLock+pombonce
2
3(*
4 * Result: Never
5 *
6 * This litmus test demonstrates how smp_mb__after_spinlock() may be
7 * used to ensure that accesses in different critical sections for a
8 * given lock running on different CPUs are nevertheless seen in order
9 * by CPUs not holding that lock.
10 *)
11
12{}
13
14P0(int *x, int *y, spinlock_t *mylock)
15{
16 spin_lock(mylock);
17 WRITE_ONCE(*x, 1);
18 WRITE_ONCE(*y, 1);
19 spin_unlock(mylock);
20}
21
22P1(int *y, int *z, spinlock_t *mylock)
23{
24 int r0;
25
26 spin_lock(mylock);
27 smp_mb__after_spinlock();
28 r0 = READ_ONCE(*y);
29 WRITE_ONCE(*z, 1);
30 spin_unlock(mylock);
31}
32
33P2(int *x, int *z)
34{
35 int r1;
36
37 WRITE_ONCE(*z, 2);
38 smp_mb();
39 r1 = READ_ONCE(*x);
40}
41
42exists (1:r0=1 /\ z=2 /\ 2:r1=0)
diff --git a/tools/memory-model/litmus-tests/Z6.0+pooncelock+pooncelock+pombonce.litmus b/tools/memory-model/litmus-tests/Z6.0+pooncelock+pooncelock+pombonce.litmus
new file mode 100644
index 000000000000..10a2aa04cd07
--- /dev/null
+++ b/tools/memory-model/litmus-tests/Z6.0+pooncelock+pooncelock+pombonce.litmus
@@ -0,0 +1,40 @@
1C Z6.0+pooncelock+pooncelock+pombonce
2
3(*
4 * Result: Sometimes
5 *
6 * This example demonstrates that a pair of accesses made by different
7 * processes each while holding a given lock will not necessarily be
8 * seen as ordered by a third process not holding that lock.
9 *)
10
11{}
12
13P0(int *x, int *y, spinlock_t *mylock)
14{
15 spin_lock(mylock);
16 WRITE_ONCE(*x, 1);
17 WRITE_ONCE(*y, 1);
18 spin_unlock(mylock);
19}
20
21P1(int *y, int *z, spinlock_t *mylock)
22{
23 int r0;
24
25 spin_lock(mylock);
26 r0 = READ_ONCE(*y);
27 WRITE_ONCE(*z, 1);
28 spin_unlock(mylock);
29}
30
31P2(int *x, int *z)
32{
33 int r1;
34
35 WRITE_ONCE(*z, 2);
36 smp_mb();
37 r1 = READ_ONCE(*x);
38}
39
40exists (1:r0=1 /\ z=2 /\ 2:r1=0)
diff --git a/tools/memory-model/litmus-tests/Z6.0+pooncerelease+poacquirerelease+mbonceonce.litmus b/tools/memory-model/litmus-tests/Z6.0+pooncerelease+poacquirerelease+mbonceonce.litmus
new file mode 100644
index 000000000000..a20fc3fafb53
--- /dev/null
+++ b/tools/memory-model/litmus-tests/Z6.0+pooncerelease+poacquirerelease+mbonceonce.litmus
@@ -0,0 +1,42 @@
1C Z6.0+pooncerelease+poacquirerelease+mbonceonce
2
3(*
4 * Result: Sometimes
5 *
6 * This litmus test shows that a release-acquire chain, while sufficient
7 * when there is but one non-reads-from (AKA non-rf) link, does not suffice
8 * if there is more than one. Of the three processes, only P1() reads from
9 * P0's write, which means that there are two non-rf links: P1() to P2()
10 * is a write-to-write link (AKA a "coherence" or just "co" link) and P2()
11 * to P0() is a read-to-write link (AKA a "from-reads" or just "fr" link).
12 * When there are two or more non-rf links, you typically will need one
13 * full barrier for each non-rf link. (Exceptions include some cases
14 * involving locking.)
15 *)
16
17{}
18
19P0(int *x, int *y)
20{
21 WRITE_ONCE(*x, 1);
22 smp_store_release(y, 1);
23}
24
25P1(int *y, int *z)
26{
27 int r0;
28
29 r0 = smp_load_acquire(y);
30 smp_store_release(z, 1);
31}
32
33P2(int *x, int *z)
34{
35 int r1;
36
37 WRITE_ONCE(*z, 2);
38 smp_mb();
39 r1 = READ_ONCE(*x);
40}
41
42exists (1:r0=1 /\ z=2 /\ 2:r1=0)
diff --git a/tools/memory-model/lock.cat b/tools/memory-model/lock.cat
new file mode 100644
index 000000000000..ba4a4ec6d313
--- /dev/null
+++ b/tools/memory-model/lock.cat
@@ -0,0 +1,99 @@
1// SPDX-License-Identifier: GPL-2.0+
2(*
3 * Copyright (C) 2016 Luc Maranget <luc.maranget@inria.fr> for Inria
4 * Copyright (C) 2017 Alan Stern <stern@rowland.harvard.edu>
5 *)
6
7(* Generate coherence orders and handle lock operations *)
8
9include "cross.cat"
10
11(* From lock reads to their partner lock writes *)
12let lk-rmw = ([LKR] ; po-loc ; [LKW]) \ (po ; po)
13let rmw = rmw | lk-rmw
14
15(*
16 * A paired LKR must always see an unlocked value; spin_lock() calls nested
17 * inside a critical section (for the same lock) always deadlock.
18 *)
19empty ([LKW] ; po-loc ; [domain(lk-rmw)]) \ (po-loc ; [UL] ; po-loc)
20 as lock-nest
21
22(* The litmus test is invalid if an LKW event is not part of an RMW pair *)
23flag ~empty LKW \ range(lk-rmw) as unpaired-LKW
24
25(* This will be allowed if we implement spin_is_locked() *)
26flag ~empty LKR \ domain(lk-rmw) as unpaired-LKR
27
28(* There should be no R or W accesses to spinlocks *)
29let ALL-LOCKS = LKR | LKW | UL | LF
30flag ~empty [M \ IW] ; loc ; [ALL-LOCKS] as mixed-lock-accesses
31
32(* The final value of a spinlock should not be tested *)
33flag ~empty [FW] ; loc ; [ALL-LOCKS] as lock-final
34
35
36(*
37 * Put lock operations in their appropriate classes, but leave UL out of W
38 * until after the co relation has been generated.
39 *)
40let R = R | LKR | LF
41let W = W | LKW
42
43let Release = Release | UL
44let Acquire = Acquire | LKR
45
46
47(* Match LKW events to their corresponding UL events *)
48let critical = ([LKW] ; po-loc ; [UL]) \ (po-loc ; [LKW | UL] ; po-loc)
49
50flag ~empty UL \ range(critical) as unmatched-unlock
51
52(* Allow up to one unmatched LKW per location; more must deadlock *)
53let UNMATCHED-LKW = LKW \ domain(critical)
54empty ([UNMATCHED-LKW] ; loc ; [UNMATCHED-LKW]) \ id as unmatched-locks
55
56
57(* rfi for LF events: link each LKW to the LF events in its critical section *)
58let rfi-lf = ([LKW] ; po-loc ; [LF]) \ ([LKW] ; po-loc ; [UL] ; po-loc)
59
60(* rfe for LF events *)
61let all-possible-rfe-lf =
62 (*
63 * Given an LF event r, compute the possible rfe edges for that event
64 * (all those starting from LKW events in other threads),
65 * and then convert that relation to a set of single-edge relations.
66 *)
67 let possible-rfe-lf r =
68 let pair-to-relation p = p ++ 0
69 in map pair-to-relation ((LKW * {r}) & loc & ext)
70 (* Do this for each LF event r that isn't in rfi-lf *)
71 in map possible-rfe-lf (LF \ range(rfi-lf))
72
73(* Generate all rf relations for LF events *)
74with rfe-lf from cross(all-possible-rfe-lf)
75let rf = rf | rfi-lf | rfe-lf
76
77
78(* Generate all co relations, including LKW events but not UL *)
79let co0 = co0 | ([IW] ; loc ; [LKW]) |
80 (([LKW] ; loc ; [UNMATCHED-LKW]) \ [UNMATCHED-LKW])
81include "cos-opt.cat"
82let W = W | UL
83let M = R | W
84
85(* Merge UL events into co *)
86let co = (co | critical | (critical^-1 ; co))+
87let coe = co & ext
88let coi = co & int
89
90(* Merge LKR events into rf *)
91let rf = rf | ([IW | UL] ; singlestep(co) ; lk-rmw^-1)
92let rfe = rf & ext
93let rfi = rf & int
94
95let fr = rf^-1 ; co
96let fre = fr & ext
97let fri = fr & int
98
99show co,rf,fr
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index c635eab6af54..749cc6055dac 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -21,7 +21,7 @@ If there is no debug info in the object, then annotated assembly is displayed.
21OPTIONS 21OPTIONS
22------- 22-------
23-i:: 23-i::
24--input=:: 24--input=<file>::
25 Input file name. (default: perf.data unless stdin is a fifo) 25 Input file name. (default: perf.data unless stdin is a fifo)
26 26
27-d:: 27-d::
@@ -55,6 +55,9 @@ OPTIONS
55--vmlinux=<file>:: 55--vmlinux=<file>::
56 vmlinux pathname. 56 vmlinux pathname.
57 57
58--ignore-vmlinux::
59 Ignore vmlinux files.
60
58-m:: 61-m::
59--modules:: 62--modules::
60 Load module symbols. WARNING: use only with -k and LIVE kernel. 63 Load module symbols. WARNING: use only with -k and LIVE kernel.
@@ -69,7 +72,9 @@ OPTIONS
69 72
70--stdio:: Use the stdio interface. 73--stdio:: Use the stdio interface.
71 74
72--stdio-color:: 75--stdio2:: Use the stdio2 interface, non-interactive, uses the TUI formatting.
76
77--stdio-color=<mode>::
73 'always', 'never' or 'auto', allowing configuring color output 78 'always', 'never' or 'auto', allowing configuring color output
74 via the command line, in addition to via "color.ui" .perfconfig. 79 via the command line, in addition to via "color.ui" .perfconfig.
75 Use '--stdio-color always' to generate color even when redirecting 80 Use '--stdio-color always' to generate color even when redirecting
@@ -84,7 +89,7 @@ OPTIONS
84--gtk:: Use the GTK interface. 89--gtk:: Use the GTK interface.
85 90
86-C:: 91-C::
87--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can 92--cpu=<cpu>:: Only report samples for the list of CPUs provided. Multiple CPUs can
88 be provided as a comma-separated list with no space: 0,1. Ranges of 93 be provided as a comma-separated list with no space: 0,1. Ranges of
89 CPUs are specified with -: 0-2. Default is to report samples on all 94 CPUs are specified with -: 0-2. Default is to report samples on all
90 CPUs. 95 CPUs.
diff --git a/tools/perf/Documentation/perf-c2c.txt b/tools/perf/Documentation/perf-c2c.txt
index 822414235170..095aebdc5bb7 100644
--- a/tools/perf/Documentation/perf-c2c.txt
+++ b/tools/perf/Documentation/perf-c2c.txt
@@ -116,7 +116,7 @@ and calls standard perf record command.
116Following perf record options are configured by default: 116Following perf record options are configured by default:
117(check perf record man page for details) 117(check perf record man page for details)
118 118
119 -W,-d,--sample-cpu 119 -W,-d,--phys-data,--sample-cpu
120 120
121Unless specified otherwise with '-e' option, following events are monitored by 121Unless specified otherwise with '-e' option, following events are monitored by
122default: 122default:
diff --git a/tools/perf/Documentation/perf-data.txt b/tools/perf/Documentation/perf-data.txt
index f0796a47dfa3..c87180764829 100644
--- a/tools/perf/Documentation/perf-data.txt
+++ b/tools/perf/Documentation/perf-data.txt
@@ -1,5 +1,5 @@
1perf-data(1) 1perf-data(1)
2============== 2============
3 3
4NAME 4NAME
5---- 5----
@@ -30,6 +30,10 @@ OPTIONS for 'convert'
30-i:: 30-i::
31 Specify input perf data file path. 31 Specify input perf data file path.
32 32
33-f::
34--force::
35 Don't complain, do it.
36
33-v:: 37-v::
34--verbose:: 38--verbose::
35 Be more verbose (show counter open errors, etc). 39 Be more verbose (show counter open errors, etc).
diff --git a/tools/perf/Documentation/perf-ftrace.txt b/tools/perf/Documentation/perf-ftrace.txt
index 721a447f046e..b80c84307dc9 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -1,5 +1,5 @@
1perf-ftrace(1) 1perf-ftrace(1)
2============= 2==============
3 3
4NAME 4NAME
5---- 5----
diff --git a/tools/perf/Documentation/perf-kallsyms.txt b/tools/perf/Documentation/perf-kallsyms.txt
index 954ea9e21236..f3c620951f6e 100644
--- a/tools/perf/Documentation/perf-kallsyms.txt
+++ b/tools/perf/Documentation/perf-kallsyms.txt
@@ -1,5 +1,5 @@
1perf-kallsyms(1) 1perf-kallsyms(1)
2============== 2================
3 3
4NAME 4NAME
5---- 5----
@@ -8,7 +8,7 @@ perf-kallsyms - Searches running kernel for symbols
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf kallsyms <options> symbol_name[,symbol_name...]' 11'perf kallsyms' [<options>] symbol_name[,symbol_name...]
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
diff --git a/tools/perf/Documentation/perf-kmem.txt b/tools/perf/Documentation/perf-kmem.txt
index 479fc3261a50..85b8ac695c87 100644
--- a/tools/perf/Documentation/perf-kmem.txt
+++ b/tools/perf/Documentation/perf-kmem.txt
@@ -25,6 +25,10 @@ OPTIONS
25--input=<file>:: 25--input=<file>::
26 Select the input file (default: perf.data unless stdin is a fifo) 26 Select the input file (default: perf.data unless stdin is a fifo)
27 27
28-f::
29--force::
30 Don't do ownership validation
31
28-v:: 32-v::
29--verbose:: 33--verbose::
30 Be more verbose. (show symbol address, etc) 34 Be more verbose. (show symbol address, etc)
@@ -61,7 +65,7 @@ OPTIONS
61 default, but this option shows live (currently allocated) pages 65 default, but this option shows live (currently allocated) pages
62 instead. (This option works with --page option only) 66 instead. (This option works with --page option only)
63 67
64--time:: 68--time=<start>,<stop>::
65 Only analyze samples within given time window: <start>,<stop>. Times 69 Only analyze samples within given time window: <start>,<stop>. Times
66 have the format seconds.microseconds. If start is not given (i.e., time 70 have the format seconds.microseconds. If start is not given (i.e., time
67 string is ',x.y') then analysis starts at the beginning of the file. If 71 string is ',x.y') then analysis starts at the beginning of the file. If
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index e2a897ae3596..2549c34a7895 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -141,7 +141,13 @@ on the first memory controller on socket 0 of a Intel Xeon system
141 141
142Each memory controller has its own PMU. Measuring the complete system 142Each memory controller has its own PMU. Measuring the complete system
143bandwidth would require specifying all imc PMUs (see perf list output), 143bandwidth would require specifying all imc PMUs (see perf list output),
144and adding the values together. 144and adding the values together. To simplify creation of multiple events,
145prefix and glob matching is supported in the PMU name, and the prefix
146'uncore_' is also ignored when performing the match. So the command above
147can be expanded to all memory controllers by using the syntaxes:
148
149 perf stat -C 0 -a imc/cas_count_read/,imc/cas_count_write/ -I 1000 ...
150 perf stat -C 0 -a *imc*/cas_count_read/,*imc*/cas_count_write/ -I 1000 ...
145 151
146This example measures the combined core power every second 152This example measures the combined core power every second
147 153
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt
index 4be08a1e3f8d..b0211410969b 100644
--- a/tools/perf/Documentation/perf-mem.txt
+++ b/tools/perf/Documentation/perf-mem.txt
@@ -28,6 +28,10 @@ OPTIONS
28<command>...:: 28<command>...::
29 Any command you can specify in a shell. 29 Any command you can specify in a shell.
30 30
31-f::
32--force::
33 Don't do ownership validation
34
31-t:: 35-t::
32--type=:: 36--type=::
33 Select the memory operation type: load or store (default: load,store) 37 Select the memory operation type: load or store (default: load,store)
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 3eea6de35a38..cc37b3a4be76 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -191,9 +191,16 @@ OPTIONS
191-i:: 191-i::
192--no-inherit:: 192--no-inherit::
193 Child tasks do not inherit counters. 193 Child tasks do not inherit counters.
194
194-F:: 195-F::
195--freq=:: 196--freq=::
196 Profile at this frequency. 197 Profile at this frequency. Use 'max' to use the currently maximum
198 allowed frequency, i.e. the value in the kernel.perf_event_max_sample_rate
199 sysctl. Will throttle down to the currently maximum allowed frequency.
200 See --strict-freq.
201
202--strict-freq::
203 Fail if the specified frequency can't be used.
197 204
198-m:: 205-m::
199--mmap-pages=:: 206--mmap-pages=::
@@ -308,7 +315,11 @@ can be provided. Each cgroup is applied to the corresponding event, i.e., first
308to first event, second cgroup to second event and so on. It is possible to provide 315to first event, second cgroup to second event and so on. It is possible to provide
309an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have 316an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have
310corresponding events, i.e., they always refer to events defined earlier on the command 317corresponding events, i.e., they always refer to events defined earlier on the command
311line. 318line. If the user wants to track multiple events for a specific cgroup, the user can
319use '-e e1 -e e2 -G foo,foo' or just use '-e e1 -e e2 -G foo'.
320
321If wanting to monitor, say, 'cycles' for a cgroup and also for system wide, this
322command line can be used: 'perf stat -e cycles -G cgroup_name -a -e cycles'.
312 323
313-b:: 324-b::
314--branch-any:: 325--branch-any::
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 907e505b6309..e1a660e60849 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -296,6 +296,9 @@ OPTIONS
296--vmlinux=<file>:: 296--vmlinux=<file>::
297 vmlinux pathname 297 vmlinux pathname
298 298
299--ignore-vmlinux::
300 Ignore vmlinux files.
301
299--kallsyms=<file>:: 302--kallsyms=<file>::
300 kallsyms pathname 303 kallsyms pathname
301 304
@@ -354,7 +357,8 @@ OPTIONS
354 Path to objdump binary. 357 Path to objdump binary.
355 358
356--group:: 359--group::
357 Show event group information together. 360 Show event group information together. It forces group output also
361 if there are no groups defined in data file.
358 362
359--demangle:: 363--demangle::
360 Demangle symbol names to human readable form. It's enabled by default, 364 Demangle symbol names to human readable form. It's enabled by default,
@@ -367,7 +371,7 @@ OPTIONS
367 Use the data addresses of samples in addition to instruction addresses 371 Use the data addresses of samples in addition to instruction addresses
368 to build the histograms. To generate meaningful output, the perf.data 372 to build the histograms. To generate meaningful output, the perf.data
369 file must have been obtained using perf record -d -W and using a 373 file must have been obtained using perf record -d -W and using a
370 special event -e cpu/mem-loads/ or -e cpu/mem-stores/. See 374 special event -e cpu/mem-loads/p or -e cpu/mem-stores/p. See
371 'perf mem' for simpler access. 375 'perf mem' for simpler access.
372 376
373--percent-limit:: 377--percent-limit::
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index c7e50f263887..bb33601a823b 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -1,5 +1,5 @@
1perf-sched(1) 1perf-sched(1)
2============== 2=============
3 3
4NAME 4NAME
5---- 5----
diff --git a/tools/perf/Documentation/perf-script-perl.txt b/tools/perf/Documentation/perf-script-perl.txt
index 142606c0ec9c..5a1f68122f50 100644
--- a/tools/perf/Documentation/perf-script-perl.txt
+++ b/tools/perf/Documentation/perf-script-perl.txt
@@ -1,5 +1,5 @@
1perf-script-perl(1) 1perf-script-perl(1)
2================== 2===================
3 3
4NAME 4NAME
5---- 5----
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 7730c1d2b5d3..36ec0257f8d3 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -303,6 +303,9 @@ OPTIONS
303--show-lost-events 303--show-lost-events
304 Display lost events i.e. events of type PERF_RECORD_LOST. 304 Display lost events i.e. events of type PERF_RECORD_LOST.
305 305
306--show-round-events
307 Display finished round events i.e. events of type PERF_RECORD_FINISHED_ROUND.
308
306--demangle:: 309--demangle::
307 Demangle symbol names to human readable form. It's enabled by default, 310 Demangle symbol names to human readable form. It's enabled by default,
308 disable with --no-demangle. 311 disable with --no-demangle.
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 823fce7674bb..f15b306be183 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -49,6 +49,13 @@ report::
49 parameters are defined by corresponding entries in 49 parameters are defined by corresponding entries in
50 /sys/bus/event_source/devices/<pmu>/format/* 50 /sys/bus/event_source/devices/<pmu>/format/*
51 51
52 Note that the last two syntaxes support prefix and glob matching in
53 the PMU name to simplify creation of events accross multiple instances
54 of the same type of PMU in large systems (e.g. memory controller PMUs).
55 Multiple PMU instances are typical for uncore PMUs, so the prefix
56 'uncore_' is also ignored when performing this match.
57
58
52-i:: 59-i::
53--no-inherit:: 60--no-inherit::
54 child tasks do not inherit counters 61 child tasks do not inherit counters
@@ -118,7 +125,11 @@ can be provided. Each cgroup is applied to the corresponding event, i.e., first
118to first event, second cgroup to second event and so on. It is possible to provide 125to first event, second cgroup to second event and so on. It is possible to provide
119an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have 126an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have
120corresponding events, i.e., they always refer to events defined earlier on the command 127corresponding events, i.e., they always refer to events defined earlier on the command
121line. 128line. If the user wants to track multiple events for a specific cgroup, the user can
129use '-e e1 -e e2 -G foo,foo' or just use '-e e1 -e e2 -G foo'.
130
131If wanting to monitor, say, 'cycles' for a cgroup and also for system wide, this
132command line can be used: 'perf stat -e cycles -G cgroup_name -a -e cycles'.
122 133
123-o file:: 134-o file::
124--output file:: 135--output file::
@@ -146,6 +157,16 @@ Print count deltas every N milliseconds (minimum: 10ms)
146The overhead percentage could be high in some cases, for instance with small, sub 100ms intervals. Use with caution. 157The overhead percentage could be high in some cases, for instance with small, sub 100ms intervals. Use with caution.
147 example: 'perf stat -I 1000 -e cycles -a sleep 5' 158 example: 'perf stat -I 1000 -e cycles -a sleep 5'
148 159
160--interval-count times::
161Print count deltas for fixed number of times.
162This option should be used together with "-I" option.
163 example: 'perf stat -I 1000 --interval-count 2 -e cycles -a'
164
165--timeout msecs::
166Stop the 'perf stat' session and print count deltas after N milliseconds (minimum: 10 ms).
167This option is not supported with the "-I" option.
168 example: 'perf stat --time 2000 -e cycles -a'
169
149--metric-only:: 170--metric-only::
150Only print computed metrics. Print them in a single line. 171Only print computed metrics. Print them in a single line.
151Don't show any raw values. Not supported with --per-thread. 172Don't show any raw values. Not supported with --per-thread.
@@ -246,6 +267,16 @@ taskset.
246--no-merge:: 267--no-merge::
247Do not merge results from same PMUs. 268Do not merge results from same PMUs.
248 269
270When multiple events are created from a single event specification,
271stat will, by default, aggregate the event counts and show the result
272in a single row. This option disables that behavior and shows
273the individual events and counts.
274
275Multiple events are created from a single event specification when:
2761. Prefix or glob matching is used for the PMU name.
2772. Aliases, which are listed immediately after the Kernel PMU events
278 by perf list, are used.
279
249--smi-cost:: 280--smi-cost::
250Measure SMI cost if msr/aperf/ and msr/smi/ events are supported. 281Measure SMI cost if msr/aperf/ and msr/smi/ events are supported.
251 282
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 8a32cc77bead..114fda12aa49 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -55,7 +55,9 @@ Default is to monitor all CPUS.
55 55
56-F <freq>:: 56-F <freq>::
57--freq=<freq>:: 57--freq=<freq>::
58 Profile at this frequency. 58 Profile at this frequency. Use 'max' to use the currently maximum
59 allowed frequency, i.e. the value in the kernel.perf_event_max_sample_rate
60 sysctl.
59 61
60-i:: 62-i::
61--inherit:: 63--inherit::
@@ -65,6 +67,9 @@ Default is to monitor all CPUS.
65--vmlinux=<path>:: 67--vmlinux=<path>::
66 Path to vmlinux. Required for annotation functionality. 68 Path to vmlinux. Required for annotation functionality.
67 69
70--ignore-vmlinux::
71 Ignore vmlinux files.
72
68-m <pages>:: 73-m <pages>::
69--mmap-pages=<pages>:: 74--mmap-pages=<pages>::
70 Number of mmap data pages (must be a power of two) or size 75 Number of mmap data pages (must be a power of two) or size
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 33a88e984e66..5a7035c5c523 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -63,6 +63,31 @@ filter out the startup phase of the program, which is often very different.
63--uid=:: 63--uid=::
64 Record events in threads owned by uid. Name or number. 64 Record events in threads owned by uid. Name or number.
65 65
66-G::
67--cgroup::
68 Record events in threads in a cgroup.
69
70 Look for cgroups to set at the /sys/fs/cgroup/perf_event directory, then
71 remove the /sys/fs/cgroup/perf_event/ part and try:
72
73 perf trace -G A -e sched:*switch
74
75 Will set all raw_syscalls:sys_{enter,exit}, pgfault, vfs_getname, etc
76 _and_ sched:sched_switch to the 'A' cgroup, while:
77
78 perf trace -e sched:*switch -G A
79
80 will only set the sched:sched_switch event to the 'A' cgroup, all the
81 other events (raw_syscalls:sys_{enter,exit}, etc are left "without"
82 a cgroup (on the root cgroup, sys wide, etc).
83
84 Multiple cgroups:
85
86 perf trace -G A -e sched:*switch -G B
87
88 the syscall ones go to the 'A' cgroup, the sched:sched_switch goes
89 to the 'B' cgroup.
90
66--filter-pids=:: 91--filter-pids=::
67 Filter out events for these pids and for 'trace' itself (comma separated list). 92 Filter out events for these pids and for 'trace' itself (comma separated list).
68 93
diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
index f7d85e89a98a..d00f0d51cab8 100644
--- a/tools/perf/Documentation/perf.data-file-format.txt
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -485,10 +485,5 @@ in pmu-tools parser. This allows to read perf.data from python and dump it.
485quipper 485quipper
486 486
487The quipper C++ parser is available at 487The quipper C++ parser is available at
488https://chromium.googlesource.com/chromiumos/platform2 488http://github.com/google/perf_data_converter/tree/master/src/quipper
489 489
490It is under the chromiumos-wide-profiling/ subdirectory. This library can
491convert a perf data file to a protobuf and vice versa.
492
493Unfortunately this parser tends to be many versions behind and may not be able
494to parse data files generated by recent perf.
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 0dfdaa9fa81e..98ff73648b51 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -27,6 +27,8 @@ NO_SYSCALL_TABLE := 1
27# Additional ARCH settings for ppc 27# Additional ARCH settings for ppc
28ifeq ($(SRCARCH),powerpc) 28ifeq ($(SRCARCH),powerpc)
29 NO_PERF_REGS := 0 29 NO_PERF_REGS := 0
30 NO_SYSCALL_TABLE := 0
31 CFLAGS += -I$(OUTPUT)arch/powerpc/include/generated
30 LIBUNWIND_LIBS := -lunwind -lunwind-ppc64 32 LIBUNWIND_LIBS := -lunwind -lunwind-ppc64
31endif 33endif
32 34
@@ -73,7 +75,7 @@ endif
73# Disable it on all other architectures in case libdw unwind 75# Disable it on all other architectures in case libdw unwind
74# support is detected in system. Add supported architectures 76# support is detected in system. Add supported architectures
75# to the check. 77# to the check.
76ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm powerpc s390)) 78ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc s390))
77 NO_LIBDW_DWARF_UNWIND := 1 79 NO_LIBDW_DWARF_UNWIND := 1
78endif 80endif
79 81
@@ -666,25 +668,10 @@ else
666 ifneq ($(feature-libpython), 1) 668 ifneq ($(feature-libpython), 1)
667 $(call disable-python,No 'Python.h' (for Python 2.x support) was found: disables Python support - please install python-devel/python-dev) 669 $(call disable-python,No 'Python.h' (for Python 2.x support) was found: disables Python support - please install python-devel/python-dev)
668 else 670 else
669 ifneq ($(feature-libpython-version), 1) 671 LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
670 $(warning Python 3 is not yet supported; please set) 672 EXTLIBS += $(PYTHON_EMBED_LIBADD)
671 $(warning PYTHON and/or PYTHON_CONFIG appropriately.) 673 LANG_BINDINGS += $(obj-perf)python/perf.so
672 $(warning If you also have Python 2 installed, then) 674 $(call detected,CONFIG_LIBPYTHON)
673 $(warning try something like:)
674 $(warning $(and ,))
675 $(warning $(and ,) make PYTHON=python2)
676 $(warning $(and ,))
677 $(warning Otherwise, disable Python support entirely:)
678 $(warning $(and ,))
679 $(warning $(and ,) make NO_LIBPYTHON=1)
680 $(warning $(and ,))
681 $(error $(and ,))
682 else
683 LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
684 EXTLIBS += $(PYTHON_EMBED_LIBADD)
685 LANG_BINDINGS += $(obj-perf)python/perf.so
686 $(call detected,CONFIG_LIBPYTHON)
687 endif
688 endif 675 endif
689 endif 676 endif
690 endif 677 endif
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 9b0351d3ce34..f7517e1b73f8 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -146,12 +146,6 @@ define allow-override
146 $(eval $(1) = $(2))) 146 $(eval $(1) = $(2)))
147endef 147endef
148 148
149# Allow setting CC and AR and LD, or setting CROSS_COMPILE as a prefix.
150$(call allow-override,CC,$(CROSS_COMPILE)gcc)
151$(call allow-override,AR,$(CROSS_COMPILE)ar)
152$(call allow-override,LD,$(CROSS_COMPILE)ld)
153$(call allow-override,CXX,$(CROSS_COMPILE)g++)
154
155LD += $(EXTRA_LDFLAGS) 149LD += $(EXTRA_LDFLAGS)
156 150
157HOSTCC ?= gcc 151HOSTCC ?= gcc
@@ -302,7 +296,7 @@ PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
302PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/ 296PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
303export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP 297export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
304 298
305python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so 299python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf*.so
306 300
307PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) 301PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
308PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI) 302PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI)
@@ -479,7 +473,7 @@ $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_D
479 $(PYTHON_WORD) util/setup.py \ 473 $(PYTHON_WORD) util/setup.py \
480 --quiet build_ext; \ 474 --quiet build_ext; \
481 mkdir -p $(OUTPUT)python && \ 475 mkdir -p $(OUTPUT)python && \
482 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/ 476 cp $(PYTHON_EXTBUILD_LIB)perf*.so $(OUTPUT)python/
483 477
484please_set_SHELL_PATH_to_a_more_modern_shell: 478please_set_SHELL_PATH_to_a_more_modern_shell:
485 $(Q)$$(:) 479 $(Q)$$(:)
@@ -714,15 +708,15 @@ TAG_FILES= ../../include/uapi/linux/perf_event.h
714 708
715TAGS: 709TAGS:
716 $(QUIET_GEN)$(RM) TAGS; \ 710 $(QUIET_GEN)$(RM) TAGS; \
717 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs etags -a $(TAG_FILES) 711 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print -o -name '*.cpp' -print | xargs etags -a $(TAG_FILES)
718 712
719tags: 713tags:
720 $(QUIET_GEN)$(RM) tags; \ 714 $(QUIET_GEN)$(RM) tags; \
721 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs ctags -a $(TAG_FILES) 715 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print -o -name '*.cpp' -print | xargs ctags -a $(TAG_FILES)
722 716
723cscope: 717cscope:
724 $(QUIET_GEN)$(RM) cscope*; \ 718 $(QUIET_GEN)$(RM) cscope*; \
725 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs cscope -b $(TAG_FILES) 719 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print -o -name '*.cpp' -print | xargs cscope -b $(TAG_FILES)
726 720
727### Testing rules 721### Testing rules
728 722
diff --git a/tools/perf/arch/arm/util/auxtrace.c b/tools/perf/arch/arm/util/auxtrace.c
index 2323581b157d..fa639e3e52ac 100644
--- a/tools/perf/arch/arm/util/auxtrace.c
+++ b/tools/perf/arch/arm/util/auxtrace.c
@@ -68,7 +68,7 @@ struct auxtrace_record
68 bool found_spe = false; 68 bool found_spe = false;
69 static struct perf_pmu **arm_spe_pmus = NULL; 69 static struct perf_pmu **arm_spe_pmus = NULL;
70 static int nr_spes = 0; 70 static int nr_spes = 0;
71 int i; 71 int i = 0;
72 72
73 if (!evlist) 73 if (!evlist)
74 return NULL; 74 return NULL;
diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c
index fbfc055d3f4d..5c655ad4621e 100644
--- a/tools/perf/arch/arm/util/cs-etm.c
+++ b/tools/perf/arch/arm/util/cs-etm.c
@@ -298,12 +298,17 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
298{ 298{
299 int i; 299 int i;
300 int etmv3 = 0, etmv4 = 0; 300 int etmv3 = 0, etmv4 = 0;
301 const struct cpu_map *cpus = evlist->cpus; 301 struct cpu_map *event_cpus = evlist->cpus;
302 struct cpu_map *online_cpus = cpu_map__new(NULL);
302 303
303 /* cpu map is not empty, we have specific CPUs to work with */ 304 /* cpu map is not empty, we have specific CPUs to work with */
304 if (!cpu_map__empty(cpus)) { 305 if (!cpu_map__empty(event_cpus)) {
305 for (i = 0; i < cpu_map__nr(cpus); i++) { 306 for (i = 0; i < cpu__max_cpu(); i++) {
306 if (cs_etm_is_etmv4(itr, cpus->map[i])) 307 if (!cpu_map__has(event_cpus, i) ||
308 !cpu_map__has(online_cpus, i))
309 continue;
310
311 if (cs_etm_is_etmv4(itr, i))
307 etmv4++; 312 etmv4++;
308 else 313 else
309 etmv3++; 314 etmv3++;
@@ -311,6 +316,9 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
311 } else { 316 } else {
312 /* get configuration for all CPUs in the system */ 317 /* get configuration for all CPUs in the system */
313 for (i = 0; i < cpu__max_cpu(); i++) { 318 for (i = 0; i < cpu__max_cpu(); i++) {
319 if (!cpu_map__has(online_cpus, i))
320 continue;
321
314 if (cs_etm_is_etmv4(itr, i)) 322 if (cs_etm_is_etmv4(itr, i))
315 etmv4++; 323 etmv4++;
316 else 324 else
@@ -318,6 +326,8 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
318 } 326 }
319 } 327 }
320 328
329 cpu_map__put(online_cpus);
330
321 return (CS_ETM_HEADER_SIZE + 331 return (CS_ETM_HEADER_SIZE +
322 (etmv4 * CS_ETMV4_PRIV_SIZE) + 332 (etmv4 * CS_ETMV4_PRIV_SIZE) +
323 (etmv3 * CS_ETMV3_PRIV_SIZE)); 333 (etmv3 * CS_ETMV3_PRIV_SIZE));
@@ -447,7 +457,9 @@ static int cs_etm_info_fill(struct auxtrace_record *itr,
447 int i; 457 int i;
448 u32 offset; 458 u32 offset;
449 u64 nr_cpu, type; 459 u64 nr_cpu, type;
450 const struct cpu_map *cpus = session->evlist->cpus; 460 struct cpu_map *cpu_map;
461 struct cpu_map *event_cpus = session->evlist->cpus;
462 struct cpu_map *online_cpus = cpu_map__new(NULL);
451 struct cs_etm_recording *ptr = 463 struct cs_etm_recording *ptr =
452 container_of(itr, struct cs_etm_recording, itr); 464 container_of(itr, struct cs_etm_recording, itr);
453 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; 465 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
@@ -458,8 +470,21 @@ static int cs_etm_info_fill(struct auxtrace_record *itr,
458 if (!session->evlist->nr_mmaps) 470 if (!session->evlist->nr_mmaps)
459 return -EINVAL; 471 return -EINVAL;
460 472
461 /* If the cpu_map is empty all CPUs are involved */ 473 /* If the cpu_map is empty all online CPUs are involved */
462 nr_cpu = cpu_map__empty(cpus) ? cpu__max_cpu() : cpu_map__nr(cpus); 474 if (cpu_map__empty(event_cpus)) {
475 cpu_map = online_cpus;
476 } else {
477 /* Make sure all specified CPUs are online */
478 for (i = 0; i < cpu_map__nr(event_cpus); i++) {
479 if (cpu_map__has(event_cpus, i) &&
480 !cpu_map__has(online_cpus, i))
481 return -EINVAL;
482 }
483
484 cpu_map = event_cpus;
485 }
486
487 nr_cpu = cpu_map__nr(cpu_map);
463 /* Get PMU type as dynamically assigned by the core */ 488 /* Get PMU type as dynamically assigned by the core */
464 type = cs_etm_pmu->type; 489 type = cs_etm_pmu->type;
465 490
@@ -472,15 +497,11 @@ static int cs_etm_info_fill(struct auxtrace_record *itr,
472 497
473 offset = CS_ETM_SNAPSHOT + 1; 498 offset = CS_ETM_SNAPSHOT + 1;
474 499
475 /* cpu map is not empty, we have specific CPUs to work with */ 500 for (i = 0; i < cpu__max_cpu() && offset < priv_size; i++)
476 if (!cpu_map__empty(cpus)) { 501 if (cpu_map__has(cpu_map, i))
477 for (i = 0; i < cpu_map__nr(cpus) && offset < priv_size; i++)
478 cs_etm_get_metadata(cpus->map[i], &offset, itr, info);
479 } else {
480 /* get configuration for all CPUs in the system */
481 for (i = 0; i < cpu__max_cpu(); i++)
482 cs_etm_get_metadata(i, &offset, itr, info); 502 cs_etm_get_metadata(i, &offset, itr, info);
483 } 503
504 cpu_map__put(online_cpus);
484 505
485 return 0; 506 return 0;
486} 507}
diff --git a/tools/perf/arch/arm64/include/arch-tests.h b/tools/perf/arch/arm64/include/arch-tests.h
new file mode 100644
index 000000000000..90ec4c8cb880
--- /dev/null
+++ b/tools/perf/arch/arm64/include/arch-tests.h
@@ -0,0 +1,12 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef ARCH_TESTS_H
3#define ARCH_TESTS_H
4
5#ifdef HAVE_DWARF_UNWIND_SUPPORT
6struct thread;
7struct perf_sample;
8#endif
9
10extern struct test arch_tests[];
11
12#endif
diff --git a/tools/perf/arch/arm64/tests/Build b/tools/perf/arch/arm64/tests/Build
index b30eff9bcc83..883c57ff0c08 100644
--- a/tools/perf/arch/arm64/tests/Build
+++ b/tools/perf/arch/arm64/tests/Build
@@ -1,2 +1,4 @@
1libperf-y += regs_load.o 1libperf-y += regs_load.o
2libperf-y += dwarf-unwind.o 2libperf-y += dwarf-unwind.o
3
4libperf-y += arch-tests.o
diff --git a/tools/perf/arch/arm64/tests/arch-tests.c b/tools/perf/arch/arm64/tests/arch-tests.c
new file mode 100644
index 000000000000..5b1543c98022
--- /dev/null
+++ b/tools/perf/arch/arm64/tests/arch-tests.c
@@ -0,0 +1,16 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <string.h>
3#include "tests/tests.h"
4#include "arch-tests.h"
5
6struct test arch_tests[] = {
7#ifdef HAVE_DWARF_UNWIND_SUPPORT
8 {
9 .desc = "DWARF unwind",
10 .func = test__dwarf_unwind,
11 },
12#endif
13 {
14 .func = NULL,
15 },
16};
diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build
index c0b8dfef98ba..68f8a8eb3ad0 100644
--- a/tools/perf/arch/arm64/util/Build
+++ b/tools/perf/arch/arm64/util/Build
@@ -2,6 +2,7 @@ libperf-y += header.o
2libperf-y += sym-handling.o 2libperf-y += sym-handling.o
3libperf-$(CONFIG_DWARF) += dwarf-regs.o 3libperf-$(CONFIG_DWARF) += dwarf-regs.o
4libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o 4libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
5libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
5 6
6libperf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \ 7libperf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \
7 ../../arm/util/auxtrace.o \ 8 ../../arm/util/auxtrace.o \
diff --git a/tools/perf/arch/arm64/util/unwind-libdw.c b/tools/perf/arch/arm64/util/unwind-libdw.c
new file mode 100644
index 000000000000..7623d85e77f3
--- /dev/null
+++ b/tools/perf/arch/arm64/util/unwind-libdw.c
@@ -0,0 +1,60 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <elfutils/libdwfl.h>
3#include "../../util/unwind-libdw.h"
4#include "../../util/perf_regs.h"
5#include "../../util/event.h"
6
7bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
8{
9 struct unwind_info *ui = arg;
10 struct regs_dump *user_regs = &ui->sample->user_regs;
11 Dwarf_Word dwarf_regs[PERF_REG_ARM64_MAX], dwarf_pc;
12
13#define REG(r) ({ \
14 Dwarf_Word val = 0; \
15 perf_reg_value(&val, user_regs, PERF_REG_ARM64_##r); \
16 val; \
17})
18
19 dwarf_regs[0] = REG(X0);
20 dwarf_regs[1] = REG(X1);
21 dwarf_regs[2] = REG(X2);
22 dwarf_regs[3] = REG(X3);
23 dwarf_regs[4] = REG(X4);
24 dwarf_regs[5] = REG(X5);
25 dwarf_regs[6] = REG(X6);
26 dwarf_regs[7] = REG(X7);
27 dwarf_regs[8] = REG(X8);
28 dwarf_regs[9] = REG(X9);
29 dwarf_regs[10] = REG(X10);
30 dwarf_regs[11] = REG(X11);
31 dwarf_regs[12] = REG(X12);
32 dwarf_regs[13] = REG(X13);
33 dwarf_regs[14] = REG(X14);
34 dwarf_regs[15] = REG(X15);
35 dwarf_regs[16] = REG(X16);
36 dwarf_regs[17] = REG(X17);
37 dwarf_regs[18] = REG(X18);
38 dwarf_regs[19] = REG(X19);
39 dwarf_regs[20] = REG(X20);
40 dwarf_regs[21] = REG(X21);
41 dwarf_regs[22] = REG(X22);
42 dwarf_regs[23] = REG(X23);
43 dwarf_regs[24] = REG(X24);
44 dwarf_regs[25] = REG(X25);
45 dwarf_regs[26] = REG(X26);
46 dwarf_regs[27] = REG(X27);
47 dwarf_regs[28] = REG(X28);
48 dwarf_regs[29] = REG(X29);
49 dwarf_regs[30] = REG(LR);
50 dwarf_regs[31] = REG(SP);
51
52 if (!dwfl_thread_state_registers(thread, 0, PERF_REG_ARM64_MAX,
53 dwarf_regs))
54 return false;
55
56 dwarf_pc = REG(PC);
57 dwfl_thread_state_register_pc(thread, dwarf_pc);
58
59 return true;
60}
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index 42dab7c8f508..a111239df182 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -6,3 +6,28 @@ endif
6HAVE_KVM_STAT_SUPPORT := 1 6HAVE_KVM_STAT_SUPPORT := 1
7PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 7PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
8PERF_HAVE_JITDUMP := 1 8PERF_HAVE_JITDUMP := 1
9
10#
11# Syscall table generation for perf
12#
13
14out := $(OUTPUT)arch/powerpc/include/generated/asm
15header32 := $(out)/syscalls_32.c
16header64 := $(out)/syscalls_64.c
17sysdef := $(srctree)/tools/arch/powerpc/include/uapi/asm/unistd.h
18sysprf := $(srctree)/tools/perf/arch/powerpc/entry/syscalls/
19systbl := $(sysprf)/mksyscalltbl
20
21# Create output directory if not already present
22_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
23
24$(header64): $(sysdef) $(systbl)
25 $(Q)$(SHELL) '$(systbl)' '64' '$(CC)' $(sysdef) > $@
26
27$(header32): $(sysdef) $(systbl)
28 $(Q)$(SHELL) '$(systbl)' '32' '$(CC)' $(sysdef) > $@
29
30clean::
31 $(call QUIET_CLEAN, powerpc) $(RM) $(header32) $(header64)
32
33archheaders: $(header32) $(header64)
diff --git a/tools/perf/arch/powerpc/entry/syscalls/mksyscalltbl b/tools/perf/arch/powerpc/entry/syscalls/mksyscalltbl
new file mode 100755
index 000000000000..ef52e1dd694b
--- /dev/null
+++ b/tools/perf/arch/powerpc/entry/syscalls/mksyscalltbl
@@ -0,0 +1,37 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3#
4# Generate system call table for perf. Derived from
5# s390 script.
6#
7# Copyright IBM Corp. 2017
8# Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
9# Changed by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
10
11wordsize=$1
12gcc=$2
13input=$3
14
15if ! test -r $input; then
16 echo "Could not read input file" >&2
17 exit 1
18fi
19
20create_table()
21{
22 local wordsize=$1
23 local max_nr
24
25 echo "static const char *syscalltbl_powerpc_${wordsize}[] = {"
26 while read sc nr; do
27 printf '\t[%d] = "%s",\n' $nr $sc
28 max_nr=$nr
29 done
30 echo '};'
31 echo "#define SYSCALLTBL_POWERPC_${wordsize}_MAX_ID $max_nr"
32}
33
34$gcc -m${wordsize} -E -dM -x c $input \
35 |sed -ne 's/^#define __NR_//p' \
36 |sort -t' ' -k2 -nu \
37 |create_table ${wordsize}
diff --git a/tools/perf/arch/s390/Makefile b/tools/perf/arch/s390/Makefile
index 48228de415d0..dfa6e3103437 100644
--- a/tools/perf/arch/s390/Makefile
+++ b/tools/perf/arch/s390/Makefile
@@ -10,15 +10,19 @@ PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
10 10
11out := $(OUTPUT)arch/s390/include/generated/asm 11out := $(OUTPUT)arch/s390/include/generated/asm
12header := $(out)/syscalls_64.c 12header := $(out)/syscalls_64.c
13sysdef := $(srctree)/tools/arch/s390/include/uapi/asm/unistd.h 13syskrn := $(srctree)/arch/s390/kernel/syscalls/syscall.tbl
14sysprf := $(srctree)/tools/perf/arch/s390/entry/syscalls/ 14sysprf := $(srctree)/tools/perf/arch/s390/entry/syscalls
15sysdef := $(sysprf)/syscall.tbl
15systbl := $(sysprf)/mksyscalltbl 16systbl := $(sysprf)/mksyscalltbl
16 17
17# Create output directory if not already present 18# Create output directory if not already present
18_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)') 19_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
19 20
20$(header): $(sysdef) $(systbl) 21$(header): $(sysdef) $(systbl)
21 $(Q)$(SHELL) '$(systbl)' '$(CC)' $(sysdef) > $@ 22 @(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \
23 (diff -B $(sysdef) $(syskrn) >/dev/null) \
24 || echo "Warning: Kernel ABI header at '$(sysdef)' differs from latest version at '$(syskrn)'" >&2 )) || true
25 $(Q)$(SHELL) '$(systbl)' $(sysdef) > $@
22 26
23clean:: 27clean::
24 $(call QUIET_CLEAN, s390) $(RM) $(header) 28 $(call QUIET_CLEAN, s390) $(RM) $(header)
diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c
index 8c72b44444cb..cee4e2f7c057 100644
--- a/tools/perf/arch/s390/annotate/instructions.c
+++ b/tools/perf/arch/s390/annotate/instructions.c
@@ -1,6 +1,113 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2#include <linux/compiler.h> 2#include <linux/compiler.h>
3 3
4static int s390_call__parse(struct arch *arch, struct ins_operands *ops,
5 struct map_symbol *ms)
6{
7 char *endptr, *tok, *name;
8 struct map *map = ms->map;
9 struct addr_map_symbol target = {
10 .map = map,
11 };
12
13 tok = strchr(ops->raw, ',');
14 if (!tok)
15 return -1;
16
17 ops->target.addr = strtoull(tok + 1, &endptr, 16);
18
19 name = strchr(endptr, '<');
20 if (name == NULL)
21 return -1;
22
23 name++;
24
25 if (arch->objdump.skip_functions_char &&
26 strchr(name, arch->objdump.skip_functions_char))
27 return -1;
28
29 tok = strchr(name, '>');
30 if (tok == NULL)
31 return -1;
32
33 *tok = '\0';
34 ops->target.name = strdup(name);
35 *tok = '>';
36
37 if (ops->target.name == NULL)
38 return -1;
39 target.addr = map__objdump_2mem(map, ops->target.addr);
40
41 if (map_groups__find_ams(&target) == 0 &&
42 map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
43 ops->target.sym = target.sym;
44
45 return 0;
46}
47
48static int call__scnprintf(struct ins *ins, char *bf, size_t size,
49 struct ins_operands *ops);
50
51static struct ins_ops s390_call_ops = {
52 .parse = s390_call__parse,
53 .scnprintf = call__scnprintf,
54};
55
56static int s390_mov__parse(struct arch *arch __maybe_unused,
57 struct ins_operands *ops,
58 struct map_symbol *ms __maybe_unused)
59{
60 char *s = strchr(ops->raw, ','), *target, *endptr;
61
62 if (s == NULL)
63 return -1;
64
65 *s = '\0';
66 ops->source.raw = strdup(ops->raw);
67 *s = ',';
68
69 if (ops->source.raw == NULL)
70 return -1;
71
72 target = ++s;
73 ops->target.raw = strdup(target);
74 if (ops->target.raw == NULL)
75 goto out_free_source;
76
77 ops->target.addr = strtoull(target, &endptr, 16);
78 if (endptr == target)
79 goto out_free_target;
80
81 s = strchr(endptr, '<');
82 if (s == NULL)
83 goto out_free_target;
84 endptr = strchr(s + 1, '>');
85 if (endptr == NULL)
86 goto out_free_target;
87
88 *endptr = '\0';
89 ops->target.name = strdup(s + 1);
90 *endptr = '>';
91 if (ops->target.name == NULL)
92 goto out_free_target;
93
94 return 0;
95
96out_free_target:
97 zfree(&ops->target.raw);
98out_free_source:
99 zfree(&ops->source.raw);
100 return -1;
101}
102
103static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
104 struct ins_operands *ops);
105
106static struct ins_ops s390_mov_ops = {
107 .parse = s390_mov__parse,
108 .scnprintf = mov__scnprintf,
109};
110
4static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *name) 111static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *name)
5{ 112{
6 struct ins_ops *ops = NULL; 113 struct ins_ops *ops = NULL;
@@ -14,21 +121,54 @@ static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *na
14 if (!strcmp(name, "bras") || 121 if (!strcmp(name, "bras") ||
15 !strcmp(name, "brasl") || 122 !strcmp(name, "brasl") ||
16 !strcmp(name, "basr")) 123 !strcmp(name, "basr"))
17 ops = &call_ops; 124 ops = &s390_call_ops;
18 if (!strcmp(name, "br")) 125 if (!strcmp(name, "br"))
19 ops = &ret_ops; 126 ops = &ret_ops;
127 /* override load/store relative to PC */
128 if (!strcmp(name, "lrl") ||
129 !strcmp(name, "lgrl") ||
130 !strcmp(name, "lgfrl") ||
131 !strcmp(name, "llgfrl") ||
132 !strcmp(name, "strl") ||
133 !strcmp(name, "stgrl"))
134 ops = &s390_mov_ops;
20 135
21 if (ops) 136 if (ops)
22 arch__associate_ins_ops(arch, name, ops); 137 arch__associate_ins_ops(arch, name, ops);
23 return ops; 138 return ops;
24} 139}
25 140
141static int s390__cpuid_parse(struct arch *arch, char *cpuid)
142{
143 unsigned int family;
144 char model[16], model_c[16], cpumf_v[16], cpumf_a[16];
145 int ret;
146
147 /*
148 * cpuid string format:
149 * "IBM,family,model-capacity,model[,cpum_cf-version,cpum_cf-authorization]"
150 */
151 ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%s", &family, model_c,
152 model, cpumf_v, cpumf_a);
153 if (ret >= 2) {
154 arch->family = family;
155 arch->model = 0;
156 return 0;
157 }
158
159 return -1;
160}
161
26static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused) 162static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
27{ 163{
164 int err = 0;
165
28 if (!arch->initialized) { 166 if (!arch->initialized) {
29 arch->initialized = true; 167 arch->initialized = true;
30 arch->associate_instruction_ops = s390__associate_ins_ops; 168 arch->associate_instruction_ops = s390__associate_ins_ops;
169 if (cpuid)
170 err = s390__cpuid_parse(arch, cpuid);
31 } 171 }
32 172
33 return 0; 173 return err;
34} 174}
diff --git a/tools/perf/arch/s390/entry/syscalls/mksyscalltbl b/tools/perf/arch/s390/entry/syscalls/mksyscalltbl
index 7fa0d0abd419..72ecbb676370 100755
--- a/tools/perf/arch/s390/entry/syscalls/mksyscalltbl
+++ b/tools/perf/arch/s390/entry/syscalls/mksyscalltbl
@@ -3,25 +3,23 @@
3# 3#
4# Generate system call table for perf 4# Generate system call table for perf
5# 5#
6# 6# Copyright IBM Corp. 2017, 2018
7# Copyright IBM Corp. 2017
8# Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com> 7# Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
9# 8#
10 9
11gcc=$1 10SYSCALL_TBL=$1
12input=$2
13 11
14if ! test -r $input; then 12if ! test -r $SYSCALL_TBL; then
15 echo "Could not read input file" >&2 13 echo "Could not read input file" >&2
16 exit 1 14 exit 1
17fi 15fi
18 16
19create_table() 17create_table()
20{ 18{
21 local max_nr 19 local max_nr nr abi sc discard
22 20
23 echo 'static const char *syscalltbl_s390_64[] = {' 21 echo 'static const char *syscalltbl_s390_64[] = {'
24 while read sc nr; do 22 while read nr abi sc discard; do
25 printf '\t[%d] = "%s",\n' $nr $sc 23 printf '\t[%d] = "%s",\n' $nr $sc
26 max_nr=$nr 24 max_nr=$nr
27 done 25 done
@@ -29,8 +27,6 @@ create_table()
29 echo "#define SYSCALLTBL_S390_64_MAX_ID $max_nr" 27 echo "#define SYSCALLTBL_S390_64_MAX_ID $max_nr"
30} 28}
31 29
32 30grep -E "^[[:digit:]]+[[:space:]]+(common|64)" $SYSCALL_TBL \
33$gcc -m64 -E -dM -x c $input \ 31 |sort -k1 -n \
34 |sed -ne 's/^#define __NR_//p' \
35 |sort -t' ' -k2 -nu \
36 |create_table 32 |create_table
diff --git a/tools/perf/arch/s390/entry/syscalls/syscall.tbl b/tools/perf/arch/s390/entry/syscalls/syscall.tbl
new file mode 100644
index 000000000000..b38d48464368
--- /dev/null
+++ b/tools/perf/arch/s390/entry/syscalls/syscall.tbl
@@ -0,0 +1,390 @@
1# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
2#
3# System call table for s390
4#
5# Format:
6#
7# <nr> <abi> <syscall> <entry-64bit> <compat-entry>
8#
9# where <abi> can be common, 64, or 32
10
111 common exit sys_exit sys_exit
122 common fork sys_fork sys_fork
133 common read sys_read compat_sys_s390_read
144 common write sys_write compat_sys_s390_write
155 common open sys_open compat_sys_open
166 common close sys_close sys_close
177 common restart_syscall sys_restart_syscall sys_restart_syscall
188 common creat sys_creat compat_sys_creat
199 common link sys_link compat_sys_link
2010 common unlink sys_unlink compat_sys_unlink
2111 common execve sys_execve compat_sys_execve
2212 common chdir sys_chdir compat_sys_chdir
2313 32 time - compat_sys_time
2414 common mknod sys_mknod compat_sys_mknod
2515 common chmod sys_chmod compat_sys_chmod
2616 32 lchown - compat_sys_s390_lchown16
2719 common lseek sys_lseek compat_sys_lseek
2820 common getpid sys_getpid sys_getpid
2921 common mount sys_mount compat_sys_mount
3022 common umount sys_oldumount compat_sys_oldumount
3123 32 setuid - compat_sys_s390_setuid16
3224 32 getuid - compat_sys_s390_getuid16
3325 32 stime - compat_sys_stime
3426 common ptrace sys_ptrace compat_sys_ptrace
3527 common alarm sys_alarm sys_alarm
3629 common pause sys_pause sys_pause
3730 common utime sys_utime compat_sys_utime
3833 common access sys_access compat_sys_access
3934 common nice sys_nice sys_nice
4036 common sync sys_sync sys_sync
4137 common kill sys_kill sys_kill
4238 common rename sys_rename compat_sys_rename
4339 common mkdir sys_mkdir compat_sys_mkdir
4440 common rmdir sys_rmdir compat_sys_rmdir
4541 common dup sys_dup sys_dup
4642 common pipe sys_pipe compat_sys_pipe
4743 common times sys_times compat_sys_times
4845 common brk sys_brk compat_sys_brk
4946 32 setgid - compat_sys_s390_setgid16
5047 32 getgid - compat_sys_s390_getgid16
5148 common signal sys_signal compat_sys_signal
5249 32 geteuid - compat_sys_s390_geteuid16
5350 32 getegid - compat_sys_s390_getegid16
5451 common acct sys_acct compat_sys_acct
5552 common umount2 sys_umount compat_sys_umount
5654 common ioctl sys_ioctl compat_sys_ioctl
5755 common fcntl sys_fcntl compat_sys_fcntl
5857 common setpgid sys_setpgid sys_setpgid
5960 common umask sys_umask sys_umask
6061 common chroot sys_chroot compat_sys_chroot
6162 common ustat sys_ustat compat_sys_ustat
6263 common dup2 sys_dup2 sys_dup2
6364 common getppid sys_getppid sys_getppid
6465 common getpgrp sys_getpgrp sys_getpgrp
6566 common setsid sys_setsid sys_setsid
6667 common sigaction sys_sigaction compat_sys_sigaction
6770 32 setreuid - compat_sys_s390_setreuid16
6871 32 setregid - compat_sys_s390_setregid16
6972 common sigsuspend sys_sigsuspend compat_sys_sigsuspend
7073 common sigpending sys_sigpending compat_sys_sigpending
7174 common sethostname sys_sethostname compat_sys_sethostname
7275 common setrlimit sys_setrlimit compat_sys_setrlimit
7376 32 getrlimit - compat_sys_old_getrlimit
7477 common getrusage sys_getrusage compat_sys_getrusage
7578 common gettimeofday sys_gettimeofday compat_sys_gettimeofday
7679 common settimeofday sys_settimeofday compat_sys_settimeofday
7780 32 getgroups - compat_sys_s390_getgroups16
7881 32 setgroups - compat_sys_s390_setgroups16
7983 common symlink sys_symlink compat_sys_symlink
8085 common readlink sys_readlink compat_sys_readlink
8186 common uselib sys_uselib compat_sys_uselib
8287 common swapon sys_swapon compat_sys_swapon
8388 common reboot sys_reboot compat_sys_reboot
8489 common readdir - compat_sys_old_readdir
8590 common mmap sys_old_mmap compat_sys_s390_old_mmap
8691 common munmap sys_munmap compat_sys_munmap
8792 common truncate sys_truncate compat_sys_truncate
8893 common ftruncate sys_ftruncate compat_sys_ftruncate
8994 common fchmod sys_fchmod sys_fchmod
9095 32 fchown - compat_sys_s390_fchown16
9196 common getpriority sys_getpriority sys_getpriority
9297 common setpriority sys_setpriority sys_setpriority
9399 common statfs sys_statfs compat_sys_statfs
94100 common fstatfs sys_fstatfs compat_sys_fstatfs
95101 32 ioperm - -
96102 common socketcall sys_socketcall compat_sys_socketcall
97103 common syslog sys_syslog compat_sys_syslog
98104 common setitimer sys_setitimer compat_sys_setitimer
99105 common getitimer sys_getitimer compat_sys_getitimer
100106 common stat sys_newstat compat_sys_newstat
101107 common lstat sys_newlstat compat_sys_newlstat
102108 common fstat sys_newfstat compat_sys_newfstat
103110 common lookup_dcookie sys_lookup_dcookie compat_sys_lookup_dcookie
104111 common vhangup sys_vhangup sys_vhangup
105112 common idle - -
106114 common wait4 sys_wait4 compat_sys_wait4
107115 common swapoff sys_swapoff compat_sys_swapoff
108116 common sysinfo sys_sysinfo compat_sys_sysinfo
109117 common ipc sys_s390_ipc compat_sys_s390_ipc
110118 common fsync sys_fsync sys_fsync
111119 common sigreturn sys_sigreturn compat_sys_sigreturn
112120 common clone sys_clone compat_sys_clone
113121 common setdomainname sys_setdomainname compat_sys_setdomainname
114122 common uname sys_newuname compat_sys_newuname
115124 common adjtimex sys_adjtimex compat_sys_adjtimex
116125 common mprotect sys_mprotect compat_sys_mprotect
117126 common sigprocmask sys_sigprocmask compat_sys_sigprocmask
118127 common create_module - -
119128 common init_module sys_init_module compat_sys_init_module
120129 common delete_module sys_delete_module compat_sys_delete_module
121130 common get_kernel_syms - -
122131 common quotactl sys_quotactl compat_sys_quotactl
123132 common getpgid sys_getpgid sys_getpgid
124133 common fchdir sys_fchdir sys_fchdir
125134 common bdflush sys_bdflush compat_sys_bdflush
126135 common sysfs sys_sysfs compat_sys_sysfs
127136 common personality sys_s390_personality sys_s390_personality
128137 common afs_syscall - -
129138 32 setfsuid - compat_sys_s390_setfsuid16
130139 32 setfsgid - compat_sys_s390_setfsgid16
131140 32 _llseek - compat_sys_llseek
132141 common getdents sys_getdents compat_sys_getdents
133142 32 _newselect - compat_sys_select
134142 64 select sys_select -
135143 common flock sys_flock sys_flock
136144 common msync sys_msync compat_sys_msync
137145 common readv sys_readv compat_sys_readv
138146 common writev sys_writev compat_sys_writev
139147 common getsid sys_getsid sys_getsid
140148 common fdatasync sys_fdatasync sys_fdatasync
141149 common _sysctl sys_sysctl compat_sys_sysctl
142150 common mlock sys_mlock compat_sys_mlock
143151 common munlock sys_munlock compat_sys_munlock
144152 common mlockall sys_mlockall sys_mlockall
145153 common munlockall sys_munlockall sys_munlockall
146154 common sched_setparam sys_sched_setparam compat_sys_sched_setparam
147155 common sched_getparam sys_sched_getparam compat_sys_sched_getparam
148156 common sched_setscheduler sys_sched_setscheduler compat_sys_sched_setscheduler
149157 common sched_getscheduler sys_sched_getscheduler sys_sched_getscheduler
150158 common sched_yield sys_sched_yield sys_sched_yield
151159 common sched_get_priority_max sys_sched_get_priority_max sys_sched_get_priority_max
152160 common sched_get_priority_min sys_sched_get_priority_min sys_sched_get_priority_min
153161 common sched_rr_get_interval sys_sched_rr_get_interval compat_sys_sched_rr_get_interval
154162 common nanosleep sys_nanosleep compat_sys_nanosleep
155163 common mremap sys_mremap compat_sys_mremap
156164 32 setresuid - compat_sys_s390_setresuid16
157165 32 getresuid - compat_sys_s390_getresuid16
158167 common query_module - -
159168 common poll sys_poll compat_sys_poll
160169 common nfsservctl - -
161170 32 setresgid - compat_sys_s390_setresgid16
162171 32 getresgid - compat_sys_s390_getresgid16
163172 common prctl sys_prctl compat_sys_prctl
164173 common rt_sigreturn sys_rt_sigreturn compat_sys_rt_sigreturn
165174 common rt_sigaction sys_rt_sigaction compat_sys_rt_sigaction
166175 common rt_sigprocmask sys_rt_sigprocmask compat_sys_rt_sigprocmask
167176 common rt_sigpending sys_rt_sigpending compat_sys_rt_sigpending
168177 common rt_sigtimedwait sys_rt_sigtimedwait compat_sys_rt_sigtimedwait
169178 common rt_sigqueueinfo sys_rt_sigqueueinfo compat_sys_rt_sigqueueinfo
170179 common rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend
171180 common pread64 sys_pread64 compat_sys_s390_pread64
172181 common pwrite64 sys_pwrite64 compat_sys_s390_pwrite64
173182 32 chown - compat_sys_s390_chown16
174183 common getcwd sys_getcwd compat_sys_getcwd
175184 common capget sys_capget compat_sys_capget
176185 common capset sys_capset compat_sys_capset
177186 common sigaltstack sys_sigaltstack compat_sys_sigaltstack
178187 common sendfile sys_sendfile64 compat_sys_sendfile
179188 common getpmsg - -
180189 common putpmsg - -
181190 common vfork sys_vfork sys_vfork
182191 32 ugetrlimit - compat_sys_getrlimit
183191 64 getrlimit sys_getrlimit -
184192 32 mmap2 - compat_sys_s390_mmap2
185193 32 truncate64 - compat_sys_s390_truncate64
186194 32 ftruncate64 - compat_sys_s390_ftruncate64
187195 32 stat64 - compat_sys_s390_stat64
188196 32 lstat64 - compat_sys_s390_lstat64
189197 32 fstat64 - compat_sys_s390_fstat64
190198 32 lchown32 - compat_sys_lchown
191198 64 lchown sys_lchown -
192199 32 getuid32 - sys_getuid
193199 64 getuid sys_getuid -
194200 32 getgid32 - sys_getgid
195200 64 getgid sys_getgid -
196201 32 geteuid32 - sys_geteuid
197201 64 geteuid sys_geteuid -
198202 32 getegid32 - sys_getegid
199202 64 getegid sys_getegid -
200203 32 setreuid32 - sys_setreuid
201203 64 setreuid sys_setreuid -
202204 32 setregid32 - sys_setregid
203204 64 setregid sys_setregid -
204205 32 getgroups32 - compat_sys_getgroups
205205 64 getgroups sys_getgroups -
206206 32 setgroups32 - compat_sys_setgroups
207206 64 setgroups sys_setgroups -
208207 32 fchown32 - sys_fchown
209207 64 fchown sys_fchown -
210208 32 setresuid32 - sys_setresuid
211208 64 setresuid sys_setresuid -
212209 32 getresuid32 - compat_sys_getresuid
213209 64 getresuid sys_getresuid -
214210 32 setresgid32 - sys_setresgid
215210 64 setresgid sys_setresgid -
216211 32 getresgid32 - compat_sys_getresgid
217211 64 getresgid sys_getresgid -
218212 32 chown32 - compat_sys_chown
219212 64 chown sys_chown -
220213 32 setuid32 - sys_setuid
221213 64 setuid sys_setuid -
222214 32 setgid32 - sys_setgid
223214 64 setgid sys_setgid -
224215 32 setfsuid32 - sys_setfsuid
225215 64 setfsuid sys_setfsuid -
226216 32 setfsgid32 - sys_setfsgid
227216 64 setfsgid sys_setfsgid -
228217 common pivot_root sys_pivot_root compat_sys_pivot_root
229218 common mincore sys_mincore compat_sys_mincore
230219 common madvise sys_madvise compat_sys_madvise
231220 common getdents64 sys_getdents64 compat_sys_getdents64
232221 32 fcntl64 - compat_sys_fcntl64
233222 common readahead sys_readahead compat_sys_s390_readahead
234223 32 sendfile64 - compat_sys_sendfile64
235224 common setxattr sys_setxattr compat_sys_setxattr
236225 common lsetxattr sys_lsetxattr compat_sys_lsetxattr
237226 common fsetxattr sys_fsetxattr compat_sys_fsetxattr
238227 common getxattr sys_getxattr compat_sys_getxattr
239228 common lgetxattr sys_lgetxattr compat_sys_lgetxattr
240229 common fgetxattr sys_fgetxattr compat_sys_fgetxattr
241230 common listxattr sys_listxattr compat_sys_listxattr
242231 common llistxattr sys_llistxattr compat_sys_llistxattr
243232 common flistxattr sys_flistxattr compat_sys_flistxattr
244233 common removexattr sys_removexattr compat_sys_removexattr
245234 common lremovexattr sys_lremovexattr compat_sys_lremovexattr
246235 common fremovexattr sys_fremovexattr compat_sys_fremovexattr
247236 common gettid sys_gettid sys_gettid
248237 common tkill sys_tkill sys_tkill
249238 common futex sys_futex compat_sys_futex
250239 common sched_setaffinity sys_sched_setaffinity compat_sys_sched_setaffinity
251240 common sched_getaffinity sys_sched_getaffinity compat_sys_sched_getaffinity
252241 common tgkill sys_tgkill sys_tgkill
253243 common io_setup sys_io_setup compat_sys_io_setup
254244 common io_destroy sys_io_destroy compat_sys_io_destroy
255245 common io_getevents sys_io_getevents compat_sys_io_getevents
256246 common io_submit sys_io_submit compat_sys_io_submit
257247 common io_cancel sys_io_cancel compat_sys_io_cancel
258248 common exit_group sys_exit_group sys_exit_group
259249 common epoll_create sys_epoll_create sys_epoll_create
260250 common epoll_ctl sys_epoll_ctl compat_sys_epoll_ctl
261251 common epoll_wait sys_epoll_wait compat_sys_epoll_wait
262252 common set_tid_address sys_set_tid_address compat_sys_set_tid_address
263253 common fadvise64 sys_fadvise64_64 compat_sys_s390_fadvise64
264254 common timer_create sys_timer_create compat_sys_timer_create
265255 common timer_settime sys_timer_settime compat_sys_timer_settime
266256 common timer_gettime sys_timer_gettime compat_sys_timer_gettime
267257 common timer_getoverrun sys_timer_getoverrun sys_timer_getoverrun
268258 common timer_delete sys_timer_delete sys_timer_delete
269259 common clock_settime sys_clock_settime compat_sys_clock_settime
270260 common clock_gettime sys_clock_gettime compat_sys_clock_gettime
271261 common clock_getres sys_clock_getres compat_sys_clock_getres
272262 common clock_nanosleep sys_clock_nanosleep compat_sys_clock_nanosleep
273264 32 fadvise64_64 - compat_sys_s390_fadvise64_64
274265 common statfs64 sys_statfs64 compat_sys_statfs64
275266 common fstatfs64 sys_fstatfs64 compat_sys_fstatfs64
276267 common remap_file_pages sys_remap_file_pages compat_sys_remap_file_pages
277268 common mbind sys_mbind compat_sys_mbind
278269 common get_mempolicy sys_get_mempolicy compat_sys_get_mempolicy
279270 common set_mempolicy sys_set_mempolicy compat_sys_set_mempolicy
280271 common mq_open sys_mq_open compat_sys_mq_open
281272 common mq_unlink sys_mq_unlink compat_sys_mq_unlink
282273 common mq_timedsend sys_mq_timedsend compat_sys_mq_timedsend
283274 common mq_timedreceive sys_mq_timedreceive compat_sys_mq_timedreceive
284275 common mq_notify sys_mq_notify compat_sys_mq_notify
285276 common mq_getsetattr sys_mq_getsetattr compat_sys_mq_getsetattr
286277 common kexec_load sys_kexec_load compat_sys_kexec_load
287278 common add_key sys_add_key compat_sys_add_key
288279 common request_key sys_request_key compat_sys_request_key
289280 common keyctl sys_keyctl compat_sys_keyctl
290281 common waitid sys_waitid compat_sys_waitid
291282 common ioprio_set sys_ioprio_set sys_ioprio_set
292283 common ioprio_get sys_ioprio_get sys_ioprio_get
293284 common inotify_init sys_inotify_init sys_inotify_init
294285 common inotify_add_watch sys_inotify_add_watch compat_sys_inotify_add_watch
295286 common inotify_rm_watch sys_inotify_rm_watch sys_inotify_rm_watch
296287 common migrate_pages sys_migrate_pages compat_sys_migrate_pages
297288 common openat sys_openat compat_sys_openat
298289 common mkdirat sys_mkdirat compat_sys_mkdirat
299290 common mknodat sys_mknodat compat_sys_mknodat
300291 common fchownat sys_fchownat compat_sys_fchownat
301292 common futimesat sys_futimesat compat_sys_futimesat
302293 32 fstatat64 - compat_sys_s390_fstatat64
303293 64 newfstatat sys_newfstatat -
304294 common unlinkat sys_unlinkat compat_sys_unlinkat
305295 common renameat sys_renameat compat_sys_renameat
306296 common linkat sys_linkat compat_sys_linkat
307297 common symlinkat sys_symlinkat compat_sys_symlinkat
308298 common readlinkat sys_readlinkat compat_sys_readlinkat
309299 common fchmodat sys_fchmodat compat_sys_fchmodat
310300 common faccessat sys_faccessat compat_sys_faccessat
311301 common pselect6 sys_pselect6 compat_sys_pselect6
312302 common ppoll sys_ppoll compat_sys_ppoll
313303 common unshare sys_unshare compat_sys_unshare
314304 common set_robust_list sys_set_robust_list compat_sys_set_robust_list
315305 common get_robust_list sys_get_robust_list compat_sys_get_robust_list
316306 common splice sys_splice compat_sys_splice
317307 common sync_file_range sys_sync_file_range compat_sys_s390_sync_file_range
318308 common tee sys_tee compat_sys_tee
319309 common vmsplice sys_vmsplice compat_sys_vmsplice
320310 common move_pages sys_move_pages compat_sys_move_pages
321311 common getcpu sys_getcpu compat_sys_getcpu
322312 common epoll_pwait sys_epoll_pwait compat_sys_epoll_pwait
323313 common utimes sys_utimes compat_sys_utimes
324314 common fallocate sys_fallocate compat_sys_s390_fallocate
325315 common utimensat sys_utimensat compat_sys_utimensat
326316 common signalfd sys_signalfd compat_sys_signalfd
327317 common timerfd - -
328318 common eventfd sys_eventfd sys_eventfd
329319 common timerfd_create sys_timerfd_create sys_timerfd_create
330320 common timerfd_settime sys_timerfd_settime compat_sys_timerfd_settime
331321 common timerfd_gettime sys_timerfd_gettime compat_sys_timerfd_gettime
332322 common signalfd4 sys_signalfd4 compat_sys_signalfd4
333323 common eventfd2 sys_eventfd2 sys_eventfd2
334324 common inotify_init1 sys_inotify_init1 sys_inotify_init1
335325 common pipe2 sys_pipe2 compat_sys_pipe2
336326 common dup3 sys_dup3 sys_dup3
337327 common epoll_create1 sys_epoll_create1 sys_epoll_create1
338328 common preadv sys_preadv compat_sys_preadv
339329 common pwritev sys_pwritev compat_sys_pwritev
340330 common rt_tgsigqueueinfo sys_rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo
341331 common perf_event_open sys_perf_event_open compat_sys_perf_event_open
342332 common fanotify_init sys_fanotify_init sys_fanotify_init
343333 common fanotify_mark sys_fanotify_mark compat_sys_fanotify_mark
344334 common prlimit64 sys_prlimit64 compat_sys_prlimit64
345335 common name_to_handle_at sys_name_to_handle_at compat_sys_name_to_handle_at
346336 common open_by_handle_at sys_open_by_handle_at compat_sys_open_by_handle_at
347337 common clock_adjtime sys_clock_adjtime compat_sys_clock_adjtime
348338 common syncfs sys_syncfs sys_syncfs
349339 common setns sys_setns sys_setns
350340 common process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv
351341 common process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev
352342 common s390_runtime_instr sys_s390_runtime_instr sys_s390_runtime_instr
353343 common kcmp sys_kcmp compat_sys_kcmp
354344 common finit_module sys_finit_module compat_sys_finit_module
355345 common sched_setattr sys_sched_setattr compat_sys_sched_setattr
356346 common sched_getattr sys_sched_getattr compat_sys_sched_getattr
357347 common renameat2 sys_renameat2 compat_sys_renameat2
358348 common seccomp sys_seccomp compat_sys_seccomp
359349 common getrandom sys_getrandom compat_sys_getrandom
360350 common memfd_create sys_memfd_create compat_sys_memfd_create
361351 common bpf sys_bpf compat_sys_bpf
362352 common s390_pci_mmio_write sys_s390_pci_mmio_write compat_sys_s390_pci_mmio_write
363353 common s390_pci_mmio_read sys_s390_pci_mmio_read compat_sys_s390_pci_mmio_read
364354 common execveat sys_execveat compat_sys_execveat
365355 common userfaultfd sys_userfaultfd sys_userfaultfd
366356 common membarrier sys_membarrier sys_membarrier
367357 common recvmmsg sys_recvmmsg compat_sys_recvmmsg
368358 common sendmmsg sys_sendmmsg compat_sys_sendmmsg
369359 common socket sys_socket sys_socket
370360 common socketpair sys_socketpair compat_sys_socketpair
371361 common bind sys_bind compat_sys_bind
372362 common connect sys_connect compat_sys_connect
373363 common listen sys_listen sys_listen
374364 common accept4 sys_accept4 compat_sys_accept4
375365 common getsockopt sys_getsockopt compat_sys_getsockopt
376366 common setsockopt sys_setsockopt compat_sys_setsockopt
377367 common getsockname sys_getsockname compat_sys_getsockname
378368 common getpeername sys_getpeername compat_sys_getpeername
379369 common sendto sys_sendto compat_sys_sendto
380370 common sendmsg sys_sendmsg compat_sys_sendmsg
381371 common recvfrom sys_recvfrom compat_sys_recvfrom
382372 common recvmsg sys_recvmsg compat_sys_recvmsg
383373 common shutdown sys_shutdown sys_shutdown
384374 common mlock2 sys_mlock2 compat_sys_mlock2
385375 common copy_file_range sys_copy_file_range compat_sys_copy_file_range
386376 common preadv2 sys_preadv2 compat_sys_preadv2
387377 common pwritev2 sys_pwritev2 compat_sys_pwritev2
388378 common s390_guarded_storage sys_s390_guarded_storage compat_sys_s390_guarded_storage
389379 common statx sys_statx compat_sys_statx
390380 common s390_sthyi sys_s390_sthyi compat_sys_s390_sthyi
diff --git a/tools/perf/arch/s390/util/header.c b/tools/perf/arch/s390/util/header.c
index 9fa6c3e5782c..a4c30f1c70be 100644
--- a/tools/perf/arch/s390/util/header.c
+++ b/tools/perf/arch/s390/util/header.c
@@ -1,8 +1,9 @@
1/* 1/*
2 * Implementation of get_cpuid(). 2 * Implementation of get_cpuid().
3 * 3 *
4 * Copyright 2014 IBM Corp. 4 * Copyright IBM Corp. 2014, 2018
5 * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com> 5 * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com>
6 * Thomas Richter <tmricht@linux.vnet.ibm.com>
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License (version 2 only) 9 * it under the terms of the GNU General Public License (version 2 only)
@@ -13,16 +14,153 @@
13#include <unistd.h> 14#include <unistd.h>
14#include <stdio.h> 15#include <stdio.h>
15#include <string.h> 16#include <string.h>
17#include <ctype.h>
16 18
17#include "../../util/header.h" 19#include "../../util/header.h"
20#include "../../util/util.h"
21
22#define SYSINFO_MANU "Manufacturer:"
23#define SYSINFO_TYPE "Type:"
24#define SYSINFO_MODEL "Model:"
25#define SRVLVL_CPUMF "CPU-MF:"
26#define SRVLVL_VERSION "version="
27#define SRVLVL_AUTHORIZATION "authorization="
28#define SYSINFO "/proc/sysinfo"
29#define SRVLVL "/proc/service_levels"
18 30
19int get_cpuid(char *buffer, size_t sz) 31int get_cpuid(char *buffer, size_t sz)
20{ 32{
21 const char *cpuid = "IBM/S390"; 33 char *cp, *line = NULL, *line2;
34 char type[8], model[33], version[8], manufacturer[32], authorization[8];
35 int tpsize = 0, mdsize = 0, vssize = 0, mfsize = 0, atsize = 0;
36 int read;
37 unsigned long line_sz;
38 size_t nbytes;
39 FILE *sysinfo;
40
41 /*
42 * Scan /proc/sysinfo line by line and read out values for
43 * Manufacturer:, Type: and Model:, for example:
44 * Manufacturer: IBM
45 * Type: 2964
46 * Model: 702 N96
47 * The first word is the Model Capacity and the second word is
48 * Model (can be omitted). Both words have a maximum size of 16
49 * bytes.
50 */
51 memset(manufacturer, 0, sizeof(manufacturer));
52 memset(type, 0, sizeof(type));
53 memset(model, 0, sizeof(model));
54 memset(version, 0, sizeof(version));
55 memset(authorization, 0, sizeof(authorization));
56
57 sysinfo = fopen(SYSINFO, "r");
58 if (sysinfo == NULL)
59 return -1;
60
61 while ((read = getline(&line, &line_sz, sysinfo)) != -1) {
62 if (!strncmp(line, SYSINFO_MANU, strlen(SYSINFO_MANU))) {
63 line2 = line + strlen(SYSINFO_MANU);
64
65 while ((cp = strtok_r(line2, "\n ", &line2))) {
66 mfsize += scnprintf(manufacturer + mfsize,
67 sizeof(manufacturer) - mfsize, "%s", cp);
68 }
69 }
70
71 if (!strncmp(line, SYSINFO_TYPE, strlen(SYSINFO_TYPE))) {
72 line2 = line + strlen(SYSINFO_TYPE);
22 73
23 if (strlen(cpuid) + 1 > sz) 74 while ((cp = strtok_r(line2, "\n ", &line2))) {
75 tpsize += scnprintf(type + tpsize,
76 sizeof(type) - tpsize, "%s", cp);
77 }
78 }
79
80 if (!strncmp(line, SYSINFO_MODEL, strlen(SYSINFO_MODEL))) {
81 line2 = line + strlen(SYSINFO_MODEL);
82
83 while ((cp = strtok_r(line2, "\n ", &line2))) {
84 mdsize += scnprintf(model + mdsize, sizeof(model) - mdsize,
85 "%s%s", model[0] ? "," : "", cp);
86 }
87 break;
88 }
89 }
90 fclose(sysinfo);
91
92 /* Missing manufacturer, type or model information should not happen */
93 if (!manufacturer[0] || !type[0] || !model[0])
24 return -1; 94 return -1;
25 95
26 strcpy(buffer, cpuid); 96 /*
27 return 0; 97 * Scan /proc/service_levels and return the CPU-MF counter facility
98 * version number and authorization level.
99 * Optional, does not exist on z/VM guests.
100 */
101 sysinfo = fopen(SRVLVL, "r");
102 if (sysinfo == NULL)
103 goto skip_sysinfo;
104 while ((read = getline(&line, &line_sz, sysinfo)) != -1) {
105 if (strncmp(line, SRVLVL_CPUMF, strlen(SRVLVL_CPUMF)))
106 continue;
107
108 line2 = line + strlen(SRVLVL_CPUMF);
109 while ((cp = strtok_r(line2, "\n ", &line2))) {
110 if (!strncmp(cp, SRVLVL_VERSION,
111 strlen(SRVLVL_VERSION))) {
112 char *sep = strchr(cp, '=');
113
114 vssize += scnprintf(version + vssize,
115 sizeof(version) - vssize, "%s", sep + 1);
116 }
117 if (!strncmp(cp, SRVLVL_AUTHORIZATION,
118 strlen(SRVLVL_AUTHORIZATION))) {
119 char *sep = strchr(cp, '=');
120
121 atsize += scnprintf(authorization + atsize,
122 sizeof(authorization) - atsize, "%s", sep + 1);
123 }
124 }
125 }
126 fclose(sysinfo);
127
128skip_sysinfo:
129 free(line);
130
131 if (version[0] && authorization[0] )
132 nbytes = snprintf(buffer, sz, "%s,%s,%s,%s,%s",
133 manufacturer, type, model, version,
134 authorization);
135 else
136 nbytes = snprintf(buffer, sz, "%s,%s,%s", manufacturer, type,
137 model);
138 return (nbytes >= sz) ? -1 : 0;
139}
140
141char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
142{
143 char *buf = malloc(128);
144
145 if (buf && get_cpuid(buf, 128) < 0)
146 zfree(&buf);
147 return buf;
148}
149
150/*
151 * Compare the cpuid string returned by get_cpuid() function
152 * with the name generated by the jevents file read from
153 * pmu-events/arch/s390/mapfile.csv.
154 *
155 * Parameter mapcpuid is the cpuid as stored in the
156 * pmu-events/arch/s390/mapfile.csv. This is just the type number.
157 * Parameter cpuid is the cpuid returned by function get_cpuid().
158 */
159int strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
160{
161 char *cp = strchr(cpuid, ',');
162
163 if (cp == NULL)
164 return -1;
165 return strncmp(cp + 1, mapcpuid, strlen(mapcpuid));
28} 166}
diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
index 06abe8108b33..7a7721604b86 100644
--- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -60,6 +60,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
60 union perf_event *event; 60 union perf_event *event;
61 u64 test_tsc, comm1_tsc, comm2_tsc; 61 u64 test_tsc, comm1_tsc, comm2_tsc;
62 u64 test_time, comm1_time = 0, comm2_time = 0; 62 u64 test_time, comm1_time = 0, comm2_time = 0;
63 struct perf_mmap *md;
63 64
64 threads = thread_map__new(-1, getpid(), UINT_MAX); 65 threads = thread_map__new(-1, getpid(), UINT_MAX);
65 CHECK_NOT_NULL__(threads); 66 CHECK_NOT_NULL__(threads);
@@ -109,7 +110,11 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
109 perf_evlist__disable(evlist); 110 perf_evlist__disable(evlist);
110 111
111 for (i = 0; i < evlist->nr_mmaps; i++) { 112 for (i = 0; i < evlist->nr_mmaps; i++) {
112 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 113 md = &evlist->mmap[i];
114 if (perf_mmap__read_init(md) < 0)
115 continue;
116
117 while ((event = perf_mmap__read_event(md)) != NULL) {
113 struct perf_sample sample; 118 struct perf_sample sample;
114 119
115 if (event->header.type != PERF_RECORD_COMM || 120 if (event->header.type != PERF_RECORD_COMM ||
@@ -128,8 +133,9 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
128 comm2_time = sample.time; 133 comm2_time = sample.time;
129 } 134 }
130next_event: 135next_event:
131 perf_evlist__mmap_consume(evlist, i); 136 perf_mmap__consume(md);
132 } 137 }
138 perf_mmap__read_done(md);
133 } 139 }
134 140
135 if (!comm1_time || !comm2_time) 141 if (!comm1_time || !comm2_time)
diff --git a/tools/perf/arch/x86/util/auxtrace.c b/tools/perf/arch/x86/util/auxtrace.c
index 6aa3f2a38321..b135af62011c 100644
--- a/tools/perf/arch/x86/util/auxtrace.c
+++ b/tools/perf/arch/x86/util/auxtrace.c
@@ -37,15 +37,11 @@ struct auxtrace_record *auxtrace_record__init_intel(struct perf_evlist *evlist,
37 intel_pt_pmu = perf_pmu__find(INTEL_PT_PMU_NAME); 37 intel_pt_pmu = perf_pmu__find(INTEL_PT_PMU_NAME);
38 intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME); 38 intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME);
39 39
40 if (evlist) { 40 evlist__for_each_entry(evlist, evsel) {
41 evlist__for_each_entry(evlist, evsel) { 41 if (intel_pt_pmu && evsel->attr.type == intel_pt_pmu->type)
42 if (intel_pt_pmu && 42 found_pt = true;
43 evsel->attr.type == intel_pt_pmu->type) 43 if (intel_bts_pmu && evsel->attr.type == intel_bts_pmu->type)
44 found_pt = true; 44 found_bts = true;
45 if (intel_bts_pmu &&
46 evsel->attr.type == intel_bts_pmu->type)
47 found_bts = true;
48 }
49 } 45 }
50 46
51 if (found_pt && found_bts) { 47 if (found_pt && found_bts) {
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index f15731a3d438..51709a961496 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -40,10 +40,11 @@
40struct perf_annotate { 40struct perf_annotate {
41 struct perf_tool tool; 41 struct perf_tool tool;
42 struct perf_session *session; 42 struct perf_session *session;
43 bool use_tui, use_stdio, use_gtk; 43 bool use_tui, use_stdio, use_stdio2, use_gtk;
44 bool full_paths; 44 bool full_paths;
45 bool print_line; 45 bool print_line;
46 bool skip_missing; 46 bool skip_missing;
47 bool has_br_stack;
47 const char *sym_hist_filter; 48 const char *sym_hist_filter;
48 const char *cpu_list; 49 const char *cpu_list;
49 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 50 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -146,16 +147,78 @@ static void process_branch_stack(struct branch_stack *bs, struct addr_location *
146 free(bi); 147 free(bi);
147} 148}
148 149
150static int hist_iter__branch_callback(struct hist_entry_iter *iter,
151 struct addr_location *al __maybe_unused,
152 bool single __maybe_unused,
153 void *arg __maybe_unused)
154{
155 struct hist_entry *he = iter->he;
156 struct branch_info *bi;
157 struct perf_sample *sample = iter->sample;
158 struct perf_evsel *evsel = iter->evsel;
159 int err;
160
161 hist__account_cycles(sample->branch_stack, al, sample, false);
162
163 bi = he->branch_info;
164 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel->idx);
165
166 if (err)
167 goto out;
168
169 err = addr_map_symbol__inc_samples(&bi->to, sample, evsel->idx);
170
171out:
172 return err;
173}
174
175static int process_branch_callback(struct perf_evsel *evsel,
176 struct perf_sample *sample,
177 struct addr_location *al __maybe_unused,
178 struct perf_annotate *ann,
179 struct machine *machine)
180{
181 struct hist_entry_iter iter = {
182 .evsel = evsel,
183 .sample = sample,
184 .add_entry_cb = hist_iter__branch_callback,
185 .hide_unresolved = symbol_conf.hide_unresolved,
186 .ops = &hist_iter_branch,
187 };
188
189 struct addr_location a;
190 int ret;
191
192 if (machine__resolve(machine, &a, sample) < 0)
193 return -1;
194
195 if (a.sym == NULL)
196 return 0;
197
198 if (a.map != NULL)
199 a.map->dso->hit = 1;
200
201 ret = hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann);
202 return ret;
203}
204
205static bool has_annotation(struct perf_annotate *ann)
206{
207 return ui__has_annotation() || ann->use_stdio2;
208}
209
149static int perf_evsel__add_sample(struct perf_evsel *evsel, 210static int perf_evsel__add_sample(struct perf_evsel *evsel,
150 struct perf_sample *sample, 211 struct perf_sample *sample,
151 struct addr_location *al, 212 struct addr_location *al,
152 struct perf_annotate *ann) 213 struct perf_annotate *ann,
214 struct machine *machine)
153{ 215{
154 struct hists *hists = evsel__hists(evsel); 216 struct hists *hists = evsel__hists(evsel);
155 struct hist_entry *he; 217 struct hist_entry *he;
156 int ret; 218 int ret;
157 219
158 if (ann->sym_hist_filter != NULL && 220 if ((!ann->has_br_stack || !has_annotation(ann)) &&
221 ann->sym_hist_filter != NULL &&
159 (al->sym == NULL || 222 (al->sym == NULL ||
160 strcmp(ann->sym_hist_filter, al->sym->name) != 0)) { 223 strcmp(ann->sym_hist_filter, al->sym->name) != 0)) {
161 /* We're only interested in a symbol named sym_hist_filter */ 224 /* We're only interested in a symbol named sym_hist_filter */
@@ -178,6 +241,9 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
178 */ 241 */
179 process_branch_stack(sample->branch_stack, al, sample); 242 process_branch_stack(sample->branch_stack, al, sample);
180 243
244 if (ann->has_br_stack && has_annotation(ann))
245 return process_branch_callback(evsel, sample, al, ann, machine);
246
181 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true); 247 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
182 if (he == NULL) 248 if (he == NULL)
183 return -ENOMEM; 249 return -ENOMEM;
@@ -206,7 +272,8 @@ static int process_sample_event(struct perf_tool *tool,
206 if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap)) 272 if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap))
207 goto out_put; 273 goto out_put;
208 274
209 if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al, ann)) { 275 if (!al.filtered &&
276 perf_evsel__add_sample(evsel, sample, &al, ann, machine)) {
210 pr_warning("problem incrementing symbol count, " 277 pr_warning("problem incrementing symbol count, "
211 "skipping event\n"); 278 "skipping event\n");
212 ret = -1; 279 ret = -1;
@@ -220,8 +287,11 @@ static int hist_entry__tty_annotate(struct hist_entry *he,
220 struct perf_evsel *evsel, 287 struct perf_evsel *evsel,
221 struct perf_annotate *ann) 288 struct perf_annotate *ann)
222{ 289{
223 return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel, 290 if (!ann->use_stdio2)
224 ann->print_line, ann->full_paths, 0, 0); 291 return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel,
292 ann->print_line, ann->full_paths, 0, 0);
293 return symbol__tty_annotate2(he->ms.sym, he->ms.map, evsel,
294 ann->print_line, ann->full_paths);
225} 295}
226 296
227static void hists__find_annotations(struct hists *hists, 297static void hists__find_annotations(struct hists *hists,
@@ -238,6 +308,10 @@ static void hists__find_annotations(struct hists *hists,
238 if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned) 308 if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned)
239 goto find_next; 309 goto find_next;
240 310
311 if (ann->sym_hist_filter &&
312 (strcmp(he->ms.sym->name, ann->sym_hist_filter) != 0))
313 goto find_next;
314
241 notes = symbol__annotation(he->ms.sym); 315 notes = symbol__annotation(he->ms.sym);
242 if (notes->src == NULL) { 316 if (notes->src == NULL) {
243find_next: 317find_next:
@@ -269,6 +343,7 @@ find_next:
269 nd = rb_next(nd); 343 nd = rb_next(nd);
270 } else if (use_browser == 1) { 344 } else if (use_browser == 1) {
271 key = hist_entry__tui_annotate(he, evsel, NULL); 345 key = hist_entry__tui_annotate(he, evsel, NULL);
346
272 switch (key) { 347 switch (key) {
273 case -1: 348 case -1:
274 if (!ann->skip_missing) 349 if (!ann->skip_missing)
@@ -420,6 +495,9 @@ int cmd_annotate(int argc, const char **argv)
420 OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"), 495 OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"),
421 OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"), 496 OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"),
422 OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"), 497 OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"),
498 OPT_BOOLEAN(0, "stdio2", &annotate.use_stdio2, "Use the stdio interface"),
499 OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
500 "don't load vmlinux even if found"),
423 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 501 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
424 "file", "vmlinux pathname"), 502 "file", "vmlinux pathname"),
425 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 503 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
@@ -489,20 +567,22 @@ int cmd_annotate(int argc, const char **argv)
489 if (annotate.session == NULL) 567 if (annotate.session == NULL)
490 return -1; 568 return -1;
491 569
570 annotate.has_br_stack = perf_header__has_feat(&annotate.session->header,
571 HEADER_BRANCH_STACK);
572
492 ret = symbol__annotation_init(); 573 ret = symbol__annotation_init();
493 if (ret < 0) 574 if (ret < 0)
494 goto out_delete; 575 goto out_delete;
495 576
577 annotation_config__init();
578
496 symbol_conf.try_vmlinux_path = true; 579 symbol_conf.try_vmlinux_path = true;
497 580
498 ret = symbol__init(&annotate.session->header.env); 581 ret = symbol__init(&annotate.session->header.env);
499 if (ret < 0) 582 if (ret < 0)
500 goto out_delete; 583 goto out_delete;
501 584
502 if (setup_sorting(NULL) < 0) 585 if (annotate.use_stdio || annotate.use_stdio2)
503 usage_with_options(annotate_usage, options);
504
505 if (annotate.use_stdio)
506 use_browser = 0; 586 use_browser = 0;
507 else if (annotate.use_tui) 587 else if (annotate.use_tui)
508 use_browser = 1; 588 use_browser = 1;
@@ -511,6 +591,15 @@ int cmd_annotate(int argc, const char **argv)
511 591
512 setup_browser(true); 592 setup_browser(true);
513 593
594 if ((use_browser == 1 || annotate.use_stdio2) && annotate.has_br_stack) {
595 sort__mode = SORT_MODE__BRANCH;
596 if (setup_sorting(annotate.session->evlist) < 0)
597 usage_with_options(annotate_usage, options);
598 } else {
599 if (setup_sorting(NULL) < 0)
600 usage_with_options(annotate_usage, options);
601 }
602
514 ret = __cmd_annotate(&annotate); 603 ret = __cmd_annotate(&annotate);
515 604
516out_delete: 605out_delete:
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index c0815a37fdb5..2126bfbcb385 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -32,6 +32,7 @@
32#include "evsel.h" 32#include "evsel.h"
33#include "ui/browsers/hists.h" 33#include "ui/browsers/hists.h"
34#include "thread.h" 34#include "thread.h"
35#include "mem2node.h"
35 36
36struct c2c_hists { 37struct c2c_hists {
37 struct hists hists; 38 struct hists hists;
@@ -49,6 +50,7 @@ struct c2c_hist_entry {
49 struct c2c_hists *hists; 50 struct c2c_hists *hists;
50 struct c2c_stats stats; 51 struct c2c_stats stats;
51 unsigned long *cpuset; 52 unsigned long *cpuset;
53 unsigned long *nodeset;
52 struct c2c_stats *node_stats; 54 struct c2c_stats *node_stats;
53 unsigned int cacheline_idx; 55 unsigned int cacheline_idx;
54 56
@@ -59,6 +61,11 @@ struct c2c_hist_entry {
59 * because of its callchain dynamic entry 61 * because of its callchain dynamic entry
60 */ 62 */
61 struct hist_entry he; 63 struct hist_entry he;
64
65 unsigned long paddr;
66 unsigned long paddr_cnt;
67 bool paddr_zero;
68 char *nodestr;
62}; 69};
63 70
64static char const *coalesce_default = "pid,iaddr"; 71static char const *coalesce_default = "pid,iaddr";
@@ -66,6 +73,7 @@ static char const *coalesce_default = "pid,iaddr";
66struct perf_c2c { 73struct perf_c2c {
67 struct perf_tool tool; 74 struct perf_tool tool;
68 struct c2c_hists hists; 75 struct c2c_hists hists;
76 struct mem2node mem2node;
69 77
70 unsigned long **nodes; 78 unsigned long **nodes;
71 int nodes_cnt; 79 int nodes_cnt;
@@ -123,6 +131,10 @@ static void *c2c_he_zalloc(size_t size)
123 if (!c2c_he->cpuset) 131 if (!c2c_he->cpuset)
124 return NULL; 132 return NULL;
125 133
134 c2c_he->nodeset = bitmap_alloc(c2c.nodes_cnt);
135 if (!c2c_he->nodeset)
136 return NULL;
137
126 c2c_he->node_stats = zalloc(c2c.nodes_cnt * sizeof(*c2c_he->node_stats)); 138 c2c_he->node_stats = zalloc(c2c.nodes_cnt * sizeof(*c2c_he->node_stats));
127 if (!c2c_he->node_stats) 139 if (!c2c_he->node_stats)
128 return NULL; 140 return NULL;
@@ -145,6 +157,8 @@ static void c2c_he_free(void *he)
145 } 157 }
146 158
147 free(c2c_he->cpuset); 159 free(c2c_he->cpuset);
160 free(c2c_he->nodeset);
161 free(c2c_he->nodestr);
148 free(c2c_he->node_stats); 162 free(c2c_he->node_stats);
149 free(c2c_he); 163 free(c2c_he);
150} 164}
@@ -194,6 +208,28 @@ static void c2c_he__set_cpu(struct c2c_hist_entry *c2c_he,
194 set_bit(sample->cpu, c2c_he->cpuset); 208 set_bit(sample->cpu, c2c_he->cpuset);
195} 209}
196 210
211static void c2c_he__set_node(struct c2c_hist_entry *c2c_he,
212 struct perf_sample *sample)
213{
214 int node;
215
216 if (!sample->phys_addr) {
217 c2c_he->paddr_zero = true;
218 return;
219 }
220
221 node = mem2node__node(&c2c.mem2node, sample->phys_addr);
222 if (WARN_ONCE(node < 0, "WARNING: failed to find node\n"))
223 return;
224
225 set_bit(node, c2c_he->nodeset);
226
227 if (c2c_he->paddr != sample->phys_addr) {
228 c2c_he->paddr_cnt++;
229 c2c_he->paddr = sample->phys_addr;
230 }
231}
232
197static void compute_stats(struct c2c_hist_entry *c2c_he, 233static void compute_stats(struct c2c_hist_entry *c2c_he,
198 struct c2c_stats *stats, 234 struct c2c_stats *stats,
199 u64 weight) 235 u64 weight)
@@ -237,9 +273,12 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
237 if (mi == NULL) 273 if (mi == NULL)
238 return -ENOMEM; 274 return -ENOMEM;
239 275
240 mi_dup = memdup(mi, sizeof(*mi)); 276 /*
241 if (!mi_dup) 277 * The mi object is released in hists__add_entry_ops,
242 goto free_mi; 278 * if it gets sorted out into existing data, so we need
279 * to take the copy now.
280 */
281 mi_dup = mem_info__get(mi);
243 282
244 c2c_decode_stats(&stats, mi); 283 c2c_decode_stats(&stats, mi);
245 284
@@ -247,13 +286,14 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
247 &al, NULL, NULL, mi, 286 &al, NULL, NULL, mi,
248 sample, true); 287 sample, true);
249 if (he == NULL) 288 if (he == NULL)
250 goto free_mi_dup; 289 goto free_mi;
251 290
252 c2c_he = container_of(he, struct c2c_hist_entry, he); 291 c2c_he = container_of(he, struct c2c_hist_entry, he);
253 c2c_add_stats(&c2c_he->stats, &stats); 292 c2c_add_stats(&c2c_he->stats, &stats);
254 c2c_add_stats(&c2c_hists->stats, &stats); 293 c2c_add_stats(&c2c_hists->stats, &stats);
255 294
256 c2c_he__set_cpu(c2c_he, sample); 295 c2c_he__set_cpu(c2c_he, sample);
296 c2c_he__set_node(c2c_he, sample);
257 297
258 hists__inc_nr_samples(&c2c_hists->hists, he->filtered); 298 hists__inc_nr_samples(&c2c_hists->hists, he->filtered);
259 ret = hist_entry__append_callchain(he, sample); 299 ret = hist_entry__append_callchain(he, sample);
@@ -272,19 +312,15 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
272 312
273 mi = mi_dup; 313 mi = mi_dup;
274 314
275 mi_dup = memdup(mi, sizeof(*mi));
276 if (!mi_dup)
277 goto free_mi;
278
279 c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2); 315 c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2);
280 if (!c2c_hists) 316 if (!c2c_hists)
281 goto free_mi_dup; 317 goto free_mi;
282 318
283 he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops, 319 he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops,
284 &al, NULL, NULL, mi, 320 &al, NULL, NULL, mi,
285 sample, true); 321 sample, true);
286 if (he == NULL) 322 if (he == NULL)
287 goto free_mi_dup; 323 goto free_mi;
288 324
289 c2c_he = container_of(he, struct c2c_hist_entry, he); 325 c2c_he = container_of(he, struct c2c_hist_entry, he);
290 c2c_add_stats(&c2c_he->stats, &stats); 326 c2c_add_stats(&c2c_he->stats, &stats);
@@ -294,6 +330,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
294 compute_stats(c2c_he, &stats, sample->weight); 330 compute_stats(c2c_he, &stats, sample->weight);
295 331
296 c2c_he__set_cpu(c2c_he, sample); 332 c2c_he__set_cpu(c2c_he, sample);
333 c2c_he__set_node(c2c_he, sample);
297 334
298 hists__inc_nr_samples(&c2c_hists->hists, he->filtered); 335 hists__inc_nr_samples(&c2c_hists->hists, he->filtered);
299 ret = hist_entry__append_callchain(he, sample); 336 ret = hist_entry__append_callchain(he, sample);
@@ -303,10 +340,9 @@ out:
303 addr_location__put(&al); 340 addr_location__put(&al);
304 return ret; 341 return ret;
305 342
306free_mi_dup:
307 free(mi_dup);
308free_mi: 343free_mi:
309 free(mi); 344 mem_info__put(mi_dup);
345 mem_info__put(mi);
310 ret = -ENOMEM; 346 ret = -ENOMEM;
311 goto out; 347 goto out;
312} 348}
@@ -457,6 +493,31 @@ static int dcacheline_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
457 return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr)); 493 return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr));
458} 494}
459 495
496static int
497dcacheline_node_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
498 struct hist_entry *he)
499{
500 struct c2c_hist_entry *c2c_he;
501 int width = c2c_width(fmt, hpp, he->hists);
502
503 c2c_he = container_of(he, struct c2c_hist_entry, he);
504 if (WARN_ON_ONCE(!c2c_he->nodestr))
505 return 0;
506
507 return scnprintf(hpp->buf, hpp->size, "%*s", width, c2c_he->nodestr);
508}
509
510static int
511dcacheline_node_count(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
512 struct hist_entry *he)
513{
514 struct c2c_hist_entry *c2c_he;
515 int width = c2c_width(fmt, hpp, he->hists);
516
517 c2c_he = container_of(he, struct c2c_hist_entry, he);
518 return scnprintf(hpp->buf, hpp->size, "%*lu", width, c2c_he->paddr_cnt);
519}
520
460static int offset_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 521static int offset_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
461 struct hist_entry *he) 522 struct hist_entry *he)
462{ 523{
@@ -1202,23 +1263,47 @@ cl_idx_empty_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1202 } 1263 }
1203 1264
1204static struct c2c_dimension dim_dcacheline = { 1265static struct c2c_dimension dim_dcacheline = {
1205 .header = HEADER_LOW("Cacheline"), 1266 .header = HEADER_SPAN("--- Cacheline ----", "Address", 2),
1206 .name = "dcacheline", 1267 .name = "dcacheline",
1207 .cmp = dcacheline_cmp, 1268 .cmp = dcacheline_cmp,
1208 .entry = dcacheline_entry, 1269 .entry = dcacheline_entry,
1209 .width = 18, 1270 .width = 18,
1210}; 1271};
1211 1272
1212static struct c2c_header header_offset_tui = HEADER_LOW("Off"); 1273static struct c2c_dimension dim_dcacheline_node = {
1274 .header = HEADER_LOW("Node"),
1275 .name = "dcacheline_node",
1276 .cmp = empty_cmp,
1277 .entry = dcacheline_node_entry,
1278 .width = 4,
1279};
1280
1281static struct c2c_dimension dim_dcacheline_count = {
1282 .header = HEADER_LOW("PA cnt"),
1283 .name = "dcacheline_count",
1284 .cmp = empty_cmp,
1285 .entry = dcacheline_node_count,
1286 .width = 6,
1287};
1288
1289static struct c2c_header header_offset_tui = HEADER_SPAN("-----", "Off", 2);
1213 1290
1214static struct c2c_dimension dim_offset = { 1291static struct c2c_dimension dim_offset = {
1215 .header = HEADER_BOTH("Data address", "Offset"), 1292 .header = HEADER_SPAN("--- Data address -", "Offset", 2),
1216 .name = "offset", 1293 .name = "offset",
1217 .cmp = offset_cmp, 1294 .cmp = offset_cmp,
1218 .entry = offset_entry, 1295 .entry = offset_entry,
1219 .width = 18, 1296 .width = 18,
1220}; 1297};
1221 1298
1299static struct c2c_dimension dim_offset_node = {
1300 .header = HEADER_LOW("Node"),
1301 .name = "offset_node",
1302 .cmp = empty_cmp,
1303 .entry = dcacheline_node_entry,
1304 .width = 4,
1305};
1306
1222static struct c2c_dimension dim_iaddr = { 1307static struct c2c_dimension dim_iaddr = {
1223 .header = HEADER_LOW("Code address"), 1308 .header = HEADER_LOW("Code address"),
1224 .name = "iaddr", 1309 .name = "iaddr",
@@ -1538,7 +1623,10 @@ static struct c2c_dimension dim_dcacheline_num_empty = {
1538 1623
1539static struct c2c_dimension *dimensions[] = { 1624static struct c2c_dimension *dimensions[] = {
1540 &dim_dcacheline, 1625 &dim_dcacheline,
1626 &dim_dcacheline_node,
1627 &dim_dcacheline_count,
1541 &dim_offset, 1628 &dim_offset,
1629 &dim_offset_node,
1542 &dim_iaddr, 1630 &dim_iaddr,
1543 &dim_tot_hitm, 1631 &dim_tot_hitm,
1544 &dim_lcl_hitm, 1632 &dim_lcl_hitm,
@@ -1841,20 +1929,56 @@ static inline int valid_hitm_or_store(struct hist_entry *he)
1841 return has_hitm || c2c_he->stats.store; 1929 return has_hitm || c2c_he->stats.store;
1842} 1930}
1843 1931
1844static void calc_width(struct hist_entry *he) 1932static void set_node_width(struct c2c_hist_entry *c2c_he, int len)
1933{
1934 struct c2c_dimension *dim;
1935
1936 dim = &c2c.hists == c2c_he->hists ?
1937 &dim_dcacheline_node : &dim_offset_node;
1938
1939 if (len > dim->width)
1940 dim->width = len;
1941}
1942
1943static int set_nodestr(struct c2c_hist_entry *c2c_he)
1944{
1945 char buf[30];
1946 int len;
1947
1948 if (c2c_he->nodestr)
1949 return 0;
1950
1951 if (bitmap_weight(c2c_he->nodeset, c2c.nodes_cnt)) {
1952 len = bitmap_scnprintf(c2c_he->nodeset, c2c.nodes_cnt,
1953 buf, sizeof(buf));
1954 } else {
1955 len = scnprintf(buf, sizeof(buf), "N/A");
1956 }
1957
1958 set_node_width(c2c_he, len);
1959 c2c_he->nodestr = strdup(buf);
1960 return c2c_he->nodestr ? 0 : -ENOMEM;
1961}
1962
1963static void calc_width(struct c2c_hist_entry *c2c_he)
1845{ 1964{
1846 struct c2c_hists *c2c_hists; 1965 struct c2c_hists *c2c_hists;
1847 1966
1848 c2c_hists = container_of(he->hists, struct c2c_hists, hists); 1967 c2c_hists = container_of(c2c_he->he.hists, struct c2c_hists, hists);
1849 hists__calc_col_len(&c2c_hists->hists, he); 1968 hists__calc_col_len(&c2c_hists->hists, &c2c_he->he);
1969 set_nodestr(c2c_he);
1850} 1970}
1851 1971
1852static int filter_cb(struct hist_entry *he) 1972static int filter_cb(struct hist_entry *he)
1853{ 1973{
1974 struct c2c_hist_entry *c2c_he;
1975
1976 c2c_he = container_of(he, struct c2c_hist_entry, he);
1977
1854 if (c2c.show_src && !he->srcline) 1978 if (c2c.show_src && !he->srcline)
1855 he->srcline = hist_entry__get_srcline(he); 1979 he->srcline = hist_entry__get_srcline(he);
1856 1980
1857 calc_width(he); 1981 calc_width(c2c_he);
1858 1982
1859 if (!valid_hitm_or_store(he)) 1983 if (!valid_hitm_or_store(he))
1860 he->filtered = HIST_FILTER__C2C; 1984 he->filtered = HIST_FILTER__C2C;
@@ -1871,12 +1995,11 @@ static int resort_cl_cb(struct hist_entry *he)
1871 c2c_he = container_of(he, struct c2c_hist_entry, he); 1995 c2c_he = container_of(he, struct c2c_hist_entry, he);
1872 c2c_hists = c2c_he->hists; 1996 c2c_hists = c2c_he->hists;
1873 1997
1874 calc_width(he);
1875
1876 if (display && c2c_hists) { 1998 if (display && c2c_hists) {
1877 static unsigned int idx; 1999 static unsigned int idx;
1878 2000
1879 c2c_he->cacheline_idx = idx++; 2001 c2c_he->cacheline_idx = idx++;
2002 calc_width(c2c_he);
1880 2003
1881 c2c_hists__reinit(c2c_hists, c2c.cl_output, c2c.cl_resort); 2004 c2c_hists__reinit(c2c_hists, c2c.cl_output, c2c.cl_resort);
1882 2005
@@ -2245,7 +2368,7 @@ static int perf_c2c__browse_cacheline(struct hist_entry *he)
2245 c2c_browser__update_nr_entries(browser); 2368 c2c_browser__update_nr_entries(browser);
2246 2369
2247 while (1) { 2370 while (1) {
2248 key = hist_browser__run(browser, "? - help"); 2371 key = hist_browser__run(browser, "? - help", true);
2249 2372
2250 switch (key) { 2373 switch (key) {
2251 case 's': 2374 case 's':
@@ -2314,7 +2437,7 @@ static int perf_c2c__hists_browse(struct hists *hists)
2314 c2c_browser__update_nr_entries(browser); 2437 c2c_browser__update_nr_entries(browser);
2315 2438
2316 while (1) { 2439 while (1) {
2317 key = hist_browser__run(browser, "? - help"); 2440 key = hist_browser__run(browser, "? - help", true);
2318 2441
2319 switch (key) { 2442 switch (key) {
2320 case 'q': 2443 case 'q':
@@ -2350,14 +2473,66 @@ static void perf_c2c_display(struct perf_session *session)
2350} 2473}
2351#endif /* HAVE_SLANG_SUPPORT */ 2474#endif /* HAVE_SLANG_SUPPORT */
2352 2475
2353static void ui_quirks(void) 2476static char *fill_line(const char *orig, int len)
2477{
2478 int i, j, olen = strlen(orig);
2479 char *buf;
2480
2481 buf = zalloc(len + 1);
2482 if (!buf)
2483 return NULL;
2484
2485 j = len / 2 - olen / 2;
2486
2487 for (i = 0; i < j - 1; i++)
2488 buf[i] = '-';
2489
2490 buf[i++] = ' ';
2491
2492 strcpy(buf + i, orig);
2493
2494 i += olen;
2495
2496 buf[i++] = ' ';
2497
2498 for (; i < len; i++)
2499 buf[i] = '-';
2500
2501 return buf;
2502}
2503
2504static int ui_quirks(void)
2354{ 2505{
2506 const char *nodestr = "Data address";
2507 char *buf;
2508
2355 if (!c2c.use_stdio) { 2509 if (!c2c.use_stdio) {
2356 dim_offset.width = 5; 2510 dim_offset.width = 5;
2357 dim_offset.header = header_offset_tui; 2511 dim_offset.header = header_offset_tui;
2512 nodestr = "CL";
2358 } 2513 }
2359 2514
2360 dim_percent_hitm.header = percent_hitm_header[c2c.display]; 2515 dim_percent_hitm.header = percent_hitm_header[c2c.display];
2516
2517 /* Fix the zero line for dcacheline column. */
2518 buf = fill_line("Cacheline", dim_dcacheline.width +
2519 dim_dcacheline_node.width +
2520 dim_dcacheline_count.width + 4);
2521 if (!buf)
2522 return -ENOMEM;
2523
2524 dim_dcacheline.header.line[0].text = buf;
2525
2526 /* Fix the zero line for offset column. */
2527 buf = fill_line(nodestr, dim_offset.width +
2528 dim_offset_node.width +
2529 dim_dcacheline_count.width + 4);
2530 if (!buf)
2531 return -ENOMEM;
2532
2533 dim_offset.header.line[0].text = buf;
2534
2535 return 0;
2361} 2536}
2362 2537
2363#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent" 2538#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent"
@@ -2473,7 +2648,7 @@ static int build_cl_output(char *cl_sort, bool no_source)
2473 "percent_lcl_hitm," 2648 "percent_lcl_hitm,"
2474 "percent_stores_l1hit," 2649 "percent_stores_l1hit,"
2475 "percent_stores_l1miss," 2650 "percent_stores_l1miss,"
2476 "offset,", 2651 "offset,offset_node,dcacheline_count,",
2477 add_pid ? "pid," : "", 2652 add_pid ? "pid," : "",
2478 add_tid ? "tid," : "", 2653 add_tid ? "tid," : "",
2479 add_iaddr ? "iaddr," : "", 2654 add_iaddr ? "iaddr," : "",
@@ -2602,17 +2777,21 @@ static int perf_c2c__report(int argc, const char **argv)
2602 goto out; 2777 goto out;
2603 } 2778 }
2604 2779
2605 err = setup_callchain(session->evlist); 2780 err = mem2node__init(&c2c.mem2node, &session->header.env);
2606 if (err) 2781 if (err)
2607 goto out_session; 2782 goto out_session;
2608 2783
2784 err = setup_callchain(session->evlist);
2785 if (err)
2786 goto out_mem2node;
2787
2609 if (symbol__init(&session->header.env) < 0) 2788 if (symbol__init(&session->header.env) < 0)
2610 goto out_session; 2789 goto out_mem2node;
2611 2790
2612 /* No pipe support at the moment. */ 2791 /* No pipe support at the moment. */
2613 if (perf_data__is_pipe(session->data)) { 2792 if (perf_data__is_pipe(session->data)) {
2614 pr_debug("No pipe support at the moment.\n"); 2793 pr_debug("No pipe support at the moment.\n");
2615 goto out_session; 2794 goto out_mem2node;
2616 } 2795 }
2617 2796
2618 if (c2c.use_stdio) 2797 if (c2c.use_stdio)
@@ -2625,12 +2804,14 @@ static int perf_c2c__report(int argc, const char **argv)
2625 err = perf_session__process_events(session); 2804 err = perf_session__process_events(session);
2626 if (err) { 2805 if (err) {
2627 pr_err("failed to process sample\n"); 2806 pr_err("failed to process sample\n");
2628 goto out_session; 2807 goto out_mem2node;
2629 } 2808 }
2630 2809
2631 c2c_hists__reinit(&c2c.hists, 2810 c2c_hists__reinit(&c2c.hists,
2632 "cl_idx," 2811 "cl_idx,"
2633 "dcacheline," 2812 "dcacheline,"
2813 "dcacheline_node,"
2814 "dcacheline_count,"
2634 "tot_recs," 2815 "tot_recs,"
2635 "percent_hitm," 2816 "percent_hitm,"
2636 "tot_hitm,lcl_hitm,rmt_hitm," 2817 "tot_hitm,lcl_hitm,rmt_hitm,"
@@ -2652,10 +2833,15 @@ static int perf_c2c__report(int argc, const char **argv)
2652 2833
2653 ui_progress__finish(); 2834 ui_progress__finish();
2654 2835
2655 ui_quirks(); 2836 if (ui_quirks()) {
2837 pr_err("failed to setup UI\n");
2838 goto out_mem2node;
2839 }
2656 2840
2657 perf_c2c_display(session); 2841 perf_c2c_display(session);
2658 2842
2843out_mem2node:
2844 mem2node__exit(&c2c.mem2node);
2659out_session: 2845out_session:
2660 perf_session__delete(session); 2846 perf_session__delete(session);
2661out: 2847out:
@@ -2706,7 +2892,7 @@ static int perf_c2c__record(int argc, const char **argv)
2706 argc = parse_options(argc, argv, options, record_mem_usage, 2892 argc = parse_options(argc, argv, options, record_mem_usage,
2707 PARSE_OPT_KEEP_UNKNOWN); 2893 PARSE_OPT_KEEP_UNKNOWN);
2708 2894
2709 rec_argc = argc + 10; /* max number of arguments */ 2895 rec_argc = argc + 11; /* max number of arguments */
2710 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 2896 rec_argv = calloc(rec_argc + 1, sizeof(char *));
2711 if (!rec_argv) 2897 if (!rec_argv)
2712 return -1; 2898 return -1;
@@ -2722,6 +2908,7 @@ static int perf_c2c__record(int argc, const char **argv)
2722 rec_argv[i++] = "-W"; 2908 rec_argv[i++] = "-W";
2723 2909
2724 rec_argv[i++] = "-d"; 2910 rec_argv[i++] = "-d";
2911 rec_argv[i++] = "--phys-data";
2725 rec_argv[i++] = "--sample-cpu"; 2912 rec_argv[i++] = "--sample-cpu";
2726 2913
2727 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { 2914 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 25a42acabee1..f42f228e8899 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -72,6 +72,7 @@ static int __write_tracing_file(const char *name, const char *val, bool append)
72 ssize_t size = strlen(val); 72 ssize_t size = strlen(val);
73 int flags = O_WRONLY; 73 int flags = O_WRONLY;
74 char errbuf[512]; 74 char errbuf[512];
75 char *val_copy;
75 76
76 file = get_tracing_file(name); 77 file = get_tracing_file(name);
77 if (!file) { 78 if (!file) {
@@ -91,12 +92,23 @@ static int __write_tracing_file(const char *name, const char *val, bool append)
91 goto out; 92 goto out;
92 } 93 }
93 94
94 if (write(fd, val, size) == size) 95 /*
96 * Copy the original value and append a '\n'. Without this,
97 * the kernel can hide possible errors.
98 */
99 val_copy = strdup(val);
100 if (!val_copy)
101 goto out_close;
102 val_copy[size] = '\n';
103
104 if (write(fd, val_copy, size + 1) == size + 1)
95 ret = 0; 105 ret = 0;
96 else 106 else
97 pr_debug("write '%s' to tracing/%s failed: %s\n", 107 pr_debug("write '%s' to tracing/%s failed: %s\n",
98 val, name, str_error_r(errno, errbuf, sizeof(errbuf))); 108 val, name, str_error_r(errno, errbuf, sizeof(errbuf)));
99 109
110 free(val_copy);
111out_close:
100 close(fd); 112 close(fd);
101out: 113out:
102 put_tracing_file(file); 114 put_tracing_file(file);
@@ -280,8 +292,10 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
280 signal(SIGCHLD, sig_handler); 292 signal(SIGCHLD, sig_handler);
281 signal(SIGPIPE, sig_handler); 293 signal(SIGPIPE, sig_handler);
282 294
283 if (reset_tracing_files(ftrace) < 0) 295 if (reset_tracing_files(ftrace) < 0) {
296 pr_err("failed to reset ftrace\n");
284 goto out; 297 goto out;
298 }
285 299
286 /* reset ftrace buffer */ 300 /* reset ftrace buffer */
287 if (write_tracing_file("trace", "0") < 0) 301 if (write_tracing_file("trace", "0") < 0)
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 55d919dc5bc6..72e2ca096bf5 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -743,16 +743,23 @@ static bool verify_vcpu(int vcpu)
743static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx, 743static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
744 u64 *mmap_time) 744 u64 *mmap_time)
745{ 745{
746 struct perf_evlist *evlist = kvm->evlist;
746 union perf_event *event; 747 union perf_event *event;
748 struct perf_mmap *md;
747 u64 timestamp; 749 u64 timestamp;
748 s64 n = 0; 750 s64 n = 0;
749 int err; 751 int err;
750 752
751 *mmap_time = ULLONG_MAX; 753 *mmap_time = ULLONG_MAX;
752 while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) { 754 md = &evlist->mmap[idx];
753 err = perf_evlist__parse_sample_timestamp(kvm->evlist, event, &timestamp); 755 err = perf_mmap__read_init(md);
756 if (err < 0)
757 return (err == -EAGAIN) ? 0 : -1;
758
759 while ((event = perf_mmap__read_event(md)) != NULL) {
760 err = perf_evlist__parse_sample_timestamp(evlist, event, &timestamp);
754 if (err) { 761 if (err) {
755 perf_evlist__mmap_consume(kvm->evlist, idx); 762 perf_mmap__consume(md);
756 pr_err("Failed to parse sample\n"); 763 pr_err("Failed to parse sample\n");
757 return -1; 764 return -1;
758 } 765 }
@@ -762,7 +769,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
762 * FIXME: Here we can't consume the event, as perf_session__queue_event will 769 * FIXME: Here we can't consume the event, as perf_session__queue_event will
763 * point to it, and it'll get possibly overwritten by the kernel. 770 * point to it, and it'll get possibly overwritten by the kernel.
764 */ 771 */
765 perf_evlist__mmap_consume(kvm->evlist, idx); 772 perf_mmap__consume(md);
766 773
767 if (err) { 774 if (err) {
768 pr_err("Failed to enqueue sample: %d\n", err); 775 pr_err("Failed to enqueue sample: %d\n", err);
@@ -779,6 +786,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
779 break; 786 break;
780 } 787 }
781 788
789 perf_mmap__read_done(md);
782 return n; 790 return n;
783} 791}
784 792
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index bf4ca749d1ac..22ebeb92ac51 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -45,6 +45,7 @@
45 45
46#include <errno.h> 46#include <errno.h>
47#include <inttypes.h> 47#include <inttypes.h>
48#include <locale.h>
48#include <poll.h> 49#include <poll.h>
49#include <unistd.h> 50#include <unistd.h>
50#include <sched.h> 51#include <sched.h>
@@ -70,7 +71,6 @@ struct record {
70 struct auxtrace_record *itr; 71 struct auxtrace_record *itr;
71 struct perf_evlist *evlist; 72 struct perf_evlist *evlist;
72 struct perf_session *session; 73 struct perf_session *session;
73 const char *progname;
74 int realtime_prio; 74 int realtime_prio;
75 bool no_buildid; 75 bool no_buildid;
76 bool no_buildid_set; 76 bool no_buildid_set;
@@ -273,6 +273,24 @@ static void record__read_auxtrace_snapshot(struct record *rec)
273 } 273 }
274} 274}
275 275
276static int record__auxtrace_init(struct record *rec)
277{
278 int err;
279
280 if (!rec->itr) {
281 rec->itr = auxtrace_record__init(rec->evlist, &err);
282 if (err)
283 return err;
284 }
285
286 err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
287 rec->opts.auxtrace_snapshot_opts);
288 if (err)
289 return err;
290
291 return auxtrace_parse_filters(rec->evlist);
292}
293
276#else 294#else
277 295
278static inline 296static inline
@@ -293,6 +311,11 @@ int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
293 return 0; 311 return 0;
294} 312}
295 313
314static int record__auxtrace_init(struct record *rec __maybe_unused)
315{
316 return 0;
317}
318
296#endif 319#endif
297 320
298static int record__mmap_evlist(struct record *rec, 321static int record__mmap_evlist(struct record *rec,
@@ -509,7 +532,7 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli
509 struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap; 532 struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
510 533
511 if (maps[i].base) { 534 if (maps[i].base) {
512 if (perf_mmap__push(&maps[i], overwrite, rec, record__pushfn) != 0) { 535 if (perf_mmap__push(&maps[i], rec, record__pushfn) != 0) {
513 rc = -1; 536 rc = -1;
514 goto out; 537 goto out;
515 } 538 }
@@ -731,13 +754,10 @@ static int record__synthesize(struct record *rec, bool tail)
731 return 0; 754 return 0;
732 755
733 if (data->is_pipe) { 756 if (data->is_pipe) {
734 err = perf_event__synthesize_features( 757 /*
735 tool, session, rec->evlist, process_synthesized_event); 758 * We need to synthesize events first, because some
736 if (err < 0) { 759 * features works on top of them (on report side).
737 pr_err("Couldn't synthesize features.\n"); 760 */
738 return err;
739 }
740
741 err = perf_event__synthesize_attrs(tool, session, 761 err = perf_event__synthesize_attrs(tool, session,
742 process_synthesized_event); 762 process_synthesized_event);
743 if (err < 0) { 763 if (err < 0) {
@@ -745,6 +765,13 @@ static int record__synthesize(struct record *rec, bool tail)
745 goto out; 765 goto out;
746 } 766 }
747 767
768 err = perf_event__synthesize_features(tool, session, rec->evlist,
769 process_synthesized_event);
770 if (err < 0) {
771 pr_err("Couldn't synthesize features.\n");
772 return err;
773 }
774
748 if (have_tracepoints(&rec->evlist->entries)) { 775 if (have_tracepoints(&rec->evlist->entries)) {
749 /* 776 /*
750 * FIXME err <= 0 here actually means that 777 * FIXME err <= 0 here actually means that
@@ -830,7 +857,6 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
830 int status = 0; 857 int status = 0;
831 unsigned long waking = 0; 858 unsigned long waking = 0;
832 const bool forks = argc > 0; 859 const bool forks = argc > 0;
833 struct machine *machine;
834 struct perf_tool *tool = &rec->tool; 860 struct perf_tool *tool = &rec->tool;
835 struct record_opts *opts = &rec->opts; 861 struct record_opts *opts = &rec->opts;
836 struct perf_data *data = &rec->data; 862 struct perf_data *data = &rec->data;
@@ -838,8 +864,6 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
838 bool disabled = false, draining = false; 864 bool disabled = false, draining = false;
839 int fd; 865 int fd;
840 866
841 rec->progname = argv[0];
842
843 atexit(record__sig_exit); 867 atexit(record__sig_exit);
844 signal(SIGCHLD, sig_handler); 868 signal(SIGCHLD, sig_handler);
845 signal(SIGINT, sig_handler); 869 signal(SIGINT, sig_handler);
@@ -881,6 +905,15 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
881 } 905 }
882 } 906 }
883 907
908 /*
909 * If we have just single event and are sending data
910 * through pipe, we need to force the ids allocation,
911 * because we synthesize event name through the pipe
912 * and need the id for that.
913 */
914 if (data->is_pipe && rec->evlist->nr_entries == 1)
915 rec->opts.sample_id = true;
916
884 if (record__open(rec) != 0) { 917 if (record__open(rec) != 0) {
885 err = -1; 918 err = -1;
886 goto out_child; 919 goto out_child;
@@ -926,8 +959,6 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
926 goto out_child; 959 goto out_child;
927 } 960 }
928 961
929 machine = &session->machines.host;
930
931 err = record__synthesize(rec, false); 962 err = record__synthesize(rec, false);
932 if (err < 0) 963 if (err < 0)
933 goto out_child; 964 goto out_child;
@@ -955,6 +986,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
955 * Let the child rip 986 * Let the child rip
956 */ 987 */
957 if (forks) { 988 if (forks) {
989 struct machine *machine = &session->machines.host;
958 union perf_event *event; 990 union perf_event *event;
959 pid_t tgid; 991 pid_t tgid;
960 992
@@ -1251,10 +1283,12 @@ static int perf_record_config(const char *var, const char *value, void *cb)
1251 return -1; 1283 return -1;
1252 return 0; 1284 return 0;
1253 } 1285 }
1254 if (!strcmp(var, "record.call-graph")) 1286 if (!strcmp(var, "record.call-graph")) {
1255 var = "call-graph.record-mode"; /* fall-through */ 1287 var = "call-graph.record-mode";
1288 return perf_default_config(var, value, cb);
1289 }
1256 1290
1257 return perf_default_config(var, value, cb); 1291 return 0;
1258} 1292}
1259 1293
1260struct clockid_map { 1294struct clockid_map {
@@ -1542,7 +1576,11 @@ static struct option __record_options[] = {
1542 OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize, 1576 OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
1543 "synthesize non-sample events at the end of output"), 1577 "synthesize non-sample events at the end of output"),
1544 OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), 1578 OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
1545 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1579 OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq,
1580 "Fail if the specified frequency can't be used"),
1581 OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'",
1582 "profile at this frequency",
1583 record__parse_freq),
1546 OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1584 OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1547 "number of mmap data pages and AUX area tracing mmap pages", 1585 "number of mmap data pages and AUX area tracing mmap pages",
1548 record__parse_mmap_pages), 1586 record__parse_mmap_pages),
@@ -1651,6 +1689,8 @@ int cmd_record(int argc, const char **argv)
1651 struct record *rec = &record; 1689 struct record *rec = &record;
1652 char errbuf[BUFSIZ]; 1690 char errbuf[BUFSIZ];
1653 1691
1692 setlocale(LC_ALL, "");
1693
1654#ifndef HAVE_LIBBPF_SUPPORT 1694#ifndef HAVE_LIBBPF_SUPPORT
1655# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 1695# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
1656 set_nobuild('\0', "clang-path", true); 1696 set_nobuild('\0', "clang-path", true);
@@ -1711,17 +1751,6 @@ int cmd_record(int argc, const char **argv)
1711 alarm(rec->switch_output.time); 1751 alarm(rec->switch_output.time);
1712 } 1752 }
1713 1753
1714 if (!rec->itr) {
1715 rec->itr = auxtrace_record__init(rec->evlist, &err);
1716 if (err)
1717 goto out;
1718 }
1719
1720 err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
1721 rec->opts.auxtrace_snapshot_opts);
1722 if (err)
1723 goto out;
1724
1725 /* 1754 /*
1726 * Allow aliases to facilitate the lookup of symbols for address 1755 * Allow aliases to facilitate the lookup of symbols for address
1727 * filters. Refer to auxtrace_parse_filters(). 1756 * filters. Refer to auxtrace_parse_filters().
@@ -1730,7 +1759,7 @@ int cmd_record(int argc, const char **argv)
1730 1759
1731 symbol__init(NULL); 1760 symbol__init(NULL);
1732 1761
1733 err = auxtrace_parse_filters(rec->evlist); 1762 err = record__auxtrace_init(rec);
1734 if (err) 1763 if (err)
1735 goto out; 1764 goto out;
1736 1765
@@ -1803,7 +1832,7 @@ int cmd_record(int argc, const char **argv)
1803 err = target__validate(&rec->opts.target); 1832 err = target__validate(&rec->opts.target);
1804 if (err) { 1833 if (err) {
1805 target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 1834 target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
1806 ui__warning("%s", errbuf); 1835 ui__warning("%s\n", errbuf);
1807 } 1836 }
1808 1837
1809 err = target__parse_uid(&rec->opts.target); 1838 err = target__parse_uid(&rec->opts.target);
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 42a52dcc41cd..0f198f6d9b77 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -68,6 +68,7 @@ struct report {
68 bool header; 68 bool header;
69 bool header_only; 69 bool header_only;
70 bool nonany_branch_mode; 70 bool nonany_branch_mode;
71 bool group_set;
71 int max_stack; 72 int max_stack;
72 struct perf_read_values show_threads_values; 73 struct perf_read_values show_threads_values;
73 const char *pretty_printing_style; 74 const char *pretty_printing_style;
@@ -193,6 +194,45 @@ out:
193 return err; 194 return err;
194} 195}
195 196
197/*
198 * Events in data file are not collect in groups, but we still want
199 * the group display. Set the artificial group and set the leader's
200 * forced_leader flag to notify the display code.
201 */
202static void setup_forced_leader(struct report *report,
203 struct perf_evlist *evlist)
204{
205 if (report->group_set && !evlist->nr_groups) {
206 struct perf_evsel *leader = perf_evlist__first(evlist);
207
208 perf_evlist__set_leader(evlist);
209 leader->forced_leader = true;
210 }
211}
212
213static int process_feature_event(struct perf_tool *tool,
214 union perf_event *event,
215 struct perf_session *session __maybe_unused)
216{
217 struct report *rep = container_of(tool, struct report, tool);
218
219 if (event->feat.feat_id < HEADER_LAST_FEATURE)
220 return perf_event__process_feature(tool, event, session);
221
222 if (event->feat.feat_id != HEADER_LAST_FEATURE) {
223 pr_err("failed: wrong feature ID: %" PRIu64 "\n",
224 event->feat.feat_id);
225 return -1;
226 }
227
228 /*
229 * All features are received, we can force the
230 * group if needed.
231 */
232 setup_forced_leader(rep, session->evlist);
233 return 0;
234}
235
196static int process_sample_event(struct perf_tool *tool, 236static int process_sample_event(struct perf_tool *tool,
197 union perf_event *event, 237 union perf_event *event,
198 struct perf_sample *sample, 238 struct perf_sample *sample,
@@ -400,8 +440,10 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
400 440
401 nr_samples = convert_unit(nr_samples, &unit); 441 nr_samples = convert_unit(nr_samples, &unit);
402 ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit); 442 ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
403 if (evname != NULL) 443 if (evname != NULL) {
404 ret += fprintf(fp, " of event '%s'", evname); 444 ret += fprintf(fp, " of event%s '%s'",
445 evsel->nr_members > 1 ? "s" : "", evname);
446 }
405 447
406 if (rep->time_str) 448 if (rep->time_str)
407 ret += fprintf(fp, " (time slices: %s)", rep->time_str); 449 ret += fprintf(fp, " (time slices: %s)", rep->time_str);
@@ -530,7 +572,8 @@ static int report__browse_hists(struct report *rep)
530 case 1: 572 case 1:
531 ret = perf_evlist__tui_browse_hists(evlist, help, NULL, 573 ret = perf_evlist__tui_browse_hists(evlist, help, NULL,
532 rep->min_percent, 574 rep->min_percent,
533 &session->header.env); 575 &session->header.env,
576 true);
534 /* 577 /*
535 * Usually "ret" is the last pressed key, and we only 578 * Usually "ret" is the last pressed key, and we only
536 * care if the key notifies us to switch data file. 579 * care if the key notifies us to switch data file.
@@ -613,6 +656,7 @@ static int stats_print(struct report *rep)
613static void tasks_setup(struct report *rep) 656static void tasks_setup(struct report *rep)
614{ 657{
615 memset(&rep->tool, 0, sizeof(rep->tool)); 658 memset(&rep->tool, 0, sizeof(rep->tool));
659 rep->tool.ordered_events = true;
616 if (rep->mmaps_mode) { 660 if (rep->mmaps_mode) {
617 rep->tool.mmap = perf_event__process_mmap; 661 rep->tool.mmap = perf_event__process_mmap;
618 rep->tool.mmap2 = perf_event__process_mmap2; 662 rep->tool.mmap2 = perf_event__process_mmap2;
@@ -953,7 +997,7 @@ int cmd_report(int argc, const char **argv)
953 .id_index = perf_event__process_id_index, 997 .id_index = perf_event__process_id_index,
954 .auxtrace_info = perf_event__process_auxtrace_info, 998 .auxtrace_info = perf_event__process_auxtrace_info,
955 .auxtrace = perf_event__process_auxtrace, 999 .auxtrace = perf_event__process_auxtrace,
956 .feature = perf_event__process_feature, 1000 .feature = process_feature_event,
957 .ordered_events = true, 1001 .ordered_events = true,
958 .ordering_requires_timestamps = true, 1002 .ordering_requires_timestamps = true,
959 }, 1003 },
@@ -974,6 +1018,8 @@ int cmd_report(int argc, const char **argv)
974 OPT_BOOLEAN(0, "mmaps", &report.mmaps_mode, "Display recorded tasks memory maps"), 1018 OPT_BOOLEAN(0, "mmaps", &report.mmaps_mode, "Display recorded tasks memory maps"),
975 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1019 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
976 "file", "vmlinux pathname"), 1020 "file", "vmlinux pathname"),
1021 OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
1022 "don't load vmlinux even if found"),
977 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, 1023 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
978 "file", "kallsyms pathname"), 1024 "file", "kallsyms pathname"),
979 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"), 1025 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
@@ -1055,7 +1101,7 @@ int cmd_report(int argc, const char **argv)
1055 "Specify disassembler style (e.g. -M intel for intel syntax)"), 1101 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1056 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 1102 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
1057 "Show a column with the sum of periods"), 1103 "Show a column with the sum of periods"),
1058 OPT_BOOLEAN(0, "group", &symbol_conf.event_group, 1104 OPT_BOOLEAN_SET(0, "group", &symbol_conf.event_group, &report.group_set,
1059 "Show event group information together"), 1105 "Show event group information together"),
1060 OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "", 1106 OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
1061 "use branch records for per branch histogram filling", 1107 "use branch records for per branch histogram filling",
@@ -1172,6 +1218,8 @@ repeat:
1172 has_br_stack = perf_header__has_feat(&session->header, 1218 has_br_stack = perf_header__has_feat(&session->header,
1173 HEADER_BRANCH_STACK); 1219 HEADER_BRANCH_STACK);
1174 1220
1221 setup_forced_leader(&report, session->evlist);
1222
1175 if (itrace_synth_opts.last_branch) 1223 if (itrace_synth_opts.last_branch)
1176 has_br_stack = true; 1224 has_br_stack = true;
1177 1225
@@ -1294,6 +1342,7 @@ repeat:
1294 symbol_conf.priv_size += sizeof(u32); 1342 symbol_conf.priv_size += sizeof(u32);
1295 symbol_conf.sort_by_name = true; 1343 symbol_conf.sort_by_name = true;
1296 } 1344 }
1345 annotation_config__init();
1297 } 1346 }
1298 1347
1299 if (symbol__init(&session->header.env) < 0) 1348 if (symbol__init(&session->header.env) < 0)
@@ -1331,6 +1380,15 @@ repeat:
1331 report.range_num = 1; 1380 report.range_num = 1;
1332 } 1381 }
1333 1382
1383 if (session->tevent.pevent &&
1384 pevent_set_function_resolver(session->tevent.pevent,
1385 machine__resolve_kernel_addr,
1386 &session->machines.host) < 0) {
1387 pr_err("%s: failed to set libtraceevent function resolver\n",
1388 __func__);
1389 return -1;
1390 }
1391
1334 sort__setup_elide(stdout); 1392 sort__setup_elide(stdout);
1335 1393
1336 ret = __cmd_report(&report); 1394 ret = __cmd_report(&report);
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 83283fedb00f..4dfdee668b0c 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -254,6 +254,10 @@ struct thread_runtime {
254 u64 total_delay_time; 254 u64 total_delay_time;
255 255
256 int last_state; 256 int last_state;
257
258 char shortname[3];
259 bool comm_changed;
260
257 u64 migrations; 261 u64 migrations;
258}; 262};
259 263
@@ -897,6 +901,37 @@ struct sort_dimension {
897 struct list_head list; 901 struct list_head list;
898}; 902};
899 903
904/*
905 * handle runtime stats saved per thread
906 */
907static struct thread_runtime *thread__init_runtime(struct thread *thread)
908{
909 struct thread_runtime *r;
910
911 r = zalloc(sizeof(struct thread_runtime));
912 if (!r)
913 return NULL;
914
915 init_stats(&r->run_stats);
916 thread__set_priv(thread, r);
917
918 return r;
919}
920
921static struct thread_runtime *thread__get_runtime(struct thread *thread)
922{
923 struct thread_runtime *tr;
924
925 tr = thread__priv(thread);
926 if (tr == NULL) {
927 tr = thread__init_runtime(thread);
928 if (tr == NULL)
929 pr_debug("Failed to malloc memory for runtime data.\n");
930 }
931
932 return tr;
933}
934
900static int 935static int
901thread_lat_cmp(struct list_head *list, struct work_atoms *l, struct work_atoms *r) 936thread_lat_cmp(struct list_head *list, struct work_atoms *l, struct work_atoms *r)
902{ 937{
@@ -1480,6 +1515,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1480{ 1515{
1481 const u32 next_pid = perf_evsel__intval(evsel, sample, "next_pid"); 1516 const u32 next_pid = perf_evsel__intval(evsel, sample, "next_pid");
1482 struct thread *sched_in; 1517 struct thread *sched_in;
1518 struct thread_runtime *tr;
1483 int new_shortname; 1519 int new_shortname;
1484 u64 timestamp0, timestamp = sample->time; 1520 u64 timestamp0, timestamp = sample->time;
1485 s64 delta; 1521 s64 delta;
@@ -1519,22 +1555,28 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1519 if (sched_in == NULL) 1555 if (sched_in == NULL)
1520 return -1; 1556 return -1;
1521 1557
1558 tr = thread__get_runtime(sched_in);
1559 if (tr == NULL) {
1560 thread__put(sched_in);
1561 return -1;
1562 }
1563
1522 sched->curr_thread[this_cpu] = thread__get(sched_in); 1564 sched->curr_thread[this_cpu] = thread__get(sched_in);
1523 1565
1524 printf(" "); 1566 printf(" ");
1525 1567
1526 new_shortname = 0; 1568 new_shortname = 0;
1527 if (!sched_in->shortname[0]) { 1569 if (!tr->shortname[0]) {
1528 if (!strcmp(thread__comm_str(sched_in), "swapper")) { 1570 if (!strcmp(thread__comm_str(sched_in), "swapper")) {
1529 /* 1571 /*
1530 * Don't allocate a letter-number for swapper:0 1572 * Don't allocate a letter-number for swapper:0
1531 * as a shortname. Instead, we use '.' for it. 1573 * as a shortname. Instead, we use '.' for it.
1532 */ 1574 */
1533 sched_in->shortname[0] = '.'; 1575 tr->shortname[0] = '.';
1534 sched_in->shortname[1] = ' '; 1576 tr->shortname[1] = ' ';
1535 } else { 1577 } else {
1536 sched_in->shortname[0] = sched->next_shortname1; 1578 tr->shortname[0] = sched->next_shortname1;
1537 sched_in->shortname[1] = sched->next_shortname2; 1579 tr->shortname[1] = sched->next_shortname2;
1538 1580
1539 if (sched->next_shortname1 < 'Z') { 1581 if (sched->next_shortname1 < 'Z') {
1540 sched->next_shortname1++; 1582 sched->next_shortname1++;
@@ -1552,6 +1594,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1552 for (i = 0; i < cpus_nr; i++) { 1594 for (i = 0; i < cpus_nr; i++) {
1553 int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i; 1595 int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i;
1554 struct thread *curr_thread = sched->curr_thread[cpu]; 1596 struct thread *curr_thread = sched->curr_thread[cpu];
1597 struct thread_runtime *curr_tr;
1555 const char *pid_color = color; 1598 const char *pid_color = color;
1556 const char *cpu_color = color; 1599 const char *cpu_color = color;
1557 1600
@@ -1569,9 +1612,14 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1569 else 1612 else
1570 color_fprintf(stdout, cpu_color, "*"); 1613 color_fprintf(stdout, cpu_color, "*");
1571 1614
1572 if (sched->curr_thread[cpu]) 1615 if (sched->curr_thread[cpu]) {
1573 color_fprintf(stdout, pid_color, "%2s ", sched->curr_thread[cpu]->shortname); 1616 curr_tr = thread__get_runtime(sched->curr_thread[cpu]);
1574 else 1617 if (curr_tr == NULL) {
1618 thread__put(sched_in);
1619 return -1;
1620 }
1621 color_fprintf(stdout, pid_color, "%2s ", curr_tr->shortname);
1622 } else
1575 color_fprintf(stdout, color, " "); 1623 color_fprintf(stdout, color, " ");
1576 } 1624 }
1577 1625
@@ -1580,14 +1628,15 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1580 1628
1581 timestamp__scnprintf_usec(timestamp, stimestamp, sizeof(stimestamp)); 1629 timestamp__scnprintf_usec(timestamp, stimestamp, sizeof(stimestamp));
1582 color_fprintf(stdout, color, " %12s secs ", stimestamp); 1630 color_fprintf(stdout, color, " %12s secs ", stimestamp);
1583 if (new_shortname || (verbose > 0 && sched_in->tid)) { 1631 if (new_shortname || tr->comm_changed || (verbose > 0 && sched_in->tid)) {
1584 const char *pid_color = color; 1632 const char *pid_color = color;
1585 1633
1586 if (thread__has_color(sched_in)) 1634 if (thread__has_color(sched_in))
1587 pid_color = COLOR_PIDS; 1635 pid_color = COLOR_PIDS;
1588 1636
1589 color_fprintf(stdout, pid_color, "%s => %s:%d", 1637 color_fprintf(stdout, pid_color, "%s => %s:%d",
1590 sched_in->shortname, thread__comm_str(sched_in), sched_in->tid); 1638 tr->shortname, thread__comm_str(sched_in), sched_in->tid);
1639 tr->comm_changed = false;
1591 } 1640 }
1592 1641
1593 if (sched->map.comp && new_cpu) 1642 if (sched->map.comp && new_cpu)
@@ -1691,6 +1740,37 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1691 return err; 1740 return err;
1692} 1741}
1693 1742
1743static int perf_sched__process_comm(struct perf_tool *tool __maybe_unused,
1744 union perf_event *event,
1745 struct perf_sample *sample,
1746 struct machine *machine)
1747{
1748 struct thread *thread;
1749 struct thread_runtime *tr;
1750 int err;
1751
1752 err = perf_event__process_comm(tool, event, sample, machine);
1753 if (err)
1754 return err;
1755
1756 thread = machine__find_thread(machine, sample->pid, sample->tid);
1757 if (!thread) {
1758 pr_err("Internal error: can't find thread\n");
1759 return -1;
1760 }
1761
1762 tr = thread__get_runtime(thread);
1763 if (tr == NULL) {
1764 thread__put(thread);
1765 return -1;
1766 }
1767
1768 tr->comm_changed = true;
1769 thread__put(thread);
1770
1771 return 0;
1772}
1773
1694static int perf_sched__read_events(struct perf_sched *sched) 1774static int perf_sched__read_events(struct perf_sched *sched)
1695{ 1775{
1696 const struct perf_evsel_str_handler handlers[] = { 1776 const struct perf_evsel_str_handler handlers[] = {
@@ -2200,37 +2280,6 @@ static void save_idle_callchain(struct idle_thread_runtime *itr,
2200 callchain_cursor__copy(&itr->cursor, &callchain_cursor); 2280 callchain_cursor__copy(&itr->cursor, &callchain_cursor);
2201} 2281}
2202 2282
2203/*
2204 * handle runtime stats saved per thread
2205 */
2206static struct thread_runtime *thread__init_runtime(struct thread *thread)
2207{
2208 struct thread_runtime *r;
2209
2210 r = zalloc(sizeof(struct thread_runtime));
2211 if (!r)
2212 return NULL;
2213
2214 init_stats(&r->run_stats);
2215 thread__set_priv(thread, r);
2216
2217 return r;
2218}
2219
2220static struct thread_runtime *thread__get_runtime(struct thread *thread)
2221{
2222 struct thread_runtime *tr;
2223
2224 tr = thread__priv(thread);
2225 if (tr == NULL) {
2226 tr = thread__init_runtime(thread);
2227 if (tr == NULL)
2228 pr_debug("Failed to malloc memory for runtime data.\n");
2229 }
2230
2231 return tr;
2232}
2233
2234static struct thread *timehist_get_thread(struct perf_sched *sched, 2283static struct thread *timehist_get_thread(struct perf_sched *sched,
2235 struct perf_sample *sample, 2284 struct perf_sample *sample,
2236 struct machine *machine, 2285 struct machine *machine,
@@ -3291,7 +3340,7 @@ int cmd_sched(int argc, const char **argv)
3291 struct perf_sched sched = { 3340 struct perf_sched sched = {
3292 .tool = { 3341 .tool = {
3293 .sample = perf_sched__process_tracepoint_sample, 3342 .sample = perf_sched__process_tracepoint_sample,
3294 .comm = perf_event__process_comm, 3343 .comm = perf_sched__process_comm,
3295 .namespaces = perf_event__process_namespaces, 3344 .namespaces = perf_event__process_namespaces,
3296 .lost = perf_event__process_lost, 3345 .lost = perf_event__process_lost,
3297 .fork = perf_sched__process_fork_event, 3346 .fork = perf_sched__process_fork_event,
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index ab19a6ee4093..313c42423393 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1489,6 +1489,7 @@ struct perf_script {
1489 bool show_switch_events; 1489 bool show_switch_events;
1490 bool show_namespace_events; 1490 bool show_namespace_events;
1491 bool show_lost_events; 1491 bool show_lost_events;
1492 bool show_round_events;
1492 bool allocated; 1493 bool allocated;
1493 bool per_event_dump; 1494 bool per_event_dump;
1494 struct cpu_map *cpus; 1495 struct cpu_map *cpus;
@@ -2104,6 +2105,16 @@ process_lost_event(struct perf_tool *tool,
2104 return 0; 2105 return 0;
2105} 2106}
2106 2107
2108static int
2109process_finished_round_event(struct perf_tool *tool __maybe_unused,
2110 union perf_event *event,
2111 struct ordered_events *oe __maybe_unused)
2112
2113{
2114 perf_event__fprintf(event, stdout);
2115 return 0;
2116}
2117
2107static void sig_handler(int sig __maybe_unused) 2118static void sig_handler(int sig __maybe_unused)
2108{ 2119{
2109 session_done = 1; 2120 session_done = 1;
@@ -2200,6 +2211,10 @@ static int __cmd_script(struct perf_script *script)
2200 script->tool.namespaces = process_namespaces_event; 2211 script->tool.namespaces = process_namespaces_event;
2201 if (script->show_lost_events) 2212 if (script->show_lost_events)
2202 script->tool.lost = process_lost_event; 2213 script->tool.lost = process_lost_event;
2214 if (script->show_round_events) {
2215 script->tool.ordered_events = false;
2216 script->tool.finished_round = process_finished_round_event;
2217 }
2203 2218
2204 if (perf_script__setup_per_event_dump(script)) { 2219 if (perf_script__setup_per_event_dump(script)) {
2205 pr_err("Couldn't create the per event dump files\n"); 2220 pr_err("Couldn't create the per event dump files\n");
@@ -2659,8 +2674,8 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
2659 } 2674 }
2660 2675
2661 for_each_lang(scripts_path, scripts_dir, lang_dirent) { 2676 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
2662 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 2677 scnprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
2663 lang_dirent->d_name); 2678 lang_dirent->d_name);
2664 lang_dir = opendir(lang_path); 2679 lang_dir = opendir(lang_path);
2665 if (!lang_dir) 2680 if (!lang_dir)
2666 continue; 2681 continue;
@@ -2669,8 +2684,8 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
2669 script_root = get_script_root(script_dirent, REPORT_SUFFIX); 2684 script_root = get_script_root(script_dirent, REPORT_SUFFIX);
2670 if (script_root) { 2685 if (script_root) {
2671 desc = script_desc__findnew(script_root); 2686 desc = script_desc__findnew(script_root);
2672 snprintf(script_path, MAXPATHLEN, "%s/%s", 2687 scnprintf(script_path, MAXPATHLEN, "%s/%s",
2673 lang_path, script_dirent->d_name); 2688 lang_path, script_dirent->d_name);
2674 read_script_info(desc, script_path); 2689 read_script_info(desc, script_path);
2675 free(script_root); 2690 free(script_root);
2676 } 2691 }
@@ -2706,7 +2721,7 @@ static int check_ev_match(char *dir_name, char *scriptname,
2706 int match, len; 2721 int match, len;
2707 FILE *fp; 2722 FILE *fp;
2708 2723
2709 sprintf(filename, "%s/bin/%s-record", dir_name, scriptname); 2724 scnprintf(filename, MAXPATHLEN, "%s/bin/%s-record", dir_name, scriptname);
2710 2725
2711 fp = fopen(filename, "r"); 2726 fp = fopen(filename, "r");
2712 if (!fp) 2727 if (!fp)
@@ -2784,8 +2799,8 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
2784 } 2799 }
2785 2800
2786 for_each_lang(scripts_path, scripts_dir, lang_dirent) { 2801 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
2787 snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path, 2802 scnprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path,
2788 lang_dirent->d_name); 2803 lang_dirent->d_name);
2789#ifdef NO_LIBPERL 2804#ifdef NO_LIBPERL
2790 if (strstr(lang_path, "perl")) 2805 if (strstr(lang_path, "perl"))
2791 continue; 2806 continue;
@@ -2840,8 +2855,8 @@ static char *get_script_path(const char *script_root, const char *suffix)
2840 return NULL; 2855 return NULL;
2841 2856
2842 for_each_lang(scripts_path, scripts_dir, lang_dirent) { 2857 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
2843 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 2858 scnprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
2844 lang_dirent->d_name); 2859 lang_dirent->d_name);
2845 lang_dir = opendir(lang_path); 2860 lang_dir = opendir(lang_path);
2846 if (!lang_dir) 2861 if (!lang_dir)
2847 continue; 2862 continue;
@@ -2852,8 +2867,8 @@ static char *get_script_path(const char *script_root, const char *suffix)
2852 free(__script_root); 2867 free(__script_root);
2853 closedir(lang_dir); 2868 closedir(lang_dir);
2854 closedir(scripts_dir); 2869 closedir(scripts_dir);
2855 snprintf(script_path, MAXPATHLEN, "%s/%s", 2870 scnprintf(script_path, MAXPATHLEN, "%s/%s",
2856 lang_path, script_dirent->d_name); 2871 lang_path, script_dirent->d_name);
2857 return strdup(script_path); 2872 return strdup(script_path);
2858 } 2873 }
2859 free(__script_root); 2874 free(__script_root);
@@ -3139,6 +3154,8 @@ int cmd_script(int argc, const char **argv)
3139 "Show namespace events (if recorded)"), 3154 "Show namespace events (if recorded)"),
3140 OPT_BOOLEAN('\0', "show-lost-events", &script.show_lost_events, 3155 OPT_BOOLEAN('\0', "show-lost-events", &script.show_lost_events,
3141 "Show lost events (if recorded)"), 3156 "Show lost events (if recorded)"),
3157 OPT_BOOLEAN('\0', "show-round-events", &script.show_round_events,
3158 "Show round events (if recorded)"),
3142 OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump, 3159 OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump,
3143 "Dump trace output to files named by the monitored events"), 3160 "Dump trace output to files named by the monitored events"),
3144 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"), 3161 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 98bf9d32f222..f5c454855908 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -168,6 +168,7 @@ static struct timespec ref_time;
168static struct cpu_map *aggr_map; 168static struct cpu_map *aggr_map;
169static aggr_get_id_t aggr_get_id; 169static aggr_get_id_t aggr_get_id;
170static bool append_file; 170static bool append_file;
171static bool interval_count;
171static const char *output_name; 172static const char *output_name;
172static int output_fd; 173static int output_fd;
173static int print_free_counters_hint; 174static int print_free_counters_hint;
@@ -507,14 +508,13 @@ static int perf_stat_synthesize_config(bool is_pipe)
507 508
508#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 509#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
509 510
510static int __store_counter_ids(struct perf_evsel *counter, 511static int __store_counter_ids(struct perf_evsel *counter)
511 struct cpu_map *cpus,
512 struct thread_map *threads)
513{ 512{
514 int cpu, thread; 513 int cpu, thread;
515 514
516 for (cpu = 0; cpu < cpus->nr; cpu++) { 515 for (cpu = 0; cpu < xyarray__max_x(counter->fd); cpu++) {
517 for (thread = 0; thread < threads->nr; thread++) { 516 for (thread = 0; thread < xyarray__max_y(counter->fd);
517 thread++) {
518 int fd = FD(counter, cpu, thread); 518 int fd = FD(counter, cpu, thread);
519 519
520 if (perf_evlist__id_add_fd(evsel_list, counter, 520 if (perf_evlist__id_add_fd(evsel_list, counter,
@@ -534,7 +534,7 @@ static int store_counter_ids(struct perf_evsel *counter)
534 if (perf_evsel__alloc_id(counter, cpus->nr, threads->nr)) 534 if (perf_evsel__alloc_id(counter, cpus->nr, threads->nr))
535 return -ENOMEM; 535 return -ENOMEM;
536 536
537 return __store_counter_ids(counter, cpus, threads); 537 return __store_counter_ids(counter);
538} 538}
539 539
540static bool perf_evsel__should_store_id(struct perf_evsel *counter) 540static bool perf_evsel__should_store_id(struct perf_evsel *counter)
@@ -571,6 +571,8 @@ static struct perf_evsel *perf_evsel__reset_weak_group(struct perf_evsel *evsel)
571static int __run_perf_stat(int argc, const char **argv) 571static int __run_perf_stat(int argc, const char **argv)
572{ 572{
573 int interval = stat_config.interval; 573 int interval = stat_config.interval;
574 int times = stat_config.times;
575 int timeout = stat_config.timeout;
574 char msg[BUFSIZ]; 576 char msg[BUFSIZ];
575 unsigned long long t0, t1; 577 unsigned long long t0, t1;
576 struct perf_evsel *counter; 578 struct perf_evsel *counter;
@@ -584,6 +586,9 @@ static int __run_perf_stat(int argc, const char **argv)
584 if (interval) { 586 if (interval) {
585 ts.tv_sec = interval / USEC_PER_MSEC; 587 ts.tv_sec = interval / USEC_PER_MSEC;
586 ts.tv_nsec = (interval % USEC_PER_MSEC) * NSEC_PER_MSEC; 588 ts.tv_nsec = (interval % USEC_PER_MSEC) * NSEC_PER_MSEC;
589 } else if (timeout) {
590 ts.tv_sec = timeout / USEC_PER_MSEC;
591 ts.tv_nsec = (timeout % USEC_PER_MSEC) * NSEC_PER_MSEC;
587 } else { 592 } else {
588 ts.tv_sec = 1; 593 ts.tv_sec = 1;
589 ts.tv_nsec = 0; 594 ts.tv_nsec = 0;
@@ -632,7 +637,19 @@ try_again:
632 if (verbose > 0) 637 if (verbose > 0)
633 ui__warning("%s\n", msg); 638 ui__warning("%s\n", msg);
634 goto try_again; 639 goto try_again;
635 } 640 } else if (target__has_per_thread(&target) &&
641 evsel_list->threads &&
642 evsel_list->threads->err_thread != -1) {
643 /*
644 * For global --per-thread case, skip current
645 * error thread.
646 */
647 if (!thread_map__remove(evsel_list->threads,
648 evsel_list->threads->err_thread)) {
649 evsel_list->threads->err_thread = -1;
650 goto try_again;
651 }
652 }
636 653
637 perf_evsel__open_strerror(counter, &target, 654 perf_evsel__open_strerror(counter, &target,
638 errno, msg, sizeof(msg)); 655 errno, msg, sizeof(msg));
@@ -696,10 +713,14 @@ try_again:
696 perf_evlist__start_workload(evsel_list); 713 perf_evlist__start_workload(evsel_list);
697 enable_counters(); 714 enable_counters();
698 715
699 if (interval) { 716 if (interval || timeout) {
700 while (!waitpid(child_pid, &status, WNOHANG)) { 717 while (!waitpid(child_pid, &status, WNOHANG)) {
701 nanosleep(&ts, NULL); 718 nanosleep(&ts, NULL);
719 if (timeout)
720 break;
702 process_interval(); 721 process_interval();
722 if (interval_count && !(--times))
723 break;
703 } 724 }
704 } 725 }
705 waitpid(child_pid, &status, 0); 726 waitpid(child_pid, &status, 0);
@@ -716,8 +737,13 @@ try_again:
716 enable_counters(); 737 enable_counters();
717 while (!done) { 738 while (!done) {
718 nanosleep(&ts, NULL); 739 nanosleep(&ts, NULL);
719 if (interval) 740 if (timeout)
741 break;
742 if (interval) {
720 process_interval(); 743 process_interval();
744 if (interval_count && !(--times))
745 break;
746 }
721 } 747 }
722 } 748 }
723 749
@@ -917,7 +943,7 @@ static void print_metric_csv(void *ctx,
917 char buf[64], *vals, *ends; 943 char buf[64], *vals, *ends;
918 944
919 if (unit == NULL || fmt == NULL) { 945 if (unit == NULL || fmt == NULL) {
920 fprintf(out, "%s%s%s%s", csv_sep, csv_sep, csv_sep, csv_sep); 946 fprintf(out, "%s%s", csv_sep, csv_sep);
921 return; 947 return;
922 } 948 }
923 snprintf(buf, sizeof(buf), fmt, val); 949 snprintf(buf, sizeof(buf), fmt, val);
@@ -1225,6 +1251,31 @@ static void aggr_update_shadow(void)
1225 } 1251 }
1226} 1252}
1227 1253
1254static void uniquify_event_name(struct perf_evsel *counter)
1255{
1256 char *new_name;
1257 char *config;
1258
1259 if (!counter->pmu_name || !strncmp(counter->name, counter->pmu_name,
1260 strlen(counter->pmu_name)))
1261 return;
1262
1263 config = strchr(counter->name, '/');
1264 if (config) {
1265 if (asprintf(&new_name,
1266 "%s%s", counter->pmu_name, config) > 0) {
1267 free(counter->name);
1268 counter->name = new_name;
1269 }
1270 } else {
1271 if (asprintf(&new_name,
1272 "%s [%s]", counter->name, counter->pmu_name) > 0) {
1273 free(counter->name);
1274 counter->name = new_name;
1275 }
1276 }
1277}
1278
1228static void collect_all_aliases(struct perf_evsel *counter, 1279static void collect_all_aliases(struct perf_evsel *counter,
1229 void (*cb)(struct perf_evsel *counter, void *data, 1280 void (*cb)(struct perf_evsel *counter, void *data,
1230 bool first), 1281 bool first),
@@ -1253,7 +1304,9 @@ static bool collect_data(struct perf_evsel *counter,
1253 if (counter->merged_stat) 1304 if (counter->merged_stat)
1254 return false; 1305 return false;
1255 cb(counter, data, true); 1306 cb(counter, data, true);
1256 if (!no_merge && counter->auto_merge_stats) 1307 if (no_merge)
1308 uniquify_event_name(counter);
1309 else if (counter->auto_merge_stats)
1257 collect_all_aliases(counter, cb, data); 1310 collect_all_aliases(counter, cb, data);
1258 return true; 1311 return true;
1259} 1312}
@@ -1891,6 +1944,10 @@ static const struct option stat_options[] = {
1891 "command to run after to the measured command"), 1944 "command to run after to the measured command"),
1892 OPT_UINTEGER('I', "interval-print", &stat_config.interval, 1945 OPT_UINTEGER('I', "interval-print", &stat_config.interval,
1893 "print counts at regular interval in ms (>= 10)"), 1946 "print counts at regular interval in ms (>= 10)"),
1947 OPT_INTEGER(0, "interval-count", &stat_config.times,
1948 "print counts for fixed number of times"),
1949 OPT_UINTEGER(0, "timeout", &stat_config.timeout,
1950 "stop workload and print counts after a timeout period in ms (>= 10ms)"),
1894 OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode, 1951 OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
1895 "aggregate counts per processor socket", AGGR_SOCKET), 1952 "aggregate counts per processor socket", AGGR_SOCKET),
1896 OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode, 1953 OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode,
@@ -2274,11 +2331,16 @@ static int add_default_attributes(void)
2274 return 0; 2331 return 0;
2275 2332
2276 if (transaction_run) { 2333 if (transaction_run) {
2334 struct parse_events_error errinfo;
2335
2277 if (pmu_have_event("cpu", "cycles-ct") && 2336 if (pmu_have_event("cpu", "cycles-ct") &&
2278 pmu_have_event("cpu", "el-start")) 2337 pmu_have_event("cpu", "el-start"))
2279 err = parse_events(evsel_list, transaction_attrs, NULL); 2338 err = parse_events(evsel_list, transaction_attrs,
2339 &errinfo);
2280 else 2340 else
2281 err = parse_events(evsel_list, transaction_limited_attrs, NULL); 2341 err = parse_events(evsel_list,
2342 transaction_limited_attrs,
2343 &errinfo);
2282 if (err) { 2344 if (err) {
2283 fprintf(stderr, "Cannot set up transaction events\n"); 2345 fprintf(stderr, "Cannot set up transaction events\n");
2284 return -1; 2346 return -1;
@@ -2688,7 +2750,7 @@ int cmd_stat(int argc, const char **argv)
2688 int status = -EINVAL, run_idx; 2750 int status = -EINVAL, run_idx;
2689 const char *mode; 2751 const char *mode;
2690 FILE *output = stderr; 2752 FILE *output = stderr;
2691 unsigned int interval; 2753 unsigned int interval, timeout;
2692 const char * const stat_subcommands[] = { "record", "report" }; 2754 const char * const stat_subcommands[] = { "record", "report" };
2693 2755
2694 setlocale(LC_ALL, ""); 2756 setlocale(LC_ALL, "");
@@ -2719,6 +2781,7 @@ int cmd_stat(int argc, const char **argv)
2719 return __cmd_report(argc, argv); 2781 return __cmd_report(argc, argv);
2720 2782
2721 interval = stat_config.interval; 2783 interval = stat_config.interval;
2784 timeout = stat_config.timeout;
2722 2785
2723 /* 2786 /*
2724 * For record command the -o is already taken care of. 2787 * For record command the -o is already taken care of.
@@ -2871,6 +2934,33 @@ int cmd_stat(int argc, const char **argv)
2871 "Please proceed with caution.\n"); 2934 "Please proceed with caution.\n");
2872 } 2935 }
2873 2936
2937 if (stat_config.times && interval)
2938 interval_count = true;
2939 else if (stat_config.times && !interval) {
2940 pr_err("interval-count option should be used together with "
2941 "interval-print.\n");
2942 parse_options_usage(stat_usage, stat_options, "interval-count", 0);
2943 parse_options_usage(stat_usage, stat_options, "I", 1);
2944 goto out;
2945 }
2946
2947 if (timeout && timeout < 100) {
2948 if (timeout < 10) {
2949 pr_err("timeout must be >= 10ms.\n");
2950 parse_options_usage(stat_usage, stat_options, "timeout", 0);
2951 goto out;
2952 } else
2953 pr_warning("timeout < 100ms. "
2954 "The overhead percentage could be high in some cases. "
2955 "Please proceed with caution.\n");
2956 }
2957 if (timeout && interval) {
2958 pr_err("timeout option is not supported with interval-print.\n");
2959 parse_options_usage(stat_usage, stat_options, "timeout", 0);
2960 parse_options_usage(stat_usage, stat_options, "I", 1);
2961 goto out;
2962 }
2963
2874 if (perf_evlist__alloc_stats(evsel_list, interval)) 2964 if (perf_evlist__alloc_stats(evsel_list, interval))
2875 goto out; 2965 goto out;
2876 2966
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c6ccda52117d..f39bd60d2708 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -283,8 +283,9 @@ static void perf_top__print_sym_table(struct perf_top *top)
283 283
284 printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 284 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
285 285
286 if (hists->stats.nr_lost_warned != 286 if (!top->record_opts.overwrite &&
287 hists->stats.nr_events[PERF_RECORD_LOST]) { 287 (hists->stats.nr_lost_warned !=
288 hists->stats.nr_events[PERF_RECORD_LOST])) {
288 hists->stats.nr_lost_warned = 289 hists->stats.nr_lost_warned =
289 hists->stats.nr_events[PERF_RECORD_LOST]; 290 hists->stats.nr_events[PERF_RECORD_LOST];
290 color_fprintf(stdout, PERF_COLOR_RED, 291 color_fprintf(stdout, PERF_COLOR_RED,
@@ -611,7 +612,8 @@ static void *display_thread_tui(void *arg)
611 612
612 perf_evlist__tui_browse_hists(top->evlist, help, &hbt, 613 perf_evlist__tui_browse_hists(top->evlist, help, &hbt,
613 top->min_percent, 614 top->min_percent,
614 &top->session->header.env); 615 &top->session->header.env,
616 !top->record_opts.overwrite);
615 617
616 done = 1; 618 done = 1;
617 return NULL; 619 return NULL;
@@ -807,15 +809,22 @@ static void perf_event__process_sample(struct perf_tool *tool,
807 809
808static void perf_top__mmap_read_idx(struct perf_top *top, int idx) 810static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
809{ 811{
812 struct record_opts *opts = &top->record_opts;
813 struct perf_evlist *evlist = top->evlist;
810 struct perf_sample sample; 814 struct perf_sample sample;
811 struct perf_evsel *evsel; 815 struct perf_evsel *evsel;
816 struct perf_mmap *md;
812 struct perf_session *session = top->session; 817 struct perf_session *session = top->session;
813 union perf_event *event; 818 union perf_event *event;
814 struct machine *machine; 819 struct machine *machine;
815 int ret; 820 int ret;
816 821
817 while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) { 822 md = opts->overwrite ? &evlist->overwrite_mmap[idx] : &evlist->mmap[idx];
818 ret = perf_evlist__parse_sample(top->evlist, event, &sample); 823 if (perf_mmap__read_init(md) < 0)
824 return;
825
826 while ((event = perf_mmap__read_event(md)) != NULL) {
827 ret = perf_evlist__parse_sample(evlist, event, &sample);
819 if (ret) { 828 if (ret) {
820 pr_err("Can't parse sample, err = %d\n", ret); 829 pr_err("Can't parse sample, err = %d\n", ret);
821 goto next_event; 830 goto next_event;
@@ -869,16 +878,120 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
869 } else 878 } else
870 ++session->evlist->stats.nr_unknown_events; 879 ++session->evlist->stats.nr_unknown_events;
871next_event: 880next_event:
872 perf_evlist__mmap_consume(top->evlist, idx); 881 perf_mmap__consume(md);
873 } 882 }
883
884 perf_mmap__read_done(md);
874} 885}
875 886
876static void perf_top__mmap_read(struct perf_top *top) 887static void perf_top__mmap_read(struct perf_top *top)
877{ 888{
889 bool overwrite = top->record_opts.overwrite;
890 struct perf_evlist *evlist = top->evlist;
891 unsigned long long start, end;
878 int i; 892 int i;
879 893
894 start = rdclock();
895 if (overwrite)
896 perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_DATA_PENDING);
897
880 for (i = 0; i < top->evlist->nr_mmaps; i++) 898 for (i = 0; i < top->evlist->nr_mmaps; i++)
881 perf_top__mmap_read_idx(top, i); 899 perf_top__mmap_read_idx(top, i);
900
901 if (overwrite) {
902 perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
903 perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_RUNNING);
904 }
905 end = rdclock();
906
907 if ((end - start) > (unsigned long long)top->delay_secs * NSEC_PER_SEC)
908 ui__warning("Too slow to read ring buffer.\n"
909 "Please try increasing the period (-c) or\n"
910 "decreasing the freq (-F) or\n"
911 "limiting the number of CPUs (-C)\n");
912}
913
914/*
915 * Check per-event overwrite term.
916 * perf top should support consistent term for all events.
917 * - All events don't have per-event term
918 * E.g. "cpu/cpu-cycles/,cpu/instructions/"
919 * Nothing change, return 0.
920 * - All events have same per-event term
921 * E.g. "cpu/cpu-cycles,no-overwrite/,cpu/instructions,no-overwrite/
922 * Using the per-event setting to replace the opts->overwrite if
923 * they are different, then return 0.
924 * - Events have different per-event term
925 * E.g. "cpu/cpu-cycles,overwrite/,cpu/instructions,no-overwrite/"
926 * Return -1
927 * - Some of the event set per-event term, but some not.
928 * E.g. "cpu/cpu-cycles/,cpu/instructions,no-overwrite/"
929 * Return -1
930 */
931static int perf_top__overwrite_check(struct perf_top *top)
932{
933 struct record_opts *opts = &top->record_opts;
934 struct perf_evlist *evlist = top->evlist;
935 struct perf_evsel_config_term *term;
936 struct list_head *config_terms;
937 struct perf_evsel *evsel;
938 int set, overwrite = -1;
939
940 evlist__for_each_entry(evlist, evsel) {
941 set = -1;
942 config_terms = &evsel->config_terms;
943 list_for_each_entry(term, config_terms, list) {
944 if (term->type == PERF_EVSEL__CONFIG_TERM_OVERWRITE)
945 set = term->val.overwrite ? 1 : 0;
946 }
947
948 /* no term for current and previous event (likely) */
949 if ((overwrite < 0) && (set < 0))
950 continue;
951
952 /* has term for both current and previous event, compare */
953 if ((overwrite >= 0) && (set >= 0) && (overwrite != set))
954 return -1;
955
956 /* no term for current event but has term for previous one */
957 if ((overwrite >= 0) && (set < 0))
958 return -1;
959
960 /* has term for current event */
961 if ((overwrite < 0) && (set >= 0)) {
962 /* if it's first event, set overwrite */
963 if (evsel == perf_evlist__first(evlist))
964 overwrite = set;
965 else
966 return -1;
967 }
968 }
969
970 if ((overwrite >= 0) && (opts->overwrite != overwrite))
971 opts->overwrite = overwrite;
972
973 return 0;
974}
975
976static int perf_top_overwrite_fallback(struct perf_top *top,
977 struct perf_evsel *evsel)
978{
979 struct record_opts *opts = &top->record_opts;
980 struct perf_evlist *evlist = top->evlist;
981 struct perf_evsel *counter;
982
983 if (!opts->overwrite)
984 return 0;
985
986 /* only fall back when first event fails */
987 if (evsel != perf_evlist__first(evlist))
988 return 0;
989
990 evlist__for_each_entry(evlist, counter)
991 counter->attr.write_backward = false;
992 opts->overwrite = false;
993 pr_debug2("fall back to non-overwrite mode\n");
994 return 1;
882} 995}
883 996
884static int perf_top__start_counters(struct perf_top *top) 997static int perf_top__start_counters(struct perf_top *top)
@@ -888,12 +1001,33 @@ static int perf_top__start_counters(struct perf_top *top)
888 struct perf_evlist *evlist = top->evlist; 1001 struct perf_evlist *evlist = top->evlist;
889 struct record_opts *opts = &top->record_opts; 1002 struct record_opts *opts = &top->record_opts;
890 1003
1004 if (perf_top__overwrite_check(top)) {
1005 ui__error("perf top only support consistent per-event "
1006 "overwrite setting for all events\n");
1007 goto out_err;
1008 }
1009
891 perf_evlist__config(evlist, opts, &callchain_param); 1010 perf_evlist__config(evlist, opts, &callchain_param);
892 1011
893 evlist__for_each_entry(evlist, counter) { 1012 evlist__for_each_entry(evlist, counter) {
894try_again: 1013try_again:
895 if (perf_evsel__open(counter, top->evlist->cpus, 1014 if (perf_evsel__open(counter, top->evlist->cpus,
896 top->evlist->threads) < 0) { 1015 top->evlist->threads) < 0) {
1016
1017 /*
1018 * Specially handle overwrite fall back.
1019 * Because perf top is the only tool which has
1020 * overwrite mode by default, support
1021 * both overwrite and non-overwrite mode, and
1022 * require consistent mode for all events.
1023 *
1024 * May move it to generic code with more tools
1025 * have similar attribute.
1026 */
1027 if (perf_missing_features.write_backward &&
1028 perf_top_overwrite_fallback(top, counter))
1029 goto try_again;
1030
897 if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) { 1031 if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) {
898 if (verbose > 0) 1032 if (verbose > 0)
899 ui__warning("%s\n", msg); 1033 ui__warning("%s\n", msg);
@@ -1033,7 +1167,7 @@ static int __cmd_top(struct perf_top *top)
1033 1167
1034 perf_top__mmap_read(top); 1168 perf_top__mmap_read(top);
1035 1169
1036 if (hits == top->samples) 1170 if (opts->overwrite || (hits == top->samples))
1037 ret = perf_evlist__poll(top->evlist, 100); 1171 ret = perf_evlist__poll(top->evlist, 100);
1038 1172
1039 if (resize) { 1173 if (resize) {
@@ -1089,8 +1223,10 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1089 1223
1090static int perf_top_config(const char *var, const char *value, void *cb __maybe_unused) 1224static int perf_top_config(const char *var, const char *value, void *cb __maybe_unused)
1091{ 1225{
1092 if (!strcmp(var, "top.call-graph")) 1226 if (!strcmp(var, "top.call-graph")) {
1093 var = "call-graph.record-mode"; /* fall-through */ 1227 var = "call-graph.record-mode";
1228 return perf_default_config(var, value, cb);
1229 }
1094 if (!strcmp(var, "top.children")) { 1230 if (!strcmp(var, "top.children")) {
1095 symbol_conf.cumulate_callchain = perf_config_bool(var, value); 1231 symbol_conf.cumulate_callchain = perf_config_bool(var, value);
1096 return 0; 1232 return 0;
@@ -1127,6 +1263,7 @@ int cmd_top(int argc, const char **argv)
1127 .uses_mmap = true, 1263 .uses_mmap = true,
1128 }, 1264 },
1129 .proc_map_timeout = 500, 1265 .proc_map_timeout = 500,
1266 .overwrite = 1,
1130 }, 1267 },
1131 .max_stack = sysctl_perf_event_max_stack, 1268 .max_stack = sysctl_perf_event_max_stack,
1132 .sym_pcnt_filter = 5, 1269 .sym_pcnt_filter = 5,
@@ -1171,7 +1308,9 @@ int cmd_top(int argc, const char **argv)
1171 OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name", 1308 OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name",
1172 "symbol to annotate"), 1309 "symbol to annotate"),
1173 OPT_BOOLEAN('z', "zero", &top.zero, "zero history across updates"), 1310 OPT_BOOLEAN('z', "zero", &top.zero, "zero history across updates"),
1174 OPT_UINTEGER('F', "freq", &opts->user_freq, "profile at this frequency"), 1311 OPT_CALLBACK('F', "freq", &top.record_opts, "freq or 'max'",
1312 "profile at this frequency",
1313 record__parse_freq),
1175 OPT_INTEGER('E', "entries", &top.print_entries, 1314 OPT_INTEGER('E', "entries", &top.print_entries,
1176 "display this many functions"), 1315 "display this many functions"),
1177 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols, 1316 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols,
@@ -1354,6 +1493,8 @@ int cmd_top(int argc, const char **argv)
1354 if (status < 0) 1493 if (status < 0)
1355 goto out_delete_evlist; 1494 goto out_delete_evlist;
1356 1495
1496 annotation_config__init();
1497
1357 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1498 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1358 if (symbol__init(NULL) < 0) 1499 if (symbol__init(NULL) < 0)
1359 return -1; 1500 return -1;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index e7f1b182fc15..87b95c9410b4 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -19,6 +19,7 @@
19#include <traceevent/event-parse.h> 19#include <traceevent/event-parse.h>
20#include <api/fs/tracing_path.h> 20#include <api/fs/tracing_path.h>
21#include "builtin.h" 21#include "builtin.h"
22#include "util/cgroup.h"
22#include "util/color.h" 23#include "util/color.h"
23#include "util/debug.h" 24#include "util/debug.h"
24#include "util/env.h" 25#include "util/env.h"
@@ -83,6 +84,7 @@ struct trace {
83 struct perf_evlist *evlist; 84 struct perf_evlist *evlist;
84 struct machine *host; 85 struct machine *host;
85 struct thread *current; 86 struct thread *current;
87 struct cgroup *cgroup;
86 u64 base_time; 88 u64 base_time;
87 FILE *output; 89 FILE *output;
88 unsigned long nr_events; 90 unsigned long nr_events;
@@ -2370,6 +2372,34 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2370 trace__sched_stat_runtime)) 2372 trace__sched_stat_runtime))
2371 goto out_error_sched_stat_runtime; 2373 goto out_error_sched_stat_runtime;
2372 2374
2375 /*
2376 * If a global cgroup was set, apply it to all the events without an
2377 * explicit cgroup. I.e.:
2378 *
2379 * trace -G A -e sched:*switch
2380 *
2381 * Will set all raw_syscalls:sys_{enter,exit}, pgfault, vfs_getname, etc
2382 * _and_ sched:sched_switch to the 'A' cgroup, while:
2383 *
2384 * trace -e sched:*switch -G A
2385 *
2386 * will only set the sched:sched_switch event to the 'A' cgroup, all the
2387 * other events (raw_syscalls:sys_{enter,exit}, etc are left "without"
2388 * a cgroup (on the root cgroup, sys wide, etc).
2389 *
2390 * Multiple cgroups:
2391 *
2392 * trace -G A -e sched:*switch -G B
2393 *
2394 * the syscall ones go to the 'A' cgroup, the sched:sched_switch goes
2395 * to the 'B' cgroup.
2396 *
2397 * evlist__set_default_cgroup() grabs a reference of the passed cgroup
2398 * only for the evsels still without a cgroup, i.e. evsel->cgroup == NULL.
2399 */
2400 if (trace->cgroup)
2401 evlist__set_default_cgroup(trace->evlist, trace->cgroup);
2402
2373 err = perf_evlist__create_maps(evlist, &trace->opts.target); 2403 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2374 if (err < 0) { 2404 if (err < 0) {
2375 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n"); 2405 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
@@ -2472,8 +2502,13 @@ again:
2472 2502
2473 for (i = 0; i < evlist->nr_mmaps; i++) { 2503 for (i = 0; i < evlist->nr_mmaps; i++) {
2474 union perf_event *event; 2504 union perf_event *event;
2505 struct perf_mmap *md;
2506
2507 md = &evlist->mmap[i];
2508 if (perf_mmap__read_init(md) < 0)
2509 continue;
2475 2510
2476 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 2511 while ((event = perf_mmap__read_event(md)) != NULL) {
2477 struct perf_sample sample; 2512 struct perf_sample sample;
2478 2513
2479 ++trace->nr_events; 2514 ++trace->nr_events;
@@ -2486,7 +2521,7 @@ again:
2486 2521
2487 trace__handle_event(trace, event, &sample); 2522 trace__handle_event(trace, event, &sample);
2488next_event: 2523next_event:
2489 perf_evlist__mmap_consume(evlist, i); 2524 perf_mmap__consume(md);
2490 2525
2491 if (interrupted) 2526 if (interrupted)
2492 goto out_disable; 2527 goto out_disable;
@@ -2496,6 +2531,7 @@ next_event:
2496 draining = true; 2531 draining = true;
2497 } 2532 }
2498 } 2533 }
2534 perf_mmap__read_done(md);
2499 } 2535 }
2500 2536
2501 if (trace->nr_events == before) { 2537 if (trace->nr_events == before) {
@@ -2533,6 +2569,7 @@ out_delete_evlist:
2533 trace__symbols__exit(trace); 2569 trace__symbols__exit(trace);
2534 2570
2535 perf_evlist__delete(evlist); 2571 perf_evlist__delete(evlist);
2572 cgroup__put(trace->cgroup);
2536 trace->evlist = NULL; 2573 trace->evlist = NULL;
2537 trace->live = false; 2574 trace->live = false;
2538 return err; 2575 return err;
@@ -2972,6 +3009,18 @@ out:
2972 return err; 3009 return err;
2973} 3010}
2974 3011
3012static int trace__parse_cgroups(const struct option *opt, const char *str, int unset)
3013{
3014 struct trace *trace = opt->value;
3015
3016 if (!list_empty(&trace->evlist->entries))
3017 return parse_cgroups(opt, str, unset);
3018
3019 trace->cgroup = evlist__findnew_cgroup(trace->evlist, str);
3020
3021 return 0;
3022}
3023
2975int cmd_trace(int argc, const char **argv) 3024int cmd_trace(int argc, const char **argv)
2976{ 3025{
2977 const char *trace_usage[] = { 3026 const char *trace_usage[] = {
@@ -3062,6 +3111,8 @@ int cmd_trace(int argc, const char **argv)
3062 "print the PERF_RECORD_SAMPLE PERF_SAMPLE_ info, for debugging"), 3111 "print the PERF_RECORD_SAMPLE PERF_SAMPLE_ info, for debugging"),
3063 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout, 3112 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3064 "per thread proc mmap processing timeout in ms"), 3113 "per thread proc mmap processing timeout in ms"),
3114 OPT_CALLBACK('G', "cgroup", &trace, "name", "monitor event in cgroup name only",
3115 trace__parse_cgroups),
3065 OPT_UINTEGER('D', "delay", &trace.opts.initial_delay, 3116 OPT_UINTEGER('D', "delay", &trace.opts.initial_delay,
3066 "ms to wait before starting measurement after program " 3117 "ms to wait before starting measurement after program "
3067 "start"), 3118 "start"),
@@ -3088,6 +3139,11 @@ int cmd_trace(int argc, const char **argv)
3088 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands, 3139 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3089 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION); 3140 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
3090 3141
3142 if ((nr_cgroups || trace.cgroup) && !trace.opts.target.system_wide) {
3143 usage_with_options_msg(trace_usage, trace_options,
3144 "cgroup monitoring only available in system-wide mode");
3145 }
3146
3091 err = bpf__setup_stdout(trace.evlist); 3147 err = bpf__setup_stdout(trace.evlist);
3092 if (err) { 3148 if (err) {
3093 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf)); 3149 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index 51abdb0a4047..9aff89bc7535 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -33,7 +33,6 @@ arch/s390/include/uapi/asm/kvm.h
33arch/s390/include/uapi/asm/kvm_perf.h 33arch/s390/include/uapi/asm/kvm_perf.h
34arch/s390/include/uapi/asm/ptrace.h 34arch/s390/include/uapi/asm/ptrace.h
35arch/s390/include/uapi/asm/sie.h 35arch/s390/include/uapi/asm/sie.h
36arch/s390/include/uapi/asm/unistd.h
37arch/arm/include/uapi/asm/kvm.h 36arch/arm/include/uapi/asm/kvm.h
38arch/arm64/include/uapi/asm/kvm.h 37arch/arm64/include/uapi/asm/kvm.h
39arch/alpha/include/uapi/asm/errno.h 38arch/alpha/include/uapi/asm/errno.h
@@ -43,6 +42,7 @@ arch/parisc/include/uapi/asm/errno.h
43arch/powerpc/include/uapi/asm/errno.h 42arch/powerpc/include/uapi/asm/errno.h
44arch/sparc/include/uapi/asm/errno.h 43arch/sparc/include/uapi/asm/errno.h
45arch/x86/include/uapi/asm/errno.h 44arch/x86/include/uapi/asm/errno.h
45arch/powerpc/include/uapi/asm/unistd.h
46include/asm-generic/bitops/arch_hweight.h 46include/asm-generic/bitops/arch_hweight.h
47include/asm-generic/bitops/const_hweight.h 47include/asm-generic/bitops/const_hweight.h
48include/asm-generic/bitops/__fls.h 48include/asm-generic/bitops/__fls.h
@@ -59,6 +59,7 @@ check () {
59 file=$1 59 file=$1
60 60
61 shift 61 shift
62 opts=
62 while [ -n "$*" ]; do 63 while [ -n "$*" ]; do
63 opts="$opts \"$1\"" 64 opts="$opts \"$1\""
64 shift 65 shift
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index cfe46236a5e5..8fec1abd0f1f 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -61,6 +61,8 @@ struct record_opts {
61 bool tail_synthesize; 61 bool tail_synthesize;
62 bool overwrite; 62 bool overwrite;
63 bool ignore_missing_thread; 63 bool ignore_missing_thread;
64 bool strict_freq;
65 bool sample_id;
64 unsigned int freq; 66 unsigned int freq;
65 unsigned int mmap_pages; 67 unsigned int mmap_pages;
66 unsigned int auxtrace_mmap_pages; 68 unsigned int auxtrace_mmap_pages;
@@ -82,4 +84,6 @@ struct record_opts {
82struct option; 84struct option;
83extern const char * const *record_usage; 85extern const char * const *record_usage;
84extern struct option *record_options; 86extern struct option *record_options;
87
88int record__parse_freq(const struct option *opt, const char *str, int unset);
85#endif 89#endif
diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build
index 999a4e878162..17783913d330 100644
--- a/tools/perf/pmu-events/Build
+++ b/tools/perf/pmu-events/Build
@@ -1,10 +1,12 @@
1hostprogs := jevents 1hostprogs := jevents
2 2
3jevents-y += json.o jsmn.o jevents.o 3jevents-y += json.o jsmn.o jevents.o
4CHOSTFLAGS_jevents.o = -I$(srctree)/tools/include
4pmu-events-y += pmu-events.o 5pmu-events-y += pmu-events.o
5JDIR = pmu-events/arch/$(SRCARCH) 6JDIR = pmu-events/arch/$(SRCARCH)
6JSON = $(shell [ -d $(JDIR) ] && \ 7JSON = $(shell [ -d $(JDIR) ] && \
7 find $(JDIR) -name '*.json' -o -name 'mapfile.csv') 8 find $(JDIR) -name '*.json' -o -name 'mapfile.csv')
9
8# 10#
9# Locate/process JSON files in pmu-events/arch/ 11# Locate/process JSON files in pmu-events/arch/
10# directory and create tables in pmu-events.c. 12# directory and create tables in pmu-events.c.
diff --git a/tools/perf/pmu-events/README b/tools/perf/pmu-events/README
index c2ee3e4417fe..e62b09b6a844 100644
--- a/tools/perf/pmu-events/README
+++ b/tools/perf/pmu-events/README
@@ -11,12 +11,17 @@ tree tools/perf/pmu-events/arch/foo.
11 - Regular files with '.json' extension in the name are assumed to be 11 - Regular files with '.json' extension in the name are assumed to be
12 JSON files, each of which describes a set of PMU events. 12 JSON files, each of which describes a set of PMU events.
13 13
14 - Regular files with basename starting with 'mapfile.csv' are assumed 14 - The CSV file that maps a specific CPU to its set of PMU events is to
15 to be a CSV file that maps a specific CPU to its set of PMU events. 15 be named 'mapfile.csv' (see below for mapfile format).
16 (see below for mapfile format)
17 16
18 - Directories are traversed, but all other files are ignored. 17 - Directories are traversed, but all other files are ignored.
19 18
19 - To reduce JSON event duplication per architecture, platform JSONs may
20 use "ArchStdEvent" keyword to dereference an "Architecture standard
21 events", defined in architecture standard JSONs.
22 Architecture standard JSONs must be located in the architecture root
23 folder. Matching is based on the "EventName" field.
24
20The PMU events supported by a CPU model are expected to grouped into topics 25The PMU events supported by a CPU model are expected to grouped into topics
21such as Pipelining, Cache, Memory, Floating-point etc. All events for a topic 26such as Pipelining, Cache, Memory, Floating-point etc. All events for a topic
22should be placed in a separate JSON file - where the file name identifies 27should be placed in a separate JSON file - where the file name identifies
@@ -29,6 +34,10 @@ sub directory. Thus for the Silvermont X86 CPU:
29 Cache.json Memory.json Virtual-Memory.json 34 Cache.json Memory.json Virtual-Memory.json
30 Frontend.json Pipeline.json 35 Frontend.json Pipeline.json
31 36
37The JSONs folder for a CPU model/family may be placed in the root arch
38folder, or may be placed in a vendor sub-folder under the arch folder
39for instances where the arch and vendor are not the same.
40
32Using the JSON files and the mapfile, 'jevents' generates the C source file, 41Using the JSON files and the mapfile, 'jevents' generates the C source file,
33'pmu-events.c', which encodes the two sets of tables: 42'pmu-events.c', which encodes the two sets of tables:
34 43
diff --git a/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/branch.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/branch.json
new file mode 100644
index 000000000000..0b0e6b26605b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/branch.json
@@ -0,0 +1,25 @@
1[
2 {
3 "ArchStdEvent": "BR_INDIRECT_SPEC",
4 },
5 {
6 "EventCode": "0xC9",
7 "EventName": "BR_COND",
8 "BriefDescription": "Conditional branch executed"
9 },
10 {
11 "EventCode": "0xCA",
12 "EventName": "BR_INDIRECT_MISPRED",
13 "BriefDescription": "Indirect branch mispredicted"
14 },
15 {
16 "EventCode": "0xCB",
17 "EventName": "BR_INDIRECT_MISPRED_ADDR",
18 "BriefDescription": "Indirect branch mispredicted because of address miscompare"
19 },
20 {
21 "EventCode": "0xCC",
22 "EventName": "BR_COND_MISPRED",
23 "BriefDescription": "Conditional branch mispredicted"
24 }
25]
diff --git a/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/bus.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/bus.json
new file mode 100644
index 000000000000..ce33b2553277
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/bus.json
@@ -0,0 +1,8 @@
1[
2 {
3 "ArchStdEvent": "BUS_ACCESS_RD",
4 },
5 {
6 "ArchStdEvent": "BUS_ACCESS_WR",
7 }
8]
diff --git a/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/cache.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/cache.json
new file mode 100644
index 000000000000..5dfbec43c9f9
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/cache.json
@@ -0,0 +1,27 @@
1[
2 {
3 "EventCode": "0xC2",
4 "EventName": "PREFETCH_LINEFILL",
5 "BriefDescription": "Linefill because of prefetch"
6 },
7 {
8 "EventCode": "0xC3",
9 "EventName": "PREFETCH_LINEFILL_DROP",
10 "BriefDescription": "Instruction Cache Throttle occurred"
11 },
12 {
13 "EventCode": "0xC4",
14 "EventName": "READ_ALLOC_ENTER",
15 "BriefDescription": "Entering read allocate mode"
16 },
17 {
18 "EventCode": "0xC5",
19 "EventName": "READ_ALLOC",
20 "BriefDescription": "Read allocate mode"
21 },
22 {
23 "EventCode": "0xC8",
24 "EventName": "EXT_SNOOP",
25 "BriefDescription": "SCU Snooped data from another CPU for this CPU"
26 }
27]
diff --git a/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/memory.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/memory.json
new file mode 100644
index 000000000000..25ae642ba381
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/memory.json
@@ -0,0 +1,12 @@
1[
2 {
3 "EventCode": "0xC0",
4 "EventName": "EXT_MEM_REQ",
5 "BriefDescription": "External memory request"
6 },
7 {
8 "EventCode": "0xC1",
9 "EventName": "EXT_MEM_REQ_NC",
10 "BriefDescription": "Non-cacheable external memory request"
11 }
12]
diff --git a/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/other.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/other.json
new file mode 100644
index 000000000000..6cc6cbd7bf0b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/other.json
@@ -0,0 +1,28 @@
1[
2 {
3 "ArchStdEvent": "EXC_IRQ",
4 },
5 {
6 "ArchStdEvent": "EXC_FIQ",
7 },
8 {
9 "EventCode": "0xC6",
10 "EventName": "PRE_DECODE_ERR",
11 "BriefDescription": "Pre-decode error"
12 },
13 {
14 "EventCode": "0xD0",
15 "EventName": "L1I_CACHE_ERR",
16 "BriefDescription": "L1 Instruction Cache (data or tag) memory error"
17 },
18 {
19 "EventCode": "0xD1",
20 "EventName": "L1D_CACHE_ERR",
21 "BriefDescription": "L1 Data Cache (data, tag or dirty) memory error, correctable or non-correctable"
22 },
23 {
24 "EventCode": "0xD2",
25 "EventName": "TLB_ERR",
26 "BriefDescription": "TLB memory error"
27 }
28]
diff --git a/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/pipeline.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/pipeline.json
new file mode 100644
index 000000000000..f45a6b5d0025
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/pipeline.json
@@ -0,0 +1,52 @@
1[
2 {
3 "EventCode": "0xC7",
4 "EventName": "STALL_SB_FULL",
5 "BriefDescription": "Data Write operation that stalls the pipeline because the store buffer is full"
6 },
7 {
8 "EventCode": "0xE0",
9 "EventName": "OTHER_IQ_DEP_STALL",
10 "BriefDescription": "Cycles that the DPU IQ is empty and that is not because of a recent micro-TLB miss, instruction cache miss or pre-decode error"
11 },
12 {
13 "EventCode": "0xE1",
14 "EventName": "IC_DEP_STALL",
15 "BriefDescription": "Cycles the DPU IQ is empty and there is an instruction cache miss being processed"
16 },
17 {
18 "EventCode": "0xE2",
19 "EventName": "IUTLB_DEP_STALL",
20 "BriefDescription": "Cycles the DPU IQ is empty and there is an instruction micro-TLB miss being processed"
21 },
22 {
23 "EventCode": "0xE3",
24 "EventName": "DECODE_DEP_STALL",
25 "BriefDescription": "Cycles the DPU IQ is empty and there is a pre-decode error being processed"
26 },
27 {
28 "EventCode": "0xE4",
29 "EventName": "OTHER_INTERLOCK_STALL",
30 "BriefDescription": "Cycles there is an interlock other than Advanced SIMD/Floating-point instructions or load/store instruction"
31 },
32 {
33 "EventCode": "0xE5",
34 "EventName": "AGU_DEP_STALL",
35 "BriefDescription": "Cycles there is an interlock for a load/store instruction waiting for data to calculate the address in the AGU"
36 },
37 {
38 "EventCode": "0xE6",
39 "EventName": "SIMD_DEP_STALL",
40 "BriefDescription": "Cycles there is an interlock for an Advanced SIMD/Floating-point operation."
41 },
42 {
43 "EventCode": "0xE7",
44 "EventName": "LD_DEP_STALL",
45 "BriefDescription": "Cycles there is a stall in the Wr stage because of a load miss"
46 },
47 {
48 "EventCode": "0xE8",
49 "EventName": "ST_DEP_STALL",
50 "BriefDescription": "Cycles there is a stall in the Wr stage because of a store"
51 }
52]
diff --git a/tools/perf/pmu-events/arch/arm64/armv8-recommended.json b/tools/perf/pmu-events/arch/arm64/armv8-recommended.json
new file mode 100644
index 000000000000..6328828c018c
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/armv8-recommended.json
@@ -0,0 +1,452 @@
1[
2 {
3 "PublicDescription": "Attributable Level 1 data cache access, read",
4 "EventCode": "0x40",
5 "EventName": "L1D_CACHE_RD",
6 "BriefDescription": "L1D cache access, read"
7 },
8 {
9 "PublicDescription": "Attributable Level 1 data cache access, write",
10 "EventCode": "0x41",
11 "EventName": "L1D_CACHE_WR",
12 "BriefDescription": "L1D cache access, write"
13 },
14 {
15 "PublicDescription": "Attributable Level 1 data cache refill, read",
16 "EventCode": "0x42",
17 "EventName": "L1D_CACHE_REFILL_RD",
18 "BriefDescription": "L1D cache refill, read"
19 },
20 {
21 "PublicDescription": "Attributable Level 1 data cache refill, write",
22 "EventCode": "0x43",
23 "EventName": "L1D_CACHE_REFILL_WR",
24 "BriefDescription": "L1D cache refill, write"
25 },
26 {
27 "PublicDescription": "Attributable Level 1 data cache refill, inner",
28 "EventCode": "0x44",
29 "EventName": "L1D_CACHE_REFILL_INNER",
30 "BriefDescription": "L1D cache refill, inner"
31 },
32 {
33 "PublicDescription": "Attributable Level 1 data cache refill, outer",
34 "EventCode": "0x45",
35 "EventName": "L1D_CACHE_REFILL_OUTER",
36 "BriefDescription": "L1D cache refill, outer"
37 },
38 {
39 "PublicDescription": "Attributable Level 1 data cache Write-Back, victim",
40 "EventCode": "0x46",
41 "EventName": "L1D_CACHE_WB_VICTIM",
42 "BriefDescription": "L1D cache Write-Back, victim"
43 },
44 {
45 "PublicDescription": "Level 1 data cache Write-Back, cleaning and coherency",
46 "EventCode": "0x47",
47 "EventName": "L1D_CACHE_WB_CLEAN",
48 "BriefDescription": "L1D cache Write-Back, cleaning and coherency"
49 },
50 {
51 "PublicDescription": "Attributable Level 1 data cache invalidate",
52 "EventCode": "0x48",
53 "EventName": "L1D_CACHE_INVAL",
54 "BriefDescription": "L1D cache invalidate"
55 },
56 {
57 "PublicDescription": "Attributable Level 1 data TLB refill, read",
58 "EventCode": "0x4C",
59 "EventName": "L1D_TLB_REFILL_RD",
60 "BriefDescription": "L1D tlb refill, read"
61 },
62 {
63 "PublicDescription": "Attributable Level 1 data TLB refill, write",
64 "EventCode": "0x4D",
65 "EventName": "L1D_TLB_REFILL_WR",
66 "BriefDescription": "L1D tlb refill, write"
67 },
68 {
69 "PublicDescription": "Attributable Level 1 data or unified TLB access, read",
70 "EventCode": "0x4E",
71 "EventName": "L1D_TLB_RD",
72 "BriefDescription": "L1D tlb access, read"
73 },
74 {
75 "PublicDescription": "Attributable Level 1 data or unified TLB access, write",
76 "EventCode": "0x4F",
77 "EventName": "L1D_TLB_WR",
78 "BriefDescription": "L1D tlb access, write"
79 },
80 {
81 "PublicDescription": "Attributable Level 2 data cache access, read",
82 "EventCode": "0x50",
83 "EventName": "L2D_CACHE_RD",
84 "BriefDescription": "L2D cache access, read"
85 },
86 {
87 "PublicDescription": "Attributable Level 2 data cache access, write",
88 "EventCode": "0x51",
89 "EventName": "L2D_CACHE_WR",
90 "BriefDescription": "L2D cache access, write"
91 },
92 {
93 "PublicDescription": "Attributable Level 2 data cache refill, read",
94 "EventCode": "0x52",
95 "EventName": "L2D_CACHE_REFILL_RD",
96 "BriefDescription": "L2D cache refill, read"
97 },
98 {
99 "PublicDescription": "Attributable Level 2 data cache refill, write",
100 "EventCode": "0x53",
101 "EventName": "L2D_CACHE_REFILL_WR",
102 "BriefDescription": "L2D cache refill, write"
103 },
104 {
105 "PublicDescription": "Attributable Level 2 data cache Write-Back, victim",
106 "EventCode": "0x56",
107 "EventName": "L2D_CACHE_WB_VICTIM",
108 "BriefDescription": "L2D cache Write-Back, victim"
109 },
110 {
111 "PublicDescription": "Level 2 data cache Write-Back, cleaning and coherency",
112 "EventCode": "0x57",
113 "EventName": "L2D_CACHE_WB_CLEAN",
114 "BriefDescription": "L2D cache Write-Back, cleaning and coherency"
115 },
116 {
117 "PublicDescription": "Attributable Level 2 data cache invalidate",
118 "EventCode": "0x58",
119 "EventName": "L2D_CACHE_INVAL",
120 "BriefDescription": "L2D cache invalidate"
121 },
122 {
123 "PublicDescription": "Attributable Level 2 data or unified TLB refill, read",
124 "EventCode": "0x5c",
125 "EventName": "L2D_TLB_REFILL_RD",
126 "BriefDescription": "L2D cache refill, read"
127 },
128 {
129 "PublicDescription": "Attributable Level 2 data or unified TLB refill, write",
130 "EventCode": "0x5d",
131 "EventName": "L2D_TLB_REFILL_WR",
132 "BriefDescription": "L2D cache refill, write"
133 },
134 {
135 "PublicDescription": "Attributable Level 2 data or unified TLB access, read",
136 "EventCode": "0x5e",
137 "EventName": "L2D_TLB_RD",
138 "BriefDescription": "L2D cache access, read"
139 },
140 {
141 "PublicDescription": "Attributable Level 2 data or unified TLB access, write",
142 "EventCode": "0x5f",
143 "EventName": "L2D_TLB_WR",
144 "BriefDescription": "L2D cache access, write"
145 },
146 {
147 "PublicDescription": "Bus access read",
148 "EventCode": "0x60",
149 "EventName": "BUS_ACCESS_RD",
150 "BriefDescription": "Bus access read"
151 },
152 {
153 "PublicDescription": "Bus access write",
154 "EventCode": "0x61",
155 "EventName": "BUS_ACCESS_WR",
156 "BriefDescription": "Bus access write"
157 }
158 {
159 "PublicDescription": "Bus access, Normal, Cacheable, Shareable",
160 "EventCode": "0x62",
161 "EventName": "BUS_ACCESS_SHARED",
162 "BriefDescription": "Bus access, Normal, Cacheable, Shareable"
163 }
164 {
165 "PublicDescription": "Bus access, not Normal, Cacheable, Shareable",
166 "EventCode": "0x63",
167 "EventName": "BUS_ACCESS_NOT_SHARED",
168 "BriefDescription": "Bus access, not Normal, Cacheable, Shareable"
169 }
170 {
171 "PublicDescription": "Bus access, Normal",
172 "EventCode": "0x64",
173 "EventName": "BUS_ACCESS_NORMAL",
174 "BriefDescription": "Bus access, Normal"
175 }
176 {
177 "PublicDescription": "Bus access, peripheral",
178 "EventCode": "0x65",
179 "EventName": "BUS_ACCESS_PERIPH",
180 "BriefDescription": "Bus access, peripheral"
181 }
182 {
183 "PublicDescription": "Data memory access, read",
184 "EventCode": "0x66",
185 "EventName": "MEM_ACCESS_RD",
186 "BriefDescription": "Data memory access, read"
187 }
188 {
189 "PublicDescription": "Data memory access, write",
190 "EventCode": "0x67",
191 "EventName": "MEM_ACCESS_WR",
192 "BriefDescription": "Data memory access, write"
193 }
194 {
195 "PublicDescription": "Unaligned access, read",
196 "EventCode": "0x68",
197 "EventName": "UNALIGNED_LD_SPEC",
198 "BriefDescription": "Unaligned access, read"
199 }
200 {
201 "PublicDescription": "Unaligned access, write",
202 "EventCode": "0x69",
203 "EventName": "UNALIGNED_ST_SPEC",
204 "BriefDescription": "Unaligned access, write"
205 }
206 {
207 "PublicDescription": "Unaligned access",
208 "EventCode": "0x6a",
209 "EventName": "UNALIGNED_LDST_SPEC",
210 "BriefDescription": "Unaligned access"
211 }
212 {
213 "PublicDescription": "Exclusive operation speculatively executed, LDREX or LDX",
214 "EventCode": "0x6c",
215 "EventName": "LDREX_SPEC",
216 "BriefDescription": "Exclusive operation speculatively executed, LDREX or LDX"
217 }
218 {
219 "PublicDescription": "Exclusive operation speculatively executed, STREX or STX pass",
220 "EventCode": "0x6d",
221 "EventName": "STREX_PASS_SPEC",
222 "BriefDescription": "Exclusive operation speculatively executed, STREX or STX pass"
223 }
224 {
225 "PublicDescription": "Exclusive operation speculatively executed, STREX or STX fail",
226 "EventCode": "0x6e",
227 "EventName": "STREX_FAIL_SPEC",
228 "BriefDescription": "Exclusive operation speculatively executed, STREX or STX fail"
229 }
230 {
231 "PublicDescription": "Exclusive operation speculatively executed, STREX or STX",
232 "EventCode": "0x6f",
233 "EventName": "STREX_SPEC",
234 "BriefDescription": "Exclusive operation speculatively executed, STREX or STX"
235 }
236 {
237 "PublicDescription": "Operation speculatively executed, load",
238 "EventCode": "0x70",
239 "EventName": "LD_SPEC",
240 "BriefDescription": "Operation speculatively executed, load"
241 }
242 {
243 "PublicDescription": "Operation speculatively executed, store"
244 "EventCode": "0x71",
245 "EventName": "ST_SPEC",
246 "BriefDescription": "Operation speculatively executed, store"
247 }
248 {
249 "PublicDescription": "Operation speculatively executed, load or store",
250 "EventCode": "0x72",
251 "EventName": "LDST_SPEC",
252 "BriefDescription": "Operation speculatively executed, load or store"
253 }
254 {
255 "PublicDescription": "Operation speculatively executed, integer data processing",
256 "EventCode": "0x73",
257 "EventName": "DP_SPEC",
258 "BriefDescription": "Operation speculatively executed, integer data processing"
259 }
260 {
261 "PublicDescription": "Operation speculatively executed, Advanced SIMD instruction",
262 "EventCode": "0x74",
263 "EventName": "ASE_SPEC",
264 "BriefDescription": "Operation speculatively executed, Advanced SIMD instruction",
265 }
266 {
267 "PublicDescription": "Operation speculatively executed, floating-point instruction",
268 "EventCode": "0x75",
269 "EventName": "VFP_SPEC",
270 "BriefDescription": "Operation speculatively executed, floating-point instruction"
271 }
272 {
273 "PublicDescription": "Operation speculatively executed, software change of the PC",
274 "EventCode": "0x76",
275 "EventName": "PC_WRITE_SPEC",
276 "BriefDescription": "Operation speculatively executed, software change of the PC"
277 }
278 {
279 "PublicDescription": "Operation speculatively executed, Cryptographic instruction",
280 "EventCode": "0x77",
281 "EventName": "CRYPTO_SPEC",
282 "BriefDescription": "Operation speculatively executed, Cryptographic instruction"
283 }
284 {
285 "PublicDescription": "Branch speculatively executed, immediate branch"
286 "EventCode": "0x78",
287 "EventName": "BR_IMMED_SPEC",
288 "BriefDescription": "Branch speculatively executed, immediate branch"
289 }
290 {
291 "PublicDescription": "Branch speculatively executed, procedure return"
292 "EventCode": "0x79",
293 "EventName": "BR_RETURN_SPEC",
294 "BriefDescription": "Branch speculatively executed, procedure return"
295 }
296 {
297 "PublicDescription": "Branch speculatively executed, indirect branch"
298 "EventCode": "0x7a",
299 "EventName": "BR_INDIRECT_SPEC",
300 "BriefDescription": "Branch speculatively executed, indirect branch"
301 }
302 {
303 "PublicDescription": "Barrier speculatively executed, ISB"
304 "EventCode": "0x7c",
305 "EventName": "ISB_SPEC",
306 "BriefDescription": "Barrier speculatively executed, ISB"
307 }
308 {
309 "PublicDescription": "Barrier speculatively executed, DSB"
310 "EventCode": "0x7d",
311 "EventName": "DSB_SPEC",
312 "BriefDescription": "Barrier speculatively executed, DSB"
313 }
314 {
315 "PublicDescription": "Barrier speculatively executed, DMB"
316 "EventCode": "0x7e",
317 "EventName": "DMB_SPEC",
318 "BriefDescription": "Barrier speculatively executed, DMB"
319 }
320 {
321 "PublicDescription": "Exception taken, Other synchronous"
322 "EventCode": "0x81",
323 "EventName": "EXC_UNDEF",
324 "BriefDescription": "Exception taken, Other synchronous"
325 }
326 {
327 "PublicDescription": "Exception taken, Supervisor Call"
328 "EventCode": "0x82",
329 "EventName": "EXC_SVC",
330 "BriefDescription": "Exception taken, Supervisor Call"
331 }
332 {
333 "PublicDescription": "Exception taken, Instruction Abort"
334 "EventCode": "0x83",
335 "EventName": "EXC_PABORT",
336 "BriefDescription": "Exception taken, Instruction Abort"
337 }
338 {
339 "PublicDescription": "Exception taken, Data Abort and SError"
340 "EventCode": "0x84",
341 "EventName": "EXC_DABORT",
342 "BriefDescription": "Exception taken, Data Abort and SError"
343 }
344 {
345 "PublicDescription": "Exception taken, IRQ"
346 "EventCode": "0x86",
347 "EventName": "EXC_IRQ",
348 "BriefDescription": "Exception taken, IRQ"
349 }
350 {
351 "PublicDescription": "Exception taken, FIQ"
352 "EventCode": "0x87",
353 "EventName": "EXC_FIQ",
354 "BriefDescription": "Exception taken, FIQ"
355 }
356 {
357 "PublicDescription": "Exception taken, Secure Monitor Call"
358 "EventCode": "0x88",
359 "EventName": "EXC_SMC",
360 "BriefDescription": "Exception taken, Secure Monitor Call"
361 }
362 {
363 "PublicDescription": "Exception taken, Hypervisor Call"
364 "EventCode": "0x8a",
365 "EventName": "EXC_HVC",
366 "BriefDescription": "Exception taken, Hypervisor Call"
367 }
368 {
369 "PublicDescription": "Exception taken, Instruction Abort not taken locally"
370 "EventCode": "0x8b",
371 "EventName": "EXC_TRAP_PABORT",
372 "BriefDescription": "Exception taken, Instruction Abort not taken locally"
373 }
374 {
375 "PublicDescription": "Exception taken, Data Abort or SError not taken locally"
376 "EventCode": "0x8c",
377 "EventName": "EXC_TRAP_DABORT",
378 "BriefDescription": "Exception taken, Data Abort or SError not taken locally"
379 }
380 {
381 "PublicDescription": "Exception taken, Other traps not taken locally"
382 "EventCode": "0x8d",
383 "EventName": "EXC_TRAP_OTHER",
384 "BriefDescription": "Exception taken, Other traps not taken locally"
385 }
386 {
387 "PublicDescription": "Exception taken, IRQ not taken locally"
388 "EventCode": "0x8e",
389 "EventName": "EXC_TRAP_IRQ",
390 "BriefDescription": "Exception taken, IRQ not taken locally"
391 }
392 {
393 "PublicDescription": "Exception taken, FIQ not taken locally"
394 "EventCode": "0x8f",
395 "EventName": "EXC_TRAP_FIQ",
396 "BriefDescription": "Exception taken, FIQ not taken locally"
397 }
398 {
399 "PublicDescription": "Release consistency operation speculatively executed, Load-Acquire"
400 "EventCode": "0x90",
401 "EventName": "RC_LD_SPEC",
402 "BriefDescription": "Release consistency operation speculatively executed, Load-Acquire"
403 }
404 {
405 "PublicDescription": "Release consistency operation speculatively executed, Store-Release"
406 "EventCode": "0x91",
407 "EventName": "RC_ST_SPEC",
408 "BriefDescription": "Release consistency operation speculatively executed, Store-Release"
409 }
410 {
411 "PublicDescription": "Attributable Level 3 data or unified cache access, read"
412 "EventCode": "0xa0",
413 "EventName": "L3D_CACHE_RD",
414 "BriefDescription": "Attributable Level 3 data or unified cache access, read"
415 }
416 {
417 "PublicDescription": "Attributable Level 3 data or unified cache access, write"
418 "EventCode": "0xa1",
419 "EventName": "L3D_CACHE_WR",
420 "BriefDescription": "Attributable Level 3 data or unified cache access, write"
421 }
422 {
423 "PublicDescription": "Attributable Level 3 data or unified cache refill, read"
424 "EventCode": "0xa2",
425 "EventName": "L3D_CACHE_REFILL_RD",
426 "BriefDescription": "Attributable Level 3 data or unified cache refill, read"
427 }
428 {
429 "PublicDescription": "Attributable Level 3 data or unified cache refill, write"
430 "EventCode": "0xa3",
431 "EventName": "L3D_CACHE_REFILL_WR",
432 "BriefDescription": "Attributable Level 3 data or unified cache refill, write"
433 }
434 {
435 "PublicDescription": "Attributable Level 3 data or unified cache Write-Back, victim"
436 "EventCode": "0xa6",
437 "EventName": "L3D_CACHE_WB_VICTIM",
438 "BriefDescription": "Attributable Level 3 data or unified cache Write-Back, victim"
439 }
440 {
441 "PublicDescription": "Attributable Level 3 data or unified cache Write-Back, cache clean"
442 "EventCode": "0xa7",
443 "EventName": "L3D_CACHE_WB_CLEAN",
444 "BriefDescription": "Attributable Level 3 data or unified cache Write-Back, cache clean"
445 }
446 {
447 "PublicDescription": "Attributable Level 3 data or unified cache access, invalidate"
448 "EventCode": "0xa8",
449 "EventName": "L3D_CACHE_INVAL",
450 "BriefDescription": "Attributable Level 3 data or unified cache access, invalidate"
451 }
452]
diff --git a/tools/perf/pmu-events/arch/arm64/cavium/thunderx2-imp-def.json b/tools/perf/pmu-events/arch/arm64/cavium/thunderx2-imp-def.json
deleted file mode 100644
index 2db45c40ebc7..000000000000
--- a/tools/perf/pmu-events/arch/arm64/cavium/thunderx2-imp-def.json
+++ /dev/null
@@ -1,62 +0,0 @@
1[
2 {
3 "PublicDescription": "Attributable Level 1 data cache access, read",
4 "EventCode": "0x40",
5 "EventName": "l1d_cache_rd",
6 "BriefDescription": "L1D cache read",
7 },
8 {
9 "PublicDescription": "Attributable Level 1 data cache access, write ",
10 "EventCode": "0x41",
11 "EventName": "l1d_cache_wr",
12 "BriefDescription": "L1D cache write",
13 },
14 {
15 "PublicDescription": "Attributable Level 1 data cache refill, read",
16 "EventCode": "0x42",
17 "EventName": "l1d_cache_refill_rd",
18 "BriefDescription": "L1D cache refill read",
19 },
20 {
21 "PublicDescription": "Attributable Level 1 data cache refill, write",
22 "EventCode": "0x43",
23 "EventName": "l1d_cache_refill_wr",
24 "BriefDescription": "L1D refill write",
25 },
26 {
27 "PublicDescription": "Attributable Level 1 data TLB refill, read",
28 "EventCode": "0x4C",
29 "EventName": "l1d_tlb_refill_rd",
30 "BriefDescription": "L1D tlb refill read",
31 },
32 {
33 "PublicDescription": "Attributable Level 1 data TLB refill, write",
34 "EventCode": "0x4D",
35 "EventName": "l1d_tlb_refill_wr",
36 "BriefDescription": "L1D tlb refill write",
37 },
38 {
39 "PublicDescription": "Attributable Level 1 data or unified TLB access, read",
40 "EventCode": "0x4E",
41 "EventName": "l1d_tlb_rd",
42 "BriefDescription": "L1D tlb read",
43 },
44 {
45 "PublicDescription": "Attributable Level 1 data or unified TLB access, write",
46 "EventCode": "0x4F",
47 "EventName": "l1d_tlb_wr",
48 "BriefDescription": "L1D tlb write",
49 },
50 {
51 "PublicDescription": "Bus access read",
52 "EventCode": "0x60",
53 "EventName": "bus_access_rd",
54 "BriefDescription": "Bus access read",
55 },
56 {
57 "PublicDescription": "Bus access write",
58 "EventCode": "0x61",
59 "EventName": "bus_access_wr",
60 "BriefDescription": "Bus access write",
61 }
62]
diff --git a/tools/perf/pmu-events/arch/arm64/cavium/thunderx2/core-imp-def.json b/tools/perf/pmu-events/arch/arm64/cavium/thunderx2/core-imp-def.json
new file mode 100644
index 000000000000..bc03c06c3918
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/cavium/thunderx2/core-imp-def.json
@@ -0,0 +1,32 @@
1[
2 {
3 "ArchStdEvent": "L1D_CACHE_RD",
4 },
5 {
6 "ArchStdEvent": "L1D_CACHE_WR",
7 },
8 {
9 "ArchStdEvent": "L1D_CACHE_REFILL_RD",
10 },
11 {
12 "ArchStdEvent": "L1D_CACHE_REFILL_WR",
13 },
14 {
15 "ArchStdEvent": "L1D_TLB_REFILL_RD",
16 },
17 {
18 "ArchStdEvent": "L1D_TLB_REFILL_WR",
19 },
20 {
21 "ArchStdEvent": "L1D_TLB_RD",
22 },
23 {
24 "ArchStdEvent": "L1D_TLB_WR",
25 },
26 {
27 "ArchStdEvent": "BUS_ACCESS_RD",
28 },
29 {
30 "ArchStdEvent": "BUS_ACCESS_WR",
31 }
32]
diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/core-imp-def.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/core-imp-def.json
new file mode 100644
index 000000000000..9f0f15d15f75
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/core-imp-def.json
@@ -0,0 +1,122 @@
1[
2 {
3 "ArchStdEvent": "L1D_CACHE_RD",
4 },
5 {
6 "ArchStdEvent": "L1D_CACHE_WR",
7 },
8 {
9 "ArchStdEvent": "L1D_CACHE_REFILL_RD",
10 },
11 {
12 "ArchStdEvent": "L1D_CACHE_REFILL_WR",
13 },
14 {
15 "ArchStdEvent": "L1D_CACHE_WB_VICTIM",
16 },
17 {
18 "ArchStdEvent": "L1D_CACHE_WB_CLEAN",
19 },
20 {
21 "ArchStdEvent": "L1D_CACHE_INVAL",
22 },
23 {
24 "ArchStdEvent": "L1D_TLB_REFILL_RD",
25 },
26 {
27 "ArchStdEvent": "L1D_TLB_REFILL_WR",
28 },
29 {
30 "ArchStdEvent": "L1D_TLB_RD",
31 },
32 {
33 "ArchStdEvent": "L1D_TLB_WR",
34 },
35 {
36 "ArchStdEvent": "L2D_CACHE_RD",
37 },
38 {
39 "ArchStdEvent": "L2D_CACHE_WR",
40 },
41 {
42 "ArchStdEvent": "L2D_CACHE_REFILL_RD",
43 },
44 {
45 "ArchStdEvent": "L2D_CACHE_REFILL_WR",
46 },
47 {
48 "ArchStdEvent": "L2D_CACHE_WB_VICTIM",
49 },
50 {
51 "ArchStdEvent": "L2D_CACHE_WB_CLEAN",
52 },
53 {
54 "ArchStdEvent": "L2D_CACHE_INVAL",
55 },
56 {
57 "PublicDescription": "Level 1 instruction cache prefetch access count",
58 "EventCode": "0x102e",
59 "EventName": "L1I_CACHE_PRF",
60 "BriefDescription": "L1I cache prefetch access count",
61 },
62 {
63 "PublicDescription": "Level 1 instruction cache miss due to prefetch access count",
64 "EventCode": "0x102f",
65 "EventName": "L1I_CACHE_PRF_REFILL",
66 "BriefDescription": "L1I cache miss due to prefetch access count",
67 },
68 {
69 "PublicDescription": "Instruction queue is empty",
70 "EventCode": "0x1043",
71 "EventName": "IQ_IS_EMPTY",
72 "BriefDescription": "Instruction queue is empty",
73 },
74 {
75 "PublicDescription": "Instruction fetch stall cycles",
76 "EventCode": "0x1044",
77 "EventName": "IF_IS_STALL",
78 "BriefDescription": "Instruction fetch stall cycles",
79 },
80 {
81 "PublicDescription": "Instructions can receive, but not send",
82 "EventCode": "0x2014",
83 "EventName": "FETCH_BUBBLE",
84 "BriefDescription": "Instructions can receive, but not send",
85 },
86 {
87 "PublicDescription": "Prefetch request from LSU",
88 "EventCode": "0x6013",
89 "EventName": "PRF_REQ",
90 "BriefDescription": "Prefetch request from LSU",
91 },
92 {
93 "PublicDescription": "Hit on prefetched data",
94 "EventCode": "0x6014",
95 "EventName": "HIT_ON_PRF",
96 "BriefDescription": "Hit on prefetched data",
97 },
98 {
99 "PublicDescription": "Cycles of that the number of issuing micro operations are less than 4",
100 "EventCode": "0x7001",
101 "EventName": "EXE_STALL_CYCLE",
102 "BriefDescription": "Cycles of that the number of issue ups are less than 4",
103 },
104 {
105 "PublicDescription": "No any micro operation is issued and meanwhile any load operation is not resolved",
106 "EventCode": "0x7004",
107 "EventName": "MEM_STALL_ANYLOAD",
108 "BriefDescription": "No any micro operation is issued and meanwhile any load operation is not resolved",
109 },
110 {
111 "PublicDescription": "No any micro operation is issued and meanwhile there is any load operation missing L1 cache and pending data refill",
112 "EventCode": "0x7006",
113 "EventName": "MEM_STALL_L1MISS",
114 "BriefDescription": "No any micro operation is issued and meanwhile there is any load operation missing L1 cache and pending data refill",
115 },
116 {
117 "PublicDescription": "No any micro operation is issued and meanwhile there is any load operation missing both L1 and L2 cache and pending data refill from L3 cache",
118 "EventCode": "0x7007",
119 "EventName": "MEM_STALL_L2MISS",
120 "BriefDescription": "No any micro operation is issued and meanwhile there is any load operation missing both L1 and L2 cache and pending data refill from L3 cache",
121 },
122]
diff --git a/tools/perf/pmu-events/arch/arm64/mapfile.csv b/tools/perf/pmu-events/arch/arm64/mapfile.csv
index 219d6756134e..f03e26ecb658 100644
--- a/tools/perf/pmu-events/arch/arm64/mapfile.csv
+++ b/tools/perf/pmu-events/arch/arm64/mapfile.csv
@@ -12,4 +12,7 @@
12# 12#
13# 13#
14#Family-model,Version,Filename,EventType 14#Family-model,Version,Filename,EventType
150x00000000420f5160,v1,cavium,core 150x00000000410fd03[[:xdigit:]],v1,arm/cortex-a53,core
160x00000000420f5160,v1,cavium/thunderx2,core
170x00000000430f0af0,v1,cavium/thunderx2,core
180x00000000480fd010,v1,hisilicon/hip08,core
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/cache.json b/tools/perf/pmu-events/arch/powerpc/power9/cache.json
index 7945c5196c43..851072105054 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/cache.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/cache.json
@@ -20,11 +20,6 @@
20 "BriefDescription": "Finish stall due to a scalar fixed point or CR instruction in the execution pipeline. These instructions get routed to the ALU, ALU2, and DIV pipes" 20 "BriefDescription": "Finish stall due to a scalar fixed point or CR instruction in the execution pipeline. These instructions get routed to the ALU, ALU2, and DIV pipes"
21 }, 21 },
22 {, 22 {,
23 "EventCode": "0x1D15C",
24 "EventName": "PM_MRK_DTLB_MISS_1G",
25 "BriefDescription": "Marked Data TLB reload (after a miss) page size 2M. Implies radix translation was used"
26 },
27 {,
28 "EventCode": "0x4D12A", 23 "EventCode": "0x4D12A",
29 "EventName": "PM_MRK_DATA_FROM_RL4_CYC", 24 "EventName": "PM_MRK_DATA_FROM_RL4_CYC",
30 "BriefDescription": "Duration in cycles to reload from another chip's L4 on the same Node or Group ( Remote) due to a marked load" 25 "BriefDescription": "Duration in cycles to reload from another chip's L4 on the same Node or Group ( Remote) due to a marked load"
@@ -80,21 +75,6 @@
80 "BriefDescription": "Threshold counter exceed a count of 4096" 75 "BriefDescription": "Threshold counter exceed a count of 4096"
81 }, 76 },
82 {, 77 {,
83 "EventCode": "0x3D156",
84 "EventName": "PM_MRK_DTLB_MISS_64K",
85 "BriefDescription": "Marked Data TLB Miss page size 64K"
86 },
87 {,
88 "EventCode": "0x4C15E",
89 "EventName": "PM_MRK_DTLB_MISS_16M",
90 "BriefDescription": "Marked Data TLB Miss page size 16M"
91 },
92 {,
93 "EventCode": "0x2D15E",
94 "EventName": "PM_MRK_DTLB_MISS_16G",
95 "BriefDescription": "Marked Data TLB Miss page size 16G"
96 },
97 {,
98 "EventCode": "0x3F14A", 78 "EventCode": "0x3F14A",
99 "EventName": "PM_MRK_DPTEG_FROM_RMEM", 79 "EventName": "PM_MRK_DPTEG_FROM_RMEM",
100 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group ( Remote) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included" 80 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group ( Remote) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
@@ -123,10 +103,5 @@
123 "EventCode": "0x1002A", 103 "EventCode": "0x1002A",
124 "EventName": "PM_CMPLU_STALL_LARX", 104 "EventName": "PM_CMPLU_STALL_LARX",
125 "BriefDescription": "Finish stall because the NTF instruction was a larx waiting to be satisfied" 105 "BriefDescription": "Finish stall because the NTF instruction was a larx waiting to be satisfied"
126 },
127 {,
128 "EventCode": "0x1C058",
129 "EventName": "PM_DTLB_MISS_16G",
130 "BriefDescription": "Data TLB Miss page size 16G"
131 } 106 }
132] \ No newline at end of file 107] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/frontend.json b/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
index bd8361b5fd6a..f9fa84b16fb5 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
@@ -155,11 +155,6 @@
155 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked load" 155 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked load"
156 }, 156 },
157 {, 157 {,
158 "EventCode": "0x3C056",
159 "EventName": "PM_DTLB_MISS_64K",
160 "BriefDescription": "Data TLB Miss page size 64K"
161 },
162 {,
163 "EventCode": "0x30060", 158 "EventCode": "0x30060",
164 "EventName": "PM_TM_TRANS_RUN_INST", 159 "EventName": "PM_TM_TRANS_RUN_INST",
165 "BriefDescription": "Run instructions completed in transactional state (gated by the run latch)" 160 "BriefDescription": "Run instructions completed in transactional state (gated by the run latch)"
@@ -345,11 +340,6 @@
345 "BriefDescription": "Larx finished" 340 "BriefDescription": "Larx finished"
346 }, 341 },
347 {, 342 {,
348 "EventCode": "0x4C056",
349 "EventName": "PM_DTLB_MISS_16M",
350 "BriefDescription": "Data TLB Miss page size 16M"
351 },
352 {,
353 "EventCode": "0x1003A", 343 "EventCode": "0x1003A",
354 "EventName": "PM_CMPLU_STALL_LSU_FIN", 344 "EventName": "PM_CMPLU_STALL_LSU_FIN",
355 "BriefDescription": "Finish stall because the NTF instruction was an LSU op (other than a load or a store) with all its dependencies met and just going through the LSU pipe to finish" 345 "BriefDescription": "Finish stall because the NTF instruction was an LSU op (other than a load or a store) with all its dependencies met and just going through the LSU pipe to finish"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/marked.json b/tools/perf/pmu-events/arch/powerpc/power9/marked.json
index 22f9f32060a8..b1954c38bab1 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/marked.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/marked.json
@@ -530,11 +530,6 @@
530 "BriefDescription": "Counts all Icache reloads includes demand, prefetch, prefetch turned into demand and demand turned into prefetch" 530 "BriefDescription": "Counts all Icache reloads includes demand, prefetch, prefetch turned into demand and demand turned into prefetch"
531 }, 531 },
532 {, 532 {,
533 "EventCode": "0x4003C",
534 "EventName": "PM_DISP_HELD_SYNC_HOLD",
535 "BriefDescription": "Cycles in which dispatch is held because of a synchronizing instruction in the pipeline"
536 },
537 {,
538 "EventCode": "0x3003C", 533 "EventCode": "0x3003C",
539 "EventName": "PM_CMPLU_STALL_NESTED_TEND", 534 "EventName": "PM_CMPLU_STALL_NESTED_TEND",
540 "BriefDescription": "Completion stall because the ISU is updating the TEXASR to keep track of the nested tend and decrement the TEXASR nested level. This is a short delay" 535 "BriefDescription": "Completion stall because the ISU is updating the TEXASR to keep track of the nested tend and decrement the TEXASR nested level. This is a short delay"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/memory.json b/tools/perf/pmu-events/arch/powerpc/power9/memory.json
index 9960d1c0dd44..2e2ebc700c74 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/memory.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/memory.json
@@ -45,11 +45,6 @@
45 "BriefDescription": "count of Loads completed" 45 "BriefDescription": "count of Loads completed"
46 }, 46 },
47 {, 47 {,
48 "EventCode": "0x2D156",
49 "EventName": "PM_MRK_DTLB_MISS_4K",
50 "BriefDescription": "Marked Data TLB Miss page size 4k"
51 },
52 {,
53 "EventCode": "0x4C042", 48 "EventCode": "0x4C042",
54 "EventName": "PM_DATA_FROM_L3", 49 "EventName": "PM_DATA_FROM_L3",
55 "BriefDescription": "The processor's data cache was reloaded from local core's L3 due to a demand load" 50 "BriefDescription": "The processor's data cache was reloaded from local core's L3 due to a demand load"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/other.json b/tools/perf/pmu-events/arch/powerpc/power9/other.json
index 5ce312973f1e..48cf4f920b3f 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/other.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/other.json
@@ -70,6 +70,11 @@
70 "BriefDescription": "Cycles thread running at priority level 0 or 1" 70 "BriefDescription": "Cycles thread running at priority level 0 or 1"
71 }, 71 },
72 {, 72 {,
73 "EventCode": "0x4C054",
74 "EventName": "PM_DERAT_MISS_16G_1G",
75 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16G (hpt mode) or 1G (radix mode)"
76 },
77 {,
73 "EventCode": "0x2084", 78 "EventCode": "0x2084",
74 "EventName": "PM_FLUSH_HB_RESTORE_CYC", 79 "EventName": "PM_FLUSH_HB_RESTORE_CYC",
75 "BriefDescription": "Cycles in which no new instructions can be dispatched to the ICT after a flush. History buffer recovery" 80 "BriefDescription": "Cycles in which no new instructions can be dispatched to the ICT after a flush. History buffer recovery"
@@ -107,12 +112,12 @@
107 {, 112 {,
108 "EventCode": "0x360B2", 113 "EventCode": "0x360B2",
109 "EventName": "PM_L3_GRP_GUESS_WRONG_LOW", 114 "EventName": "PM_L3_GRP_GUESS_WRONG_LOW",
110 "BriefDescription": "Initial scope=group (GS or NNS) but data from outside group (far or rem). Prediction too Low" 115 "BriefDescription": "Prefetch scope predictor selected GS or NNS, but was wrong because scope was LNS"
111 }, 116 },
112 {, 117 {,
113 "EventCode": "0x168A6", 118 "EventCode": "0x168A6",
114 "EventName": "PM_TM_CAM_OVERFLOW", 119 "EventName": "PM_TM_CAM_OVERFLOW",
115 "BriefDescription": "L3 TM cam overflow during L2 co of SC" 120 "BriefDescription": "L3 TM CAM is full when a L2 castout of TM_SC line occurs. Line is pushed to memory"
116 }, 121 },
117 {, 122 {,
118 "EventCode": "0xE8B0", 123 "EventCode": "0xE8B0",
@@ -150,11 +155,6 @@
150 "BriefDescription": "All ISU rejects" 155 "BriefDescription": "All ISU rejects"
151 }, 156 },
152 {, 157 {,
153 "EventCode": "0x460A6",
154 "EventName": "PM_RD_FORMING_SC",
155 "BriefDescription": "Read forming SC"
156 },
157 {,
158 "EventCode": "0x468A0", 158 "EventCode": "0x468A0",
159 "EventName": "PM_L3_PF_OFF_CHIP_MEM", 159 "EventName": "PM_L3_PF_OFF_CHIP_MEM",
160 "BriefDescription": "L3 PF from Off chip memory" 160 "BriefDescription": "L3 PF from Off chip memory"
@@ -187,7 +187,7 @@
187 {, 187 {,
188 "EventCode": "0x368A6", 188 "EventCode": "0x368A6",
189 "EventName": "PM_SNP_TM_HIT_T", 189 "EventName": "PM_SNP_TM_HIT_T",
190 "BriefDescription": "Snp TM sthit T/Tn/Te" 190 "BriefDescription": "TM snoop that is a store hits line in L3 in T, Tn or Te state (shared modified)"
191 }, 191 },
192 {, 192 {,
193 "EventCode": "0x3001A", 193 "EventCode": "0x3001A",
@@ -205,6 +205,11 @@
205 "BriefDescription": "Duration in cycles to reload with Modified (M) data from another core's ECO L3 on the same chip due to a marked load" 205 "BriefDescription": "Duration in cycles to reload with Modified (M) data from another core's ECO L3 on the same chip due to a marked load"
206 }, 206 },
207 {, 207 {,
208 "EventCode": "0xF0B4",
209 "EventName": "PM_DC_PREF_CONS_ALLOC",
210 "BriefDescription": "Prefetch stream allocated in the conservative phase by either the hardware prefetch mechanism or software prefetch. The sum of this pair subtracted from the total number of allocs will give the total allocs in normal phase"
211 },
212 {,
208 "EventCode": "0xF894", 213 "EventCode": "0xF894",
209 "EventName": "PM_LSU3_L1_CAM_CANCEL", 214 "EventName": "PM_LSU3_L1_CAM_CANCEL",
210 "BriefDescription": "ls3 l1 tm cam cancel" 215 "BriefDescription": "ls3 l1 tm cam cancel"
@@ -227,7 +232,12 @@
227 {, 232 {,
228 "EventCode": "0x468A6", 233 "EventCode": "0x468A6",
229 "EventName": "PM_RD_CLEARING_SC", 234 "EventName": "PM_RD_CLEARING_SC",
230 "BriefDescription": "Read clearing SC" 235 "BriefDescription": "Core TM load hits line in L3 in TM_SC state and causes it to be invalidated"
236 },
237 {,
238 "EventCode": "0xD0B0",
239 "EventName": "PM_HWSYNC",
240 "BriefDescription": ""
231 }, 241 },
232 {, 242 {,
233 "EventCode": "0x168B0", 243 "EventCode": "0x168B0",
@@ -265,6 +275,11 @@
265 "BriefDescription": "Prefetch stream allocated by the hardware prefetch mechanism" 275 "BriefDescription": "Prefetch stream allocated by the hardware prefetch mechanism"
266 }, 276 },
267 {, 277 {,
278 "EventCode": "0xF0BC",
279 "EventName": "PM_LS2_UNALIGNED_ST",
280 "BriefDescription": "Store instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the Store of that size. If the Store wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
281 },
282 {,
268 "EventCode": "0xD0AC", 283 "EventCode": "0xD0AC",
269 "EventName": "PM_SRQ_SYNC_CYC", 284 "EventName": "PM_SRQ_SYNC_CYC",
270 "BriefDescription": "A sync is in the S2Q (edge detect to count)" 285 "BriefDescription": "A sync is in the S2Q (edge detect to count)"
@@ -275,6 +290,11 @@
275 "BriefDescription": "Marked instruction was reloaded from a location beyond the local chiplet" 290 "BriefDescription": "Marked instruction was reloaded from a location beyond the local chiplet"
276 }, 291 },
277 {, 292 {,
293 "EventCode": "0x58A8",
294 "EventName": "PM_DECODE_HOLD_ICT_FULL",
295 "BriefDescription": "Counts the number of cycles in which the IFU was not able to decode and transmit one or more instructions because all itags were in use. This means the ICT is full for this thread"
296 },
297 {,
278 "EventCode": "0x26082", 298 "EventCode": "0x26082",
279 "EventName": "PM_L2_IC_INV", 299 "EventName": "PM_L2_IC_INV",
280 "BriefDescription": "I-cache Invalidates sent over the realod bus to the core" 300 "BriefDescription": "I-cache Invalidates sent over the realod bus to the core"
@@ -365,6 +385,16 @@
365 "BriefDescription": "Duration in cycles to reload either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked load" 385 "BriefDescription": "Duration in cycles to reload either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked load"
366 }, 386 },
367 {, 387 {,
388 "EventCode": "0xF888",
389 "EventName": "PM_LSU1_STORE_REJECT",
390 "BriefDescription": "All internal store rejects cause the instruction to go back to the SRQ and go to sleep until woken up to try again after the condition has been met"
391 },
392 {,
393 "EventCode": "0xC098",
394 "EventName": "PM_LS2_UNALIGNED_LD",
395 "BriefDescription": "Load instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the load of that size. If the load wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
396 },
397 {,
368 "EventCode": "0x20058", 398 "EventCode": "0x20058",
369 "EventName": "PM_DARQ1_10_12_ENTRIES", 399 "EventName": "PM_DARQ1_10_12_ENTRIES",
370 "BriefDescription": "Cycles in which 10 or more DARQ1 entries (out of 12) are in use" 400 "BriefDescription": "Cycles in which 10 or more DARQ1 entries (out of 12) are in use"
@@ -372,7 +402,7 @@
372 {, 402 {,
373 "EventCode": "0x360A6", 403 "EventCode": "0x360A6",
374 "EventName": "PM_SNP_TM_HIT_M", 404 "EventName": "PM_SNP_TM_HIT_M",
375 "BriefDescription": "Snp TM st hit M/Mu" 405 "BriefDescription": "TM snoop that is a store hits line in L3 in M or Mu state (exclusive modified)"
376 }, 406 },
377 {, 407 {,
378 "EventCode": "0x5898", 408 "EventCode": "0x5898",
@@ -395,9 +425,9 @@
395 "BriefDescription": "A data line was written to the L1 due to a hardware or software prefetch" 425 "BriefDescription": "A data line was written to the L1 due to a hardware or software prefetch"
396 }, 426 },
397 {, 427 {,
398 "EventCode": "0xF888", 428 "EventCode": "0x2608E",
399 "EventName": "PM_LSU1_STORE_REJECT", 429 "EventName": "PM_TM_LD_CONF",
400 "BriefDescription": "All internal store rejects cause the instruction to go back to the SRQ and go to sleep until woken up to try again after the condition has been met" 430 "BriefDescription": "TM Load (fav or non-fav) ran into conflict (failed)"
401 }, 431 },
402 {, 432 {,
403 "EventCode": "0x1D144", 433 "EventCode": "0x1D144",
@@ -422,7 +452,7 @@
422 {, 452 {,
423 "EventCode": "0x26884", 453 "EventCode": "0x26884",
424 "EventName": "PM_DSIDE_MRU_TOUCH", 454 "EventName": "PM_DSIDE_MRU_TOUCH",
425 "BriefDescription": "D-side L2 MRU touch sent to L2" 455 "BriefDescription": "D-side L2 MRU touch commands sent to the L2"
426 }, 456 },
427 {, 457 {,
428 "EventCode": "0x30134", 458 "EventCode": "0x30134",
@@ -440,6 +470,16 @@
440 "BriefDescription": "XL-form branch was mispredicted due to the predicted target address missing from EAT. The EAT forces a mispredict in this case since there is no predicated target to validate. This is a rare case that may occur when the EAT is full and a branch is issued" 470 "BriefDescription": "XL-form branch was mispredicted due to the predicted target address missing from EAT. The EAT forces a mispredict in this case since there is no predicated target to validate. This is a rare case that may occur when the EAT is full and a branch is issued"
441 }, 471 },
442 {, 472 {,
473 "EventCode": "0xC094",
474 "EventName": "PM_LS0_UNALIGNED_LD",
475 "BriefDescription": "Load instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the load of that size. If the load wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
476 },
477 {,
478 "EventCode": "0xF8BC",
479 "EventName": "PM_LS3_UNALIGNED_ST",
480 "BriefDescription": "Store instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the Store of that size. If the Store wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
481 },
482 {,
443 "EventCode": "0x460AE", 483 "EventCode": "0x460AE",
444 "EventName": "PM_L3_P2_CO_RTY", 484 "EventName": "PM_L3_P2_CO_RTY",
445 "BriefDescription": "L3 CO received retry port 2 (memory only), every retry counted" 485 "BriefDescription": "L3 CO received retry port 2 (memory only), every retry counted"
@@ -492,7 +532,7 @@
492 {, 532 {,
493 "EventCode": "0xC880", 533 "EventCode": "0xC880",
494 "EventName": "PM_LS1_LD_VECTOR_FIN", 534 "EventName": "PM_LS1_LD_VECTOR_FIN",
495 "BriefDescription": "" 535 "BriefDescription": "LS1 finished load vector op"
496 }, 536 },
497 {, 537 {,
498 "EventCode": "0x2894", 538 "EventCode": "0x2894",
@@ -515,6 +555,11 @@
515 "BriefDescription": "Marked derat reload (miss) for any page size" 555 "BriefDescription": "Marked derat reload (miss) for any page size"
516 }, 556 },
517 {, 557 {,
558 "EventCode": "0x160A0",
559 "EventName": "PM_L3_PF_MISS_L3",
560 "BriefDescription": "L3 PF missed in L3"
561 },
562 {,
518 "EventCode": "0x1C04A", 563 "EventCode": "0x1C04A",
519 "EventName": "PM_DATA_FROM_RL2L3_SHR", 564 "EventName": "PM_DATA_FROM_RL2L3_SHR",
520 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a demand load" 565 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a demand load"
@@ -565,11 +610,21 @@
565 "BriefDescription": "L2 guess local (LNS) and guess was not correct (ie data not on chip)" 610 "BriefDescription": "L2 guess local (LNS) and guess was not correct (ie data not on chip)"
566 }, 611 },
567 {, 612 {,
613 "EventCode": "0xC888",
614 "EventName": "PM_LSU_DTLB_MISS_64K",
615 "BriefDescription": "Data TLB Miss page size 64K"
616 },
617 {,
568 "EventCode": "0xE0A4", 618 "EventCode": "0xE0A4",
569 "EventName": "PM_TMA_REQ_L2", 619 "EventName": "PM_TMA_REQ_L2",
570 "BriefDescription": "addrs only req to L2 only on the first one,Indication that Load footprint is not expanding" 620 "BriefDescription": "addrs only req to L2 only on the first one,Indication that Load footprint is not expanding"
571 }, 621 },
572 {, 622 {,
623 "EventCode": "0xC088",
624 "EventName": "PM_LSU_DTLB_MISS_4K",
625 "BriefDescription": "Data TLB Miss page size 4K"
626 },
627 {,
573 "EventCode": "0x3C042", 628 "EventCode": "0x3C042",
574 "EventName": "PM_DATA_FROM_L3_DISP_CONFLICT", 629 "EventName": "PM_DATA_FROM_L3_DISP_CONFLICT",
575 "BriefDescription": "The processor's data cache was reloaded from local core's L3 with dispatch conflict due to a demand load" 630 "BriefDescription": "The processor's data cache was reloaded from local core's L3 with dispatch conflict due to a demand load"
@@ -602,7 +657,7 @@
602 {, 657 {,
603 "EventCode": "0x26084", 658 "EventCode": "0x26084",
604 "EventName": "PM_L2_RCLD_DISP_FAIL_OTHER", 659 "EventName": "PM_L2_RCLD_DISP_FAIL_OTHER",
605 "BriefDescription": "All I-or-D side load dispatch attempts for this thread that failed due to reason other than address collision (excludes i_l2mru_tch_reqs)" 660 "BriefDescription": "All D-side-Ld or I-side-instruction-fetch dispatch attempts for this thread that failed due to reasons other than an address collision conflicts with an L2 machines (e.g. Read-Claim/Snoop machine not available)"
606 }, 661 },
607 {, 662 {,
608 "EventCode": "0x101E4", 663 "EventCode": "0x101E4",
@@ -647,12 +702,12 @@
647 {, 702 {,
648 "EventCode": "0x46080", 703 "EventCode": "0x46080",
649 "EventName": "PM_L2_DISP_ALL_L2MISS", 704 "EventName": "PM_L2_DISP_ALL_L2MISS",
650 "BriefDescription": "All successful Ld/St dispatches for this thread that were an L2 miss (excludes i_l2mru_tch_reqs)" 705 "BriefDescription": "All successful D-side-Ld/St or I-side-instruction-fetch dispatches for this thread that were an L2 miss"
651 }, 706 },
652 {, 707 {,
653 "EventCode": "0x160A0", 708 "EventCode": "0xF8B8",
654 "EventName": "PM_L3_PF_MISS_L3", 709 "EventName": "PM_LS1_UNALIGNED_ST",
655 "BriefDescription": "L3 PF missed in L3" 710 "BriefDescription": "Store instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the Store of that size. If the Store wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
656 }, 711 },
657 {, 712 {,
658 "EventCode": "0x408C", 713 "EventCode": "0x408C",
@@ -667,7 +722,7 @@
667 {, 722 {,
668 "EventCode": "0x160B2", 723 "EventCode": "0x160B2",
669 "EventName": "PM_L3_LOC_GUESS_CORRECT", 724 "EventName": "PM_L3_LOC_GUESS_CORRECT",
670 "BriefDescription": "initial scope=node/chip (LNS) and data from local node (local) (pred successful) - always PFs only" 725 "BriefDescription": "Prefetch scope predictor selected LNS and was correct"
671 }, 726 },
672 {, 727 {,
673 "EventCode": "0x48B4", 728 "EventCode": "0x48B4",
@@ -767,7 +822,7 @@
767 {, 822 {,
768 "EventCode": "0x36082", 823 "EventCode": "0x36082",
769 "EventName": "PM_L2_LD_DISP", 824 "EventName": "PM_L2_LD_DISP",
770 "BriefDescription": "All successful I-or-D side load dispatches for this thread (excludes i_l2mru_tch_reqs)" 825 "BriefDescription": "All successful D-side-Ld or I-side-instruction-fetch dispatches for this thread"
771 }, 826 },
772 {, 827 {,
773 "EventCode": "0xF8B0", 828 "EventCode": "0xF8B0",
@@ -787,7 +842,7 @@
787 {, 842 {,
788 "EventCode": "0x16884", 843 "EventCode": "0x16884",
789 "EventName": "PM_L2_RCLD_DISP_FAIL_ADDR", 844 "EventName": "PM_L2_RCLD_DISP_FAIL_ADDR",
790 "BriefDescription": "All I-od-D side load dispatch attempts for this thread that failed due to address collision with RC/CO/SN/SQ machine (excludes i_l2mru_tch_reqs)" 845 "BriefDescription": "All D-side-Ld or I-side-instruction-fetch dispatch attempts for this thread that failed due to an address collision conflicts with an L2 machines already working on this line (e.g. ld-hit-stq or Read-claim/Castout/Snoop machines)"
791 }, 846 },
792 {, 847 {,
793 "EventCode": "0x460A0", 848 "EventCode": "0x460A0",
@@ -830,6 +885,11 @@
830 "BriefDescription": "Instruction prefetch requests" 885 "BriefDescription": "Instruction prefetch requests"
831 }, 886 },
832 {, 887 {,
888 "EventCode": "0xC898",
889 "EventName": "PM_LS3_UNALIGNED_LD",
890 "BriefDescription": "Load instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the load of that size. If the load wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
891 },
892 {,
833 "EventCode": "0x488C", 893 "EventCode": "0x488C",
834 "EventName": "PM_IC_PREF_WRITE", 894 "EventName": "PM_IC_PREF_WRITE",
835 "BriefDescription": "Instruction prefetch written into IL1" 895 "BriefDescription": "Instruction prefetch written into IL1"
@@ -837,7 +897,7 @@
837 {, 897 {,
838 "EventCode": "0xF89C", 898 "EventCode": "0xF89C",
839 "EventName": "PM_XLATE_MISS", 899 "EventName": "PM_XLATE_MISS",
840 "BriefDescription": "The LSU requested a line from L2 for translation. It may be satisfied from any source beyond L2. Includes speculative instructions" 900 "BriefDescription": "The LSU requested a line from L2 for translation. It may be satisfied from any source beyond L2. Includes speculative instructions. Includes instruction, prefetch and demand"
841 }, 901 },
842 {, 902 {,
843 "EventCode": "0x14158", 903 "EventCode": "0x14158",
@@ -850,9 +910,14 @@
850 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's L3 on the same chip due to a marked load" 910 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's L3 on the same chip due to a marked load"
851 }, 911 },
852 {, 912 {,
913 "EventCode": "0xC88C",
914 "EventName": "PM_LSU_DTLB_MISS_16G_1G",
915 "BriefDescription": "Data TLB Miss page size 16G (HPT) or 1G (Radix)"
916 },
917 {,
853 "EventCode": "0x268A6", 918 "EventCode": "0x268A6",
854 "EventName": "PM_TM_RST_SC", 919 "EventName": "PM_TM_RST_SC",
855 "BriefDescription": "TM-snp rst RM SC" 920 "BriefDescription": "TM snoop hits line in L3 that is TM_SC state and causes it to be invalidated"
856 }, 921 },
857 {, 922 {,
858 "EventCode": "0x468A4", 923 "EventCode": "0x468A4",
@@ -917,7 +982,7 @@
917 {, 982 {,
918 "EventCode": "0x46086", 983 "EventCode": "0x46086",
919 "EventName": "PM_L2_SN_M_RD_DONE", 984 "EventName": "PM_L2_SN_M_RD_DONE",
920 "BriefDescription": "SNP dispatched for a read and was M (true M)" 985 "BriefDescription": "Snoop dispatched for a read and was M (true M)"
921 }, 986 },
922 {, 987 {,
923 "EventCode": "0x40154", 988 "EventCode": "0x40154",
@@ -980,14 +1045,9 @@
980 "BriefDescription": "Link stack predicts right address" 1045 "BriefDescription": "Link stack predicts right address"
981 }, 1046 },
982 {, 1047 {,
983 "EventCode": "0x4C05A",
984 "EventName": "PM_DTLB_MISS_1G",
985 "BriefDescription": "Data TLB reload (after a miss) page size 1G. Implies radix translation was used"
986 },
987 {,
988 "EventCode": "0x36886", 1048 "EventCode": "0x36886",
989 "EventName": "PM_L2_SN_SX_I_DONE", 1049 "EventName": "PM_L2_SN_SX_I_DONE",
990 "BriefDescription": "SNP dispatched and went from Sx to Ix" 1050 "BriefDescription": "Snoop dispatched and went from Sx to Ix"
991 }, 1051 },
992 {, 1052 {,
993 "EventCode": "0x4E04A", 1053 "EventCode": "0x4E04A",
@@ -1000,11 +1060,6 @@
1000 "BriefDescription": "Duration in cycles to reload from another chip's L4 on a different Node or Group (Distant) due to a marked load" 1060 "BriefDescription": "Duration in cycles to reload from another chip's L4 on a different Node or Group (Distant) due to a marked load"
1001 }, 1061 },
1002 {, 1062 {,
1003 "EventCode": "0x2608E",
1004 "EventName": "PM_TM_LD_CONF",
1005 "BriefDescription": "TM Load (fav or non-fav) ran into conflict (failed)"
1006 },
1007 {,
1008 "EventCode": "0x4080", 1063 "EventCode": "0x4080",
1009 "EventName": "PM_INST_FROM_L1", 1064 "EventName": "PM_INST_FROM_L1",
1010 "BriefDescription": "Instruction fetches from L1. L1 instruction hit" 1065 "BriefDescription": "Instruction fetches from L1. L1 instruction hit"
@@ -1037,7 +1092,7 @@
1037 {, 1092 {,
1038 "EventCode": "0x260A6", 1093 "EventCode": "0x260A6",
1039 "EventName": "PM_NON_TM_RST_SC", 1094 "EventName": "PM_NON_TM_RST_SC",
1040 "BriefDescription": "Non-TM snp rst TM SC" 1095 "BriefDescription": "Non-TM snoop hits line in L3 that is TM_SC state and causes it to be invalidated"
1041 }, 1096 },
1042 {, 1097 {,
1043 "EventCode": "0x3608A", 1098 "EventCode": "0x3608A",
@@ -1065,11 +1120,6 @@
1065 "BriefDescription": "Branch mispredict flushes. Includes target and address misprecition" 1120 "BriefDescription": "Branch mispredict flushes. Includes target and address misprecition"
1066 }, 1121 },
1067 {, 1122 {,
1068 "EventCode": "0x508C",
1069 "EventName": "PM_SHL_CREATED",
1070 "BriefDescription": "Store-Hit-Load Table Entry Created"
1071 },
1072 {,
1073 "EventCode": "0x1504C", 1123 "EventCode": "0x1504C",
1074 "EventName": "PM_IPTEG_FROM_LL4", 1124 "EventName": "PM_IPTEG_FROM_LL4",
1075 "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's L4 cache due to a instruction side request" 1125 "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's L4 cache due to a instruction side request"
@@ -1107,7 +1157,7 @@
1107 {, 1157 {,
1108 "EventCode": "0x2608A", 1158 "EventCode": "0x2608A",
1109 "EventName": "PM_ISIDE_DISP_FAIL_ADDR", 1159 "EventName": "PM_ISIDE_DISP_FAIL_ADDR",
1110 "BriefDescription": "All I-side dispatch attempts for this thread that failed due to a addr collision with another machine (excludes i_l2mru_tch_reqs)" 1160 "BriefDescription": "All I-side-instruction-fetch dispatch attempts for this thread that failed due to an address collision conflict with an L2 machine already working on this line (e.g. ld-hit-stq or RC/CO/SN machines)"
1111 }, 1161 },
1112 {, 1162 {,
1113 "EventCode": "0x50B4", 1163 "EventCode": "0x50B4",
@@ -1180,9 +1230,9 @@
1180 "BriefDescription": "Number of stcx instructions finished. This includes instructions in the speculative path of a branch that may be flushed" 1230 "BriefDescription": "Number of stcx instructions finished. This includes instructions in the speculative path of a branch that may be flushed"
1181 }, 1231 },
1182 {, 1232 {,
1183 "EventCode": "0xE0B8", 1233 "EventCode": "0xD8AC",
1184 "EventName": "PM_LS2_TM_DISALLOW", 1234 "EventName": "PM_LWSYNC",
1185 "BriefDescription": "A TM-ineligible instruction tries to execute inside a transaction and the LSU disallows it" 1235 "BriefDescription": ""
1186 }, 1236 },
1187 {, 1237 {,
1188 "EventCode": "0x2094", 1238 "EventCode": "0x2094",
@@ -1210,6 +1260,11 @@
1210 "BriefDescription": "Ict empty for this thread due to dispatch holds because the History Buffer was full. Could be GPR/VSR/VMR/FPR/CR/XVF; CR; XVF (XER/VSCR/FPSCR)" 1260 "BriefDescription": "Ict empty for this thread due to dispatch holds because the History Buffer was full. Could be GPR/VSR/VMR/FPR/CR/XVF; CR; XVF (XER/VSCR/FPSCR)"
1211 }, 1261 },
1212 {, 1262 {,
1263 "EventCode": "0xC894",
1264 "EventName": "PM_LS1_UNALIGNED_LD",
1265 "BriefDescription": "Load instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the load of that size. If the load wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
1266 },
1267 {,
1213 "EventCode": "0x360A2", 1268 "EventCode": "0x360A2",
1214 "EventName": "PM_L3_L2_CO_HIT", 1269 "EventName": "PM_L3_L2_CO_HIT",
1215 "BriefDescription": "L2 CO hits" 1270 "BriefDescription": "L2 CO hits"
@@ -1292,7 +1347,7 @@
1292 {, 1347 {,
1293 "EventCode": "0xC084", 1348 "EventCode": "0xC084",
1294 "EventName": "PM_LS2_LD_VECTOR_FIN", 1349 "EventName": "PM_LS2_LD_VECTOR_FIN",
1295 "BriefDescription": "" 1350 "BriefDescription": "LS2 finished load vector op"
1296 }, 1351 },
1297 {, 1352 {,
1298 "EventCode": "0x1608E", 1353 "EventCode": "0x1608E",
@@ -1345,6 +1400,11 @@
1345 "BriefDescription": "Continuous 16 cycle (2to1) window where this signals rotates thru sampling each SN machine busy. PMU uses this wave to then do 16 cyc count to sample total number of machs running" 1400 "BriefDescription": "Continuous 16 cycle (2to1) window where this signals rotates thru sampling each SN machine busy. PMU uses this wave to then do 16 cyc count to sample total number of machs running"
1346 }, 1401 },
1347 {, 1402 {,
1403 "EventCode": "0x36084",
1404 "EventName": "PM_L2_RCST_DISP",
1405 "BriefDescription": "All D-side store dispatch attempts for this thread"
1406 },
1407 {,
1348 "EventCode": "0x46084", 1408 "EventCode": "0x46084",
1349 "EventName": "PM_L2_RCST_DISP_FAIL_OTHER", 1409 "EventName": "PM_L2_RCST_DISP_FAIL_OTHER",
1350 "BriefDescription": "All D-side store dispatch attempts for this thread that failed due to reason other than address collision" 1410 "BriefDescription": "All D-side store dispatch attempts for this thread that failed due to reason other than address collision"
@@ -1355,11 +1415,6 @@
1355 "BriefDescription": "A demand load referenced a line in an active strided prefetch stream. The stream could have been allocated through the hardware prefetch mechanism or through software." 1415 "BriefDescription": "A demand load referenced a line in an active strided prefetch stream. The stream could have been allocated through the hardware prefetch mechanism or through software."
1356 }, 1416 },
1357 {, 1417 {,
1358 "EventCode": "0x36084",
1359 "EventName": "PM_L2_RCST_DISP",
1360 "BriefDescription": "All D-side store dispatch attempts for this thread"
1361 },
1362 {,
1363 "EventCode": "0x45054", 1418 "EventCode": "0x45054",
1364 "EventName": "PM_FMA_CMPL", 1419 "EventName": "PM_FMA_CMPL",
1365 "BriefDescription": "two flops operation completed (fmadd, fnmadd, fmsub, fnmsub) Scalar instructions only. " 1420 "BriefDescription": "two flops operation completed (fmadd, fnmadd, fmsub, fnmsub) Scalar instructions only. "
@@ -1372,7 +1427,7 @@
1372 {, 1427 {,
1373 "EventCode": "0x36080", 1428 "EventCode": "0x36080",
1374 "EventName": "PM_L2_INST", 1429 "EventName": "PM_L2_INST",
1375 "BriefDescription": "All successful I-side dispatches for this thread (excludes i_l2mru_tch reqs)" 1430 "BriefDescription": "All successful I-side-instruction-fetch (e.g. i-demand, i-prefetch) dispatches for this thread"
1376 }, 1431 },
1377 {, 1432 {,
1378 "EventCode": "0x3504C", 1433 "EventCode": "0x3504C",
@@ -1387,7 +1442,7 @@
1387 {, 1442 {,
1388 "EventCode": "0x1688A", 1443 "EventCode": "0x1688A",
1389 "EventName": "PM_ISIDE_DISP", 1444 "EventName": "PM_ISIDE_DISP",
1390 "BriefDescription": "All I-side dispatch attempts for this thread (excludes i_l2mru_tch_reqs)" 1445 "BriefDescription": "All I-side-instruction-fetch dispatch attempts for this thread"
1391 }, 1446 },
1392 {, 1447 {,
1393 "EventCode": "0x468AA", 1448 "EventCode": "0x468AA",
@@ -1420,6 +1475,11 @@
1420 "BriefDescription": "Load tm hit in L1" 1475 "BriefDescription": "Load tm hit in L1"
1421 }, 1476 },
1422 {, 1477 {,
1478 "EventCode": "0xE0B8",
1479 "EventName": "PM_LS2_TM_DISALLOW",
1480 "BriefDescription": "A TM-ineligible instruction tries to execute inside a transaction and the LSU disallows it"
1481 },
1482 {,
1423 "EventCode": "0x44044", 1483 "EventCode": "0x44044",
1424 "EventName": "PM_INST_FROM_L31_ECO_MOD", 1484 "EventName": "PM_INST_FROM_L31_ECO_MOD",
1425 "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to an instruction fetch (not prefetch)" 1485 "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to an instruction fetch (not prefetch)"
@@ -1467,7 +1527,7 @@
1467 {, 1527 {,
1468 "EventCode": "0x36086", 1528 "EventCode": "0x36086",
1469 "EventName": "PM_L2_RC_ST_DONE", 1529 "EventName": "PM_L2_RC_ST_DONE",
1470 "BriefDescription": "RC did store to line that was Tx or Sx" 1530 "BriefDescription": "Read-claim machine did store to line that was in Tx or Sx (Tagged or Shared state)"
1471 }, 1531 },
1472 {, 1532 {,
1473 "EventCode": "0xE8AC", 1533 "EventCode": "0xE8AC",
@@ -1500,6 +1560,11 @@
1500 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a instruction side request" 1560 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a instruction side request"
1501 }, 1561 },
1502 {, 1562 {,
1563 "EventCode": "0x460A6",
1564 "EventName": "PM_RD_FORMING_SC",
1565 "BriefDescription": "Doesn't occur"
1566 },
1567 {,
1503 "EventCode": "0x35042", 1568 "EventCode": "0x35042",
1504 "EventName": "PM_IPTEG_FROM_L3_DISP_CONFLICT", 1569 "EventName": "PM_IPTEG_FROM_L3_DISP_CONFLICT",
1505 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 with dispatch conflict due to a instruction side request" 1570 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 with dispatch conflict due to a instruction side request"
@@ -1527,7 +1592,7 @@
1527 {, 1592 {,
1528 "EventCode": "0x36882", 1593 "EventCode": "0x36882",
1529 "EventName": "PM_L2_LD_HIT", 1594 "EventName": "PM_L2_LD_HIT",
1530 "BriefDescription": "All successful I-or-D side load dispatches for this thread that were L2 hits (excludes i_l2mru_tch_reqs)" 1595 "BriefDescription": "All successful D-side-Ld or I-side-instruction-fetch dispatches for this thread that were L2 hits"
1531 }, 1596 },
1532 {, 1597 {,
1533 "EventCode": "0x168AC", 1598 "EventCode": "0x168AC",
@@ -1555,11 +1620,6 @@
1555 "BriefDescription": "ProbeNops dispatched" 1620 "BriefDescription": "ProbeNops dispatched"
1556 }, 1621 },
1557 {, 1622 {,
1558 "EventCode": "0x58A8",
1559 "EventName": "PM_DECODE_HOLD_ICT_FULL",
1560 "BriefDescription": "Counts the number of cycles in which the IFU was not able to decode and transmit one or more instructions because all itags were in use. This means the ICT is full for this thread"
1561 },
1562 {,
1563 "EventCode": "0x10052", 1623 "EventCode": "0x10052",
1564 "EventName": "PM_GRP_PUMP_MPRED_RTY", 1624 "EventName": "PM_GRP_PUMP_MPRED_RTY",
1565 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)" 1625 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
@@ -1572,7 +1632,7 @@
1572 {, 1632 {,
1573 "EventCode": "0x2688A", 1633 "EventCode": "0x2688A",
1574 "EventName": "PM_ISIDE_DISP_FAIL_OTHER", 1634 "EventName": "PM_ISIDE_DISP_FAIL_OTHER",
1575 "BriefDescription": "All I-side dispatch attempts for this thread that failed due to a reason other than addrs collision (excludes i_l2mru_tch_reqs)" 1635 "BriefDescription": "All I-side-instruction-fetch dispatch attempts for this thread that failed due to reasons other than an address collision conflict with an L2 machine (e.g. no available RC/CO machines)"
1576 }, 1636 },
1577 {, 1637 {,
1578 "EventCode": "0x2001A", 1638 "EventCode": "0x2001A",
@@ -1652,12 +1712,12 @@
1652 {, 1712 {,
1653 "EventCode": "0x46880", 1713 "EventCode": "0x46880",
1654 "EventName": "PM_ISIDE_MRU_TOUCH", 1714 "EventName": "PM_ISIDE_MRU_TOUCH",
1655 "BriefDescription": "I-side L2 MRU touch sent to L2 for this thread" 1715 "BriefDescription": "I-side L2 MRU touch sent to L2 for this thread I-side L2 MRU touch commands sent to the L2 for this thread"
1656 }, 1716 },
1657 {, 1717 {,
1658 "EventCode": "0x1C05C", 1718 "EventCode": "0x508C",
1659 "EventName": "PM_DTLB_MISS_2M", 1719 "EventName": "PM_SHL_CREATED",
1660 "BriefDescription": "Data TLB reload (after a miss) page size 2M. Implies radix translation was used" 1720 "BriefDescription": "Store-Hit-Load Table Entry Created"
1661 }, 1721 },
1662 {, 1722 {,
1663 "EventCode": "0x50B8", 1723 "EventCode": "0x50B8",
@@ -1672,7 +1732,7 @@
1672 {, 1732 {,
1673 "EventCode": "0x268B2", 1733 "EventCode": "0x268B2",
1674 "EventName": "PM_L3_LOC_GUESS_WRONG", 1734 "EventName": "PM_L3_LOC_GUESS_WRONG",
1675 "BriefDescription": "Initial scope=node (LNS) but data from out side local node (near or far or rem). Prediction too Low" 1735 "BriefDescription": "Prefetch scope predictor selected LNS, but was wrong"
1676 }, 1736 },
1677 {, 1737 {,
1678 "EventCode": "0x36088", 1738 "EventCode": "0x36088",
@@ -1685,6 +1745,11 @@
1685 "BriefDescription": "L3 PF received retry port 2, every retry counted" 1745 "BriefDescription": "L3 PF received retry port 2, every retry counted"
1686 }, 1746 },
1687 {, 1747 {,
1748 "EventCode": "0xD8B0",
1749 "EventName": "PM_PTESYNC",
1750 "BriefDescription": ""
1751 },
1752 {,
1688 "EventCode": "0x26086", 1753 "EventCode": "0x26086",
1689 "EventName": "PM_CO_TM_SC_FOOTPRINT", 1754 "EventName": "PM_CO_TM_SC_FOOTPRINT",
1690 "BriefDescription": "L2 did a cleanifdirty CO to the L3 (ie created an SC line in the L3) OR L2 TM_store hit dirty HPC line and L3 indicated SC line formed in L3 on RDR bus" 1755 "BriefDescription": "L2 did a cleanifdirty CO to the L3 (ie created an SC line in the L3) OR L2 TM_store hit dirty HPC line and L3 indicated SC line formed in L3 on RDR bus"
@@ -1740,6 +1805,11 @@
1740 "BriefDescription": "All successful D-Side Store dispatches that were an L2 miss for this thread" 1805 "BriefDescription": "All successful D-Side Store dispatches that were an L2 miss for this thread"
1741 }, 1806 },
1742 {, 1807 {,
1808 "EventCode": "0xF8B4",
1809 "EventName": "PM_DC_PREF_XCONS_ALLOC",
1810 "BriefDescription": "Prefetch stream allocated in the Ultra conservative phase by either the hardware prefetch mechanism or software prefetch"
1811 },
1812 {,
1743 "EventCode": "0x35048", 1813 "EventCode": "0x35048",
1744 "EventName": "PM_IPTEG_FROM_DL2L3_SHR", 1814 "EventName": "PM_IPTEG_FROM_DL2L3_SHR",
1745 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a instruction side request" 1815 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a instruction side request"
@@ -1782,7 +1852,7 @@
1782 {, 1852 {,
1783 "EventCode": "0x460B2", 1853 "EventCode": "0x460B2",
1784 "EventName": "PM_L3_SYS_GUESS_WRONG", 1854 "EventName": "PM_L3_SYS_GUESS_WRONG",
1785 "BriefDescription": "Initial scope=system (VGS or RNS) but data from local or near. Prediction too high" 1855 "BriefDescription": "Prefetch scope predictor selected VGS or RNS, but was wrong"
1786 }, 1856 },
1787 {, 1857 {,
1788 "EventCode": "0x58B8", 1858 "EventCode": "0x58B8",
@@ -1800,11 +1870,6 @@
1800 "BriefDescription": "Completion time tabortnoncd, tabortcd, treclaim" 1870 "BriefDescription": "Completion time tabortnoncd, tabortcd, treclaim"
1801 }, 1871 },
1802 {, 1872 {,
1803 "EventCode": "0x4C054",
1804 "EventName": "PM_DERAT_MISS_16G",
1805 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16G"
1806 },
1807 {,
1808 "EventCode": "0x268A0", 1873 "EventCode": "0x268A0",
1809 "EventName": "PM_L3_CO_L31", 1874 "EventName": "PM_L3_CO_L31",
1810 "BriefDescription": "L3 CO to L3.1 OR of port 0 and 1 (lossy = may undercount if two cresps come in the same cyc)" 1875 "BriefDescription": "L3 CO to L3.1 OR of port 0 and 1 (lossy = may undercount if two cresps come in the same cyc)"
@@ -1862,7 +1927,7 @@
1862 {, 1927 {,
1863 "EventCode": "0x368B2", 1928 "EventCode": "0x368B2",
1864 "EventName": "PM_L3_GRP_GUESS_WRONG_HIGH", 1929 "EventName": "PM_L3_GRP_GUESS_WRONG_HIGH",
1865 "BriefDescription": "Initial scope=group (GS or NNS) but data from local node. Prediction too high" 1930 "BriefDescription": "Prefetch scope predictor selected GS or NNS, but was wrong because scope was VGS or RNS"
1866 }, 1931 },
1867 {, 1932 {,
1868 "EventCode": "0xE8BC", 1933 "EventCode": "0xE8BC",
@@ -1897,7 +1962,7 @@
1897 {, 1962 {,
1898 "EventCode": "0x260B2", 1963 "EventCode": "0x260B2",
1899 "EventName": "PM_L3_SYS_GUESS_CORRECT", 1964 "EventName": "PM_L3_SYS_GUESS_CORRECT",
1900 "BriefDescription": "Initial scope=system (VGS or RNS) and data from outside group (far or rem)(pred successful)" 1965 "BriefDescription": "Prefetch scope predictor selected VGS or RNS and was correct"
1901 }, 1966 },
1902 {, 1967 {,
1903 "EventCode": "0x1D146", 1968 "EventCode": "0x1D146",
@@ -1915,6 +1980,11 @@
1915 "BriefDescription": "RC requests that were on group (aka nodel) pump attempts" 1980 "BriefDescription": "RC requests that were on group (aka nodel) pump attempts"
1916 }, 1981 },
1917 {, 1982 {,
1983 "EventCode": "0xC08C",
1984 "EventName": "PM_LSU_DTLB_MISS_16M_2M",
1985 "BriefDescription": "Data TLB Miss page size 16M (HPT) or 2M (Radix)"
1986 },
1987 {,
1918 "EventCode": "0x16080", 1988 "EventCode": "0x16080",
1919 "EventName": "PM_L2_LD", 1989 "EventName": "PM_L2_LD",
1920 "BriefDescription": "All successful D-side Load dispatches for this thread (L2 miss + L2 hits)" 1990 "BriefDescription": "All successful D-side Load dispatches for this thread (L2 miss + L2 hits)"
@@ -1927,7 +1997,7 @@
1927 {, 1997 {,
1928 "EventCode": "0xC080", 1998 "EventCode": "0xC080",
1929 "EventName": "PM_LS0_LD_VECTOR_FIN", 1999 "EventName": "PM_LS0_LD_VECTOR_FIN",
1930 "BriefDescription": "" 2000 "BriefDescription": "LS0 finished load vector op"
1931 }, 2001 },
1932 {, 2002 {,
1933 "EventCode": "0x368B0", 2003 "EventCode": "0x368B0",
@@ -2000,6 +2070,11 @@
2000 "BriefDescription": "Conditional Branch Completed in which the HW correctly predicted the direction as taken. Counted at completion time" 2070 "BriefDescription": "Conditional Branch Completed in which the HW correctly predicted the direction as taken. Counted at completion time"
2001 }, 2071 },
2002 {, 2072 {,
2073 "EventCode": "0xF0B8",
2074 "EventName": "PM_LS0_UNALIGNED_ST",
2075 "BriefDescription": "Store instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the Store of that size. If the Store wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
2076 },
2077 {,
2003 "EventCode": "0x20132", 2078 "EventCode": "0x20132",
2004 "EventName": "PM_MRK_DFU_FIN", 2079 "EventName": "PM_MRK_DFU_FIN",
2005 "BriefDescription": "Decimal Unit marked Instruction Finish" 2080 "BriefDescription": "Decimal Unit marked Instruction Finish"
@@ -2007,7 +2082,7 @@
2007 {, 2082 {,
2008 "EventCode": "0x160A6", 2083 "EventCode": "0x160A6",
2009 "EventName": "PM_TM_SC_CO", 2084 "EventName": "PM_TM_SC_CO",
2010 "BriefDescription": "L3 castout TM SC line" 2085 "BriefDescription": "L3 castout of line that was StoreCopy (original value of speculatively written line) in a Transaction"
2011 }, 2086 },
2012 {, 2087 {,
2013 "EventCode": "0xC8B0", 2088 "EventCode": "0xC8B0",
@@ -2017,7 +2092,7 @@
2017 {, 2092 {,
2018 "EventCode": "0x16084", 2093 "EventCode": "0x16084",
2019 "EventName": "PM_L2_RCLD_DISP", 2094 "EventName": "PM_L2_RCLD_DISP",
2020 "BriefDescription": "All I-or-D side load dispatch attempts for this thread (excludes i_l2mru_tch_reqs)" 2095 "BriefDescription": "All D-side-Ld or I-side-instruction-fetch dispatch attempts for this thread"
2021 }, 2096 },
2022 {, 2097 {,
2023 "EventCode": "0x3F150", 2098 "EventCode": "0x3F150",
@@ -2122,12 +2197,12 @@
2122 {, 2197 {,
2123 "EventCode": "0x46082", 2198 "EventCode": "0x46082",
2124 "EventName": "PM_L2_ST_DISP", 2199 "EventName": "PM_L2_ST_DISP",
2125 "BriefDescription": "All successful D-side store dispatches for this thread (L2 miss + L2 hits)" 2200 "BriefDescription": "All successful D-side store dispatches for this thread"
2126 }, 2201 },
2127 {, 2202 {,
2128 "EventCode": "0x36880", 2203 "EventCode": "0x36880",
2129 "EventName": "PM_L2_INST_MISS", 2204 "EventName": "PM_L2_INST_MISS",
2130 "BriefDescription": "All successful I-side dispatches that were an L2 miss for this thread (excludes i_l2mru_tch reqs)" 2205 "BriefDescription": "All successful I-side-instruction-fetch (e.g. i-demand, i-prefetch) dispatches for this thread that were an L2 miss"
2131 }, 2206 },
2132 {, 2207 {,
2133 "EventCode": "0xE084", 2208 "EventCode": "0xE084",
@@ -2217,7 +2292,7 @@
2217 {, 2292 {,
2218 "EventCode": "0xC884", 2293 "EventCode": "0xC884",
2219 "EventName": "PM_LS3_LD_VECTOR_FIN", 2294 "EventName": "PM_LS3_LD_VECTOR_FIN",
2220 "BriefDescription": "" 2295 "BriefDescription": "LS3 finished load vector op"
2221 }, 2296 },
2222 {, 2297 {,
2223 "EventCode": "0x360A8", 2298 "EventCode": "0x360A8",
@@ -2242,7 +2317,7 @@
2242 {, 2317 {,
2243 "EventCode": "0x168B2", 2318 "EventCode": "0x168B2",
2244 "EventName": "PM_L3_GRP_GUESS_CORRECT", 2319 "EventName": "PM_L3_GRP_GUESS_CORRECT",
2245 "BriefDescription": "Initial scope=group (GS or NNS) and data from same group (near) (pred successful)" 2320 "BriefDescription": "Prefetch scope predictor selected GS or NNS and was correct"
2246 }, 2321 },
2247 {, 2322 {,
2248 "EventCode": "0x48A4", 2323 "EventCode": "0x48A4",
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json b/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
index 5af1abbe82c4..b4772f54a271 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
@@ -65,11 +65,6 @@
65 "BriefDescription": "Dispatch Held" 65 "BriefDescription": "Dispatch Held"
66 }, 66 },
67 {, 67 {,
68 "EventCode": "0x3D154",
69 "EventName": "PM_MRK_DERAT_MISS_16M",
70 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 16M"
71 },
72 {,
73 "EventCode": "0x200F8", 68 "EventCode": "0x200F8",
74 "EventName": "PM_EXT_INT", 69 "EventName": "PM_EXT_INT",
75 "BriefDescription": "external interrupt" 70 "BriefDescription": "external interrupt"
@@ -120,6 +115,11 @@
120 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without dispatch conflicts hit on Mepf state. due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included" 115 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without dispatch conflicts hit on Mepf state. due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
121 }, 116 },
122 {, 117 {,
118 "EventCode": "0x4C15C",
119 "EventName": "PM_MRK_DERAT_MISS_16G_1G",
120 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 16G (hpt mode) and 1G (radix mode)"
121 },
122 {,
123 "EventCode": "0x10024", 123 "EventCode": "0x10024",
124 "EventName": "PM_PMC5_OVERFLOW", 124 "EventName": "PM_PMC5_OVERFLOW",
125 "BriefDescription": "Overflow from counter 5" 125 "BriefDescription": "Overflow from counter 5"
@@ -155,11 +155,6 @@
155 "BriefDescription": "Ict empty for this thread due to Icache Miss" 155 "BriefDescription": "Ict empty for this thread due to Icache Miss"
156 }, 156 },
157 {, 157 {,
158 "EventCode": "0x3D152",
159 "EventName": "PM_MRK_DERAT_MISS_1G",
160 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 1G. Implies radix translation"
161 },
162 {,
163 "EventCode": "0x4F14A", 158 "EventCode": "0x4F14A",
164 "EventName": "PM_MRK_DPTEG_FROM_OFF_CHIP_CACHE", 159 "EventName": "PM_MRK_DPTEG_FROM_OFF_CHIP_CACHE",
165 "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included" 160 "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
@@ -185,11 +180,6 @@
185 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included" 180 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
186 }, 181 },
187 {, 182 {,
188 "EventCode": "0x2C05A",
189 "EventName": "PM_DERAT_MISS_1G",
190 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 1G. Implies radix translation"
191 },
192 {,
193 "EventCode": "0x1F058", 183 "EventCode": "0x1F058",
194 "EventName": "PM_RADIX_PWC_L2_PTE_FROM_L2", 184 "EventName": "PM_RADIX_PWC_L2_PTE_FROM_L2",
195 "BriefDescription": "A Page Table Entry was reloaded to a level 2 page walk cache from the core's L2 data cache. This implies that level 3 and level 4 PWC accesses were not necessary for this translation" 185 "BriefDescription": "A Page Table Entry was reloaded to a level 2 page walk cache from the core's L2 data cache. This implies that level 3 and level 4 PWC accesses were not necessary for this translation"
@@ -240,11 +230,6 @@
240 "BriefDescription": "Data PTEG reload" 230 "BriefDescription": "Data PTEG reload"
241 }, 231 },
242 {, 232 {,
243 "EventCode": "0x2D152",
244 "EventName": "PM_MRK_DERAT_MISS_2M",
245 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 2M. Implies radix translation"
246 },
247 {,
248 "EventCode": "0x2C046", 233 "EventCode": "0x2C046",
249 "EventName": "PM_DATA_FROM_RL2L3_MOD", 234 "EventName": "PM_DATA_FROM_RL2L3_MOD",
250 "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a demand load" 235 "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a demand load"
@@ -290,6 +275,11 @@
290 "BriefDescription": "Finish stall because the NTF instruction was issued to the Decimal Floating Point execution pipe and waiting to finish. Includes decimal floating point instructions + 128 bit binary floating point instructions. Not qualified by multicycle" 275 "BriefDescription": "Finish stall because the NTF instruction was issued to the Decimal Floating Point execution pipe and waiting to finish. Includes decimal floating point instructions + 128 bit binary floating point instructions. Not qualified by multicycle"
291 }, 276 },
292 {, 277 {,
278 "EventCode": "0x3C054",
279 "EventName": "PM_DERAT_MISS_16M_2M",
280 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16M (HPT mode) or 2M (Radix mode)"
281 },
282 {,
293 "EventCode": "0x4C04C", 283 "EventCode": "0x4C04C",
294 "EventName": "PM_DATA_FROM_DMEM", 284 "EventName": "PM_DATA_FROM_DMEM",
295 "BriefDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group (Distant) due to a demand load" 285 "BriefDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group (Distant) due to a demand load"
@@ -360,11 +350,6 @@
360 "BriefDescription": "The processor's Instruction cache was reloaded from a memory location including L4 from local remote or distant due to an instruction fetch (not prefetch)" 350 "BriefDescription": "The processor's Instruction cache was reloaded from a memory location including L4 from local remote or distant due to an instruction fetch (not prefetch)"
361 }, 351 },
362 {, 352 {,
363 "EventCode": "0x1C05A",
364 "EventName": "PM_DERAT_MISS_2M",
365 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 2M. Implies radix translation"
366 },
367 {,
368 "EventCode": "0x30024", 353 "EventCode": "0x30024",
369 "EventName": "PM_PMC6_OVERFLOW", 354 "EventName": "PM_PMC6_OVERFLOW",
370 "BriefDescription": "Overflow from counter 6" 355 "BriefDescription": "Overflow from counter 6"
@@ -375,6 +360,11 @@
375 "BriefDescription": "Branch Instruction Finished" 360 "BriefDescription": "Branch Instruction Finished"
376 }, 361 },
377 {, 362 {,
363 "EventCode": "0x3D154",
364 "EventName": "PM_MRK_DERAT_MISS_16M_2M",
365 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 16M (hpt mode) or 2M (radix mode)"
366 },
367 {,
378 "EventCode": "0x30020", 368 "EventCode": "0x30020",
379 "EventName": "PM_PMC2_REWIND", 369 "EventName": "PM_PMC2_REWIND",
380 "BriefDescription": "PMC2 Rewind Event (did not match condition)" 370 "BriefDescription": "PMC2 Rewind Event (did not match condition)"
@@ -410,11 +400,6 @@
410 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L3 on the same chip due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included" 400 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L3 on the same chip due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
411 }, 401 },
412 {, 402 {,
413 "EventCode": "0x4C15C",
414 "EventName": "PM_MRK_DERAT_MISS_16G",
415 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 16G"
416 },
417 {,
418 "EventCode": "0x14052", 403 "EventCode": "0x14052",
419 "EventName": "PM_INST_GRP_PUMP_MPRED_RTY", 404 "EventName": "PM_INST_GRP_PUMP_MPRED_RTY",
420 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for an instruction fetch" 405 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for an instruction fetch"
@@ -445,11 +430,6 @@
445 "BriefDescription": "Icache miss demand cycles" 430 "BriefDescription": "Icache miss demand cycles"
446 }, 431 },
447 {, 432 {,
448 "EventCode": "0x3C054",
449 "EventName": "PM_DERAT_MISS_16M",
450 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16M"
451 },
452 {,
453 "EventCode": "0x2D14E", 433 "EventCode": "0x2D14E",
454 "EventName": "PM_MRK_DATA_FROM_L21_SHR", 434 "EventName": "PM_MRK_DATA_FROM_L21_SHR",
455 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L2 on the same chip due to a marked load" 435 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L2 on the same chip due to a marked load"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/pmc.json b/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
index d0b89f930567..8b3b0f3be664 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
@@ -10,11 +10,6 @@
10 "BriefDescription": "Local memory above threshold for LSU medium" 10 "BriefDescription": "Local memory above threshold for LSU medium"
11 }, 11 },
12 {, 12 {,
13 "EventCode": "0x2C056",
14 "EventName": "PM_DTLB_MISS_4K",
15 "BriefDescription": "Data TLB Miss page size 4k"
16 },
17 {,
18 "EventCode": "0x40118", 13 "EventCode": "0x40118",
19 "EventName": "PM_MRK_DCACHE_RELOAD_INTV", 14 "EventName": "PM_MRK_DCACHE_RELOAD_INTV",
20 "BriefDescription": "Combined Intervention event" 15 "BriefDescription": "Combined Intervention event"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/translation.json b/tools/perf/pmu-events/arch/powerpc/power9/translation.json
index bc8e03d7a6b0..b27642676244 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/translation.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/translation.json
@@ -30,11 +30,6 @@
30 "BriefDescription": "Store finish count. Includes speculative activity" 30 "BriefDescription": "Store finish count. Includes speculative activity"
31 }, 31 },
32 {, 32 {,
33 "EventCode": "0x44042",
34 "EventName": "PM_INST_FROM_L3",
35 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 due to an instruction fetch (not prefetch)"
36 },
37 {,
38 "EventCode": "0x1504A", 33 "EventCode": "0x1504A",
39 "EventName": "PM_IPTEG_FROM_RL2L3_SHR", 34 "EventName": "PM_IPTEG_FROM_RL2L3_SHR",
40 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a instruction side request" 35 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a instruction side request"
@@ -125,6 +120,11 @@
125 "BriefDescription": "PMC1 Rewind Value saved" 120 "BriefDescription": "PMC1 Rewind Value saved"
126 }, 121 },
127 {, 122 {,
123 "EventCode": "0x44042",
124 "EventName": "PM_INST_FROM_L3",
125 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 due to an instruction fetch (not prefetch)"
126 },
127 {,
128 "EventCode": "0x200FE", 128 "EventCode": "0x200FE",
129 "EventName": "PM_DATA_FROM_L2MISS", 129 "EventName": "PM_DATA_FROM_L2MISS",
130 "BriefDescription": "Demand LD - L2 Miss (not L2 hit)" 130 "BriefDescription": "Demand LD - L2 Miss (not L2 hit)"
diff --git a/tools/perf/pmu-events/arch/s390/cf_z10/basic.json b/tools/perf/pmu-events/arch/s390/cf_z10/basic.json
new file mode 100644
index 000000000000..8bf16759ca53
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z10/basic.json
@@ -0,0 +1,74 @@
1[
2 {
3 "EventCode": "0",
4 "EventName": "CPU_CYCLES",
5 "BriefDescription": "CPU Cycles",
6 "PublicDescription": "Cycle Count"
7 },
8 {
9 "EventCode": "1",
10 "EventName": "INSTRUCTIONS",
11 "BriefDescription": "Instructions",
12 "PublicDescription": "Instruction Count"
13 },
14 {
15 "EventCode": "2",
16 "EventName": "L1I_DIR_WRITES",
17 "BriefDescription": "L1I Directory Writes",
18 "PublicDescription": "Level-1 I-Cache Directory Write Count"
19 },
20 {
21 "EventCode": "3",
22 "EventName": "L1I_PENALTY_CYCLES",
23 "BriefDescription": "L1I Penalty Cycles",
24 "PublicDescription": "Level-1 I-Cache Penalty Cycle Count"
25 },
26 {
27 "EventCode": "4",
28 "EventName": "L1D_DIR_WRITES",
29 "BriefDescription": "L1D Directory Writes",
30 "PublicDescription": "Level-1 D-Cache Directory Write Count"
31 },
32 {
33 "EventCode": "5",
34 "EventName": "L1D_PENALTY_CYCLES",
35 "BriefDescription": "L1D Penalty Cycles",
36 "PublicDescription": "Level-1 D-Cache Penalty Cycle Count"
37 },
38 {
39 "EventCode": "32",
40 "EventName": "PROBLEM_STATE_CPU_CYCLES",
41 "BriefDescription": "Problem-State CPU Cycles",
42 "PublicDescription": "Problem-State Cycle Count"
43 },
44 {
45 "EventCode": "33",
46 "EventName": "PROBLEM_STATE_INSTRUCTIONS",
47 "BriefDescription": "Problem-State Instructions",
48 "PublicDescription": "Problem-State Instruction Count"
49 },
50 {
51 "EventCode": "34",
52 "EventName": "PROBLEM_STATE_L1I_DIR_WRITES",
53 "BriefDescription": "Problem-State L1I Directory Writes",
54 "PublicDescription": "Problem-State Level-1 I-Cache Directory Write Count"
55 },
56 {
57 "EventCode": "35",
58 "EventName": "PROBLEM_STATE_L1I_PENALTY_CYCLES",
59 "BriefDescription": "Problem-State L1I Penalty Cycles",
60 "PublicDescription": "Problem-State Level-1 I-Cache Penalty Cycle Count"
61 },
62 {
63 "EventCode": "36",
64 "EventName": "PROBLEM_STATE_L1D_DIR_WRITES",
65 "BriefDescription": "Problem-State L1D Directory Writes",
66 "PublicDescription": "Problem-State Level-1 D-Cache Directory Write Count"
67 },
68 {
69 "EventCode": "37",
70 "EventName": "PROBLEM_STATE_L1D_PENALTY_CYCLES",
71 "BriefDescription": "Problem-State L1D Penalty Cycles",
72 "PublicDescription": "Problem-State Level-1 D-Cache Penalty Cycle Count"
73 },
74]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z10/crypto.json b/tools/perf/pmu-events/arch/s390/cf_z10/crypto.json
new file mode 100644
index 000000000000..7e5b72492141
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z10/crypto.json
@@ -0,0 +1,98 @@
1[
2 {
3 "EventCode": "64",
4 "EventName": "PRNG_FUNCTIONS",
5 "BriefDescription": "PRNG Functions",
6 "PublicDescription": "Total number of the PRNG functions issued by the CPU"
7 },
8 {
9 "EventCode": "65",
10 "EventName": "PRNG_CYCLES",
11 "BriefDescription": "PRNG Cycles",
12 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing PRNG functions issued by the CPU"
13 },
14 {
15 "EventCode": "66",
16 "EventName": "PRNG_BLOCKED_FUNCTIONS",
17 "BriefDescription": "PRNG Blocked Functions",
18 "PublicDescription": "Total number of the PRNG functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
19 },
20 {
21 "EventCode": "67",
22 "EventName": "PRNG_BLOCKED_CYCLES",
23 "BriefDescription": "PRNG Blocked Cycles",
24 "PublicDescription": "Total number of CPU cycles blocked for the PRNG functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
25 },
26 {
27 "EventCode": "68",
28 "EventName": "SHA_FUNCTIONS",
29 "BriefDescription": "SHA Functions",
30 "PublicDescription": "Total number of SHA functions issued by the CPU"
31 },
32 {
33 "EventCode": "69",
34 "EventName": "SHA_CYCLES",
35 "BriefDescription": "SHA Cycles",
36 "PublicDescription": "Total number of CPU cycles when the SHA coprocessor is busy performing the SHA functions issued by the CPU"
37 },
38 {
39 "EventCode": "70",
40 "EventName": "SHA_BLOCKED_FUNCTIONS",
41 "BriefDescription": "SHA Blocked Functions",
42 "PublicDescription": "Total number of the SHA functions that are issued by the CPU and are blocked because the SHA coprocessor is busy performing a function issued by another CPU"
43 },
44 {
45 "EventCode": "71",
46 "EventName": "SHA_BLOCKED_CYCLES",
47 "BriefDescription": "SHA Bloced Cycles",
48 "PublicDescription": "Total number of CPU cycles blocked for the SHA functions issued by the CPU because the SHA coprocessor is busy performing a function issued by another CPU"
49 },
50 {
51 "EventCode": "72",
52 "EventName": "DEA_FUNCTIONS",
53 "BriefDescription": "DEA Functions",
54 "PublicDescription": "Total number of the DEA functions issued by the CPU"
55 },
56 {
57 "EventCode": "73",
58 "EventName": "DEA_CYCLES",
59 "BriefDescription": "DEA Cycles",
60 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the DEA functions issued by the CPU"
61 },
62 {
63 "EventCode": "74",
64 "EventName": "DEA_BLOCKED_FUNCTIONS",
65 "BriefDescription": "DEA Blocked Functions",
66 "PublicDescription": "Total number of the DEA functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
67 },
68 {
69 "EventCode": "75",
70 "EventName": "DEA_BLOCKED_CYCLES",
71 "BriefDescription": "DEA Blocked Cycles",
72 "PublicDescription": "Total number of CPU cycles blocked for the DEA functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
73 },
74 {
75 "EventCode": "76",
76 "EventName": "AES_FUNCTIONS",
77 "BriefDescription": "AES Functions",
78 "PublicDescription": "Total number of AES functions issued by the CPU"
79 },
80 {
81 "EventCode": "77",
82 "EventName": "AES_CYCLES",
83 "BriefDescription": "AES Cycles",
84 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the AES functions issued by the CPU"
85 },
86 {
87 "EventCode": "78",
88 "EventName": "AES_BLOCKED_FUNCTIONS",
89 "BriefDescription": "AES Blocked Functions",
90 "PublicDescription": "Total number of AES functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
91 },
92 {
93 "EventCode": "79",
94 "EventName": "AES_BLOCKED_CYCLES",
95 "BriefDescription": "AES Blocked Cycles",
96 "PublicDescription": "Total number of CPU cycles blocked for the AES functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
97 },
98]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z10/extended.json b/tools/perf/pmu-events/arch/s390/cf_z10/extended.json
new file mode 100644
index 000000000000..0feedb40f30f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z10/extended.json
@@ -0,0 +1,110 @@
1[
2 {
3 "EventCode": "128",
4 "EventName": "L1I_L2_SOURCED_WRITES",
5 "BriefDescription": "L1I L2 Sourced Writes",
6 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from the Level-2 (L1.5) cache"
7 },
8 {
9 "EventCode": "129",
10 "EventName": "L1D_L2_SOURCED_WRITES",
11 "BriefDescription": "L1D L2 Sourced Writes",
12 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the installed cache line was sourced from the Level-2 (L1.5) cache"
13 },
14 {
15 "EventCode": "130",
16 "EventName": "L1I_L3_LOCAL_WRITES",
17 "BriefDescription": "L1I L3 Local Writes",
18 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the installed cache line was sourced from the Level-3 cache that is on the same book as the Instruction cache (Local L2 cache)"
19 },
20 {
21 "EventCode": "131",
22 "EventName": "L1D_L3_LOCAL_WRITES",
23 "BriefDescription": "L1D L3 Local Writes",
24 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the installtion cache line was source from the Level-3 cache that is on the same book as the Data cache (Local L2 cache)"
25 },
26 {
27 "EventCode": "132",
28 "EventName": "L1I_L3_REMOTE_WRITES",
29 "BriefDescription": "L1I L3 Remote Writes",
30 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the installed cache line was sourced from a Level-3 cache that is not on the same book as the Instruction cache (Remote L2 cache)"
31 },
32 {
33 "EventCode": "133",
34 "EventName": "L1D_L3_REMOTE_WRITES",
35 "BriefDescription": "L1D L3 Remote Writes",
36 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the installed cache line was sourced from a Level-3 cache that is not on the same book as the Data cache (Remote L2 cache)"
37 },
38 {
39 "EventCode": "134",
40 "EventName": "L1D_LMEM_SOURCED_WRITES",
41 "BriefDescription": "L1D Local Memory Sourced Writes",
42 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the installed cache line was sourced from memory that is attached to the same book as the Data cache (Local Memory)"
43 },
44 {
45 "EventCode": "135",
46 "EventName": "L1I_LMEM_SOURCED_WRITES",
47 "BriefDescription": "L1I Local Memory Sourced Writes",
48 "PublicDescription": "A directory write to the Level-1 I-Cache where the installed cache line was sourced from memory that is attached to the s ame book as the Instruction cache (Local Memory)"
49 },
50 {
51 "EventCode": "136",
52 "EventName": "L1D_RO_EXCL_WRITES",
53 "BriefDescription": "L1D Read-only Exclusive Writes",
54 "PublicDescription": "A directory write to the Level-1 D-Cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
55 },
56 {
57 "EventCode": "137",
58 "EventName": "L1I_CACHELINE_INVALIDATES",
59 "BriefDescription": "L1I Cacheline Invalidates",
60 "PublicDescription": "A cache line in the Level-1 I-Cache has been invalidated by a store on the same CPU as the Level-1 I-Cache"
61 },
62 {
63 "EventCode": "138",
64 "EventName": "ITLB1_WRITES",
65 "BriefDescription": "ITLB1 Writes",
66 "PublicDescription": "A translation entry has been written into the Level-1 Instruction Translation Lookaside Buffer"
67 },
68 {
69 "EventCode": "139",
70 "EventName": "DTLB1_WRITES",
71 "BriefDescription": "DTLB1 Writes",
72 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer"
73 },
74 {
75 "EventCode": "140",
76 "EventName": "TLB2_PTE_WRITES",
77 "BriefDescription": "TLB2 PTE Writes",
78 "PublicDescription": "A translation entry has been written to the Level-2 TLB Page Table Entry arrays"
79 },
80 {
81 "EventCode": "141",
82 "EventName": "TLB2_CRSTE_WRITES",
83 "BriefDescription": "TLB2 CRSTE Writes",
84 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays"
85 },
86 {
87 "EventCode": "142",
88 "EventName": "TLB2_CRSTE_HPAGE_WRITES",
89 "BriefDescription": "TLB2 CRSTE One-Megabyte Page Writes",
90 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays for a one-megabyte large page translation"
91 },
92 {
93 "EventCode": "145",
94 "EventName": "ITLB1_MISSES",
95 "BriefDescription": "ITLB1 Misses",
96 "PublicDescription": "Level-1 Instruction TLB miss in progress. Incremented by one for every cycle an ITLB1 miss is in progress"
97 },
98 {
99 "EventCode": "146",
100 "EventName": "DTLB1_MISSES",
101 "BriefDescription": "DTLB1 Misses",
102 "PublicDescription": "Level-1 Data TLB miss in progress. Incremented by one for every cycle an DTLB1 miss is in progress"
103 },
104 {
105 "EventCode": "147",
106 "EventName": "L2C_STORES_SENT",
107 "BriefDescription": "L2C Stores Sent",
108 "PublicDescription": "Incremented by one for every store sent to Level-2 (L1.5) cache"
109 },
110]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z13/basic.json b/tools/perf/pmu-events/arch/s390/cf_z13/basic.json
new file mode 100644
index 000000000000..8bf16759ca53
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z13/basic.json
@@ -0,0 +1,74 @@
1[
2 {
3 "EventCode": "0",
4 "EventName": "CPU_CYCLES",
5 "BriefDescription": "CPU Cycles",
6 "PublicDescription": "Cycle Count"
7 },
8 {
9 "EventCode": "1",
10 "EventName": "INSTRUCTIONS",
11 "BriefDescription": "Instructions",
12 "PublicDescription": "Instruction Count"
13 },
14 {
15 "EventCode": "2",
16 "EventName": "L1I_DIR_WRITES",
17 "BriefDescription": "L1I Directory Writes",
18 "PublicDescription": "Level-1 I-Cache Directory Write Count"
19 },
20 {
21 "EventCode": "3",
22 "EventName": "L1I_PENALTY_CYCLES",
23 "BriefDescription": "L1I Penalty Cycles",
24 "PublicDescription": "Level-1 I-Cache Penalty Cycle Count"
25 },
26 {
27 "EventCode": "4",
28 "EventName": "L1D_DIR_WRITES",
29 "BriefDescription": "L1D Directory Writes",
30 "PublicDescription": "Level-1 D-Cache Directory Write Count"
31 },
32 {
33 "EventCode": "5",
34 "EventName": "L1D_PENALTY_CYCLES",
35 "BriefDescription": "L1D Penalty Cycles",
36 "PublicDescription": "Level-1 D-Cache Penalty Cycle Count"
37 },
38 {
39 "EventCode": "32",
40 "EventName": "PROBLEM_STATE_CPU_CYCLES",
41 "BriefDescription": "Problem-State CPU Cycles",
42 "PublicDescription": "Problem-State Cycle Count"
43 },
44 {
45 "EventCode": "33",
46 "EventName": "PROBLEM_STATE_INSTRUCTIONS",
47 "BriefDescription": "Problem-State Instructions",
48 "PublicDescription": "Problem-State Instruction Count"
49 },
50 {
51 "EventCode": "34",
52 "EventName": "PROBLEM_STATE_L1I_DIR_WRITES",
53 "BriefDescription": "Problem-State L1I Directory Writes",
54 "PublicDescription": "Problem-State Level-1 I-Cache Directory Write Count"
55 },
56 {
57 "EventCode": "35",
58 "EventName": "PROBLEM_STATE_L1I_PENALTY_CYCLES",
59 "BriefDescription": "Problem-State L1I Penalty Cycles",
60 "PublicDescription": "Problem-State Level-1 I-Cache Penalty Cycle Count"
61 },
62 {
63 "EventCode": "36",
64 "EventName": "PROBLEM_STATE_L1D_DIR_WRITES",
65 "BriefDescription": "Problem-State L1D Directory Writes",
66 "PublicDescription": "Problem-State Level-1 D-Cache Directory Write Count"
67 },
68 {
69 "EventCode": "37",
70 "EventName": "PROBLEM_STATE_L1D_PENALTY_CYCLES",
71 "BriefDescription": "Problem-State L1D Penalty Cycles",
72 "PublicDescription": "Problem-State Level-1 D-Cache Penalty Cycle Count"
73 },
74]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z13/crypto.json b/tools/perf/pmu-events/arch/s390/cf_z13/crypto.json
new file mode 100644
index 000000000000..7e5b72492141
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z13/crypto.json
@@ -0,0 +1,98 @@
1[
2 {
3 "EventCode": "64",
4 "EventName": "PRNG_FUNCTIONS",
5 "BriefDescription": "PRNG Functions",
6 "PublicDescription": "Total number of the PRNG functions issued by the CPU"
7 },
8 {
9 "EventCode": "65",
10 "EventName": "PRNG_CYCLES",
11 "BriefDescription": "PRNG Cycles",
12 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing PRNG functions issued by the CPU"
13 },
14 {
15 "EventCode": "66",
16 "EventName": "PRNG_BLOCKED_FUNCTIONS",
17 "BriefDescription": "PRNG Blocked Functions",
18 "PublicDescription": "Total number of the PRNG functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
19 },
20 {
21 "EventCode": "67",
22 "EventName": "PRNG_BLOCKED_CYCLES",
23 "BriefDescription": "PRNG Blocked Cycles",
24 "PublicDescription": "Total number of CPU cycles blocked for the PRNG functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
25 },
26 {
27 "EventCode": "68",
28 "EventName": "SHA_FUNCTIONS",
29 "BriefDescription": "SHA Functions",
30 "PublicDescription": "Total number of SHA functions issued by the CPU"
31 },
32 {
33 "EventCode": "69",
34 "EventName": "SHA_CYCLES",
35 "BriefDescription": "SHA Cycles",
36 "PublicDescription": "Total number of CPU cycles when the SHA coprocessor is busy performing the SHA functions issued by the CPU"
37 },
38 {
39 "EventCode": "70",
40 "EventName": "SHA_BLOCKED_FUNCTIONS",
41 "BriefDescription": "SHA Blocked Functions",
42 "PublicDescription": "Total number of the SHA functions that are issued by the CPU and are blocked because the SHA coprocessor is busy performing a function issued by another CPU"
43 },
44 {
45 "EventCode": "71",
46 "EventName": "SHA_BLOCKED_CYCLES",
47 "BriefDescription": "SHA Bloced Cycles",
48 "PublicDescription": "Total number of CPU cycles blocked for the SHA functions issued by the CPU because the SHA coprocessor is busy performing a function issued by another CPU"
49 },
50 {
51 "EventCode": "72",
52 "EventName": "DEA_FUNCTIONS",
53 "BriefDescription": "DEA Functions",
54 "PublicDescription": "Total number of the DEA functions issued by the CPU"
55 },
56 {
57 "EventCode": "73",
58 "EventName": "DEA_CYCLES",
59 "BriefDescription": "DEA Cycles",
60 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the DEA functions issued by the CPU"
61 },
62 {
63 "EventCode": "74",
64 "EventName": "DEA_BLOCKED_FUNCTIONS",
65 "BriefDescription": "DEA Blocked Functions",
66 "PublicDescription": "Total number of the DEA functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
67 },
68 {
69 "EventCode": "75",
70 "EventName": "DEA_BLOCKED_CYCLES",
71 "BriefDescription": "DEA Blocked Cycles",
72 "PublicDescription": "Total number of CPU cycles blocked for the DEA functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
73 },
74 {
75 "EventCode": "76",
76 "EventName": "AES_FUNCTIONS",
77 "BriefDescription": "AES Functions",
78 "PublicDescription": "Total number of AES functions issued by the CPU"
79 },
80 {
81 "EventCode": "77",
82 "EventName": "AES_CYCLES",
83 "BriefDescription": "AES Cycles",
84 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the AES functions issued by the CPU"
85 },
86 {
87 "EventCode": "78",
88 "EventName": "AES_BLOCKED_FUNCTIONS",
89 "BriefDescription": "AES Blocked Functions",
90 "PublicDescription": "Total number of AES functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
91 },
92 {
93 "EventCode": "79",
94 "EventName": "AES_BLOCKED_CYCLES",
95 "BriefDescription": "AES Blocked Cycles",
96 "PublicDescription": "Total number of CPU cycles blocked for the AES functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
97 },
98]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z13/extended.json b/tools/perf/pmu-events/arch/s390/cf_z13/extended.json
new file mode 100644
index 000000000000..9a002b6967f1
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z13/extended.json
@@ -0,0 +1,338 @@
1[
2 {
3 "EventCode": "128",
4 "EventName": "L1D_RO_EXCL_WRITES",
5 "BriefDescription": "L1D Read-only Exclusive Writes",
6 "PublicDescription": "A directory write to the Level-1 Data cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line."
7 },
8 {
9 "EventCode": "129",
10 "EventName": "DTLB1_WRITES",
11 "BriefDescription": "DTLB1 Writes",
12 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer"
13 },
14 {
15 "EventCode": "130",
16 "EventName": "DTLB1_MISSES",
17 "BriefDescription": "DTLB1 Misses",
18 "PublicDescription": "Level-1 Data TLB miss in progress. Incremented by one for every cycle a DTLB1 miss is in progress."
19 },
20 {
21 "EventCode": "131",
22 "EventName": "DTLB1_HPAGE_WRITES",
23 "BriefDescription": "DTLB1 One-Megabyte Page Writes",
24 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a one-megabyte page"
25 },
26 {
27 "EventCode": "132",
28 "EventName": "DTLB1_GPAGE_WRITES",
29 "BriefDescription": "DTLB1 Two-Gigabyte Page Writes",
30 "PublicDescription": "Counter:132 Name:DTLB1_GPAGE_WRITES A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a two-gigabyte page."
31 },
32 {
33 "EventCode": "133",
34 "EventName": "L1D_L2D_SOURCED_WRITES",
35 "BriefDescription": "L1D L2D Sourced Writes",
36 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from the Level-2 Data cache"
37 },
38 {
39 "EventCode": "134",
40 "EventName": "ITLB1_WRITES",
41 "BriefDescription": "ITLB1 Writes",
42 "PublicDescription": "A translation entry has been written to the Level-1 Instruction Translation Lookaside Buffer"
43 },
44 {
45 "EventCode": "135",
46 "EventName": "ITLB1_MISSES",
47 "BriefDescription": "ITLB1 Misses",
48 "PublicDescription": "Level-1 Instruction TLB miss in progress. Incremented by one for every cycle an ITLB1 miss is in progress"
49 },
50 {
51 "EventCode": "136",
52 "EventName": "L1I_L2I_SOURCED_WRITES",
53 "BriefDescription": "L1I L2I Sourced Writes",
54 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from the Level-2 Instruction cache"
55 },
56 {
57 "EventCode": "137",
58 "EventName": "TLB2_PTE_WRITES",
59 "BriefDescription": "TLB2 PTE Writes",
60 "PublicDescription": "A translation entry has been written to the Level-2 TLB Page Table Entry arrays"
61 },
62 {
63 "EventCode": "138",
64 "EventName": "TLB2_CRSTE_HPAGE_WRITES",
65 "BriefDescription": "TLB2 CRSTE One-Megabyte Page Writes",
66 "PublicDescription": "A translation entry has been written to the Level-2 TLB Combined Region Segment Table Entry arrays for a one-megabyte large page translation"
67 },
68 {
69 "EventCode": "139",
70 "EventName": "TLB2_CRSTE_WRITES",
71 "BriefDescription": "TLB2 CRSTE Writes",
72 "PublicDescription": "A translation entry has been written to the Level-2 TLB Combined Region Segment Table Entry arrays"
73 },
74 {
75 "EventCode": "140",
76 "EventName": "TX_C_TEND",
77 "BriefDescription": "Completed TEND instructions in constrained TX mode",
78 "PublicDescription": "A TEND instruction has completed in a constrained transactional-execution mode"
79 },
80 {
81 "EventCode": "141",
82 "EventName": "TX_NC_TEND",
83 "BriefDescription": "Completed TEND instructions in non-constrained TX mode",
84 "PublicDescription": "A TEND instruction has completed in a non-constrained transactional-execution mode"
85 },
86 {
87 "EventCode": "143",
88 "EventName": "L1C_TLB1_MISSES",
89 "BriefDescription": "L1C TLB1 Misses",
90 "PublicDescription": "Increments by one for any cycle where a Level-1 cache or Level-1 TLB miss is in progress."
91 },
92 {
93 "EventCode": "144",
94 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES",
95 "BriefDescription": "L1D On-Chip L3 Sourced Writes",
96 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Chip Level-3 cache without intervention"
97 },
98 {
99 "EventCode": "145",
100 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES_IV",
101 "BriefDescription": "L1D On-Chip L3 Sourced Writes with Intervention",
102 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Chip Level-3 cache with intervention"
103 },
104 {
105 "EventCode": "146",
106 "EventName": "L1D_ONNODE_L4_SOURCED_WRITES",
107 "BriefDescription": "L1D On-Node L4 Sourced Writes",
108 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Node Level-4 cache"
109 },
110 {
111 "EventCode": "147",
112 "EventName": "L1D_ONNODE_L3_SOURCED_WRITES_IV",
113 "BriefDescription": "L1D On-Node L3 Sourced Writes with Intervention",
114 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Node Level-3 cache with intervention"
115 },
116 {
117 "EventCode": "148",
118 "EventName": "L1D_ONNODE_L3_SOURCED_WRITES",
119 "BriefDescription": "L1D On-Node L3 Sourced Writes",
120 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Node Level-3 cache without intervention"
121 },
122 {
123 "EventCode": "149",
124 "EventName": "L1D_ONDRAWER_L4_SOURCED_WRITES",
125 "BriefDescription": "L1D On-Drawer L4 Sourced Writes",
126 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Drawer Level-4 cache"
127 },
128 {
129 "EventCode": "150",
130 "EventName": "L1D_ONDRAWER_L3_SOURCED_WRITES_IV",
131 "BriefDescription": "L1D On-Drawer L3 Sourced Writes with Intervention",
132 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Drawer Level-3 cache with intervention"
133 },
134 {
135 "EventCode": "151",
136 "EventName": "L1D_ONDRAWER_L3_SOURCED_WRITES",
137 "BriefDescription": "L1D On-Drawer L3 Sourced Writes",
138 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Drawer Level-3 cache without intervention"
139 },
140 {
141 "EventCode": "152",
142 "EventName": "L1D_OFFDRAWER_SCOL_L4_SOURCED_WRITES",
143 "BriefDescription": "L1D Off-Drawer Same-Column L4 Sourced Writes",
144 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-4 cache"
145 },
146 {
147 "EventCode": "153",
148 "EventName": "L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV",
149 "BriefDescription": "L1D Off-Drawer Same-Column L3 Sourced Writes with Intervention",
150 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-3 cache with intervention"
151 },
152 {
153 "EventCode": "154",
154 "EventName": "L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES",
155 "BriefDescription": "L1D Off-Drawer Same-Column L3 Sourced Writes",
156 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-3 cache without intervention"
157 },
158 {
159 "EventCode": "155",
160 "EventName": "L1D_OFFDRAWER_FCOL_L4_SOURCED_WRITES",
161 "BriefDescription": "L1D Off-Drawer Far-Column L3 Sourced Writes",
162 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-4 cache"
163 },
164 {
165 "EventCode": "156",
166 "EventName": "L1D_OFFDRAWER_FCOL_L3_SOURCED_WRITES_IV",
167 "BriefDescription": "L1D Off-Drawer Far-Column L3 Sourced Writes with Intervention",
168 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-3 cache with intervention"
169 },
170 {
171 "EventCode": "157",
172 "EventName": "L1D_OFFDRAWER_FCOL_L3_SOURCED_WRITES",
173 "BriefDescription": "L1D Off-Drawer Far-Column L3 Sourced Writes",
174 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-3 cache without intervention"
175 },
176 {
177 "EventCode": "158",
178 "EventName": "L1D_ONNODE_MEM_SOURCED_WRITES",
179 "BriefDescription": "L1D On-Node Memory Sourced Writes",
180 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Node memory"
181 },
182 {
183 "EventCode": "159",
184 "EventName": "L1D_ONDRAWER_MEM_SOURCED_WRITES",
185 "BriefDescription": "L1D On-Drawer Memory Sourced Writes",
186 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Drawer memory"
187 },
188 {
189 "EventCode": "160",
190 "EventName": "L1D_OFFDRAWER_MEM_SOURCED_WRITES",
191 "BriefDescription": "L1D Off-Drawer Memory Sourced Writes",
192 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Drawer memory"
193 },
194 {
195 "EventCode": "161",
196 "EventName": "L1D_ONCHIP_MEM_SOURCED_WRITES",
197 "BriefDescription": "L1D On-Chip Memory Sourced Writes",
198 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Chip memory"
199 },
200 {
201 "EventCode": "162",
202 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES",
203 "BriefDescription": "L1I On-Chip L3 Sourced Writes",
204 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Chip Level-3 cache without intervention"
205 },
206 {
207 "EventCode": "163",
208 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
209 "BriefDescription": "L1I On-Chip L3 Sourced Writes with Intervention",
210 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On Chip Level-3 cache with intervention"
211 },
212 {
213 "EventCode": "164",
214 "EventName": "L1I_ONNODE_L4_SOURCED_WRITES",
215 "BriefDescription": "L1I On-Chip L4 Sourced Writes",
216 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Node Level-4 cache"
217 },
218 {
219 "EventCode": "165",
220 "EventName": "L1I_ONNODE_L3_SOURCED_WRITES_IV",
221 "BriefDescription": "L1I On-Node L3 Sourced Writes with Intervention",
222 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Node Level-3 cache with intervention"
223 },
224 {
225 "EventCode": "166",
226 "EventName": "L1I_ONNODE_L3_SOURCED_WRITES",
227 "BriefDescription": "L1I On-Node L3 Sourced Writes",
228 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Node Level-3 cache without intervention"
229 },
230 {
231 "EventCode": "167",
232 "EventName": "L1I_ONDRAWER_L4_SOURCED_WRITES",
233 "BriefDescription": "L1I On-Drawer L4 Sourced Writes",
234 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Drawer Level-4 cache"
235 },
236 {
237 "EventCode": "168",
238 "EventName": "L1I_ONDRAWER_L3_SOURCED_WRITES_IV",
239 "BriefDescription": "L1I On-Drawer L3 Sourced Writes with Intervention",
240 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Drawer Level-3 cache with intervention"
241 },
242 {
243 "EventCode": "169",
244 "EventName": "L1I_ONDRAWER_L3_SOURCED_WRITES",
245 "BriefDescription": "L1I On-Drawer L3 Sourced Writes",
246 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Drawer Level-3 cache without intervention"
247 },
248 {
249 "EventCode": "170",
250 "EventName": "L1I_OFFDRAWER_SCOL_L4_SOURCED_WRITES",
251 "BriefDescription": "L1I Off-Drawer Same-Column L4 Sourced Writes",
252 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-4 cache"
253 },
254 {
255 "EventCode": "171",
256 "EventName": "L1I_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV",
257 "BriefDescription": "L1I Off-Drawer Same-Column L3 Sourced Writes with Intervention",
258 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-3 cache with intervention"
259 },
260 {
261 "EventCode": "172",
262 "EventName": "L1I_OFFDRAWER_SCOL_L3_SOURCED_WRITES",
263 "BriefDescription": "L1I Off-Drawer Same-Column L3 Sourced Writes",
264 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-3 cache without intervention"
265 },
266 {
267 "EventCode": "173",
268 "EventName": "L1I_OFFDRAWER_FCOL_L4_SOURCED_WRITES",
269 "BriefDescription": "L1I Off-Drawer Far-Column L4 Sourced Writes",
270 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-4 cache"
271 },
272 {
273 "EventCode": "174",
274 "EventName": "L1I_OFFDRAWER_FCOL_L3_SOURCED_WRITES_IV",
275 "BriefDescription": "L1I Off-Drawer Far-Column L3 Sourced Writes with Intervention",
276 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-3 cache with intervention"
277 },
278 {
279 "EventCode": "175",
280 "EventName": "L1I_OFFDRAWER_FCOL_L3_SOURCED_WRITES",
281 "BriefDescription": "L1I Off-Drawer Far-Column L3 Sourced Writes",
282 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-3 cache without intervention"
283 },
284 {
285 "EventCode": "176",
286 "EventName": "L1I_ONNODE_MEM_SOURCED_WRITES",
287 "BriefDescription": "L1I On-Node Memory Sourced Writes",
288 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Node memory"
289 },
290 {
291 "EventCode": "177",
292 "EventName": "L1I_ONDRAWER_MEM_SOURCED_WRITES",
293 "BriefDescription": "L1I On-Drawer Memory Sourced Writes",
294 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Drawer memory"
295 },
296 {
297 "EventCode": "178",
298 "EventName": "L1I_OFFDRAWER_MEM_SOURCED_WRITES",
299 "BriefDescription": "L1I Off-Drawer Memory Sourced Writes",
300 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Drawer memory"
301 },
302 {
303 "EventCode": "179",
304 "EventName": "L1I_ONCHIP_MEM_SOURCED_WRITES",
305 "BriefDescription": "L1I On-Chip Memory Sourced Writes",
306 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Chip memory"
307 },
308 {
309 "EventCode": "218",
310 "EventName": "TX_NC_TABORT",
311 "BriefDescription": "Aborted transactions in non-constrained TX mode",
312 "PublicDescription": "A transaction abort has occurred in a non-constrained transactional-execution mode"
313 },
314 {
315 "EventCode": "219",
316 "EventName": "TX_C_TABORT_NO_SPECIAL",
317 "BriefDescription": "Aborted transactions in constrained TX mode not using special completion logic",
318 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is not using any special logic to allow the transaction to complete"
319 },
320 {
321 "EventCode": "220",
322 "EventName": "TX_C_TABORT_SPECIAL",
323 "BriefDescription": "Aborted transactions in constrained TX mode using special completion logic",
324 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is using special logic to allow the transaction to complete"
325 },
326 {
327 "EventCode": "448",
328 "EventName": "MT_DIAG_CYCLES_ONE_THR_ACTIVE",
329 "BriefDescription": "Cycle count with one thread active",
330 "PublicDescription": "Cycle count with one thread active"
331 },
332 {
333 "EventCode": "449",
334 "EventName": "MT_DIAG_CYCLES_TWO_THR_ACTIVE",
335 "BriefDescription": "Cycle count with two threads active",
336 "PublicDescription": "Cycle count with two threads active"
337 },
338]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z14/basic.json b/tools/perf/pmu-events/arch/s390/cf_z14/basic.json
new file mode 100644
index 000000000000..8f653c9d899d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z14/basic.json
@@ -0,0 +1,50 @@
1[
2 {
3 "EventCode": "0",
4 "EventName": "CPU_CYCLES",
5 "BriefDescription": "CPU Cycles",
6 "PublicDescription": "Cycle Count"
7 },
8 {
9 "EventCode": "1",
10 "EventName": "INSTRUCTIONS",
11 "BriefDescription": "Instructions",
12 "PublicDescription": "Instruction Count"
13 },
14 {
15 "EventCode": "2",
16 "EventName": "L1I_DIR_WRITES",
17 "BriefDescription": "L1I Directory Writes",
18 "PublicDescription": "Level-1 I-Cache Directory Write Count"
19 },
20 {
21 "EventCode": "3",
22 "EventName": "L1I_PENALTY_CYCLES",
23 "BriefDescription": "L1I Penalty Cycles",
24 "PublicDescription": "Level-1 I-Cache Penalty Cycle Count"
25 },
26 {
27 "EventCode": "4",
28 "EventName": "L1D_DIR_WRITES",
29 "BriefDescription": "L1D Directory Writes",
30 "PublicDescription": "Level-1 D-Cache Directory Write Count"
31 },
32 {
33 "EventCode": "5",
34 "EventName": "L1D_PENALTY_CYCLES",
35 "BriefDescription": "L1D Penalty Cycles",
36 "PublicDescription": "Level-1 D-Cache Penalty Cycle Count"
37 },
38 {
39 "EventCode": "32",
40 "EventName": "PROBLEM_STATE_CPU_CYCLES",
41 "BriefDescription": "Problem-State CPU Cycles",
42 "PublicDescription": "Problem-State Cycle Count"
43 },
44 {
45 "EventCode": "33",
46 "EventName": "PROBLEM_STATE_INSTRUCTIONS",
47 "BriefDescription": "Problem-State Instructions",
48 "PublicDescription": "Problem-State Instruction Count"
49 },
50]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z14/crypto.json b/tools/perf/pmu-events/arch/s390/cf_z14/crypto.json
new file mode 100644
index 000000000000..7e5b72492141
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z14/crypto.json
@@ -0,0 +1,98 @@
1[
2 {
3 "EventCode": "64",
4 "EventName": "PRNG_FUNCTIONS",
5 "BriefDescription": "PRNG Functions",
6 "PublicDescription": "Total number of the PRNG functions issued by the CPU"
7 },
8 {
9 "EventCode": "65",
10 "EventName": "PRNG_CYCLES",
11 "BriefDescription": "PRNG Cycles",
12 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing PRNG functions issued by the CPU"
13 },
14 {
15 "EventCode": "66",
16 "EventName": "PRNG_BLOCKED_FUNCTIONS",
17 "BriefDescription": "PRNG Blocked Functions",
18 "PublicDescription": "Total number of the PRNG functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
19 },
20 {
21 "EventCode": "67",
22 "EventName": "PRNG_BLOCKED_CYCLES",
23 "BriefDescription": "PRNG Blocked Cycles",
24 "PublicDescription": "Total number of CPU cycles blocked for the PRNG functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
25 },
26 {
27 "EventCode": "68",
28 "EventName": "SHA_FUNCTIONS",
29 "BriefDescription": "SHA Functions",
30 "PublicDescription": "Total number of SHA functions issued by the CPU"
31 },
32 {
33 "EventCode": "69",
34 "EventName": "SHA_CYCLES",
35 "BriefDescription": "SHA Cycles",
36 "PublicDescription": "Total number of CPU cycles when the SHA coprocessor is busy performing the SHA functions issued by the CPU"
37 },
38 {
39 "EventCode": "70",
40 "EventName": "SHA_BLOCKED_FUNCTIONS",
41 "BriefDescription": "SHA Blocked Functions",
42 "PublicDescription": "Total number of the SHA functions that are issued by the CPU and are blocked because the SHA coprocessor is busy performing a function issued by another CPU"
43 },
44 {
45 "EventCode": "71",
46 "EventName": "SHA_BLOCKED_CYCLES",
47 "BriefDescription": "SHA Bloced Cycles",
48 "PublicDescription": "Total number of CPU cycles blocked for the SHA functions issued by the CPU because the SHA coprocessor is busy performing a function issued by another CPU"
49 },
50 {
51 "EventCode": "72",
52 "EventName": "DEA_FUNCTIONS",
53 "BriefDescription": "DEA Functions",
54 "PublicDescription": "Total number of the DEA functions issued by the CPU"
55 },
56 {
57 "EventCode": "73",
58 "EventName": "DEA_CYCLES",
59 "BriefDescription": "DEA Cycles",
60 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the DEA functions issued by the CPU"
61 },
62 {
63 "EventCode": "74",
64 "EventName": "DEA_BLOCKED_FUNCTIONS",
65 "BriefDescription": "DEA Blocked Functions",
66 "PublicDescription": "Total number of the DEA functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
67 },
68 {
69 "EventCode": "75",
70 "EventName": "DEA_BLOCKED_CYCLES",
71 "BriefDescription": "DEA Blocked Cycles",
72 "PublicDescription": "Total number of CPU cycles blocked for the DEA functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
73 },
74 {
75 "EventCode": "76",
76 "EventName": "AES_FUNCTIONS",
77 "BriefDescription": "AES Functions",
78 "PublicDescription": "Total number of AES functions issued by the CPU"
79 },
80 {
81 "EventCode": "77",
82 "EventName": "AES_CYCLES",
83 "BriefDescription": "AES Cycles",
84 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the AES functions issued by the CPU"
85 },
86 {
87 "EventCode": "78",
88 "EventName": "AES_BLOCKED_FUNCTIONS",
89 "BriefDescription": "AES Blocked Functions",
90 "PublicDescription": "Total number of AES functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
91 },
92 {
93 "EventCode": "79",
94 "EventName": "AES_BLOCKED_CYCLES",
95 "BriefDescription": "AES Blocked Cycles",
96 "PublicDescription": "Total number of CPU cycles blocked for the AES functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
97 },
98]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z14/extended.json b/tools/perf/pmu-events/arch/s390/cf_z14/extended.json
new file mode 100644
index 000000000000..aa4dfb46b65b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z14/extended.json
@@ -0,0 +1,320 @@
1[
2 {
3 "EventCode": "128",
4 "EventName": "L1D_RO_EXCL_WRITES",
5 "BriefDescription": "L1D Read-only Exclusive Writes",
6 "PublicDescription": "Counter:128 Name:L1D_RO_EXCL_WRITES A directory write to the Level-1 Data cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
7 },
8 {
9 "EventCode": "129",
10 "EventName": "DTLB2_WRITES",
11 "BriefDescription": "DTLB2 Writes",
12 "PublicDescription": "A translation has been written into The Translation Lookaside Buffer 2 (TLB2) and the request was made by the data cache"
13 },
14 {
15 "EventCode": "130",
16 "EventName": "DTLB2_MISSES",
17 "BriefDescription": "DTLB2 Misses",
18 "PublicDescription": "A TLB2 miss is in progress for a request made by the data cache. Incremented by one for every TLB2 miss in progress for the Level-1 Data cache on this cycle"
19 },
20 {
21 "EventCode": "131",
22 "EventName": "DTLB2_HPAGE_WRITES",
23 "BriefDescription": "DTLB2 One-Megabyte Page Writes",
24 "PublicDescription": "A translation entry was written into the Combined Region and Segment Table Entry array in the Level-2 TLB for a one-megabyte page or a Last Host Translation was done"
25 },
26 {
27 "EventCode": "132",
28 "EventName": "DTLB2_GPAGE_WRITES",
29 "BriefDescription": "DTLB2 Two-Gigabyte Page Writes",
30 "PublicDescription": "A translation entry for a two-gigabyte page was written into the Level-2 TLB"
31 },
32 {
33 "EventCode": "133",
34 "EventName": "L1D_L2D_SOURCED_WRITES",
35 "BriefDescription": "L1D L2D Sourced Writes",
36 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from the Level-2 Data cache"
37 },
38 {
39 "EventCode": "134",
40 "EventName": "ITLB2_WRITES",
41 "BriefDescription": "ITLB2 Writes",
42 "PublicDescription": "A translation entry has been written into the Translation Lookaside Buffer 2 (TLB2) and the request was made by the instruction cache"
43 },
44 {
45 "EventCode": "135",
46 "EventName": "ITLB2_MISSES",
47 "BriefDescription": "ITLB2 Misses",
48 "PublicDescription": "A TLB2 miss is in progress for a request made by the instruction cache. Incremented by one for every TLB2 miss in progress for the Level-1 Instruction cache in a cycle"
49 },
50 {
51 "EventCode": "136",
52 "EventName": "L1I_L2I_SOURCED_WRITES",
53 "BriefDescription": "L1I L2I Sourced Writes",
54 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from the Level-2 Instruction cache"
55 },
56 {
57 "EventCode": "137",
58 "EventName": "TLB2_PTE_WRITES",
59 "BriefDescription": "TLB2 PTE Writes",
60 "PublicDescription": "A translation entry was written into the Page Table Entry array in the Level-2 TLB"
61 },
62 {
63 "EventCode": "138",
64 "EventName": "TLB2_CRSTE_WRITES",
65 "BriefDescription": "TLB2 CRSTE Writes",
66 "PublicDescription": "Translation entries were written into the Combined Region and Segment Table Entry array and the Page Table Entry array in the Level-2 TLB"
67 },
68 {
69 "EventCode": "139",
70 "EventName": "TLB2_ENGINES_BUSY",
71 "BriefDescription": "TLB2 Engines Busy",
72 "PublicDescription": "The number of Level-2 TLB translation engines busy in a cycle"
73 },
74 {
75 "EventCode": "140",
76 "EventName": "TX_C_TEND",
77 "BriefDescription": "Completed TEND instructions in constrained TX mode",
78 "PublicDescription": "A TEND instruction has completed in a constrained transactional-execution mode"
79 },
80 {
81 "EventCode": "141",
82 "EventName": "TX_NC_TEND",
83 "BriefDescription": "Completed TEND instructions in non-constrained TX mode",
84 "PublicDescription": "A TEND instruction has completed in a non-constrained transactional-execution mode"
85 },
86 {
87 "EventCode": "143",
88 "EventName": "L1C_TLB2_MISSES",
89 "BriefDescription": "L1C TLB2 Misses",
90 "PublicDescription": "Increments by one for any cycle where a level-1 cache or level-2 TLB miss is in progress"
91 },
92 {
93 "EventCode": "144",
94 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES",
95 "BriefDescription": "L1D On-Chip L3 Sourced Writes",
96 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Chip Level-3 cache without intervention"
97 },
98 {
99 "EventCode": "145",
100 "EventName": "L1D_ONCHIP_MEMORY_SOURCED_WRITES",
101 "BriefDescription": "L1D On-Chip Memory Sourced Writes",
102 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Chip memory"
103 },
104 {
105 "EventCode": "146",
106 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES_IV",
107 "BriefDescription": "L1D On-Chip L3 Sourced Writes with Intervention",
108 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Chip Level-3 cache with intervention"
109 },
110 {
111 "EventCode": "147",
112 "EventName": "L1D_ONCLUSTER_L3_SOURCED_WRITES",
113 "BriefDescription": "L1D On-Cluster L3 Sourced Writes",
114 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Cluster Level-3 cache withountervention"
115 },
116 {
117 "EventCode": "148",
118 "EventName": "L1D_ONCLUSTER_MEMORY_SOURCED_WRITES",
119 "BriefDescription": "L1D On-Cluster Memory Sourced Writes",
120 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Cluster memory"
121 },
122 {
123 "EventCode": "149",
124 "EventName": "L1D_ONCLUSTER_L3_SOURCED_WRITES_IV",
125 "BriefDescription": "L1D On-Cluster L3 Sourced Writes with Intervention",
126 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Cluster Level-3 cache with intervention"
127 },
128 {
129 "EventCode": "150",
130 "EventName": "L1D_OFFCLUSTER_L3_SOURCED_WRITES",
131 "BriefDescription": "L1D Off-Cluster L3 Sourced Writes",
132 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Cluster Level-3 cache without intervention"
133 },
134 {
135 "EventCode": "151",
136 "EventName": "L1D_OFFCLUSTER_MEMORY_SOURCED_WRITES",
137 "BriefDescription": "L1D Off-Cluster Memory Sourced Writes",
138 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from Off-Cluster memory"
139 },
140 {
141 "EventCode": "152",
142 "EventName": "L1D_OFFCLUSTER_L3_SOURCED_WRITES_IV",
143 "BriefDescription": "L1D Off-Cluster L3 Sourced Writes with Intervention",
144 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Cluster Level-3 cache with intervention"
145 },
146 {
147 "EventCode": "153",
148 "EventName": "L1D_OFFDRAWER_L3_SOURCED_WRITES",
149 "BriefDescription": "L1D Off-Drawer L3 Sourced Writes",
150 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Level-3 cache without intervention"
151 },
152 {
153 "EventCode": "154",
154 "EventName": "L1D_OFFDRAWER_MEMORY_SOURCED_WRITES",
155 "BriefDescription": "L1D Off-Drawer Memory Sourced Writes",
156 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from Off-Drawer memory"
157 },
158 {
159 "EventCode": "155",
160 "EventName": "L1D_OFFDRAWER_L3_SOURCED_WRITES_IV",
161 "BriefDescription": "L1D Off-Drawer L3 Sourced Writes with Intervention",
162 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Level-3 cache with intervention"
163 },
164 {
165 "EventCode": "156",
166 "EventName": "L1D_ONDRAWER_L4_SOURCED_WRITES",
167 "BriefDescription": "L1D On-Drawer L4 Sourced Writes",
168 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Drawer Level-4 cache"
169 },
170 {
171 "EventCode": "157",
172 "EventName": "L1D_OFFDRAWER_L4_SOURCED_WRITES",
173 "BriefDescription": "L1D Off-Drawer L4 Sourced Writes",
174 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from Off-Drawer Level-4 cache"
175 },
176 {
177 "EventCode": "158",
178 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES_RO",
179 "BriefDescription": "L1D On-Chip L3 Sourced Writes read-only",
180 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Chip L3 but a read-only invalidate was done to remove other copies of the cache line"
181 },
182 {
183 "EventCode": "162",
184 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES",
185 "BriefDescription": "L1I On-Chip L3 Sourced Writes",
186 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache ine was sourced from an On-Chip Level-3 cache without intervention"
187 },
188 {
189 "EventCode": "163",
190 "EventName": "L1I_ONCHIP_MEMORY_SOURCED_WRITES",
191 "BriefDescription": "L1I On-Chip Memory Sourced Writes",
192 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache ine was sourced from On-Chip memory"
193 },
194 {
195 "EventCode": "164",
196 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
197 "BriefDescription": "L1I On-Chip L3 Sourced Writes with Intervention",
198 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache ine was sourced from an On-Chip Level-3 cache with intervention"
199 },
200 {
201 "EventCode": "165",
202 "EventName": "L1I_ONCLUSTER_L3_SOURCED_WRITES",
203 "BriefDescription": "L1I On-Cluster L3 Sourced Writes",
204 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Cluster Level-3 cache without intervention"
205 },
206 {
207 "EventCode": "166",
208 "EventName": "L1I_ONCLUSTER_MEMORY_SOURCED_WRITES",
209 "BriefDescription": "L1I On-Cluster Memory Sourced Writes",
210 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Cluster memory"
211 },
212 {
213 "EventCode": "167",
214 "EventName": "L1I_ONCLUSTER_L3_SOURCED_WRITES_IV",
215 "BriefDescription": "L1I On-Cluster L3 Sourced Writes with Intervention",
216 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Cluster Level-3 cache with intervention"
217 },
218 {
219 "EventCode": "168",
220 "EventName": "L1I_OFFCLUSTER_L3_SOURCED_WRITES",
221 "BriefDescription": "L1I Off-Cluster L3 Sourced Writes",
222 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Cluster Level-3 cache without intervention"
223 },
224 {
225 "EventCode": "169",
226 "EventName": "L1I_OFFCLUSTER_MEMORY_SOURCED_WRITES",
227 "BriefDescription": "L1I Off-Cluster Memory Sourced Writes",
228 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from Off-Cluster memory"
229 },
230 {
231 "EventCode": "170",
232 "EventName": "L1I_OFFCLUSTER_L3_SOURCED_WRITES_IV",
233 "BriefDescription": "L1I Off-Cluster L3 Sourced Writes with Intervention",
234 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Cluster Level-3 cache with intervention"
235 },
236 {
237 "EventCode": "171",
238 "EventName": "L1I_OFFDRAWER_L3_SOURCED_WRITES",
239 "BriefDescription": "L1I Off-Drawer L3 Sourced Writes",
240 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Level-3 cache without intervention"
241 },
242 {
243 "EventCode": "172",
244 "EventName": "L1I_OFFDRAWER_MEMORY_SOURCED_WRITES",
245 "BriefDescription": "L1I Off-Drawer Memory Sourced Writes",
246 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from Off-Drawer memory"
247 },
248 {
249 "EventCode": "173",
250 "EventName": "L1I_OFFDRAWER_L3_SOURCED_WRITES_IV",
251 "BriefDescription": "L1I Off-Drawer L3 Sourced Writes with Intervention",
252 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Level-3 cache with intervention"
253 },
254 {
255 "EventCode": "174",
256 "EventName": "L1I_ONDRAWER_L4_SOURCED_WRITES",
257 "BriefDescription": "L1I On-Drawer L4 Sourced Writes",
258 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Drawer Level-4 cache"
259 },
260 {
261 "EventCode": "175",
262 "EventName": "L1I_OFFDRAWER_L4_SOURCED_WRITES",
263 "BriefDescription": "L1I Off-Drawer L4 Sourced Writes",
264 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from Off-Drawer Level-4 cache"
265 },
266 {
267 "EventCode": "224",
268 "EventName": "BCD_DFP_EXECUTION_SLOTS",
269 "BriefDescription": "BCD DFP Execution Slots",
270 "PublicDescription": "Count of floating point execution slots used for finished Binary Coded Decimal to Decimal Floating Point conversions. Instructions: CDZT, CXZT, CZDT, CZXT"
271 },
272 {
273 "EventCode": "225",
274 "EventName": "VX_BCD_EXECUTION_SLOTS",
275 "BriefDescription": "VX BCD Execution Slots",
276 "PublicDescription": "Count of floating point execution slots used for finished vector arithmetic Binary Coded Decimal instructions. Instructions: VAP, VSP, VMPVMSP, VDP, VSDP, VRP, VLIP, VSRP, VPSOPVCP, VTP, VPKZ, VUPKZ, VCVB, VCVBG, VCVDVCVDG"
277 },
278 {
279 "EventCode": "226",
280 "EventName": "DECIMAL_INSTRUCTIONS",
281 "BriefDescription": "Decimal Instructions",
282 "PublicDescription": "Decimal instructions dispatched. Instructions: CVB, CVD, AP, CP, DP, ED, EDMK, MP, SRP, SP, ZAP"
283 },
284 {
285 "EventCode": "232",
286 "EventName": "LAST_HOST_TRANSLATIONS",
287 "BriefDescription": "Last host translation done",
288 "PublicDescription": "Last Host Translation done"
289 },
290 {
291 "EventCode": "243",
292 "EventName": "TX_NC_TABORT",
293 "BriefDescription": "Aborted transactions in non-constrained TX mode",
294 "PublicDescription": "A transaction abort has occurred in a non-constrained transactional-execution mode"
295 },
296 {
297 "EventCode": "244",
298 "EventName": "TX_C_TABORT_NO_SPECIAL",
299 "BriefDescription": "Aborted transactions in constrained TX mode not using special completion logic",
300 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is not using any special logic to allow the transaction to complete"
301 },
302 {
303 "EventCode": "245",
304 "EventName": "TX_C_TABORT_SPECIAL",
305 "BriefDescription": "Aborted transactions in constrained TX mode using special completion logic",
306 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is using special logic to allow the transaction to complete"
307 },
308 {
309 "EventCode": "448",
310 "EventName": "MT_DIAG_CYCLES_ONE_THR_ACTIVE",
311 "BriefDescription": "Cycle count with one thread active",
312 "PublicDescription": "Cycle count with one thread active"
313 },
314 {
315 "EventCode": "449",
316 "EventName": "MT_DIAG_CYCLES_TWO_THR_ACTIVE",
317 "BriefDescription": "Cycle count with two threads active",
318 "PublicDescription": "Cycle count with two threads active"
319 },
320]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z196/basic.json b/tools/perf/pmu-events/arch/s390/cf_z196/basic.json
new file mode 100644
index 000000000000..8bf16759ca53
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z196/basic.json
@@ -0,0 +1,74 @@
1[
2 {
3 "EventCode": "0",
4 "EventName": "CPU_CYCLES",
5 "BriefDescription": "CPU Cycles",
6 "PublicDescription": "Cycle Count"
7 },
8 {
9 "EventCode": "1",
10 "EventName": "INSTRUCTIONS",
11 "BriefDescription": "Instructions",
12 "PublicDescription": "Instruction Count"
13 },
14 {
15 "EventCode": "2",
16 "EventName": "L1I_DIR_WRITES",
17 "BriefDescription": "L1I Directory Writes",
18 "PublicDescription": "Level-1 I-Cache Directory Write Count"
19 },
20 {
21 "EventCode": "3",
22 "EventName": "L1I_PENALTY_CYCLES",
23 "BriefDescription": "L1I Penalty Cycles",
24 "PublicDescription": "Level-1 I-Cache Penalty Cycle Count"
25 },
26 {
27 "EventCode": "4",
28 "EventName": "L1D_DIR_WRITES",
29 "BriefDescription": "L1D Directory Writes",
30 "PublicDescription": "Level-1 D-Cache Directory Write Count"
31 },
32 {
33 "EventCode": "5",
34 "EventName": "L1D_PENALTY_CYCLES",
35 "BriefDescription": "L1D Penalty Cycles",
36 "PublicDescription": "Level-1 D-Cache Penalty Cycle Count"
37 },
38 {
39 "EventCode": "32",
40 "EventName": "PROBLEM_STATE_CPU_CYCLES",
41 "BriefDescription": "Problem-State CPU Cycles",
42 "PublicDescription": "Problem-State Cycle Count"
43 },
44 {
45 "EventCode": "33",
46 "EventName": "PROBLEM_STATE_INSTRUCTIONS",
47 "BriefDescription": "Problem-State Instructions",
48 "PublicDescription": "Problem-State Instruction Count"
49 },
50 {
51 "EventCode": "34",
52 "EventName": "PROBLEM_STATE_L1I_DIR_WRITES",
53 "BriefDescription": "Problem-State L1I Directory Writes",
54 "PublicDescription": "Problem-State Level-1 I-Cache Directory Write Count"
55 },
56 {
57 "EventCode": "35",
58 "EventName": "PROBLEM_STATE_L1I_PENALTY_CYCLES",
59 "BriefDescription": "Problem-State L1I Penalty Cycles",
60 "PublicDescription": "Problem-State Level-1 I-Cache Penalty Cycle Count"
61 },
62 {
63 "EventCode": "36",
64 "EventName": "PROBLEM_STATE_L1D_DIR_WRITES",
65 "BriefDescription": "Problem-State L1D Directory Writes",
66 "PublicDescription": "Problem-State Level-1 D-Cache Directory Write Count"
67 },
68 {
69 "EventCode": "37",
70 "EventName": "PROBLEM_STATE_L1D_PENALTY_CYCLES",
71 "BriefDescription": "Problem-State L1D Penalty Cycles",
72 "PublicDescription": "Problem-State Level-1 D-Cache Penalty Cycle Count"
73 },
74]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z196/crypto.json b/tools/perf/pmu-events/arch/s390/cf_z196/crypto.json
new file mode 100644
index 000000000000..7e5b72492141
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z196/crypto.json
@@ -0,0 +1,98 @@
1[
2 {
3 "EventCode": "64",
4 "EventName": "PRNG_FUNCTIONS",
5 "BriefDescription": "PRNG Functions",
6 "PublicDescription": "Total number of the PRNG functions issued by the CPU"
7 },
8 {
9 "EventCode": "65",
10 "EventName": "PRNG_CYCLES",
11 "BriefDescription": "PRNG Cycles",
12 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing PRNG functions issued by the CPU"
13 },
14 {
15 "EventCode": "66",
16 "EventName": "PRNG_BLOCKED_FUNCTIONS",
17 "BriefDescription": "PRNG Blocked Functions",
18 "PublicDescription": "Total number of the PRNG functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
19 },
20 {
21 "EventCode": "67",
22 "EventName": "PRNG_BLOCKED_CYCLES",
23 "BriefDescription": "PRNG Blocked Cycles",
24 "PublicDescription": "Total number of CPU cycles blocked for the PRNG functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
25 },
26 {
27 "EventCode": "68",
28 "EventName": "SHA_FUNCTIONS",
29 "BriefDescription": "SHA Functions",
30 "PublicDescription": "Total number of SHA functions issued by the CPU"
31 },
32 {
33 "EventCode": "69",
34 "EventName": "SHA_CYCLES",
35 "BriefDescription": "SHA Cycles",
36 "PublicDescription": "Total number of CPU cycles when the SHA coprocessor is busy performing the SHA functions issued by the CPU"
37 },
38 {
39 "EventCode": "70",
40 "EventName": "SHA_BLOCKED_FUNCTIONS",
41 "BriefDescription": "SHA Blocked Functions",
42 "PublicDescription": "Total number of the SHA functions that are issued by the CPU and are blocked because the SHA coprocessor is busy performing a function issued by another CPU"
43 },
44 {
45 "EventCode": "71",
46 "EventName": "SHA_BLOCKED_CYCLES",
47 "BriefDescription": "SHA Bloced Cycles",
48 "PublicDescription": "Total number of CPU cycles blocked for the SHA functions issued by the CPU because the SHA coprocessor is busy performing a function issued by another CPU"
49 },
50 {
51 "EventCode": "72",
52 "EventName": "DEA_FUNCTIONS",
53 "BriefDescription": "DEA Functions",
54 "PublicDescription": "Total number of the DEA functions issued by the CPU"
55 },
56 {
57 "EventCode": "73",
58 "EventName": "DEA_CYCLES",
59 "BriefDescription": "DEA Cycles",
60 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the DEA functions issued by the CPU"
61 },
62 {
63 "EventCode": "74",
64 "EventName": "DEA_BLOCKED_FUNCTIONS",
65 "BriefDescription": "DEA Blocked Functions",
66 "PublicDescription": "Total number of the DEA functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
67 },
68 {
69 "EventCode": "75",
70 "EventName": "DEA_BLOCKED_CYCLES",
71 "BriefDescription": "DEA Blocked Cycles",
72 "PublicDescription": "Total number of CPU cycles blocked for the DEA functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
73 },
74 {
75 "EventCode": "76",
76 "EventName": "AES_FUNCTIONS",
77 "BriefDescription": "AES Functions",
78 "PublicDescription": "Total number of AES functions issued by the CPU"
79 },
80 {
81 "EventCode": "77",
82 "EventName": "AES_CYCLES",
83 "BriefDescription": "AES Cycles",
84 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the AES functions issued by the CPU"
85 },
86 {
87 "EventCode": "78",
88 "EventName": "AES_BLOCKED_FUNCTIONS",
89 "BriefDescription": "AES Blocked Functions",
90 "PublicDescription": "Total number of AES functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
91 },
92 {
93 "EventCode": "79",
94 "EventName": "AES_BLOCKED_CYCLES",
95 "BriefDescription": "AES Blocked Cycles",
96 "PublicDescription": "Total number of CPU cycles blocked for the AES functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
97 },
98]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z196/extended.json b/tools/perf/pmu-events/arch/s390/cf_z196/extended.json
new file mode 100644
index 000000000000..b6d7fec7c2e7
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z196/extended.json
@@ -0,0 +1,146 @@
1[
2 {
3 "EventCode": "128",
4 "EventName": "L1D_L2_SOURCED_WRITES",
5 "BriefDescription": "L1D L2 Sourced Writes",
6 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from the Level-2 cache"
7 },
8 {
9 "EventCode": "129",
10 "EventName": "L1I_L2_SOURCED_WRITES",
11 "BriefDescription": "L1I L2 Sourced Writes",
12 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from the Level-2 cache"
13 },
14 {
15 "EventCode": "130",
16 "EventName": "DTLB1_MISSES",
17 "BriefDescription": "DTLB1 Misses",
18 "PublicDescription": "Level-1 Data TLB miss in progress. Incremented by one for every cycle a DTLB1 miss is in progress."
19 },
20 {
21 "EventCode": "131",
22 "EventName": "ITLB1_MISSES",
23 "BriefDescription": "ITLB1 Misses",
24 "PublicDescription": "Level-1 Instruction TLB miss in progress. Incremented by one for every cycle a ITLB1 miss is in progress."
25 },
26 {
27 "EventCode": "133",
28 "EventName": "L2C_STORES_SENT",
29 "BriefDescription": "L2C Stores Sent",
30 "PublicDescription": "Incremented by one for every store sent to Level-2 cache"
31 },
32 {
33 "EventCode": "134",
34 "EventName": "L1D_OFFBOOK_L3_SOURCED_WRITES",
35 "BriefDescription": "L1D Off-Book L3 Sourced Writes",
36 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from an Off Book Level-3 cache"
37 },
38 {
39 "EventCode": "135",
40 "EventName": "L1D_ONBOOK_L4_SOURCED_WRITES",
41 "BriefDescription": "L1D On-Book L4 Sourced Writes",
42 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from an On Book Level-4 cache"
43 },
44 {
45 "EventCode": "136",
46 "EventName": "L1I_ONBOOK_L4_SOURCED_WRITES",
47 "BriefDescription": "L1I On-Book L4 Sourced Writes",
48 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from an On Book Level-4 cache"
49 },
50 {
51 "EventCode": "137",
52 "EventName": "L1D_RO_EXCL_WRITES",
53 "BriefDescription": "L1D Read-only Exclusive Writes",
54 "PublicDescription": "A directory write to the Level-1 D-Cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
55 },
56 {
57 "EventCode": "138",
58 "EventName": "L1D_OFFBOOK_L4_SOURCED_WRITES",
59 "BriefDescription": "L1D Off-Book L4 Sourced Writes",
60 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from an Off Book Level-4 cache"
61 },
62 {
63 "EventCode": "139",
64 "EventName": "L1I_OFFBOOK_L4_SOURCED_WRITES",
65 "BriefDescription": "L1I Off-Book L4 Sourced Writes",
66 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from an Off Book Level-4 cache"
67 },
68 {
69 "EventCode": "140",
70 "EventName": "DTLB1_HPAGE_WRITES",
71 "BriefDescription": "DTLB1 One-Megabyte Page Writes",
72 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a one-megabyte page"
73 },
74 {
75 "EventCode": "141",
76 "EventName": "L1D_LMEM_SOURCED_WRITES",
77 "BriefDescription": "L1D Local Memory Sourced Writes",
78 "PublicDescription": "A directory write to the Level-1 D-Cache where the installed cache line was sourced from memory that is attached to the same book as the Data cache (Local Memory)"
79 },
80 {
81 "EventCode": "142",
82 "EventName": "L1I_LMEM_SOURCED_WRITES",
83 "BriefDescription": "L1I Local Memory Sourced Writes",
84 "PublicDescription": "A directory write to the Level-1 I-Cache where the installed cache line was sourced from memory that is attached to the same book as the Instruction cache (Local Memory)"
85 },
86 {
87 "EventCode": "143",
88 "EventName": "L1I_OFFBOOK_L3_SOURCED_WRITES",
89 "BriefDescription": "L1I Off-Book L3 Sourced Writes",
90 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from an Off Book Level-3 cache"
91 },
92 {
93 "EventCode": "144",
94 "EventName": "DTLB1_WRITES",
95 "BriefDescription": "DTLB1 Writes",
96 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer"
97 },
98 {
99 "EventCode": "145",
100 "EventName": "ITLB1_WRITES",
101 "BriefDescription": "ITLB1 Writes",
102 "PublicDescription": "A translation entry has been written to the Level-1 Instruction Translation Lookaside Buffer"
103 },
104 {
105 "EventCode": "146",
106 "EventName": "TLB2_PTE_WRITES",
107 "BriefDescription": "TLB2 PTE Writes",
108 "PublicDescription": "A translation entry has been written to the Level-2 TLB Page Table Entry arrays"
109 },
110 {
111 "EventCode": "147",
112 "EventName": "TLB2_CRSTE_HPAGE_WRITES",
113 "BriefDescription": "TLB2 CRSTE One-Megabyte Page Writes",
114 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays for a one-megabyte large page translation"
115 },
116 {
117 "EventCode": "148",
118 "EventName": "TLB2_CRSTE_WRITES",
119 "BriefDescription": "TLB2 CRSTE Writes",
120 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays"
121 },
122 {
123 "EventCode": "150",
124 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES",
125 "BriefDescription": "L1D On-Chip L3 Sourced Writes",
126 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from an On Chip Level-3 cache"
127 },
128 {
129 "EventCode": "152",
130 "EventName": "L1D_OFFCHIP_L3_SOURCED_WRITES",
131 "BriefDescription": "L1D Off-Chip L3 Sourced Writes",
132 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache"
133 },
134 {
135 "EventCode": "153",
136 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES",
137 "BriefDescription": "L1I On-Chip L3 Sourced Writes",
138 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from an On Chip Level-3 cache"
139 },
140 {
141 "EventCode": "155",
142 "EventName": "L1I_OFFCHIP_L3_SOURCED_WRITES",
143 "BriefDescription": "L1I Off-Chip L3 Sourced Writes",
144 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache"
145 },
146]
diff --git a/tools/perf/pmu-events/arch/s390/cf_zec12/basic.json b/tools/perf/pmu-events/arch/s390/cf_zec12/basic.json
new file mode 100644
index 000000000000..8bf16759ca53
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_zec12/basic.json
@@ -0,0 +1,74 @@
1[
2 {
3 "EventCode": "0",
4 "EventName": "CPU_CYCLES",
5 "BriefDescription": "CPU Cycles",
6 "PublicDescription": "Cycle Count"
7 },
8 {
9 "EventCode": "1",
10 "EventName": "INSTRUCTIONS",
11 "BriefDescription": "Instructions",
12 "PublicDescription": "Instruction Count"
13 },
14 {
15 "EventCode": "2",
16 "EventName": "L1I_DIR_WRITES",
17 "BriefDescription": "L1I Directory Writes",
18 "PublicDescription": "Level-1 I-Cache Directory Write Count"
19 },
20 {
21 "EventCode": "3",
22 "EventName": "L1I_PENALTY_CYCLES",
23 "BriefDescription": "L1I Penalty Cycles",
24 "PublicDescription": "Level-1 I-Cache Penalty Cycle Count"
25 },
26 {
27 "EventCode": "4",
28 "EventName": "L1D_DIR_WRITES",
29 "BriefDescription": "L1D Directory Writes",
30 "PublicDescription": "Level-1 D-Cache Directory Write Count"
31 },
32 {
33 "EventCode": "5",
34 "EventName": "L1D_PENALTY_CYCLES",
35 "BriefDescription": "L1D Penalty Cycles",
36 "PublicDescription": "Level-1 D-Cache Penalty Cycle Count"
37 },
38 {
39 "EventCode": "32",
40 "EventName": "PROBLEM_STATE_CPU_CYCLES",
41 "BriefDescription": "Problem-State CPU Cycles",
42 "PublicDescription": "Problem-State Cycle Count"
43 },
44 {
45 "EventCode": "33",
46 "EventName": "PROBLEM_STATE_INSTRUCTIONS",
47 "BriefDescription": "Problem-State Instructions",
48 "PublicDescription": "Problem-State Instruction Count"
49 },
50 {
51 "EventCode": "34",
52 "EventName": "PROBLEM_STATE_L1I_DIR_WRITES",
53 "BriefDescription": "Problem-State L1I Directory Writes",
54 "PublicDescription": "Problem-State Level-1 I-Cache Directory Write Count"
55 },
56 {
57 "EventCode": "35",
58 "EventName": "PROBLEM_STATE_L1I_PENALTY_CYCLES",
59 "BriefDescription": "Problem-State L1I Penalty Cycles",
60 "PublicDescription": "Problem-State Level-1 I-Cache Penalty Cycle Count"
61 },
62 {
63 "EventCode": "36",
64 "EventName": "PROBLEM_STATE_L1D_DIR_WRITES",
65 "BriefDescription": "Problem-State L1D Directory Writes",
66 "PublicDescription": "Problem-State Level-1 D-Cache Directory Write Count"
67 },
68 {
69 "EventCode": "37",
70 "EventName": "PROBLEM_STATE_L1D_PENALTY_CYCLES",
71 "BriefDescription": "Problem-State L1D Penalty Cycles",
72 "PublicDescription": "Problem-State Level-1 D-Cache Penalty Cycle Count"
73 },
74]
diff --git a/tools/perf/pmu-events/arch/s390/cf_zec12/crypto.json b/tools/perf/pmu-events/arch/s390/cf_zec12/crypto.json
new file mode 100644
index 000000000000..7e5b72492141
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_zec12/crypto.json
@@ -0,0 +1,98 @@
1[
2 {
3 "EventCode": "64",
4 "EventName": "PRNG_FUNCTIONS",
5 "BriefDescription": "PRNG Functions",
6 "PublicDescription": "Total number of the PRNG functions issued by the CPU"
7 },
8 {
9 "EventCode": "65",
10 "EventName": "PRNG_CYCLES",
11 "BriefDescription": "PRNG Cycles",
12 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing PRNG functions issued by the CPU"
13 },
14 {
15 "EventCode": "66",
16 "EventName": "PRNG_BLOCKED_FUNCTIONS",
17 "BriefDescription": "PRNG Blocked Functions",
18 "PublicDescription": "Total number of the PRNG functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
19 },
20 {
21 "EventCode": "67",
22 "EventName": "PRNG_BLOCKED_CYCLES",
23 "BriefDescription": "PRNG Blocked Cycles",
24 "PublicDescription": "Total number of CPU cycles blocked for the PRNG functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
25 },
26 {
27 "EventCode": "68",
28 "EventName": "SHA_FUNCTIONS",
29 "BriefDescription": "SHA Functions",
30 "PublicDescription": "Total number of SHA functions issued by the CPU"
31 },
32 {
33 "EventCode": "69",
34 "EventName": "SHA_CYCLES",
35 "BriefDescription": "SHA Cycles",
36 "PublicDescription": "Total number of CPU cycles when the SHA coprocessor is busy performing the SHA functions issued by the CPU"
37 },
38 {
39 "EventCode": "70",
40 "EventName": "SHA_BLOCKED_FUNCTIONS",
41 "BriefDescription": "SHA Blocked Functions",
42 "PublicDescription": "Total number of the SHA functions that are issued by the CPU and are blocked because the SHA coprocessor is busy performing a function issued by another CPU"
43 },
44 {
45 "EventCode": "71",
46 "EventName": "SHA_BLOCKED_CYCLES",
47 "BriefDescription": "SHA Bloced Cycles",
48 "PublicDescription": "Total number of CPU cycles blocked for the SHA functions issued by the CPU because the SHA coprocessor is busy performing a function issued by another CPU"
49 },
50 {
51 "EventCode": "72",
52 "EventName": "DEA_FUNCTIONS",
53 "BriefDescription": "DEA Functions",
54 "PublicDescription": "Total number of the DEA functions issued by the CPU"
55 },
56 {
57 "EventCode": "73",
58 "EventName": "DEA_CYCLES",
59 "BriefDescription": "DEA Cycles",
60 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the DEA functions issued by the CPU"
61 },
62 {
63 "EventCode": "74",
64 "EventName": "DEA_BLOCKED_FUNCTIONS",
65 "BriefDescription": "DEA Blocked Functions",
66 "PublicDescription": "Total number of the DEA functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
67 },
68 {
69 "EventCode": "75",
70 "EventName": "DEA_BLOCKED_CYCLES",
71 "BriefDescription": "DEA Blocked Cycles",
72 "PublicDescription": "Total number of CPU cycles blocked for the DEA functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
73 },
74 {
75 "EventCode": "76",
76 "EventName": "AES_FUNCTIONS",
77 "BriefDescription": "AES Functions",
78 "PublicDescription": "Total number of AES functions issued by the CPU"
79 },
80 {
81 "EventCode": "77",
82 "EventName": "AES_CYCLES",
83 "BriefDescription": "AES Cycles",
84 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the AES functions issued by the CPU"
85 },
86 {
87 "EventCode": "78",
88 "EventName": "AES_BLOCKED_FUNCTIONS",
89 "BriefDescription": "AES Blocked Functions",
90 "PublicDescription": "Total number of AES functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
91 },
92 {
93 "EventCode": "79",
94 "EventName": "AES_BLOCKED_CYCLES",
95 "BriefDescription": "AES Blocked Cycles",
96 "PublicDescription": "Total number of CPU cycles blocked for the AES functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
97 },
98]
diff --git a/tools/perf/pmu-events/arch/s390/cf_zec12/extended.json b/tools/perf/pmu-events/arch/s390/cf_zec12/extended.json
new file mode 100644
index 000000000000..8682126aabb2
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_zec12/extended.json
@@ -0,0 +1,212 @@
1[
2 {
3 "EventCode": "128",
4 "EventName": "DTLB1_MISSES",
5 "BriefDescription": "DTLB1 Misses",
6 "PublicDescription": "Level-1 Data TLB miss in progress. Incremented by one for every cycle a DTLB1 miss is in progress."
7 },
8 {
9 "EventCode": "129",
10 "EventName": "ITLB1_MISSES",
11 "BriefDescription": "ITLB1 Misses",
12 "PublicDescription": "Level-1 Instruction TLB miss in progress. Incremented by one for every cycle a ITLB1 miss is in progress."
13 },
14 {
15 "EventCode": "130",
16 "EventName": "L1D_L2I_SOURCED_WRITES",
17 "BriefDescription": "L1D L2I Sourced Writes",
18 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from the Level-2 Instruction cache"
19 },
20 {
21 "EventCode": "131",
22 "EventName": "L1I_L2I_SOURCED_WRITES",
23 "BriefDescription": "L1I L2I Sourced Writes",
24 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from the Level-2 Instruction cache"
25 },
26 {
27 "EventCode": "132",
28 "EventName": "L1D_L2D_SOURCED_WRITES",
29 "BriefDescription": "L1D L2D Sourced Writes",
30 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from the Level-2 Data cache"
31 },
32 {
33 "EventCode": "133",
34 "EventName": "DTLB1_WRITES",
35 "BriefDescription": "DTLB1 Writes",
36 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer"
37 },
38 {
39 "EventCode": "135",
40 "EventName": "L1D_LMEM_SOURCED_WRITES",
41 "BriefDescription": "L1D Local Memory Sourced Writes",
42 "PublicDescription": "A directory write to the Level-1 Data cache where the installed cache line was sourced from memory that is attached to the same book as the Data cache (Local Memory)"
43 },
44 {
45 "EventCode": "137",
46 "EventName": "L1I_LMEM_SOURCED_WRITES",
47 "BriefDescription": "L1I Local Memory Sourced Writes",
48 "PublicDescription": "A directory write to the Level-1 Instruction cache where the installed cache line was sourced from memory that is attached to the same book as the Instruction cache (Local Memory)"
49 },
50 {
51 "EventCode": "138",
52 "EventName": "L1D_RO_EXCL_WRITES",
53 "BriefDescription": "L1D Read-only Exclusive Writes",
54 "PublicDescription": "A directory write to the Level-1 D-Cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
55 },
56 {
57 "EventCode": "139",
58 "EventName": "DTLB1_HPAGE_WRITES",
59 "BriefDescription": "DTLB1 One-Megabyte Page Writes",
60 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a one-megabyte page"
61 },
62 {
63 "EventCode": "140",
64 "EventName": "ITLB1_WRITES",
65 "BriefDescription": "ITLB1 Writes",
66 "PublicDescription": "A translation entry has been written to the Level-1 Instruction Translation Lookaside Buffer"
67 },
68 {
69 "EventCode": "141",
70 "EventName": "TLB2_PTE_WRITES",
71 "BriefDescription": "TLB2 PTE Writes",
72 "PublicDescription": "A translation entry has been written to the Level-2 TLB Page Table Entry arrays"
73 },
74 {
75 "EventCode": "142",
76 "EventName": "TLB2_CRSTE_HPAGE_WRITES",
77 "BriefDescription": "TLB2 CRSTE One-Megabyte Page Writes",
78 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays for a one-megabyte large page translation"
79 },
80 {
81 "EventCode": "143",
82 "EventName": "TLB2_CRSTE_WRITES",
83 "BriefDescription": "TLB2 CRSTE Writes",
84 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays"
85 },
86 {
87 "EventCode": "144",
88 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES",
89 "BriefDescription": "L1D On-Chip L3 Sourced Writes",
90 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On Chip Level-3 cache without intervention"
91 },
92 {
93 "EventCode": "145",
94 "EventName": "L1D_OFFCHIP_L3_SOURCED_WRITES",
95 "BriefDescription": "L1D Off-Chip L3 Sourced Writes",
96 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache without intervention"
97 },
98 {
99 "EventCode": "146",
100 "EventName": "L1D_OFFBOOK_L3_SOURCED_WRITES",
101 "BriefDescription": "L1D Off-Book L3 Sourced Writes",
102 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off Book Level-3 cache without intervention"
103 },
104 {
105 "EventCode": "147",
106 "EventName": "L1D_ONBOOK_L4_SOURCED_WRITES",
107 "BriefDescription": "L1D On-Book L4 Sourced Writes",
108 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On Book Level-4 cache"
109 },
110 {
111 "EventCode": "148",
112 "EventName": "L1D_OFFBOOK_L4_SOURCED_WRITES",
113 "BriefDescription": "L1D Off-Book L4 Sourced Writes",
114 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off Book Level-4 cache"
115 },
116 {
117 "EventCode": "149",
118 "EventName": "TX_NC_TEND",
119 "BriefDescription": "Completed TEND instructions in non-constrained TX mode",
120 "PublicDescription": "A TEND instruction has completed in a nonconstrained transactional-execution mode"
121 },
122 {
123 "EventCode": "150",
124 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES_IV",
125 "BriefDescription": "L1D On-Chip L3 Sourced Writes with Intervention",
126 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from a On Chip Level-3 cache with intervention"
127 },
128 {
129 "EventCode": "151",
130 "EventName": "L1D_OFFCHIP_L3_SOURCED_WRITES_IV",
131 "BriefDescription": "L1D Off-Chip L3 Sourced Writes with Intervention",
132 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache with intervention"
133 },
134 {
135 "EventCode": "152",
136 "EventName": "L1D_OFFBOOK_L3_SOURCED_WRITES_IV",
137 "BriefDescription": "L1D Off-Book L3 Sourced Writes with Intervention",
138 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off Book Level-3 cache with intervention"
139 },
140 {
141 "EventCode": "153",
142 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES",
143 "BriefDescription": "L1I On-Chip L3 Sourced Writes",
144 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On Chip Level-3 cache without intervention"
145 },
146 {
147 "EventCode": "154",
148 "EventName": "L1I_OFFCHIP_L3_SOURCED_WRITES",
149 "BriefDescription": "L1I Off-Chip L3 Sourced Writes",
150 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache without intervention"
151 },
152 {
153 "EventCode": "155",
154 "EventName": "L1I_OFFBOOK_L3_SOURCED_WRITES",
155 "BriefDescription": "L1I Off-Book L3 Sourced Writes",
156 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off Book Level-3 cache without intervention"
157 },
158 {
159 "EventCode": "156",
160 "EventName": "L1I_ONBOOK_L4_SOURCED_WRITES",
161 "BriefDescription": "L1I On-Book L4 Sourced Writes",
162 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On Book Level-4 cache"
163 },
164 {
165 "EventCode": "157",
166 "EventName": "L1I_OFFBOOK_L4_SOURCED_WRITES",
167 "BriefDescription": "L1I Off-Book L4 Sourced Writes",
168 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off Book Level-4 cache"
169 },
170 {
171 "EventCode": "158",
172 "EventName": "TX_C_TEND",
173 "BriefDescription": "Completed TEND instructions in constrained TX mode",
174 "PublicDescription": "A TEND instruction has completed in a constrained transactional-execution mode"
175 },
176 {
177 "EventCode": "159",
178 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
179 "BriefDescription": "L1I On-Chip L3 Sourced Writes with Intervention",
180 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On Chip Level-3 cache with intervention"
181 },
182 {
183 "EventCode": "160",
184 "EventName": "L1I_OFFCHIP_L3_SOURCED_WRITES_IV",
185 "BriefDescription": "L1I Off-Chip L3 Sourced Writes with Intervention",
186 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache with intervention"
187 },
188 {
189 "EventCode": "161",
190 "EventName": "L1I_OFFBOOK_L3_SOURCED_WRITES_IV",
191 "BriefDescription": "L1I Off-Book L3 Sourced Writes with Intervention",
192 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off Book Level-3 cache with intervention"
193 },
194 {
195 "EventCode": "177",
196 "EventName": "TX_NC_TABORT",
197 "BriefDescription": "Aborted transactions in non-constrained TX mode",
198 "PublicDescription": "A transaction abort has occurred in a nonconstrained transactional-execution mode"
199 },
200 {
201 "EventCode": "178",
202 "EventName": "TX_C_TABORT_NO_SPECIAL",
203 "BriefDescription": "Aborted transactions in constrained TX mode not using special completion logic",
204 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is not using any special logic to allow the transaction to complete"
205 },
206 {
207 "EventCode": "179",
208 "EventName": "TX_C_TABORT_SPECIAL",
209 "BriefDescription": "Aborted transactions in constrained TX mode using special completion logic",
210 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is using special logic to allow the transaction to complete"
211 },
212]
diff --git a/tools/perf/pmu-events/arch/s390/mapfile.csv b/tools/perf/pmu-events/arch/s390/mapfile.csv
new file mode 100644
index 000000000000..ca7682748a4b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/mapfile.csv
@@ -0,0 +1,6 @@
1Family-model,Version,Filename,EventType
2209[78],1,cf_z10,core
3281[78],1,cf_z196,core
4282[78],1,cf_zec12,core
5296[45],1,cf_z13,core
63906,3,cf_z14,core
diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
index b578aa26e375..db3a594ee1e4 100644
--- a/tools/perf/pmu-events/jevents.c
+++ b/tools/perf/pmu-events/jevents.c
@@ -39,11 +39,13 @@
39#include <unistd.h> 39#include <unistd.h>
40#include <stdarg.h> 40#include <stdarg.h>
41#include <libgen.h> 41#include <libgen.h>
42#include <limits.h>
42#include <dirent.h> 43#include <dirent.h>
43#include <sys/time.h> /* getrlimit */ 44#include <sys/time.h> /* getrlimit */
44#include <sys/resource.h> /* getrlimit */ 45#include <sys/resource.h> /* getrlimit */
45#include <ftw.h> 46#include <ftw.h>
46#include <sys/stat.h> 47#include <sys/stat.h>
48#include <linux/list.h>
47#include "jsmn.h" 49#include "jsmn.h"
48#include "json.h" 50#include "json.h"
49#include "jevents.h" 51#include "jevents.h"
@@ -249,31 +251,25 @@ static const char *field_to_perf(struct map *table, char *map, jsmntok_t *val)
249 jsmntok_t *loc = (t); \ 251 jsmntok_t *loc = (t); \
250 if (!(t)->start && (t) > tokens) \ 252 if (!(t)->start && (t) > tokens) \
251 loc = (t) - 1; \ 253 loc = (t) - 1; \
252 pr_err("%s:%d: " m ", got %s\n", fn, \ 254 pr_err("%s:%d: " m ", got %s\n", fn, \
253 json_line(map, loc), \ 255 json_line(map, loc), \
254 json_name(t)); \ 256 json_name(t)); \
257 err = -EIO; \
255 goto out_free; \ 258 goto out_free; \
256} } while (0) 259} } while (0)
257 260
258#define TOPIC_DEPTH 256 261static char *topic;
259static char *topic_array[TOPIC_DEPTH];
260static int topic_level;
261 262
262static char *get_topic(void) 263static char *get_topic(void)
263{ 264{
264 char *tp_old, *tp = NULL; 265 char *tp;
265 int i; 266 int i;
266 267
267 for (i = 0; i < topic_level + 1; i++) { 268 /* tp is free'd in process_one_file() */
268 int n; 269 i = asprintf(&tp, "%s", topic);
269 270 if (i < 0) {
270 tp_old = tp; 271 pr_info("%s: asprintf() error %s\n", prog);
271 n = asprintf(&tp, "%s%s", tp ?: "", topic_array[i]); 272 return NULL;
272 if (n < 0) {
273 pr_info("%s: asprintf() error %s\n", prog);
274 return NULL;
275 }
276 free(tp_old);
277 } 273 }
278 274
279 for (i = 0; i < (int) strlen(tp); i++) { 275 for (i = 0; i < (int) strlen(tp); i++) {
@@ -290,25 +286,15 @@ static char *get_topic(void)
290 return tp; 286 return tp;
291} 287}
292 288
293static int add_topic(int level, char *bname) 289static int add_topic(char *bname)
294{ 290{
295 char *topic; 291 free(topic);
296
297 level -= 2;
298
299 if (level >= TOPIC_DEPTH)
300 return -EINVAL;
301
302 topic = strdup(bname); 292 topic = strdup(bname);
303 if (!topic) { 293 if (!topic) {
304 pr_info("%s: strdup() error %s for file %s\n", prog, 294 pr_info("%s: strdup() error %s for file %s\n", prog,
305 strerror(errno), bname); 295 strerror(errno), bname);
306 return -ENOMEM; 296 return -ENOMEM;
307 } 297 }
308
309 free(topic_array[topic_level]);
310 topic_array[topic_level] = topic;
311 topic_level = level;
312 return 0; 298 return 0;
313} 299}
314 300
@@ -366,6 +352,81 @@ static int print_events_table_entry(void *data, char *name, char *event,
366 return 0; 352 return 0;
367} 353}
368 354
355struct event_struct {
356 struct list_head list;
357 char *name;
358 char *event;
359 char *desc;
360 char *long_desc;
361 char *pmu;
362 char *unit;
363 char *perpkg;
364 char *metric_expr;
365 char *metric_name;
366 char *metric_group;
367};
368
369#define ADD_EVENT_FIELD(field) do { if (field) { \
370 es->field = strdup(field); \
371 if (!es->field) \
372 goto out_free; \
373} } while (0)
374
375#define FREE_EVENT_FIELD(field) free(es->field)
376
377#define TRY_FIXUP_FIELD(field) do { if (es->field && !*field) {\
378 *field = strdup(es->field); \
379 if (!*field) \
380 return -ENOMEM; \
381} } while (0)
382
383#define FOR_ALL_EVENT_STRUCT_FIELDS(op) do { \
384 op(name); \
385 op(event); \
386 op(desc); \
387 op(long_desc); \
388 op(pmu); \
389 op(unit); \
390 op(perpkg); \
391 op(metric_expr); \
392 op(metric_name); \
393 op(metric_group); \
394} while (0)
395
396static LIST_HEAD(arch_std_events);
397
398static void free_arch_std_events(void)
399{
400 struct event_struct *es, *next;
401
402 list_for_each_entry_safe(es, next, &arch_std_events, list) {
403 FOR_ALL_EVENT_STRUCT_FIELDS(FREE_EVENT_FIELD);
404 list_del(&es->list);
405 free(es);
406 }
407}
408
409static int save_arch_std_events(void *data, char *name, char *event,
410 char *desc, char *long_desc, char *pmu,
411 char *unit, char *perpkg, char *metric_expr,
412 char *metric_name, char *metric_group)
413{
414 struct event_struct *es;
415 struct stat *sb = data;
416
417 es = malloc(sizeof(*es));
418 if (!es)
419 return -ENOMEM;
420 memset(es, 0, sizeof(*es));
421 FOR_ALL_EVENT_STRUCT_FIELDS(ADD_EVENT_FIELD);
422 list_add_tail(&es->list, &arch_std_events);
423 return 0;
424out_free:
425 FOR_ALL_EVENT_STRUCT_FIELDS(FREE_EVENT_FIELD);
426 free(es);
427 return -ENOMEM;
428}
429
369static void print_events_table_suffix(FILE *outfp) 430static void print_events_table_suffix(FILE *outfp)
370{ 431{
371 fprintf(outfp, "{\n"); 432 fprintf(outfp, "{\n");
@@ -407,6 +468,32 @@ static char *real_event(const char *name, char *event)
407 return event; 468 return event;
408} 469}
409 470
471static int
472try_fixup(const char *fn, char *arch_std, char **event, char **desc,
473 char **name, char **long_desc, char **pmu, char **filter,
474 char **perpkg, char **unit, char **metric_expr, char **metric_name,
475 char **metric_group, unsigned long long eventcode)
476{
477 /* try to find matching event from arch standard values */
478 struct event_struct *es;
479
480 list_for_each_entry(es, &arch_std_events, list) {
481 if (!strcmp(arch_std, es->name)) {
482 if (!eventcode && es->event) {
483 /* allow EventCode to be overridden */
484 free(*event);
485 *event = NULL;
486 }
487 FOR_ALL_EVENT_STRUCT_FIELDS(TRY_FIXUP_FIELD);
488 return 0;
489 }
490 }
491
492 pr_err("%s: could not find matching %s for %s\n",
493 prog, arch_std, fn);
494 return -1;
495}
496
410/* Call func with each event in the json file */ 497/* Call func with each event in the json file */
411int json_events(const char *fn, 498int json_events(const char *fn,
412 int (*func)(void *data, char *name, char *event, char *desc, 499 int (*func)(void *data, char *name, char *event, char *desc,
@@ -416,7 +503,7 @@ int json_events(const char *fn,
416 char *metric_name, char *metric_group), 503 char *metric_name, char *metric_group),
417 void *data) 504 void *data)
418{ 505{
419 int err = -EIO; 506 int err;
420 size_t size; 507 size_t size;
421 jsmntok_t *tokens, *tok; 508 jsmntok_t *tokens, *tok;
422 int i, j, len; 509 int i, j, len;
@@ -442,6 +529,7 @@ int json_events(const char *fn,
442 char *metric_expr = NULL; 529 char *metric_expr = NULL;
443 char *metric_name = NULL; 530 char *metric_name = NULL;
444 char *metric_group = NULL; 531 char *metric_group = NULL;
532 char *arch_std = NULL;
445 unsigned long long eventcode = 0; 533 unsigned long long eventcode = 0;
446 struct msrmap *msr = NULL; 534 struct msrmap *msr = NULL;
447 jsmntok_t *msrval = NULL; 535 jsmntok_t *msrval = NULL;
@@ -527,6 +615,10 @@ int json_events(const char *fn,
527 addfield(map, &metric_expr, "", "", val); 615 addfield(map, &metric_expr, "", "", val);
528 for (s = metric_expr; *s; s++) 616 for (s = metric_expr; *s; s++)
529 *s = tolower(*s); 617 *s = tolower(*s);
618 } else if (json_streq(map, field, "ArchStdEvent")) {
619 addfield(map, &arch_std, "", "", val);
620 for (s = arch_std; *s; s++)
621 *s = tolower(*s);
530 } 622 }
531 /* ignore unknown fields */ 623 /* ignore unknown fields */
532 } 624 }
@@ -551,8 +643,21 @@ int json_events(const char *fn,
551 if (name) 643 if (name)
552 fixname(name); 644 fixname(name);
553 645
646 if (arch_std) {
647 /*
648 * An arch standard event is referenced, so try to
649 * fixup any unassigned values.
650 */
651 err = try_fixup(fn, arch_std, &event, &desc, &name,
652 &long_desc, &pmu, &filter, &perpkg,
653 &unit, &metric_expr, &metric_name,
654 &metric_group, eventcode);
655 if (err)
656 goto free_strings;
657 }
554 err = func(data, name, real_event(name, event), desc, long_desc, 658 err = func(data, name, real_event(name, event), desc, long_desc,
555 pmu, unit, perpkg, metric_expr, metric_name, metric_group); 659 pmu, unit, perpkg, metric_expr, metric_name, metric_group);
660free_strings:
556 free(event); 661 free(event);
557 free(desc); 662 free(desc);
558 free(name); 663 free(name);
@@ -565,6 +670,8 @@ int json_events(const char *fn,
565 free(metric_expr); 670 free(metric_expr);
566 free(metric_name); 671 free(metric_name);
567 free(metric_group); 672 free(metric_group);
673 free(arch_std);
674
568 if (err) 675 if (err)
569 break; 676 break;
570 tok += j; 677 tok += j;
@@ -588,7 +695,7 @@ static char *file_name_to_table_name(char *fname)
588 * Derive rest of table name from basename of the JSON file, 695 * Derive rest of table name from basename of the JSON file,
589 * replacing hyphens and stripping out .json suffix. 696 * replacing hyphens and stripping out .json suffix.
590 */ 697 */
591 n = asprintf(&tblname, "pme_%s", basename(fname)); 698 n = asprintf(&tblname, "pme_%s", fname);
592 if (n < 0) { 699 if (n < 0) {
593 pr_info("%s: asprintf() error %s for file %s\n", prog, 700 pr_info("%s: asprintf() error %s for file %s\n", prog,
594 strerror(errno), fname); 701 strerror(errno), fname);
@@ -598,7 +705,7 @@ static char *file_name_to_table_name(char *fname)
598 for (i = 0; i < strlen(tblname); i++) { 705 for (i = 0; i < strlen(tblname); i++) {
599 c = tblname[i]; 706 c = tblname[i];
600 707
601 if (c == '-') 708 if (c == '-' || c == '/')
602 tblname[i] = '_'; 709 tblname[i] = '_';
603 else if (c == '.') { 710 else if (c == '.') {
604 tblname[i] = '\0'; 711 tblname[i] = '\0';
@@ -755,25 +862,106 @@ static int get_maxfds(void)
755static FILE *eventsfp; 862static FILE *eventsfp;
756static char *mapfile; 863static char *mapfile;
757 864
865static int is_leaf_dir(const char *fpath)
866{
867 DIR *d;
868 struct dirent *dir;
869 int res = 1;
870
871 d = opendir(fpath);
872 if (!d)
873 return 0;
874
875 while ((dir = readdir(d)) != NULL) {
876 if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
877 continue;
878
879 if (dir->d_type == DT_DIR) {
880 res = 0;
881 break;
882 } else if (dir->d_type == DT_UNKNOWN) {
883 char path[PATH_MAX];
884 struct stat st;
885
886 sprintf(path, "%s/%s", fpath, dir->d_name);
887 if (stat(path, &st))
888 break;
889
890 if (S_ISDIR(st.st_mode)) {
891 res = 0;
892 break;
893 }
894 }
895 }
896
897 closedir(d);
898
899 return res;
900}
901
902static int is_json_file(const char *name)
903{
904 const char *suffix;
905
906 if (strlen(name) < 5)
907 return 0;
908
909 suffix = name + strlen(name) - 5;
910
911 if (strncmp(suffix, ".json", 5) == 0)
912 return 1;
913 return 0;
914}
915
916static int preprocess_arch_std_files(const char *fpath, const struct stat *sb,
917 int typeflag, struct FTW *ftwbuf)
918{
919 int level = ftwbuf->level;
920 int is_file = typeflag == FTW_F;
921
922 if (level == 1 && is_file && is_json_file(fpath))
923 return json_events(fpath, save_arch_std_events, (void *)sb);
924
925 return 0;
926}
927
758static int process_one_file(const char *fpath, const struct stat *sb, 928static int process_one_file(const char *fpath, const struct stat *sb,
759 int typeflag, struct FTW *ftwbuf) 929 int typeflag, struct FTW *ftwbuf)
760{ 930{
761 char *tblname, *bname = (char *) fpath + ftwbuf->base; 931 char *tblname, *bname;
762 int is_dir = typeflag == FTW_D; 932 int is_dir = typeflag == FTW_D;
763 int is_file = typeflag == FTW_F; 933 int is_file = typeflag == FTW_F;
764 int level = ftwbuf->level; 934 int level = ftwbuf->level;
765 int err = 0; 935 int err = 0;
766 936
937 if (level == 2 && is_dir) {
938 /*
939 * For level 2 directory, bname will include parent name,
940 * like vendor/platform. So search back from platform dir
941 * to find this.
942 */
943 bname = (char *) fpath + ftwbuf->base - 2;
944 for (;;) {
945 if (*bname == '/')
946 break;
947 bname--;
948 }
949 bname++;
950 } else
951 bname = (char *) fpath + ftwbuf->base;
952
767 pr_debug("%s %d %7jd %-20s %s\n", 953 pr_debug("%s %d %7jd %-20s %s\n",
768 is_file ? "f" : is_dir ? "d" : "x", 954 is_file ? "f" : is_dir ? "d" : "x",
769 level, sb->st_size, bname, fpath); 955 level, sb->st_size, bname, fpath);
770 956
771 /* base dir */ 957 /* base dir or too deep */
772 if (level == 0) 958 if (level == 0 || level > 3)
773 return 0; 959 return 0;
774 960
961
775 /* model directory, reset topic */ 962 /* model directory, reset topic */
776 if (level == 1 && is_dir) { 963 if ((level == 1 && is_dir && is_leaf_dir(fpath)) ||
964 (level == 2 && is_dir)) {
777 if (close_table) 965 if (close_table)
778 print_events_table_suffix(eventsfp); 966 print_events_table_suffix(eventsfp);
779 967
@@ -798,16 +986,10 @@ static int process_one_file(const char *fpath, const struct stat *sb,
798 * after processing all JSON files (so we can write out the 986 * after processing all JSON files (so we can write out the
799 * mapping table after all PMU events tables). 987 * mapping table after all PMU events tables).
800 * 988 *
801 * TODO: Allow for multiple mapfiles? Punt for now.
802 */ 989 */
803 if (level == 1 && is_file) { 990 if (level == 1 && is_file) {
804 if (!strncmp(bname, "mapfile.csv", 11)) { 991 if (!strcmp(bname, "mapfile.csv")) {
805 if (mapfile) { 992 mapfile = strdup(fpath);
806 pr_info("%s: Many mapfiles? Using %s, ignoring %s\n",
807 prog, mapfile, fpath);
808 } else {
809 mapfile = strdup(fpath);
810 }
811 return 0; 993 return 0;
812 } 994 }
813 995
@@ -820,16 +1002,14 @@ static int process_one_file(const char *fpath, const struct stat *sb,
820 * ignore it. It could be a readme.txt for instance. 1002 * ignore it. It could be a readme.txt for instance.
821 */ 1003 */
822 if (is_file) { 1004 if (is_file) {
823 char *suffix = bname + strlen(bname) - 5; 1005 if (!is_json_file(bname)) {
824
825 if (strncmp(suffix, ".json", 5)) {
826 pr_info("%s: Ignoring file without .json suffix %s\n", prog, 1006 pr_info("%s: Ignoring file without .json suffix %s\n", prog,
827 fpath); 1007 fpath);
828 return 0; 1008 return 0;
829 } 1009 }
830 } 1010 }
831 1011
832 if (level > 1 && add_topic(level, bname)) 1012 if (level > 1 && add_topic(bname))
833 return -ENOMEM; 1013 return -ENOMEM;
834 1014
835 /* 1015 /*
@@ -928,12 +1108,26 @@ int main(int argc, char *argv[])
928 1108
929 maxfds = get_maxfds(); 1109 maxfds = get_maxfds();
930 mapfile = NULL; 1110 mapfile = NULL;
1111 rc = nftw(ldirname, preprocess_arch_std_files, maxfds, 0);
1112 if (rc && verbose) {
1113 pr_info("%s: Error preprocessing arch standard files %s\n",
1114 prog, ldirname);
1115 goto empty_map;
1116 } else if (rc < 0) {
1117 /* Make build fail */
1118 free_arch_std_events();
1119 return 1;
1120 } else if (rc) {
1121 goto empty_map;
1122 }
1123
931 rc = nftw(ldirname, process_one_file, maxfds, 0); 1124 rc = nftw(ldirname, process_one_file, maxfds, 0);
932 if (rc && verbose) { 1125 if (rc && verbose) {
933 pr_info("%s: Error walking file tree %s\n", prog, ldirname); 1126 pr_info("%s: Error walking file tree %s\n", prog, ldirname);
934 goto empty_map; 1127 goto empty_map;
935 } else if (rc < 0) { 1128 } else if (rc < 0) {
936 /* Make build fail */ 1129 /* Make build fail */
1130 free_arch_std_events();
937 return 1; 1131 return 1;
938 } else if (rc) { 1132 } else if (rc) {
939 goto empty_map; 1133 goto empty_map;
@@ -958,5 +1152,6 @@ int main(int argc, char *argv[])
958empty_map: 1152empty_map:
959 fclose(eventsfp); 1153 fclose(eventsfp);
960 create_empty_mapping(output_file); 1154 create_empty_mapping(output_file);
1155 free_arch_std_events();
961 return 0; 1156 return 0;
962} 1157}
diff --git a/tools/perf/python/twatch.py b/tools/perf/python/twatch.py
index c235c22b107a..0a29c5c3079f 100755
--- a/tools/perf/python/twatch.py
+++ b/tools/perf/python/twatch.py
@@ -42,10 +42,10 @@ def main(context_switch = 0, thread = -1):
42 event = evlist.read_on_cpu(cpu) 42 event = evlist.read_on_cpu(cpu)
43 if not event: 43 if not event:
44 continue 44 continue
45 print "cpu: %2d, pid: %4d, tid: %4d" % (event.sample_cpu, 45 print("cpu: {0}, pid: {1}, tid: {2} {3}".format(event.sample_cpu,
46 event.sample_pid, 46 event.sample_pid,
47 event.sample_tid), 47 event.sample_tid,
48 print event 48 event))
49 49
50if __name__ == '__main__': 50if __name__ == '__main__':
51 """ 51 """
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
index fcd1dd667906..1a0d27757eec 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/Context.c
+++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
@@ -23,7 +23,17 @@
23#include "../../../perf.h" 23#include "../../../perf.h"
24#include "../../../util/trace-event.h" 24#include "../../../util/trace-event.h"
25 25
26#if PY_MAJOR_VERSION < 3
27#define _PyCapsule_GetPointer(arg1, arg2) \
28 PyCObject_AsVoidPtr(arg1)
29
26PyMODINIT_FUNC initperf_trace_context(void); 30PyMODINIT_FUNC initperf_trace_context(void);
31#else
32#define _PyCapsule_GetPointer(arg1, arg2) \
33 PyCapsule_GetPointer((arg1), (arg2))
34
35PyMODINIT_FUNC PyInit_perf_trace_context(void);
36#endif
27 37
28static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args) 38static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args)
29{ 39{
@@ -34,7 +44,7 @@ static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args)
34 if (!PyArg_ParseTuple(args, "O", &context)) 44 if (!PyArg_ParseTuple(args, "O", &context))
35 return NULL; 45 return NULL;
36 46
37 scripting_context = PyCObject_AsVoidPtr(context); 47 scripting_context = _PyCapsule_GetPointer(context, NULL);
38 retval = common_pc(scripting_context); 48 retval = common_pc(scripting_context);
39 49
40 return Py_BuildValue("i", retval); 50 return Py_BuildValue("i", retval);
@@ -50,7 +60,7 @@ static PyObject *perf_trace_context_common_flags(PyObject *obj,
50 if (!PyArg_ParseTuple(args, "O", &context)) 60 if (!PyArg_ParseTuple(args, "O", &context))
51 return NULL; 61 return NULL;
52 62
53 scripting_context = PyCObject_AsVoidPtr(context); 63 scripting_context = _PyCapsule_GetPointer(context, NULL);
54 retval = common_flags(scripting_context); 64 retval = common_flags(scripting_context);
55 65
56 return Py_BuildValue("i", retval); 66 return Py_BuildValue("i", retval);
@@ -66,7 +76,7 @@ static PyObject *perf_trace_context_common_lock_depth(PyObject *obj,
66 if (!PyArg_ParseTuple(args, "O", &context)) 76 if (!PyArg_ParseTuple(args, "O", &context))
67 return NULL; 77 return NULL;
68 78
69 scripting_context = PyCObject_AsVoidPtr(context); 79 scripting_context = _PyCapsule_GetPointer(context, NULL);
70 retval = common_lock_depth(scripting_context); 80 retval = common_lock_depth(scripting_context);
71 81
72 return Py_BuildValue("i", retval); 82 return Py_BuildValue("i", retval);
@@ -82,7 +92,25 @@ static PyMethodDef ContextMethods[] = {
82 { NULL, NULL, 0, NULL} 92 { NULL, NULL, 0, NULL}
83}; 93};
84 94
95#if PY_MAJOR_VERSION < 3
85PyMODINIT_FUNC initperf_trace_context(void) 96PyMODINIT_FUNC initperf_trace_context(void)
86{ 97{
87 (void) Py_InitModule("perf_trace_context", ContextMethods); 98 (void) Py_InitModule("perf_trace_context", ContextMethods);
88} 99}
100#else
101PyMODINIT_FUNC PyInit_perf_trace_context(void)
102{
103 static struct PyModuleDef moduledef = {
104 PyModuleDef_HEAD_INIT,
105 "perf_trace_context", /* m_name */
106 "", /* m_doc */
107 -1, /* m_size */
108 ContextMethods, /* m_methods */
109 NULL, /* m_reload */
110 NULL, /* m_traverse */
111 NULL, /* m_clear */
112 NULL, /* m_free */
113 };
114 return PyModule_Create(&moduledef);
115}
116#endif
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 87bf3edb037c..6c108fa79ae3 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -20,6 +20,7 @@ perf-y += hists_cumulate.o
20perf-y += python-use.o 20perf-y += python-use.o
21perf-y += bp_signal.o 21perf-y += bp_signal.o
22perf-y += bp_signal_overflow.o 22perf-y += bp_signal_overflow.o
23perf-y += bp_account.o
23perf-y += task-exit.o 24perf-y += task-exit.o
24perf-y += sw-clock.o 25perf-y += sw-clock.o
25perf-y += mmap-thread-lookup.o 26perf-y += mmap-thread-lookup.o
@@ -47,6 +48,7 @@ perf-y += bitmap.o
47perf-y += perf-hooks.o 48perf-y += perf-hooks.o
48perf-y += clang.o 49perf-y += clang.o
49perf-y += unit_number__scnprintf.o 50perf-y += unit_number__scnprintf.o
51perf-y += mem2node.o
50 52
51$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build 53$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
52 $(call rule_mkdir) 54 $(call rule_mkdir)
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c
index 97f64ad7fa08..05dfe11c2f9e 100644
--- a/tools/perf/tests/attr.c
+++ b/tools/perf/tests/attr.c
@@ -170,8 +170,8 @@ static int run_dir(const char *d, const char *perf)
170 if (verbose > 0) 170 if (verbose > 0)
171 vcnt++; 171 vcnt++;
172 172
173 snprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %.*s", 173 scnprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %.*s",
174 d, d, perf, vcnt, v); 174 d, d, perf, vcnt, v);
175 175
176 return system(cmd) ? TEST_FAIL : TEST_OK; 176 return system(cmd) ? TEST_FAIL : TEST_OK;
177} 177}
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c
index 4035d43523c3..6d598cc071ae 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -31,10 +31,11 @@ static int count_samples(struct perf_evlist *evlist, int *sample_count,
31 int i; 31 int i;
32 32
33 for (i = 0; i < evlist->nr_mmaps; i++) { 33 for (i = 0; i < evlist->nr_mmaps; i++) {
34 struct perf_mmap *map = &evlist->overwrite_mmap[i];
34 union perf_event *event; 35 union perf_event *event;
35 36
36 perf_mmap__read_catchup(&evlist->overwrite_mmap[i]); 37 perf_mmap__read_init(map);
37 while ((event = perf_mmap__read_backward(&evlist->overwrite_mmap[i])) != NULL) { 38 while ((event = perf_mmap__read_event(map)) != NULL) {
38 const u32 type = event->header.type; 39 const u32 type = event->header.type;
39 40
40 switch (type) { 41 switch (type) {
@@ -49,6 +50,7 @@ static int count_samples(struct perf_evlist *evlist, int *sample_count,
49 return TEST_FAIL; 50 return TEST_FAIL;
50 } 51 }
51 } 52 }
53 perf_mmap__read_done(map);
52 } 54 }
53 return TEST_OK; 55 return TEST_OK;
54} 56}
diff --git a/tools/perf/tests/bp_account.c b/tools/perf/tests/bp_account.c
new file mode 100644
index 000000000000..a20cbc445426
--- /dev/null
+++ b/tools/perf/tests/bp_account.c
@@ -0,0 +1,193 @@
1/*
2 * Powerpc needs __SANE_USERSPACE_TYPES__ before <linux/types.h> to select
3 * 'int-ll64.h' and avoid compile warnings when printing __u64 with %llu.
4 */
5#define __SANE_USERSPACE_TYPES__
6
7#include <stdlib.h>
8#include <stdio.h>
9#include <unistd.h>
10#include <string.h>
11#include <sys/ioctl.h>
12#include <time.h>
13#include <fcntl.h>
14#include <signal.h>
15#include <sys/mman.h>
16#include <linux/compiler.h>
17#include <linux/hw_breakpoint.h>
18#include <sys/ioctl.h>
19
20#include "tests.h"
21#include "debug.h"
22#include "perf.h"
23#include "cloexec.h"
24
25volatile long the_var;
26
27static noinline int test_function(void)
28{
29 return 0;
30}
31
32static int __event(bool is_x, void *addr, struct perf_event_attr *attr)
33{
34 int fd;
35
36 memset(attr, 0, sizeof(struct perf_event_attr));
37 attr->type = PERF_TYPE_BREAKPOINT;
38 attr->size = sizeof(struct perf_event_attr);
39
40 attr->config = 0;
41 attr->bp_type = is_x ? HW_BREAKPOINT_X : HW_BREAKPOINT_W;
42 attr->bp_addr = (unsigned long) addr;
43 attr->bp_len = sizeof(long);
44
45 attr->sample_period = 1;
46 attr->sample_type = PERF_SAMPLE_IP;
47
48 attr->exclude_kernel = 1;
49 attr->exclude_hv = 1;
50
51 fd = sys_perf_event_open(attr, -1, 0, -1,
52 perf_event_open_cloexec_flag());
53 if (fd < 0) {
54 pr_debug("failed opening event %llx\n", attr->config);
55 return TEST_FAIL;
56 }
57
58 return fd;
59}
60
61static int wp_event(void *addr, struct perf_event_attr *attr)
62{
63 return __event(false, addr, attr);
64}
65
66static int bp_event(void *addr, struct perf_event_attr *attr)
67{
68 return __event(true, addr, attr);
69}
70
71static int bp_accounting(int wp_cnt, int share)
72{
73 struct perf_event_attr attr, attr_mod, attr_new;
74 int i, fd[wp_cnt], fd_wp, ret;
75
76 for (i = 0; i < wp_cnt; i++) {
77 fd[i] = wp_event((void *)&the_var, &attr);
78 TEST_ASSERT_VAL("failed to create wp\n", fd[i] != -1);
79 pr_debug("wp %d created\n", i);
80 }
81
82 attr_mod = attr;
83 attr_mod.bp_type = HW_BREAKPOINT_X;
84 attr_mod.bp_addr = (unsigned long) test_function;
85
86 ret = ioctl(fd[0], PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &attr_mod);
87 TEST_ASSERT_VAL("failed to modify wp\n", ret == 0);
88
89 pr_debug("wp 0 modified to bp\n");
90
91 if (!share) {
92 fd_wp = wp_event((void *)&the_var, &attr_new);
93 TEST_ASSERT_VAL("failed to create max wp\n", fd_wp != -1);
94 pr_debug("wp max created\n");
95 }
96
97 for (i = 0; i < wp_cnt; i++)
98 close(fd[i]);
99
100 return 0;
101}
102
103static int detect_cnt(bool is_x)
104{
105 struct perf_event_attr attr;
106 void *addr = is_x ? (void *)test_function : (void *)&the_var;
107 int fd[100], cnt = 0, i;
108
109 while (1) {
110 if (cnt == 100) {
111 pr_debug("way too many debug registers, fix the test\n");
112 return 0;
113 }
114 fd[cnt] = __event(is_x, addr, &attr);
115
116 if (fd[cnt] < 0)
117 break;
118 cnt++;
119 }
120
121 for (i = 0; i < cnt; i++)
122 close(fd[i]);
123
124 return cnt;
125}
126
127static int detect_ioctl(void)
128{
129 struct perf_event_attr attr;
130 int fd, ret = 1;
131
132 fd = wp_event((void *) &the_var, &attr);
133 if (fd > 0) {
134 ret = ioctl(fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &attr);
135 close(fd);
136 }
137
138 return ret ? 0 : 1;
139}
140
141static int detect_share(int wp_cnt, int bp_cnt)
142{
143 struct perf_event_attr attr;
144 int i, fd[wp_cnt + bp_cnt], ret;
145
146 for (i = 0; i < wp_cnt; i++) {
147 fd[i] = wp_event((void *)&the_var, &attr);
148 TEST_ASSERT_VAL("failed to create wp\n", fd[i] != -1);
149 }
150
151 for (; i < (bp_cnt + wp_cnt); i++) {
152 fd[i] = bp_event((void *)test_function, &attr);
153 if (fd[i] == -1)
154 break;
155 }
156
157 ret = i != (bp_cnt + wp_cnt);
158
159 while (i--)
160 close(fd[i]);
161
162 return ret;
163}
164
165/*
166 * This test does following:
167 * - detects the number of watch/break-points,
168 * skip test if any is missing
169 * - detects PERF_EVENT_IOC_MODIFY_ATTRIBUTES ioctl,
170 * skip test if it's missing
171 * - detects if watchpoints and breakpoints share
172 * same slots
173 * - create all possible watchpoints on cpu 0
174 * - change one of it to breakpoint
175 * - in case wp and bp do not share slots,
176 * we create another watchpoint to ensure
177 * the slot accounting is correct
178 */
179int test__bp_accounting(struct test *test __maybe_unused, int subtest __maybe_unused)
180{
181 int has_ioctl = detect_ioctl();
182 int wp_cnt = detect_cnt(false);
183 int bp_cnt = detect_cnt(true);
184 int share = detect_share(wp_cnt, bp_cnt);
185
186 pr_debug("watchpoints count %d, breakpoints count %d, has_ioctl %d, share %d\n",
187 wp_cnt, bp_cnt, has_ioctl, share);
188
189 if (!wp_cnt || !bp_cnt || !has_ioctl)
190 return TEST_SKIP;
191
192 return bp_accounting(wp_cnt, share);
193}
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index e8399beca62b..79b54f8ddebf 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -176,13 +176,19 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
176 176
177 for (i = 0; i < evlist->nr_mmaps; i++) { 177 for (i = 0; i < evlist->nr_mmaps; i++) {
178 union perf_event *event; 178 union perf_event *event;
179 struct perf_mmap *md;
179 180
180 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 181 md = &evlist->mmap[i];
182 if (perf_mmap__read_init(md) < 0)
183 continue;
184
185 while ((event = perf_mmap__read_event(md)) != NULL) {
181 const u32 type = event->header.type; 186 const u32 type = event->header.type;
182 187
183 if (type == PERF_RECORD_SAMPLE) 188 if (type == PERF_RECORD_SAMPLE)
184 count ++; 189 count ++;
185 } 190 }
191 perf_mmap__read_done(md);
186 } 192 }
187 193
188 if (count != expect) { 194 if (count != expect) {
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index fafa014240cd..625f5a6772af 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -116,6 +116,10 @@ static struct test generic_tests[] = {
116 .is_supported = test__bp_signal_is_supported, 116 .is_supported = test__bp_signal_is_supported,
117 }, 117 },
118 { 118 {
119 .desc = "Breakpoint accounting",
120 .func = test__bp_accounting,
121 },
122 {
119 .desc = "Number of exit events of a simple workload", 123 .desc = "Number of exit events of a simple workload",
120 .func = test__task_exit, 124 .func = test__task_exit,
121 }, 125 },
@@ -271,6 +275,10 @@ static struct test generic_tests[] = {
271 .func = test__unit_number__scnprint, 275 .func = test__unit_number__scnprint,
272 }, 276 },
273 { 277 {
278 .desc = "mem2node",
279 .func = test__mem2node,
280 },
281 {
274 .func = NULL, 282 .func = NULL,
275 }, 283 },
276}; 284};
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 3bf7b145b826..99936352df4f 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -409,15 +409,21 @@ static int process_events(struct machine *machine, struct perf_evlist *evlist,
409 struct state *state) 409 struct state *state)
410{ 410{
411 union perf_event *event; 411 union perf_event *event;
412 struct perf_mmap *md;
412 int i, ret; 413 int i, ret;
413 414
414 for (i = 0; i < evlist->nr_mmaps; i++) { 415 for (i = 0; i < evlist->nr_mmaps; i++) {
415 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 416 md = &evlist->mmap[i];
417 if (perf_mmap__read_init(md) < 0)
418 continue;
419
420 while ((event = perf_mmap__read_event(md)) != NULL) {
416 ret = process_event(machine, evlist, event, state); 421 ret = process_event(machine, evlist, event, state);
417 perf_evlist__mmap_consume(evlist, i); 422 perf_mmap__consume(md);
418 if (ret < 0) 423 if (ret < 0)
419 return ret; 424 return ret;
420 } 425 }
426 perf_mmap__read_done(md);
421 } 427 }
422 return 0; 428 return 0;
423} 429}
@@ -482,6 +488,34 @@ static void fs_something(void)
482 } 488 }
483} 489}
484 490
491static const char *do_determine_event(bool excl_kernel)
492{
493 const char *event = excl_kernel ? "cycles:u" : "cycles";
494
495#ifdef __s390x__
496 char cpuid[128], model[16], model_c[16], cpum_cf_v[16];
497 unsigned int family;
498 int ret, cpum_cf_a;
499
500 if (get_cpuid(cpuid, sizeof(cpuid)))
501 goto out_clocks;
502 ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%x", &family, model_c,
503 model, cpum_cf_v, &cpum_cf_a);
504 if (ret != 5) /* Not available */
505 goto out_clocks;
506 if (excl_kernel && (cpum_cf_a & 4))
507 return event;
508 if (!excl_kernel && (cpum_cf_a & 2))
509 return event;
510
511 /* Fall through: missing authorization */
512out_clocks:
513 event = excl_kernel ? "cpu-clock:u" : "cpu-clock";
514
515#endif
516 return event;
517}
518
485static void do_something(void) 519static void do_something(void)
486{ 520{
487 fs_something(); 521 fs_something();
@@ -592,10 +626,7 @@ static int do_test_code_reading(bool try_kcore)
592 626
593 perf_evlist__set_maps(evlist, cpus, threads); 627 perf_evlist__set_maps(evlist, cpus, threads);
594 628
595 if (excl_kernel) 629 str = do_determine_event(excl_kernel);
596 str = "cycles:u";
597 else
598 str = "cycles";
599 pr_debug("Parsing event '%s'\n", str); 630 pr_debug("Parsing event '%s'\n", str);
600 ret = parse_events(evlist, str, NULL); 631 ret = parse_events(evlist, str, NULL);
601 if (ret < 0) { 632 if (ret < 0) {
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 260418969120..2f008067d989 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -37,6 +37,19 @@ static int init_live_machine(struct machine *machine)
37 mmap_handler, machine, true, 500); 37 mmap_handler, machine, true, 500);
38} 38}
39 39
40/*
41 * We need to keep these functions global, despite the
42 * fact that they are used only locally in this object,
43 * in order to keep them around even if the binary is
44 * stripped. If they are gone, the unwind check for
45 * symbol fails.
46 */
47int test_dwarf_unwind__thread(struct thread *thread);
48int test_dwarf_unwind__compare(void *p1, void *p2);
49int test_dwarf_unwind__krava_3(struct thread *thread);
50int test_dwarf_unwind__krava_2(struct thread *thread);
51int test_dwarf_unwind__krava_1(struct thread *thread);
52
40#define MAX_STACK 8 53#define MAX_STACK 8
41 54
42static int unwind_entry(struct unwind_entry *entry, void *arg) 55static int unwind_entry(struct unwind_entry *entry, void *arg)
@@ -45,12 +58,12 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
45 char *symbol = entry->sym ? entry->sym->name : NULL; 58 char *symbol = entry->sym ? entry->sym->name : NULL;
46 static const char *funcs[MAX_STACK] = { 59 static const char *funcs[MAX_STACK] = {
47 "test__arch_unwind_sample", 60 "test__arch_unwind_sample",
48 "unwind_thread", 61 "test_dwarf_unwind__thread",
49 "compare", 62 "test_dwarf_unwind__compare",
50 "bsearch", 63 "bsearch",
51 "krava_3", 64 "test_dwarf_unwind__krava_3",
52 "krava_2", 65 "test_dwarf_unwind__krava_2",
53 "krava_1", 66 "test_dwarf_unwind__krava_1",
54 "test__dwarf_unwind" 67 "test__dwarf_unwind"
55 }; 68 };
56 /* 69 /*
@@ -77,7 +90,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
77 return strcmp((const char *) symbol, funcs[idx]); 90 return strcmp((const char *) symbol, funcs[idx]);
78} 91}
79 92
80static noinline int unwind_thread(struct thread *thread) 93noinline int test_dwarf_unwind__thread(struct thread *thread)
81{ 94{
82 struct perf_sample sample; 95 struct perf_sample sample;
83 unsigned long cnt = 0; 96 unsigned long cnt = 0;
@@ -108,7 +121,7 @@ static noinline int unwind_thread(struct thread *thread)
108 121
109static int global_unwind_retval = -INT_MAX; 122static int global_unwind_retval = -INT_MAX;
110 123
111static noinline int compare(void *p1, void *p2) 124noinline int test_dwarf_unwind__compare(void *p1, void *p2)
112{ 125{
113 /* Any possible value should be 'thread' */ 126 /* Any possible value should be 'thread' */
114 struct thread *thread = *(struct thread **)p1; 127 struct thread *thread = *(struct thread **)p1;
@@ -117,17 +130,17 @@ static noinline int compare(void *p1, void *p2)
117 /* Call unwinder twice for both callchain orders. */ 130 /* Call unwinder twice for both callchain orders. */
118 callchain_param.order = ORDER_CALLER; 131 callchain_param.order = ORDER_CALLER;
119 132
120 global_unwind_retval = unwind_thread(thread); 133 global_unwind_retval = test_dwarf_unwind__thread(thread);
121 if (!global_unwind_retval) { 134 if (!global_unwind_retval) {
122 callchain_param.order = ORDER_CALLEE; 135 callchain_param.order = ORDER_CALLEE;
123 global_unwind_retval = unwind_thread(thread); 136 global_unwind_retval = test_dwarf_unwind__thread(thread);
124 } 137 }
125 } 138 }
126 139
127 return p1 - p2; 140 return p1 - p2;
128} 141}
129 142
130static noinline int krava_3(struct thread *thread) 143noinline int test_dwarf_unwind__krava_3(struct thread *thread)
131{ 144{
132 struct thread *array[2] = {thread, thread}; 145 struct thread *array[2] = {thread, thread};
133 void *fp = &bsearch; 146 void *fp = &bsearch;
@@ -141,18 +154,19 @@ static noinline int krava_3(struct thread *thread)
141 size_t, int (*)(void *, void *)); 154 size_t, int (*)(void *, void *));
142 155
143 _bsearch = fp; 156 _bsearch = fp;
144 _bsearch(array, &thread, 2, sizeof(struct thread **), compare); 157 _bsearch(array, &thread, 2, sizeof(struct thread **),
158 test_dwarf_unwind__compare);
145 return global_unwind_retval; 159 return global_unwind_retval;
146} 160}
147 161
148static noinline int krava_2(struct thread *thread) 162noinline int test_dwarf_unwind__krava_2(struct thread *thread)
149{ 163{
150 return krava_3(thread); 164 return test_dwarf_unwind__krava_3(thread);
151} 165}
152 166
153static noinline int krava_1(struct thread *thread) 167noinline int test_dwarf_unwind__krava_1(struct thread *thread)
154{ 168{
155 return krava_2(thread); 169 return test_dwarf_unwind__krava_2(thread);
156} 170}
157 171
158int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unused) 172int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unused)
@@ -189,7 +203,7 @@ int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unu
189 goto out; 203 goto out;
190 } 204 }
191 205
192 err = krava_1(thread); 206 err = test_dwarf_unwind__krava_1(thread);
193 thread__put(thread); 207 thread__put(thread);
194 208
195 out: 209 out:
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index c46530918938..17c46f3e6f1e 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -27,18 +27,23 @@
27static int find_comm(struct perf_evlist *evlist, const char *comm) 27static int find_comm(struct perf_evlist *evlist, const char *comm)
28{ 28{
29 union perf_event *event; 29 union perf_event *event;
30 struct perf_mmap *md;
30 int i, found; 31 int i, found;
31 32
32 found = 0; 33 found = 0;
33 for (i = 0; i < evlist->nr_mmaps; i++) { 34 for (i = 0; i < evlist->nr_mmaps; i++) {
34 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 35 md = &evlist->mmap[i];
36 if (perf_mmap__read_init(md) < 0)
37 continue;
38 while ((event = perf_mmap__read_event(md)) != NULL) {
35 if (event->header.type == PERF_RECORD_COMM && 39 if (event->header.type == PERF_RECORD_COMM &&
36 (pid_t)event->comm.pid == getpid() && 40 (pid_t)event->comm.pid == getpid() &&
37 (pid_t)event->comm.tid == getpid() && 41 (pid_t)event->comm.tid == getpid() &&
38 strcmp(event->comm.comm, comm) == 0) 42 strcmp(event->comm.comm, comm) == 0)
39 found += 1; 43 found += 1;
40 perf_evlist__mmap_consume(evlist, i); 44 perf_mmap__consume(md);
41 } 45 }
46 perf_mmap__read_done(md);
42 } 47 }
43 return found; 48 return found;
44} 49}
diff --git a/tools/perf/tests/mem.c b/tools/perf/tests/mem.c
index 21952e1e6e6d..0f82ee9fd3f7 100644
--- a/tools/perf/tests/mem.c
+++ b/tools/perf/tests/mem.c
@@ -16,7 +16,7 @@ static int check(union perf_mem_data_src data_src,
16 16
17 n = perf_mem__snp_scnprintf(out, sizeof out, &mi); 17 n = perf_mem__snp_scnprintf(out, sizeof out, &mi);
18 n += perf_mem__lvl_scnprintf(out + n, sizeof out - n, &mi); 18 n += perf_mem__lvl_scnprintf(out + n, sizeof out - n, &mi);
19 snprintf(failure, sizeof failure, "unexpected %s", out); 19 scnprintf(failure, sizeof failure, "unexpected %s", out);
20 TEST_ASSERT_VAL(failure, !strcmp(string, out)); 20 TEST_ASSERT_VAL(failure, !strcmp(string, out));
21 return 0; 21 return 0;
22} 22}
diff --git a/tools/perf/tests/mem2node.c b/tools/perf/tests/mem2node.c
new file mode 100644
index 000000000000..0c3c87f86e03
--- /dev/null
+++ b/tools/perf/tests/mem2node.c
@@ -0,0 +1,75 @@
1#include <linux/compiler.h>
2#include <linux/bitmap.h>
3#include "cpumap.h"
4#include "mem2node.h"
5#include "tests.h"
6
7static struct node {
8 int node;
9 const char *map;
10} test_nodes[] = {
11 { .node = 0, .map = "0" },
12 { .node = 1, .map = "1-2" },
13 { .node = 3, .map = "5-7,9" },
14};
15
16#define T TEST_ASSERT_VAL
17
18static unsigned long *get_bitmap(const char *str, int nbits)
19{
20 struct cpu_map *map = cpu_map__new(str);
21 unsigned long *bm = NULL;
22 int i;
23
24 bm = bitmap_alloc(nbits);
25
26 if (map && bm) {
27 bitmap_zero(bm, nbits);
28
29 for (i = 0; i < map->nr; i++) {
30 set_bit(map->map[i], bm);
31 }
32 }
33
34 if (map)
35 cpu_map__put(map);
36 else
37 free(bm);
38
39 return bm && map ? bm : NULL;
40}
41
42int test__mem2node(struct test *t __maybe_unused, int subtest __maybe_unused)
43{
44 struct mem2node map;
45 struct memory_node nodes[3];
46 struct perf_env env = {
47 .memory_nodes = (struct memory_node *) &nodes[0],
48 .nr_memory_nodes = ARRAY_SIZE(nodes),
49 .memory_bsize = 0x100,
50 };
51 unsigned int i;
52
53 for (i = 0; i < ARRAY_SIZE(nodes); i++) {
54 nodes[i].node = test_nodes[i].node;
55 nodes[i].size = 10;
56
57 T("failed: alloc bitmap",
58 (nodes[i].set = get_bitmap(test_nodes[i].map, 10)));
59 }
60
61 T("failed: mem2node__init", !mem2node__init(&map, &env));
62 T("failed: mem2node__node", 0 == mem2node__node(&map, 0x50));
63 T("failed: mem2node__node", 1 == mem2node__node(&map, 0x100));
64 T("failed: mem2node__node", 1 == mem2node__node(&map, 0x250));
65 T("failed: mem2node__node", 3 == mem2node__node(&map, 0x500));
66 T("failed: mem2node__node", 3 == mem2node__node(&map, 0x650));
67 T("failed: mem2node__node", -1 == mem2node__node(&map, 0x450));
68 T("failed: mem2node__node", -1 == mem2node__node(&map, 0x1050));
69
70 for (i = 0; i < ARRAY_SIZE(nodes); i++)
71 free(nodes[i].set);
72
73 mem2node__exit(&map);
74 return 0;
75}
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index c0e971da965c..bb8e6bcb0d96 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -38,6 +38,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse
38 expected_nr_events[nsyscalls], i, j; 38 expected_nr_events[nsyscalls], i, j;
39 struct perf_evsel *evsels[nsyscalls], *evsel; 39 struct perf_evsel *evsels[nsyscalls], *evsel;
40 char sbuf[STRERR_BUFSIZE]; 40 char sbuf[STRERR_BUFSIZE];
41 struct perf_mmap *md;
41 42
42 threads = thread_map__new(-1, getpid(), UINT_MAX); 43 threads = thread_map__new(-1, getpid(), UINT_MAX);
43 if (threads == NULL) { 44 if (threads == NULL) {
@@ -106,7 +107,11 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse
106 ++foo; 107 ++foo;
107 } 108 }
108 109
109 while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { 110 md = &evlist->mmap[0];
111 if (perf_mmap__read_init(md) < 0)
112 goto out_init;
113
114 while ((event = perf_mmap__read_event(md)) != NULL) {
110 struct perf_sample sample; 115 struct perf_sample sample;
111 116
112 if (event->header.type != PERF_RECORD_SAMPLE) { 117 if (event->header.type != PERF_RECORD_SAMPLE) {
@@ -129,9 +134,11 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse
129 goto out_delete_evlist; 134 goto out_delete_evlist;
130 } 135 }
131 nr_events[evsel->idx]++; 136 nr_events[evsel->idx]++;
132 perf_evlist__mmap_consume(evlist, 0); 137 perf_mmap__consume(md);
133 } 138 }
139 perf_mmap__read_done(md);
134 140
141out_init:
135 err = 0; 142 err = 0;
136 evlist__for_each_entry(evlist, evsel) { 143 evlist__for_each_entry(evlist, evsel) {
137 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { 144 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
index 43519267b93b..344dc3ac2469 100644
--- a/tools/perf/tests/openat-syscall-tp-fields.c
+++ b/tools/perf/tests/openat-syscall-tp-fields.c
@@ -86,8 +86,13 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest
86 86
87 for (i = 0; i < evlist->nr_mmaps; i++) { 87 for (i = 0; i < evlist->nr_mmaps; i++) {
88 union perf_event *event; 88 union perf_event *event;
89 struct perf_mmap *md;
89 90
90 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 91 md = &evlist->mmap[i];
92 if (perf_mmap__read_init(md) < 0)
93 continue;
94
95 while ((event = perf_mmap__read_event(md)) != NULL) {
91 const u32 type = event->header.type; 96 const u32 type = event->header.type;
92 int tp_flags; 97 int tp_flags;
93 struct perf_sample sample; 98 struct perf_sample sample;
@@ -95,7 +100,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest
95 ++nr_events; 100 ++nr_events;
96 101
97 if (type != PERF_RECORD_SAMPLE) { 102 if (type != PERF_RECORD_SAMPLE) {
98 perf_evlist__mmap_consume(evlist, i); 103 perf_mmap__consume(md);
99 continue; 104 continue;
100 } 105 }
101 106
@@ -115,6 +120,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest
115 120
116 goto out_ok; 121 goto out_ok;
117 } 122 }
123 perf_mmap__read_done(md);
118 } 124 }
119 125
120 if (nr_events == before) 126 if (nr_events == before)
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 0afafab85238..34394cc05077 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -164,8 +164,13 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus
164 164
165 for (i = 0; i < evlist->nr_mmaps; i++) { 165 for (i = 0; i < evlist->nr_mmaps; i++) {
166 union perf_event *event; 166 union perf_event *event;
167 struct perf_mmap *md;
167 168
168 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 169 md = &evlist->mmap[i];
170 if (perf_mmap__read_init(md) < 0)
171 continue;
172
173 while ((event = perf_mmap__read_event(md)) != NULL) {
169 const u32 type = event->header.type; 174 const u32 type = event->header.type;
170 const char *name = perf_event__name(type); 175 const char *name = perf_event__name(type);
171 176
@@ -266,8 +271,9 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus
266 ++errs; 271 ++errs;
267 } 272 }
268 273
269 perf_evlist__mmap_consume(evlist, i); 274 perf_mmap__consume(md);
270 } 275 }
276 perf_mmap__read_done(md);
271 } 277 }
272 278
273 /* 279 /*
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index 9abca267afa9..7bedf8608fdd 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -98,7 +98,7 @@ static char *test_format_dir_get(void)
98 struct test_format *format = &test_formats[i]; 98 struct test_format *format = &test_formats[i];
99 FILE *file; 99 FILE *file;
100 100
101 snprintf(name, PATH_MAX, "%s/%s", dir, format->name); 101 scnprintf(name, PATH_MAX, "%s/%s", dir, format->name);
102 102
103 file = fopen(name, "w"); 103 file = fopen(name, "w");
104 if (!file) 104 if (!file)
diff --git a/tools/perf/tests/shell/lib/probe_vfs_getname.sh b/tools/perf/tests/shell/lib/probe_vfs_getname.sh
index 30a950c9d407..1c16e56cd93e 100644
--- a/tools/perf/tests/shell/lib/probe_vfs_getname.sh
+++ b/tools/perf/tests/shell/lib/probe_vfs_getname.sh
@@ -5,7 +5,7 @@ had_vfs_getname=$?
5 5
6cleanup_probe_vfs_getname() { 6cleanup_probe_vfs_getname() {
7 if [ $had_vfs_getname -eq 1 ] ; then 7 if [ $had_vfs_getname -eq 1 ] ; then
8 perf probe -q -d probe:vfs_getname 8 perf probe -q -d probe:vfs_getname*
9 fi 9 fi
10} 10}
11 11
diff --git a/tools/perf/tests/shell/trace+probe_libc_inet_pton.sh b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
index 8b3da21a08f1..1ecc1f0ff84a 100755
--- a/tools/perf/tests/shell/trace+probe_libc_inet_pton.sh
+++ b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
@@ -15,17 +15,28 @@ nm -g $libc 2>/dev/null | fgrep -q inet_pton || exit 254
15 15
16trace_libc_inet_pton_backtrace() { 16trace_libc_inet_pton_backtrace() {
17 idx=0 17 idx=0
18 expected[0]="PING.*bytes" 18 expected[0]="ping[][0-9 \.:]+probe_libc:inet_pton: \([[:xdigit:]]+\)"
19 expected[1]="64 bytes from ::1.*" 19 expected[1]=".*inet_pton[[:space:]]\($libc\)$"
20 expected[2]=".*ping statistics.*" 20 case "$(uname -m)" in
21 expected[3]=".*packets transmitted.*" 21 s390x)
22 expected[4]="rtt min.*" 22 eventattr='call-graph=dwarf'
23 expected[5]="[0-9]+\.[0-9]+[[:space:]]+probe_libc:inet_pton:\([[:xdigit:]]+\)" 23 expected[2]="gaih_inet.*[[:space:]]\($libc|inlined\)$"
24 expected[6]=".*inet_pton[[:space:]]\($libc\)$" 24 expected[3]="__GI_getaddrinfo[[:space:]]\($libc|inlined\)$"
25 expected[7]="getaddrinfo[[:space:]]\($libc\)$" 25 expected[4]="main[[:space:]]\(.*/bin/ping.*\)$"
26 expected[8]=".*\(.*/bin/ping.*\)$" 26 expected[5]="__libc_start_main[[:space:]]\($libc\)$"
27 27 expected[6]="_start[[:space:]]\(.*/bin/ping.*\)$"
28 perf trace --no-syscalls -e probe_libc:inet_pton/max-stack=3/ ping -6 -c 1 ::1 2>&1 | grep -v ^$ | while read line ; do 28 ;;
29 *)
30 eventattr='max-stack=3'
31 expected[2]="getaddrinfo[[:space:]]\($libc\)$"
32 expected[3]=".*\(.*/bin/ping.*\)$"
33 ;;
34 esac
35
36 file=`mktemp -u /tmp/perf.data.XXX`
37
38 perf record -e probe_libc:inet_pton/$eventattr/ -o $file ping -6 -c 1 ::1 > /dev/null 2>&1
39 perf script -i $file | while read line ; do
29 echo $line 40 echo $line
30 echo "$line" | egrep -q "${expected[$idx]}" 41 echo "$line" | egrep -q "${expected[$idx]}"
31 if [ $? -ne 0 ] ; then 42 if [ $? -ne 0 ] ; then
@@ -33,8 +44,13 @@ trace_libc_inet_pton_backtrace() {
33 exit 1 44 exit 1
34 fi 45 fi
35 let idx+=1 46 let idx+=1
36 [ $idx -eq 9 ] && break 47 [ -z "${expected[$idx]}" ] && break
37 done 48 done
49
50 # If any statements are executed from this point onwards,
51 # the exit code of the last among these will be reflected
52 # in err below. If the exit code is 0, the test will pass
53 # even if the perf script output does not match.
38} 54}
39 55
40# Check for IPv6 interface existence 56# Check for IPv6 interface existence
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index f6c72f915d48..f9490b237893 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -39,6 +39,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
39 }; 39 };
40 struct cpu_map *cpus; 40 struct cpu_map *cpus;
41 struct thread_map *threads; 41 struct thread_map *threads;
42 struct perf_mmap *md;
42 43
43 attr.sample_freq = 500; 44 attr.sample_freq = 500;
44 45
@@ -93,7 +94,11 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
93 94
94 perf_evlist__disable(evlist); 95 perf_evlist__disable(evlist);
95 96
96 while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { 97 md = &evlist->mmap[0];
98 if (perf_mmap__read_init(md) < 0)
99 goto out_init;
100
101 while ((event = perf_mmap__read_event(md)) != NULL) {
97 struct perf_sample sample; 102 struct perf_sample sample;
98 103
99 if (event->header.type != PERF_RECORD_SAMPLE) 104 if (event->header.type != PERF_RECORD_SAMPLE)
@@ -108,9 +113,11 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
108 total_periods += sample.period; 113 total_periods += sample.period;
109 nr_samples++; 114 nr_samples++;
110next_event: 115next_event:
111 perf_evlist__mmap_consume(evlist, 0); 116 perf_mmap__consume(md);
112 } 117 }
118 perf_mmap__read_done(md);
113 119
120out_init:
114 if ((u64) nr_samples == total_periods) { 121 if ((u64) nr_samples == total_periods) {
115 pr_debug("All (%d) samples have period value of 1!\n", 122 pr_debug("All (%d) samples have period value of 1!\n",
116 nr_samples); 123 nr_samples);
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
index 33e00295a972..9b5be51e5e7b 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -258,16 +258,22 @@ static int process_events(struct perf_evlist *evlist,
258 unsigned pos, cnt = 0; 258 unsigned pos, cnt = 0;
259 LIST_HEAD(events); 259 LIST_HEAD(events);
260 struct event_node *events_array, *node; 260 struct event_node *events_array, *node;
261 struct perf_mmap *md;
261 int i, ret; 262 int i, ret;
262 263
263 for (i = 0; i < evlist->nr_mmaps; i++) { 264 for (i = 0; i < evlist->nr_mmaps; i++) {
264 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 265 md = &evlist->mmap[i];
266 if (perf_mmap__read_init(md) < 0)
267 continue;
268
269 while ((event = perf_mmap__read_event(md)) != NULL) {
265 cnt += 1; 270 cnt += 1;
266 ret = add_event(evlist, &events, event); 271 ret = add_event(evlist, &events, event);
267 perf_evlist__mmap_consume(evlist, i); 272 perf_mmap__consume(md);
268 if (ret < 0) 273 if (ret < 0)
269 goto out_free_nodes; 274 goto out_free_nodes;
270 } 275 }
276 perf_mmap__read_done(md);
271 } 277 }
272 278
273 events_array = calloc(cnt, sizeof(struct event_node)); 279 events_array = calloc(cnt, sizeof(struct event_node));
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index 01b62b81751b..e92fa6029ac7 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -47,6 +47,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused
47 char sbuf[STRERR_BUFSIZE]; 47 char sbuf[STRERR_BUFSIZE];
48 struct cpu_map *cpus; 48 struct cpu_map *cpus;
49 struct thread_map *threads; 49 struct thread_map *threads;
50 struct perf_mmap *md;
50 51
51 signal(SIGCHLD, sig_handler); 52 signal(SIGCHLD, sig_handler);
52 53
@@ -110,13 +111,19 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused
110 perf_evlist__start_workload(evlist); 111 perf_evlist__start_workload(evlist);
111 112
112retry: 113retry:
113 while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { 114 md = &evlist->mmap[0];
115 if (perf_mmap__read_init(md) < 0)
116 goto out_init;
117
118 while ((event = perf_mmap__read_event(md)) != NULL) {
114 if (event->header.type == PERF_RECORD_EXIT) 119 if (event->header.type == PERF_RECORD_EXIT)
115 nr_exit++; 120 nr_exit++;
116 121
117 perf_evlist__mmap_consume(evlist, 0); 122 perf_mmap__consume(md);
118 } 123 }
124 perf_mmap__read_done(md);
119 125
126out_init:
120 if (!exited || !nr_exit) { 127 if (!exited || !nr_exit) {
121 perf_evlist__poll(evlist, -1); 128 perf_evlist__poll(evlist, -1);
122 goto retry; 129 goto retry;
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 2862b80bc288..a9760e790563 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -58,6 +58,7 @@ int test__hists_link(struct test *test, int subtest);
58int test__python_use(struct test *test, int subtest); 58int test__python_use(struct test *test, int subtest);
59int test__bp_signal(struct test *test, int subtest); 59int test__bp_signal(struct test *test, int subtest);
60int test__bp_signal_overflow(struct test *test, int subtest); 60int test__bp_signal_overflow(struct test *test, int subtest);
61int test__bp_accounting(struct test *test, int subtest);
61int test__task_exit(struct test *test, int subtest); 62int test__task_exit(struct test *test, int subtest);
62int test__mem(struct test *test, int subtest); 63int test__mem(struct test *test, int subtest);
63int test__sw_clock_freq(struct test *test, int subtest); 64int test__sw_clock_freq(struct test *test, int subtest);
@@ -102,6 +103,7 @@ int test__clang(struct test *test, int subtest);
102const char *test__clang_subtest_get_desc(int subtest); 103const char *test__clang_subtest_get_desc(int subtest);
103int test__clang_subtest_get_nr(void); 104int test__clang_subtest_get_nr(void);
104int test__unit_number__scnprint(struct test *test, int subtest); 105int test__unit_number__scnprint(struct test *test, int subtest);
106int test__mem2node(struct test *t, int subtest);
105 107
106bool test__bp_signal_is_supported(void); 108bool test__bp_signal_is_supported(void);
107 109
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index f6789fb029d6..1e5adb65632a 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -56,7 +56,7 @@ int test__vmlinux_matches_kallsyms(struct test *test __maybe_unused, int subtest
56 * be compacted against the list of modules found in the "vmlinux" 56 * be compacted against the list of modules found in the "vmlinux"
57 * code and with the one got from /proc/modules from the "kallsyms" code. 57 * code and with the one got from /proc/modules from the "kallsyms" code.
58 */ 58 */
59 if (__machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, true) <= 0) { 59 if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type) <= 0) {
60 pr_debug("dso__load_kallsyms "); 60 pr_debug("dso__load_kallsyms ");
61 goto out; 61 goto out;
62 } 62 }
@@ -125,7 +125,7 @@ int test__vmlinux_matches_kallsyms(struct test *test __maybe_unused, int subtest
125 125
126 if (pair && UM(pair->start) == mem_start) { 126 if (pair && UM(pair->start) == mem_start) {
127next_pair: 127next_pair:
128 if (strcmp(sym->name, pair->name) == 0) { 128 if (arch__compare_symbol_names(sym->name, pair->name) == 0) {
129 /* 129 /*
130 * kallsyms don't have the symbol end, so we 130 * kallsyms don't have the symbol end, so we
131 * set that by using the next symbol start - 1, 131 * set that by using the next symbol start - 1,
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index 63399af3049f..9f6ce29b83b4 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -56,12 +56,17 @@ void ui_browser__write_nstring(struct ui_browser *browser __maybe_unused, const
56 slsmg_write_nstring(msg, width); 56 slsmg_write_nstring(msg, width);
57} 57}
58 58
59void ui_browser__vprintf(struct ui_browser *browser __maybe_unused, const char *fmt, va_list args)
60{
61 slsmg_vprintf(fmt, args);
62}
63
59void ui_browser__printf(struct ui_browser *browser __maybe_unused, const char *fmt, ...) 64void ui_browser__printf(struct ui_browser *browser __maybe_unused, const char *fmt, ...)
60{ 65{
61 va_list args; 66 va_list args;
62 67
63 va_start(args, fmt); 68 va_start(args, fmt);
64 slsmg_vprintf(fmt, args); 69 ui_browser__vprintf(browser, fmt, args);
65 va_end(args); 70 va_end(args);
66} 71}
67 72
@@ -779,6 +784,4 @@ void ui_browser__init(void)
779 struct ui_browser_colorset *c = &ui_browser__colorsets[i++]; 784 struct ui_browser_colorset *c = &ui_browser__colorsets[i++];
780 sltt_set_color(c->colorset, c->name, c->fg, c->bg); 785 sltt_set_color(c->colorset, c->name, c->fg, c->bg);
781 } 786 }
782
783 annotate_browser__init();
784} 787}
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index 03e1734412b9..70057178ee34 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -3,6 +3,7 @@
3#define _PERF_UI_BROWSER_H_ 1 3#define _PERF_UI_BROWSER_H_ 1
4 4
5#include <linux/types.h> 5#include <linux/types.h>
6#include <stdarg.h>
6 7
7#define HE_COLORSET_TOP 50 8#define HE_COLORSET_TOP 50
8#define HE_COLORSET_MEDIUM 51 9#define HE_COLORSET_MEDIUM 51
@@ -40,6 +41,7 @@ void ui_browser__reset_index(struct ui_browser *browser);
40void ui_browser__gotorc(struct ui_browser *browser, int y, int x); 41void ui_browser__gotorc(struct ui_browser *browser, int y, int x);
41void ui_browser__write_nstring(struct ui_browser *browser, const char *msg, 42void ui_browser__write_nstring(struct ui_browser *browser, const char *msg,
42 unsigned int width); 43 unsigned int width);
44void ui_browser__vprintf(struct ui_browser *browser, const char *fmt, va_list args);
43void ui_browser__printf(struct ui_browser *browser, const char *fmt, ...); 45void ui_browser__printf(struct ui_browser *browser, const char *fmt, ...);
44void ui_browser__write_graph(struct ui_browser *browser, int graph); 46void ui_browser__write_graph(struct ui_browser *browser, int graph);
45void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column, 47void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
@@ -77,5 +79,4 @@ void ui_browser__list_head_seek(struct ui_browser *browser, off_t offset, int wh
77unsigned int ui_browser__list_head_refresh(struct ui_browser *browser); 79unsigned int ui_browser__list_head_refresh(struct ui_browser *browser);
78 80
79void ui_browser__init(void); 81void ui_browser__init(void);
80void annotate_browser__init(void);
81#endif /* _PERF_UI_BROWSER_H_ */ 82#endif /* _PERF_UI_BROWSER_H_ */
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 286427975112..c02fb437ac8e 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -9,7 +9,6 @@
9#include "../../util/sort.h" 9#include "../../util/sort.h"
10#include "../../util/symbol.h" 10#include "../../util/symbol.h"
11#include "../../util/evsel.h" 11#include "../../util/evsel.h"
12#include "../../util/config.h"
13#include "../../util/evlist.h" 12#include "../../util/evlist.h"
14#include <inttypes.h> 13#include <inttypes.h>
15#include <pthread.h> 14#include <pthread.h>
@@ -22,28 +21,6 @@ struct disasm_line_samples {
22 struct sym_hist_entry he; 21 struct sym_hist_entry he;
23}; 22};
24 23
25#define IPC_WIDTH 6
26#define CYCLES_WIDTH 6
27
28struct browser_line {
29 u32 idx;
30 int idx_asm;
31 int jump_sources;
32};
33
34static struct annotate_browser_opt {
35 bool hide_src_code,
36 use_offset,
37 jump_arrows,
38 show_linenr,
39 show_nr_jumps,
40 show_nr_samples,
41 show_total_period;
42} annotate_browser__opts = {
43 .use_offset = true,
44 .jump_arrows = true,
45};
46
47struct arch; 24struct arch;
48 25
49struct annotate_browser { 26struct annotate_browser {
@@ -51,245 +28,98 @@ struct annotate_browser {
51 struct rb_root entries; 28 struct rb_root entries;
52 struct rb_node *curr_hot; 29 struct rb_node *curr_hot;
53 struct annotation_line *selection; 30 struct annotation_line *selection;
54 struct annotation_line **offsets;
55 struct arch *arch; 31 struct arch *arch;
56 int nr_events;
57 u64 start;
58 int nr_asm_entries;
59 int nr_entries;
60 int max_jump_sources;
61 int nr_jumps;
62 bool searching_backwards; 32 bool searching_backwards;
63 bool have_cycles;
64 u8 addr_width;
65 u8 jumps_width;
66 u8 target_width;
67 u8 min_addr_width;
68 u8 max_addr_width;
69 char search_bf[128]; 33 char search_bf[128];
70}; 34};
71 35
72static inline struct browser_line *browser_line(struct annotation_line *al) 36static inline struct annotation *browser__annotation(struct ui_browser *browser)
73{ 37{
74 void *ptr = al; 38 struct map_symbol *ms = browser->priv;
75 39 return symbol__annotation(ms->sym);
76 ptr = container_of(al, struct disasm_line, al);
77 return ptr - sizeof(struct browser_line);
78} 40}
79 41
80static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, 42static bool disasm_line__filter(struct ui_browser *browser, void *entry)
81 void *entry)
82{ 43{
83 if (annotate_browser__opts.hide_src_code) { 44 struct annotation *notes = browser__annotation(browser);
84 struct annotation_line *al = list_entry(entry, struct annotation_line, node); 45 struct annotation_line *al = list_entry(entry, struct annotation_line, node);
85 46 return annotation_line__filter(al, notes);
86 return al->offset == -1;
87 }
88
89 return false;
90} 47}
91 48
92static int annotate_browser__jumps_percent_color(struct annotate_browser *browser, 49static int ui_browser__jumps_percent_color(struct ui_browser *browser, int nr, bool current)
93 int nr, bool current)
94{ 50{
95 if (current && (!browser->b.use_navkeypressed || browser->b.navkeypressed)) 51 struct annotation *notes = browser__annotation(browser);
52
53 if (current && (!browser->use_navkeypressed || browser->navkeypressed))
96 return HE_COLORSET_SELECTED; 54 return HE_COLORSET_SELECTED;
97 if (nr == browser->max_jump_sources) 55 if (nr == notes->max_jump_sources)
98 return HE_COLORSET_TOP; 56 return HE_COLORSET_TOP;
99 if (nr > 1) 57 if (nr > 1)
100 return HE_COLORSET_MEDIUM; 58 return HE_COLORSET_MEDIUM;
101 return HE_COLORSET_NORMAL; 59 return HE_COLORSET_NORMAL;
102} 60}
103 61
104static int annotate_browser__set_jumps_percent_color(struct annotate_browser *browser, 62static int ui_browser__set_jumps_percent_color(void *browser, int nr, bool current)
105 int nr, bool current)
106{ 63{
107 int color = annotate_browser__jumps_percent_color(browser, nr, current); 64 int color = ui_browser__jumps_percent_color(browser, nr, current);
108 return ui_browser__set_color(&browser->b, color); 65 return ui_browser__set_color(browser, color);
109} 66}
110 67
111static int annotate_browser__pcnt_width(struct annotate_browser *ab) 68static int annotate_browser__set_color(void *browser, int color)
112{ 69{
113 return (annotate_browser__opts.show_total_period ? 12 : 7) * ab->nr_events; 70 return ui_browser__set_color(browser, color);
114} 71}
115 72
116static int annotate_browser__cycles_width(struct annotate_browser *ab) 73static void annotate_browser__write_graph(void *browser, int graph)
117{ 74{
118 return ab->have_cycles ? IPC_WIDTH + CYCLES_WIDTH : 0; 75 ui_browser__write_graph(browser, graph);
119} 76}
120 77
121static void disasm_line__write(struct disasm_line *dl, struct ui_browser *browser, 78static void annotate_browser__set_percent_color(void *browser, double percent, bool current)
122 char *bf, size_t size)
123{ 79{
124 if (dl->ins.ops && dl->ins.ops->scnprintf) { 80 ui_browser__set_percent_color(browser, percent, current);
125 if (ins__is_jump(&dl->ins)) { 81}
126 bool fwd = dl->ops.target.offset > dl->al.offset;
127
128 ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR :
129 SLSMG_UARROW_CHAR);
130 SLsmg_write_char(' ');
131 } else if (ins__is_call(&dl->ins)) {
132 ui_browser__write_graph(browser, SLSMG_RARROW_CHAR);
133 SLsmg_write_char(' ');
134 } else if (ins__is_ret(&dl->ins)) {
135 ui_browser__write_graph(browser, SLSMG_LARROW_CHAR);
136 SLsmg_write_char(' ');
137 } else {
138 ui_browser__write_nstring(browser, " ", 2);
139 }
140 } else {
141 ui_browser__write_nstring(browser, " ", 2);
142 }
143 82
144 disasm_line__scnprintf(dl, bf, size, !annotate_browser__opts.use_offset); 83static void annotate_browser__printf(void *browser, const char *fmt, ...)
84{
85 va_list args;
86
87 va_start(args, fmt);
88 ui_browser__vprintf(browser, fmt, args);
89 va_end(args);
145} 90}
146 91
147static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 92static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
148{ 93{
149 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 94 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
95 struct annotation *notes = browser__annotation(browser);
150 struct annotation_line *al = list_entry(entry, struct annotation_line, node); 96 struct annotation_line *al = list_entry(entry, struct annotation_line, node);
151 struct browser_line *bl = browser_line(al); 97 struct annotation_write_ops ops = {
152 bool current_entry = ui_browser__is_current_entry(browser, row); 98 .first_line = row == 0,
153 bool change_color = (!annotate_browser__opts.hide_src_code && 99 .current_entry = ui_browser__is_current_entry(browser, row),
154 (!current_entry || (browser->use_navkeypressed && 100 .change_color = (!notes->options->hide_src_code &&
155 !browser->navkeypressed))); 101 (!ops.current_entry ||
156 int width = browser->width, printed; 102 (browser->use_navkeypressed &&
157 int i, pcnt_width = annotate_browser__pcnt_width(ab), 103 !browser->navkeypressed))),
158 cycles_width = annotate_browser__cycles_width(ab); 104 .width = browser->width,
159 double percent_max = 0.0; 105 .obj = browser,
160 char bf[256]; 106 .set_color = annotate_browser__set_color,
161 bool show_title = false; 107 .set_percent_color = annotate_browser__set_percent_color,
162 108 .set_jumps_percent_color = ui_browser__set_jumps_percent_color,
163 for (i = 0; i < ab->nr_events; i++) { 109 .printf = annotate_browser__printf,
164 if (al->samples[i].percent > percent_max) 110 .write_graph = annotate_browser__write_graph,
165 percent_max = al->samples[i].percent; 111 };
166 }
167
168 if ((row == 0) && (al->offset == -1 || percent_max == 0.0)) {
169 if (ab->have_cycles) {
170 if (al->ipc == 0.0 && al->cycles == 0)
171 show_title = true;
172 } else
173 show_title = true;
174 }
175
176 if (al->offset != -1 && percent_max != 0.0) {
177 for (i = 0; i < ab->nr_events; i++) {
178 ui_browser__set_percent_color(browser,
179 al->samples[i].percent,
180 current_entry);
181 if (annotate_browser__opts.show_total_period) {
182 ui_browser__printf(browser, "%11" PRIu64 " ",
183 al->samples[i].he.period);
184 } else if (annotate_browser__opts.show_nr_samples) {
185 ui_browser__printf(browser, "%6" PRIu64 " ",
186 al->samples[i].he.nr_samples);
187 } else {
188 ui_browser__printf(browser, "%6.2f ",
189 al->samples[i].percent);
190 }
191 }
192 } else {
193 ui_browser__set_percent_color(browser, 0, current_entry);
194
195 if (!show_title)
196 ui_browser__write_nstring(browser, " ", pcnt_width);
197 else {
198 ui_browser__printf(browser, "%*s", pcnt_width,
199 annotate_browser__opts.show_total_period ? "Period" :
200 annotate_browser__opts.show_nr_samples ? "Samples" : "Percent");
201 }
202 }
203 if (ab->have_cycles) {
204 if (al->ipc)
205 ui_browser__printf(browser, "%*.2f ", IPC_WIDTH - 1, al->ipc);
206 else if (!show_title)
207 ui_browser__write_nstring(browser, " ", IPC_WIDTH);
208 else
209 ui_browser__printf(browser, "%*s ", IPC_WIDTH - 1, "IPC");
210
211 if (al->cycles)
212 ui_browser__printf(browser, "%*" PRIu64 " ",
213 CYCLES_WIDTH - 1, al->cycles);
214 else if (!show_title)
215 ui_browser__write_nstring(browser, " ", CYCLES_WIDTH);
216 else
217 ui_browser__printf(browser, "%*s ", CYCLES_WIDTH - 1, "Cycle");
218 }
219
220 SLsmg_write_char(' ');
221 112
222 /* The scroll bar isn't being used */ 113 /* The scroll bar isn't being used */
223 if (!browser->navkeypressed) 114 if (!browser->navkeypressed)
224 width += 1; 115 ops.width += 1;
225
226 if (!*al->line)
227 ui_browser__write_nstring(browser, " ", width - pcnt_width - cycles_width);
228 else if (al->offset == -1) {
229 if (al->line_nr && annotate_browser__opts.show_linenr)
230 printed = scnprintf(bf, sizeof(bf), "%-*d ",
231 ab->addr_width + 1, al->line_nr);
232 else
233 printed = scnprintf(bf, sizeof(bf), "%*s ",
234 ab->addr_width, " ");
235 ui_browser__write_nstring(browser, bf, printed);
236 ui_browser__write_nstring(browser, al->line, width - printed - pcnt_width - cycles_width + 1);
237 } else {
238 u64 addr = al->offset;
239 int color = -1;
240
241 if (!annotate_browser__opts.use_offset)
242 addr += ab->start;
243
244 if (!annotate_browser__opts.use_offset) {
245 printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr);
246 } else {
247 if (bl->jump_sources) {
248 if (annotate_browser__opts.show_nr_jumps) {
249 int prev;
250 printed = scnprintf(bf, sizeof(bf), "%*d ",
251 ab->jumps_width,
252 bl->jump_sources);
253 prev = annotate_browser__set_jumps_percent_color(ab, bl->jump_sources,
254 current_entry);
255 ui_browser__write_nstring(browser, bf, printed);
256 ui_browser__set_color(browser, prev);
257 }
258
259 printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ",
260 ab->target_width, addr);
261 } else {
262 printed = scnprintf(bf, sizeof(bf), "%*s ",
263 ab->addr_width, " ");
264 }
265 }
266
267 if (change_color)
268 color = ui_browser__set_color(browser, HE_COLORSET_ADDR);
269 ui_browser__write_nstring(browser, bf, printed);
270 if (change_color)
271 ui_browser__set_color(browser, color);
272 116
273 disasm_line__write(disasm_line(al), browser, bf, sizeof(bf)); 117 annotation_line__write(al, notes, &ops);
274 118
275 ui_browser__write_nstring(browser, bf, width - pcnt_width - cycles_width - 3 - printed); 119 if (ops.current_entry)
276 }
277
278 if (current_entry)
279 ab->selection = al; 120 ab->selection = al;
280} 121}
281 122
282static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym)
283{
284 if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins)
285 || !disasm_line__has_offset(dl)
286 || dl->ops.target.offset < 0
287 || dl->ops.target.offset >= (s64)symbol__size(sym))
288 return false;
289
290 return true;
291}
292
293static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor) 123static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
294{ 124{
295 struct disasm_line *pos = list_prev_entry(cursor, al.node); 125 struct disasm_line *pos = list_prev_entry(cursor, al.node);
@@ -314,39 +144,65 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
314 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 144 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
315 struct disasm_line *cursor = disasm_line(ab->selection); 145 struct disasm_line *cursor = disasm_line(ab->selection);
316 struct annotation_line *target; 146 struct annotation_line *target;
317 struct browser_line *btarget, *bcursor;
318 unsigned int from, to; 147 unsigned int from, to;
319 struct map_symbol *ms = ab->b.priv; 148 struct map_symbol *ms = ab->b.priv;
320 struct symbol *sym = ms->sym; 149 struct symbol *sym = ms->sym;
321 u8 pcnt_width = annotate_browser__pcnt_width(ab); 150 struct annotation *notes = symbol__annotation(sym);
151 u8 pcnt_width = annotation__pcnt_width(notes);
152 int width;
322 153
323 /* PLT symbols contain external offsets */ 154 /* PLT symbols contain external offsets */
324 if (strstr(sym->name, "@plt")) 155 if (strstr(sym->name, "@plt"))
325 return; 156 return;
326 157
327 if (!disasm_line__is_valid_jump(cursor, sym)) 158 if (!disasm_line__is_valid_local_jump(cursor, sym))
328 return; 159 return;
329 160
330 target = ab->offsets[cursor->ops.target.offset]; 161 /*
331 162 * This first was seen with a gcc function, _cpp_lex_token, that
332 bcursor = browser_line(&cursor->al); 163 * has the usual jumps:
333 btarget = browser_line(target); 164 *
165 * │1159e6c: ↓ jne 115aa32 <_cpp_lex_token@@Base+0xf92>
166 *
167 * I.e. jumps to a label inside that function (_cpp_lex_token), and
168 * those works, but also this kind:
169 *
170 * │1159e8b: ↓ jne c469be <cpp_named_operator2name@@Base+0xa72>
171 *
172 * I.e. jumps to another function, outside _cpp_lex_token, which
173 * are not being correctly handled generating as a side effect references
174 * to ab->offset[] entries that are set to NULL, so to make this code
175 * more robust, check that here.
176 *
177 * A proper fix for will be put in place, looking at the function
178 * name right after the '<' token and probably treating this like a
179 * 'call' instruction.
180 */
181 target = notes->offsets[cursor->ops.target.offset];
182 if (target == NULL) {
183 ui_helpline__printf("WARN: jump target inconsistency, press 'o', notes->offsets[%#x] = NULL\n",
184 cursor->ops.target.offset);
185 return;
186 }
334 187
335 if (annotate_browser__opts.hide_src_code) { 188 if (notes->options->hide_src_code) {
336 from = bcursor->idx_asm; 189 from = cursor->al.idx_asm;
337 to = btarget->idx_asm; 190 to = target->idx_asm;
338 } else { 191 } else {
339 from = (u64)bcursor->idx; 192 from = (u64)cursor->al.idx;
340 to = (u64)btarget->idx; 193 to = (u64)target->idx;
341 } 194 }
342 195
196 width = annotation__cycles_width(notes);
197
343 ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS); 198 ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS);
344 __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width, 199 __ui_browser__line_arrow(browser,
200 pcnt_width + 2 + notes->widths.addr + width,
345 from, to); 201 from, to);
346 202
347 if (is_fused(ab, cursor)) { 203 if (is_fused(ab, cursor)) {
348 ui_browser__mark_fused(browser, 204 ui_browser__mark_fused(browser,
349 pcnt_width + 3 + ab->addr_width, 205 pcnt_width + 3 + notes->widths.addr + width,
350 from - 1, 206 from - 1,
351 to > from ? true : false); 207 to > from ? true : false);
352 } 208 }
@@ -354,11 +210,11 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
354 210
355static unsigned int annotate_browser__refresh(struct ui_browser *browser) 211static unsigned int annotate_browser__refresh(struct ui_browser *browser)
356{ 212{
357 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 213 struct annotation *notes = browser__annotation(browser);
358 int ret = ui_browser__list_head_refresh(browser); 214 int ret = ui_browser__list_head_refresh(browser);
359 int pcnt_width = annotate_browser__pcnt_width(ab); 215 int pcnt_width = annotation__pcnt_width(notes);
360 216
361 if (annotate_browser__opts.jump_arrows) 217 if (notes->options->jump_arrows)
362 annotate_browser__draw_current_jump(browser); 218 annotate_browser__draw_current_jump(browser);
363 219
364 ui_browser__set_color(browser, HE_COLORSET_NORMAL); 220 ui_browser__set_color(browser, HE_COLORSET_NORMAL);
@@ -400,6 +256,7 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line
400static void annotate_browser__set_top(struct annotate_browser *browser, 256static void annotate_browser__set_top(struct annotate_browser *browser,
401 struct annotation_line *pos, u32 idx) 257 struct annotation_line *pos, u32 idx)
402{ 258{
259 struct annotation *notes = browser__annotation(&browser->b);
403 unsigned back; 260 unsigned back;
404 261
405 ui_browser__refresh_dimensions(&browser->b); 262 ui_browser__refresh_dimensions(&browser->b);
@@ -409,7 +266,7 @@ static void annotate_browser__set_top(struct annotate_browser *browser,
409 while (browser->b.top_idx != 0 && back != 0) { 266 while (browser->b.top_idx != 0 && back != 0) {
410 pos = list_entry(pos->node.prev, struct annotation_line, node); 267 pos = list_entry(pos->node.prev, struct annotation_line, node);
411 268
412 if (disasm_line__filter(&browser->b, &pos->node)) 269 if (annotation_line__filter(pos, notes))
413 continue; 270 continue;
414 271
415 --browser->b.top_idx; 272 --browser->b.top_idx;
@@ -423,16 +280,12 @@ static void annotate_browser__set_top(struct annotate_browser *browser,
423static void annotate_browser__set_rb_top(struct annotate_browser *browser, 280static void annotate_browser__set_rb_top(struct annotate_browser *browser,
424 struct rb_node *nd) 281 struct rb_node *nd)
425{ 282{
426 struct browser_line *bpos; 283 struct annotation *notes = browser__annotation(&browser->b);
427 struct annotation_line *pos; 284 struct annotation_line * pos = rb_entry(nd, struct annotation_line, rb_node);
428 u32 idx; 285 u32 idx = pos->idx;
429 286
430 pos = rb_entry(nd, struct annotation_line, rb_node); 287 if (notes->options->hide_src_code)
431 bpos = browser_line(pos); 288 idx = pos->idx_asm;
432
433 idx = bpos->idx;
434 if (annotate_browser__opts.hide_src_code)
435 idx = bpos->idx_asm;
436 annotate_browser__set_top(browser, pos, idx); 289 annotate_browser__set_top(browser, pos, idx);
437 browser->curr_hot = nd; 290 browser->curr_hot = nd;
438} 291}
@@ -480,47 +333,47 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
480 333
481static bool annotate_browser__toggle_source(struct annotate_browser *browser) 334static bool annotate_browser__toggle_source(struct annotate_browser *browser)
482{ 335{
336 struct annotation *notes = browser__annotation(&browser->b);
483 struct annotation_line *al; 337 struct annotation_line *al;
484 struct browser_line *bl;
485 off_t offset = browser->b.index - browser->b.top_idx; 338 off_t offset = browser->b.index - browser->b.top_idx;
486 339
487 browser->b.seek(&browser->b, offset, SEEK_CUR); 340 browser->b.seek(&browser->b, offset, SEEK_CUR);
488 al = list_entry(browser->b.top, struct annotation_line, node); 341 al = list_entry(browser->b.top, struct annotation_line, node);
489 bl = browser_line(al);
490 342
491 if (annotate_browser__opts.hide_src_code) { 343 if (notes->options->hide_src_code) {
492 if (bl->idx_asm < offset) 344 if (al->idx_asm < offset)
493 offset = bl->idx; 345 offset = al->idx;
494 346
495 browser->b.nr_entries = browser->nr_entries; 347 browser->b.nr_entries = notes->nr_entries;
496 annotate_browser__opts.hide_src_code = false; 348 notes->options->hide_src_code = false;
497 browser->b.seek(&browser->b, -offset, SEEK_CUR); 349 browser->b.seek(&browser->b, -offset, SEEK_CUR);
498 browser->b.top_idx = bl->idx - offset; 350 browser->b.top_idx = al->idx - offset;
499 browser->b.index = bl->idx; 351 browser->b.index = al->idx;
500 } else { 352 } else {
501 if (bl->idx_asm < 0) { 353 if (al->idx_asm < 0) {
502 ui_helpline__puts("Only available for assembly lines."); 354 ui_helpline__puts("Only available for assembly lines.");
503 browser->b.seek(&browser->b, -offset, SEEK_CUR); 355 browser->b.seek(&browser->b, -offset, SEEK_CUR);
504 return false; 356 return false;
505 } 357 }
506 358
507 if (bl->idx_asm < offset) 359 if (al->idx_asm < offset)
508 offset = bl->idx_asm; 360 offset = al->idx_asm;
509 361
510 browser->b.nr_entries = browser->nr_asm_entries; 362 browser->b.nr_entries = notes->nr_asm_entries;
511 annotate_browser__opts.hide_src_code = true; 363 notes->options->hide_src_code = true;
512 browser->b.seek(&browser->b, -offset, SEEK_CUR); 364 browser->b.seek(&browser->b, -offset, SEEK_CUR);
513 browser->b.top_idx = bl->idx_asm - offset; 365 browser->b.top_idx = al->idx_asm - offset;
514 browser->b.index = bl->idx_asm; 366 browser->b.index = al->idx_asm;
515 } 367 }
516 368
517 return true; 369 return true;
518} 370}
519 371
520static void annotate_browser__init_asm_mode(struct annotate_browser *browser) 372static void ui_browser__init_asm_mode(struct ui_browser *browser)
521{ 373{
522 ui_browser__reset_index(&browser->b); 374 struct annotation *notes = browser__annotation(browser);
523 browser->b.nr_entries = browser->nr_asm_entries; 375 ui_browser__reset_index(browser);
376 browser->nr_entries = notes->nr_asm_entries;
524} 377}
525 378
526#define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) 379#define SYM_TITLE_MAX_SIZE (PATH_MAX + 64)
@@ -531,6 +384,15 @@ static int sym_title(struct symbol *sym, struct map *map, char *title,
531 return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); 384 return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name);
532} 385}
533 386
387/*
388 * This can be called from external jumps, i.e. jumps from one functon
389 * to another, like from the kernel's entry_SYSCALL_64 function to the
390 * swapgs_restore_regs_and_return_to_usermode() function.
391 *
392 * So all we check here is that dl->ops.target.sym is set, if it is, just
393 * go to that function and when exiting from its disassembly, come back
394 * to the calling function.
395 */
534static bool annotate_browser__callq(struct annotate_browser *browser, 396static bool annotate_browser__callq(struct annotate_browser *browser,
535 struct perf_evsel *evsel, 397 struct perf_evsel *evsel,
536 struct hist_browser_timer *hbt) 398 struct hist_browser_timer *hbt)
@@ -538,35 +400,25 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
538 struct map_symbol *ms = browser->b.priv; 400 struct map_symbol *ms = browser->b.priv;
539 struct disasm_line *dl = disasm_line(browser->selection); 401 struct disasm_line *dl = disasm_line(browser->selection);
540 struct annotation *notes; 402 struct annotation *notes;
541 struct addr_map_symbol target = {
542 .map = ms->map,
543 .addr = map__objdump_2mem(ms->map, dl->ops.target.addr),
544 };
545 char title[SYM_TITLE_MAX_SIZE]; 403 char title[SYM_TITLE_MAX_SIZE];
546 404
547 if (!ins__is_call(&dl->ins)) 405 if (!dl->ops.target.sym) {
548 return false;
549
550 if (map_groups__find_ams(&target) ||
551 map__rip_2objdump(target.map, target.map->map_ip(target.map,
552 target.addr)) !=
553 dl->ops.target.addr) {
554 ui_helpline__puts("The called function was not found."); 406 ui_helpline__puts("The called function was not found.");
555 return true; 407 return true;
556 } 408 }
557 409
558 notes = symbol__annotation(target.sym); 410 notes = symbol__annotation(dl->ops.target.sym);
559 pthread_mutex_lock(&notes->lock); 411 pthread_mutex_lock(&notes->lock);
560 412
561 if (notes->src == NULL && symbol__alloc_hist(target.sym) < 0) { 413 if (notes->src == NULL && symbol__alloc_hist(dl->ops.target.sym) < 0) {
562 pthread_mutex_unlock(&notes->lock); 414 pthread_mutex_unlock(&notes->lock);
563 ui__warning("Not enough memory for annotating '%s' symbol!\n", 415 ui__warning("Not enough memory for annotating '%s' symbol!\n",
564 target.sym->name); 416 dl->ops.target.sym->name);
565 return true; 417 return true;
566 } 418 }
567 419
568 pthread_mutex_unlock(&notes->lock); 420 pthread_mutex_unlock(&notes->lock);
569 symbol__tui_annotate(target.sym, target.map, evsel, hbt); 421 symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt);
570 sym_title(ms->sym, ms->map, title, sizeof(title)); 422 sym_title(ms->sym, ms->map, title, sizeof(title));
571 ui_browser__show_title(&browser->b, title); 423 ui_browser__show_title(&browser->b, title);
572 return true; 424 return true;
@@ -576,23 +428,23 @@ static
576struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser, 428struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser,
577 s64 offset, s64 *idx) 429 s64 offset, s64 *idx)
578{ 430{
579 struct map_symbol *ms = browser->b.priv; 431 struct annotation *notes = browser__annotation(&browser->b);
580 struct symbol *sym = ms->sym;
581 struct annotation *notes = symbol__annotation(sym);
582 struct disasm_line *pos; 432 struct disasm_line *pos;
583 433
584 *idx = 0; 434 *idx = 0;
585 list_for_each_entry(pos, &notes->src->source, al.node) { 435 list_for_each_entry(pos, &notes->src->source, al.node) {
586 if (pos->al.offset == offset) 436 if (pos->al.offset == offset)
587 return pos; 437 return pos;
588 if (!disasm_line__filter(&browser->b, &pos->al.node)) 438 if (!annotation_line__filter(&pos->al, notes))
589 ++*idx; 439 ++*idx;
590 } 440 }
591 441
592 return NULL; 442 return NULL;
593} 443}
594 444
595static bool annotate_browser__jump(struct annotate_browser *browser) 445static bool annotate_browser__jump(struct annotate_browser *browser,
446 struct perf_evsel *evsel,
447 struct hist_browser_timer *hbt)
596{ 448{
597 struct disasm_line *dl = disasm_line(browser->selection); 449 struct disasm_line *dl = disasm_line(browser->selection);
598 u64 offset; 450 u64 offset;
@@ -601,6 +453,11 @@ static bool annotate_browser__jump(struct annotate_browser *browser)
601 if (!ins__is_jump(&dl->ins)) 453 if (!ins__is_jump(&dl->ins))
602 return false; 454 return false;
603 455
456 if (dl->ops.target.outside) {
457 annotate_browser__callq(browser, evsel, hbt);
458 return true;
459 }
460
604 offset = dl->ops.target.offset; 461 offset = dl->ops.target.offset;
605 dl = annotate_browser__find_offset(browser, offset, &idx); 462 dl = annotate_browser__find_offset(browser, offset, &idx);
606 if (dl == NULL) { 463 if (dl == NULL) {
@@ -617,14 +474,12 @@ static
617struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser, 474struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser,
618 char *s, s64 *idx) 475 char *s, s64 *idx)
619{ 476{
620 struct map_symbol *ms = browser->b.priv; 477 struct annotation *notes = browser__annotation(&browser->b);
621 struct symbol *sym = ms->sym;
622 struct annotation *notes = symbol__annotation(sym);
623 struct annotation_line *al = browser->selection; 478 struct annotation_line *al = browser->selection;
624 479
625 *idx = browser->b.index; 480 *idx = browser->b.index;
626 list_for_each_entry_continue(al, &notes->src->source, node) { 481 list_for_each_entry_continue(al, &notes->src->source, node) {
627 if (disasm_line__filter(&browser->b, &al->node)) 482 if (annotation_line__filter(al, notes))
628 continue; 483 continue;
629 484
630 ++*idx; 485 ++*idx;
@@ -656,14 +511,12 @@ static
656struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser, 511struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser,
657 char *s, s64 *idx) 512 char *s, s64 *idx)
658{ 513{
659 struct map_symbol *ms = browser->b.priv; 514 struct annotation *notes = browser__annotation(&browser->b);
660 struct symbol *sym = ms->sym;
661 struct annotation *notes = symbol__annotation(sym);
662 struct annotation_line *al = browser->selection; 515 struct annotation_line *al = browser->selection;
663 516
664 *idx = browser->b.index; 517 *idx = browser->b.index;
665 list_for_each_entry_continue_reverse(al, &notes->src->source, node) { 518 list_for_each_entry_continue_reverse(al, &notes->src->source, node) {
666 if (disasm_line__filter(&browser->b, &al->node)) 519 if (annotation_line__filter(al, notes))
667 continue; 520 continue;
668 521
669 --*idx; 522 --*idx;
@@ -739,19 +592,6 @@ bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,
739 return __annotate_browser__search_reverse(browser); 592 return __annotate_browser__search_reverse(browser);
740} 593}
741 594
742static void annotate_browser__update_addr_width(struct annotate_browser *browser)
743{
744 if (annotate_browser__opts.use_offset)
745 browser->target_width = browser->min_addr_width;
746 else
747 browser->target_width = browser->max_addr_width;
748
749 browser->addr_width = browser->target_width;
750
751 if (annotate_browser__opts.show_nr_jumps)
752 browser->addr_width += browser->jumps_width + 1;
753}
754
755static int annotate_browser__run(struct annotate_browser *browser, 595static int annotate_browser__run(struct annotate_browser *browser,
756 struct perf_evsel *evsel, 596 struct perf_evsel *evsel,
757 struct hist_browser_timer *hbt) 597 struct hist_browser_timer *hbt)
@@ -759,6 +599,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
759 struct rb_node *nd = NULL; 599 struct rb_node *nd = NULL;
760 struct map_symbol *ms = browser->b.priv; 600 struct map_symbol *ms = browser->b.priv;
761 struct symbol *sym = ms->sym; 601 struct symbol *sym = ms->sym;
602 struct annotation *notes = symbol__annotation(ms->sym);
762 const char *help = "Press 'h' for help on key bindings"; 603 const char *help = "Press 'h' for help on key bindings";
763 int delay_secs = hbt ? hbt->refresh : 0; 604 int delay_secs = hbt ? hbt->refresh : 0;
764 int key; 605 int key;
@@ -833,6 +674,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
833 "t Circulate percent, total period, samples view\n" 674 "t Circulate percent, total period, samples view\n"
834 "/ Search string\n" 675 "/ Search string\n"
835 "k Toggle line numbers\n" 676 "k Toggle line numbers\n"
677 "P Print to [symbol_name].annotation file.\n"
836 "r Run available scripts\n" 678 "r Run available scripts\n"
837 "? Search string backwards\n"); 679 "? Search string backwards\n");
838 continue; 680 continue;
@@ -842,8 +684,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
842 continue; 684 continue;
843 } 685 }
844 case 'k': 686 case 'k':
845 annotate_browser__opts.show_linenr = 687 notes->options->show_linenr = !notes->options->show_linenr;
846 !annotate_browser__opts.show_linenr;
847 break; 688 break;
848 case 'H': 689 case 'H':
849 nd = browser->curr_hot; 690 nd = browser->curr_hot;
@@ -853,15 +694,15 @@ static int annotate_browser__run(struct annotate_browser *browser,
853 ui_helpline__puts(help); 694 ui_helpline__puts(help);
854 continue; 695 continue;
855 case 'o': 696 case 'o':
856 annotate_browser__opts.use_offset = !annotate_browser__opts.use_offset; 697 notes->options->use_offset = !notes->options->use_offset;
857 annotate_browser__update_addr_width(browser); 698 annotation__update_column_widths(notes);
858 continue; 699 continue;
859 case 'j': 700 case 'j':
860 annotate_browser__opts.jump_arrows = !annotate_browser__opts.jump_arrows; 701 notes->options->jump_arrows = !notes->options->jump_arrows;
861 continue; 702 continue;
862 case 'J': 703 case 'J':
863 annotate_browser__opts.show_nr_jumps = !annotate_browser__opts.show_nr_jumps; 704 notes->options->show_nr_jumps = !notes->options->show_nr_jumps;
864 annotate_browser__update_addr_width(browser); 705 annotation__update_column_widths(notes);
865 continue; 706 continue;
866 case '/': 707 case '/':
867 if (annotate_browser__search(browser, delay_secs)) { 708 if (annotate_browser__search(browser, delay_secs)) {
@@ -887,7 +728,7 @@ show_help:
887 browser->b.height, 728 browser->b.height,
888 browser->b.index, 729 browser->b.index,
889 browser->b.top_idx, 730 browser->b.top_idx,
890 browser->nr_asm_entries); 731 notes->nr_asm_entries);
891 } 732 }
892 continue; 733 continue;
893 case K_ENTER: 734 case K_ENTER:
@@ -903,22 +744,25 @@ show_help:
903 goto show_sup_ins; 744 goto show_sup_ins;
904 else if (ins__is_ret(&dl->ins)) 745 else if (ins__is_ret(&dl->ins))
905 goto out; 746 goto out;
906 else if (!(annotate_browser__jump(browser) || 747 else if (!(annotate_browser__jump(browser, evsel, hbt) ||
907 annotate_browser__callq(browser, evsel, hbt))) { 748 annotate_browser__callq(browser, evsel, hbt))) {
908show_sup_ins: 749show_sup_ins:
909 ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions."); 750 ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions.");
910 } 751 }
911 continue; 752 continue;
912 } 753 }
754 case 'P':
755 map_symbol__annotation_dump(ms, evsel);
756 continue;
913 case 't': 757 case 't':
914 if (annotate_browser__opts.show_total_period) { 758 if (notes->options->show_total_period) {
915 annotate_browser__opts.show_total_period = false; 759 notes->options->show_total_period = false;
916 annotate_browser__opts.show_nr_samples = true; 760 notes->options->show_nr_samples = true;
917 } else if (annotate_browser__opts.show_nr_samples) 761 } else if (notes->options->show_nr_samples)
918 annotate_browser__opts.show_nr_samples = false; 762 notes->options->show_nr_samples = false;
919 else 763 else
920 annotate_browser__opts.show_total_period = true; 764 notes->options->show_total_period = true;
921 annotate_browser__update_addr_width(browser); 765 annotation__update_column_widths(notes);
922 continue; 766 continue;
923 case K_LEFT: 767 case K_LEFT:
924 case K_ESC: 768 case K_ESC:
@@ -940,12 +784,6 @@ out:
940int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 784int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
941 struct hist_browser_timer *hbt) 785 struct hist_browser_timer *hbt)
942{ 786{
943 /* Set default value for show_total_period and show_nr_samples */
944 annotate_browser__opts.show_total_period =
945 symbol_conf.show_total_period;
946 annotate_browser__opts.show_nr_samples =
947 symbol_conf.show_nr_samples;
948
949 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); 787 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt);
950} 788}
951 789
@@ -959,129 +797,11 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
959 return map_symbol__tui_annotate(&he->ms, evsel, hbt); 797 return map_symbol__tui_annotate(&he->ms, evsel, hbt);
960} 798}
961 799
962
963static unsigned count_insn(struct annotate_browser *browser, u64 start, u64 end)
964{
965 unsigned n_insn = 0;
966 u64 offset;
967
968 for (offset = start; offset <= end; offset++) {
969 if (browser->offsets[offset])
970 n_insn++;
971 }
972 return n_insn;
973}
974
975static void count_and_fill(struct annotate_browser *browser, u64 start, u64 end,
976 struct cyc_hist *ch)
977{
978 unsigned n_insn;
979 u64 offset;
980
981 n_insn = count_insn(browser, start, end);
982 if (n_insn && ch->num && ch->cycles) {
983 float ipc = n_insn / ((double)ch->cycles / (double)ch->num);
984
985 /* Hide data when there are too many overlaps. */
986 if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2)
987 return;
988
989 for (offset = start; offset <= end; offset++) {
990 struct annotation_line *al = browser->offsets[offset];
991
992 if (al)
993 al->ipc = ipc;
994 }
995 }
996}
997
998/*
999 * This should probably be in util/annotate.c to share with the tty
1000 * annotate, but right now we need the per byte offsets arrays,
1001 * which are only here.
1002 */
1003static void annotate__compute_ipc(struct annotate_browser *browser, size_t size,
1004 struct symbol *sym)
1005{
1006 u64 offset;
1007 struct annotation *notes = symbol__annotation(sym);
1008
1009 if (!notes->src || !notes->src->cycles_hist)
1010 return;
1011
1012 pthread_mutex_lock(&notes->lock);
1013 for (offset = 0; offset < size; ++offset) {
1014 struct cyc_hist *ch;
1015
1016 ch = &notes->src->cycles_hist[offset];
1017 if (ch && ch->cycles) {
1018 struct annotation_line *al;
1019
1020 if (ch->have_start)
1021 count_and_fill(browser, ch->start, offset, ch);
1022 al = browser->offsets[offset];
1023 if (al && ch->num_aggr)
1024 al->cycles = ch->cycles_aggr / ch->num_aggr;
1025 browser->have_cycles = true;
1026 }
1027 }
1028 pthread_mutex_unlock(&notes->lock);
1029}
1030
1031static void annotate_browser__mark_jump_targets(struct annotate_browser *browser,
1032 size_t size)
1033{
1034 u64 offset;
1035 struct map_symbol *ms = browser->b.priv;
1036 struct symbol *sym = ms->sym;
1037
1038 /* PLT symbols contain external offsets */
1039 if (strstr(sym->name, "@plt"))
1040 return;
1041
1042 for (offset = 0; offset < size; ++offset) {
1043 struct annotation_line *al = browser->offsets[offset];
1044 struct disasm_line *dl;
1045 struct browser_line *blt;
1046
1047 dl = disasm_line(al);
1048
1049 if (!disasm_line__is_valid_jump(dl, sym))
1050 continue;
1051
1052 al = browser->offsets[dl->ops.target.offset];
1053
1054 /*
1055 * FIXME: Oops, no jump target? Buggy disassembler? Or do we
1056 * have to adjust to the previous offset?
1057 */
1058 if (al == NULL)
1059 continue;
1060
1061 blt = browser_line(al);
1062 if (++blt->jump_sources > browser->max_jump_sources)
1063 browser->max_jump_sources = blt->jump_sources;
1064
1065 ++browser->nr_jumps;
1066 }
1067}
1068
1069static inline int width_jumps(int n)
1070{
1071 if (n >= 100)
1072 return 5;
1073 if (n / 10)
1074 return 2;
1075 return 1;
1076}
1077
1078int symbol__tui_annotate(struct symbol *sym, struct map *map, 800int symbol__tui_annotate(struct symbol *sym, struct map *map,
1079 struct perf_evsel *evsel, 801 struct perf_evsel *evsel,
1080 struct hist_browser_timer *hbt) 802 struct hist_browser_timer *hbt)
1081{ 803{
1082 struct annotation_line *al; 804 struct annotation *notes = symbol__annotation(sym);
1083 struct annotation *notes;
1084 size_t size;
1085 struct map_symbol ms = { 805 struct map_symbol ms = {
1086 .map = map, 806 .map = map,
1087 .sym = sym, 807 .sym = sym,
@@ -1097,26 +817,14 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1097 }, 817 },
1098 }; 818 };
1099 int ret = -1, err; 819 int ret = -1, err;
1100 int nr_pcnt = 1;
1101 820
1102 if (sym == NULL) 821 if (sym == NULL)
1103 return -1; 822 return -1;
1104 823
1105 size = symbol__size(sym);
1106
1107 if (map->dso->annotate_warned) 824 if (map->dso->annotate_warned)
1108 return -1; 825 return -1;
1109 826
1110 browser.offsets = zalloc(size * sizeof(struct annotation_line *)); 827 err = symbol__annotate2(sym, map, evsel, &annotation__default_options, &browser.arch);
1111 if (browser.offsets == NULL) {
1112 ui__error("Not enough memory!");
1113 return -1;
1114 }
1115
1116 if (perf_evsel__is_group_event(evsel))
1117 nr_pcnt = evsel->nr_members;
1118
1119 err = symbol__annotate(sym, map, evsel, sizeof(struct browser_line), &browser.arch);
1120 if (err) { 828 if (err) {
1121 char msg[BUFSIZ]; 829 char msg[BUFSIZ];
1122 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 830 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
@@ -1124,110 +832,21 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1124 goto out_free_offsets; 832 goto out_free_offsets;
1125 } 833 }
1126 834
1127 symbol__calc_percent(sym, evsel);
1128
1129 ui_helpline__push("Press ESC to exit"); 835 ui_helpline__push("Press ESC to exit");
1130 836
1131 notes = symbol__annotation(sym); 837 browser.b.width = notes->max_line_len;
1132 browser.start = map__rip_2objdump(map, sym->start); 838 browser.b.nr_entries = notes->nr_entries;
1133
1134 list_for_each_entry(al, &notes->src->source, node) {
1135 struct browser_line *bpos;
1136 size_t line_len = strlen(al->line);
1137
1138 if (browser.b.width < line_len)
1139 browser.b.width = line_len;
1140 bpos = browser_line(al);
1141 bpos->idx = browser.nr_entries++;
1142 if (al->offset != -1) {
1143 bpos->idx_asm = browser.nr_asm_entries++;
1144 /*
1145 * FIXME: short term bandaid to cope with assembly
1146 * routines that comes with labels in the same column
1147 * as the address in objdump, sigh.
1148 *
1149 * E.g. copy_user_generic_unrolled
1150 */
1151 if (al->offset < (s64)size)
1152 browser.offsets[al->offset] = al;
1153 } else
1154 bpos->idx_asm = -1;
1155 }
1156
1157 annotate_browser__mark_jump_targets(&browser, size);
1158 annotate__compute_ipc(&browser, size, sym);
1159
1160 browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size);
1161 browser.max_addr_width = hex_width(sym->end);
1162 browser.jumps_width = width_jumps(browser.max_jump_sources);
1163 browser.nr_events = nr_pcnt;
1164 browser.b.nr_entries = browser.nr_entries;
1165 browser.b.entries = &notes->src->source, 839 browser.b.entries = &notes->src->source,
1166 browser.b.width += 18; /* Percentage */ 840 browser.b.width += 18; /* Percentage */
1167 841
1168 if (annotate_browser__opts.hide_src_code) 842 if (notes->options->hide_src_code)
1169 annotate_browser__init_asm_mode(&browser); 843 ui_browser__init_asm_mode(&browser.b);
1170
1171 annotate_browser__update_addr_width(&browser);
1172 844
1173 ret = annotate_browser__run(&browser, evsel, hbt); 845 ret = annotate_browser__run(&browser, evsel, hbt);
1174 846
1175 annotated_source__purge(notes->src); 847 annotated_source__purge(notes->src);
1176 848
1177out_free_offsets: 849out_free_offsets:
1178 free(browser.offsets); 850 zfree(&notes->offsets);
1179 return ret; 851 return ret;
1180} 852}
1181
1182#define ANNOTATE_CFG(n) \
1183 { .name = #n, .value = &annotate_browser__opts.n, }
1184
1185/*
1186 * Keep the entries sorted, they are bsearch'ed
1187 */
1188static struct annotate_config {
1189 const char *name;
1190 bool *value;
1191} annotate__configs[] = {
1192 ANNOTATE_CFG(hide_src_code),
1193 ANNOTATE_CFG(jump_arrows),
1194 ANNOTATE_CFG(show_linenr),
1195 ANNOTATE_CFG(show_nr_jumps),
1196 ANNOTATE_CFG(show_nr_samples),
1197 ANNOTATE_CFG(show_total_period),
1198 ANNOTATE_CFG(use_offset),
1199};
1200
1201#undef ANNOTATE_CFG
1202
1203static int annotate_config__cmp(const void *name, const void *cfgp)
1204{
1205 const struct annotate_config *cfg = cfgp;
1206
1207 return strcmp(name, cfg->name);
1208}
1209
1210static int annotate__config(const char *var, const char *value,
1211 void *data __maybe_unused)
1212{
1213 struct annotate_config *cfg;
1214 const char *name;
1215
1216 if (!strstarts(var, "annotate."))
1217 return 0;
1218
1219 name = var + 9;
1220 cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs),
1221 sizeof(struct annotate_config), annotate_config__cmp);
1222
1223 if (cfg == NULL)
1224 ui__warning("%s variable unknown, ignoring...", var);
1225 else
1226 *cfg->value = perf_config_bool(name, value);
1227 return 0;
1228}
1229
1230void annotate_browser__init(void)
1231{
1232 perf_config(annotate__config, NULL);
1233}
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 68146f4620a5..8b4e82548f8e 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -608,7 +608,8 @@ static int hist_browser__title(struct hist_browser *browser, char *bf, size_t si
608 return browser->title ? browser->title(browser, bf, size) : 0; 608 return browser->title ? browser->title(browser, bf, size) : 0;
609} 609}
610 610
611int hist_browser__run(struct hist_browser *browser, const char *help) 611int hist_browser__run(struct hist_browser *browser, const char *help,
612 bool warn_lost_event)
612{ 613{
613 int key; 614 int key;
614 char title[160]; 615 char title[160];
@@ -638,8 +639,9 @@ int hist_browser__run(struct hist_browser *browser, const char *help)
638 nr_entries = hist_browser__nr_entries(browser); 639 nr_entries = hist_browser__nr_entries(browser);
639 ui_browser__update_nr_entries(&browser->b, nr_entries); 640 ui_browser__update_nr_entries(&browser->b, nr_entries);
640 641
641 if (browser->hists->stats.nr_lost_warned != 642 if (warn_lost_event &&
642 browser->hists->stats.nr_events[PERF_RECORD_LOST]) { 643 (browser->hists->stats.nr_lost_warned !=
644 browser->hists->stats.nr_events[PERF_RECORD_LOST])) {
643 browser->hists->stats.nr_lost_warned = 645 browser->hists->stats.nr_lost_warned =
644 browser->hists->stats.nr_events[PERF_RECORD_LOST]; 646 browser->hists->stats.nr_events[PERF_RECORD_LOST];
645 ui_browser__warn_lost_events(&browser->b); 647 ui_browser__warn_lost_events(&browser->b);
@@ -2221,7 +2223,7 @@ static int perf_evsel_browser_title(struct hist_browser *browser,
2221 u64 nr_events = hists->stats.total_period; 2223 u64 nr_events = hists->stats.total_period;
2222 struct perf_evsel *evsel = hists_to_evsel(hists); 2224 struct perf_evsel *evsel = hists_to_evsel(hists);
2223 const char *ev_name = perf_evsel__name(evsel); 2225 const char *ev_name = perf_evsel__name(evsel);
2224 char buf[512]; 2226 char buf[512], sample_freq_str[64] = "";
2225 size_t buflen = sizeof(buf); 2227 size_t buflen = sizeof(buf);
2226 char ref[30] = " show reference callgraph, "; 2228 char ref[30] = " show reference callgraph, ";
2227 bool enable_ref = false; 2229 bool enable_ref = false;
@@ -2253,10 +2255,15 @@ static int perf_evsel_browser_title(struct hist_browser *browser,
2253 if (symbol_conf.show_ref_callgraph && 2255 if (symbol_conf.show_ref_callgraph &&
2254 strstr(ev_name, "call-graph=no")) 2256 strstr(ev_name, "call-graph=no"))
2255 enable_ref = true; 2257 enable_ref = true;
2258
2259 if (!is_report_browser(hbt))
2260 scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq);
2261
2256 nr_samples = convert_unit(nr_samples, &unit); 2262 nr_samples = convert_unit(nr_samples, &unit);
2257 printed = scnprintf(bf, size, 2263 printed = scnprintf(bf, size,
2258 "Samples: %lu%c of event '%s',%sEvent count (approx.): %" PRIu64, 2264 "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64,
2259 nr_samples, unit, ev_name, enable_ref ? ref : " ", nr_events); 2265 nr_samples, unit, evsel->nr_members > 1 ? "s" : "",
2266 ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
2260 2267
2261 2268
2262 if (hists->uid_filter_str) 2269 if (hists->uid_filter_str)
@@ -2763,7 +2770,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2763 bool left_exits, 2770 bool left_exits,
2764 struct hist_browser_timer *hbt, 2771 struct hist_browser_timer *hbt,
2765 float min_pcnt, 2772 float min_pcnt,
2766 struct perf_env *env) 2773 struct perf_env *env,
2774 bool warn_lost_event)
2767{ 2775{
2768 struct hists *hists = evsel__hists(evsel); 2776 struct hists *hists = evsel__hists(evsel);
2769 struct hist_browser *browser = perf_evsel_browser__new(evsel, hbt, env); 2777 struct hist_browser *browser = perf_evsel_browser__new(evsel, hbt, env);
@@ -2844,7 +2852,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2844 2852
2845 nr_options = 0; 2853 nr_options = 0;
2846 2854
2847 key = hist_browser__run(browser, helpline); 2855 key = hist_browser__run(browser, helpline,
2856 warn_lost_event);
2848 2857
2849 if (browser->he_selection != NULL) { 2858 if (browser->he_selection != NULL) {
2850 thread = hist_browser__selected_thread(browser); 2859 thread = hist_browser__selected_thread(browser);
@@ -3184,7 +3193,8 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
3184 3193
3185static int perf_evsel_menu__run(struct perf_evsel_menu *menu, 3194static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
3186 int nr_events, const char *help, 3195 int nr_events, const char *help,
3187 struct hist_browser_timer *hbt) 3196 struct hist_browser_timer *hbt,
3197 bool warn_lost_event)
3188{ 3198{
3189 struct perf_evlist *evlist = menu->b.priv; 3199 struct perf_evlist *evlist = menu->b.priv;
3190 struct perf_evsel *pos; 3200 struct perf_evsel *pos;
@@ -3203,7 +3213,9 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
3203 case K_TIMER: 3213 case K_TIMER:
3204 hbt->timer(hbt->arg); 3214 hbt->timer(hbt->arg);
3205 3215
3206 if (!menu->lost_events_warned && menu->lost_events) { 3216 if (!menu->lost_events_warned &&
3217 menu->lost_events &&
3218 warn_lost_event) {
3207 ui_browser__warn_lost_events(&menu->b); 3219 ui_browser__warn_lost_events(&menu->b);
3208 menu->lost_events_warned = true; 3220 menu->lost_events_warned = true;
3209 } 3221 }
@@ -3224,7 +3236,8 @@ browse_hists:
3224 key = perf_evsel__hists_browse(pos, nr_events, help, 3236 key = perf_evsel__hists_browse(pos, nr_events, help,
3225 true, hbt, 3237 true, hbt,
3226 menu->min_pcnt, 3238 menu->min_pcnt,
3227 menu->env); 3239 menu->env,
3240 warn_lost_event);
3228 ui_browser__show_title(&menu->b, title); 3241 ui_browser__show_title(&menu->b, title);
3229 switch (key) { 3242 switch (key) {
3230 case K_TAB: 3243 case K_TAB:
@@ -3282,7 +3295,8 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
3282 int nr_entries, const char *help, 3295 int nr_entries, const char *help,
3283 struct hist_browser_timer *hbt, 3296 struct hist_browser_timer *hbt,
3284 float min_pcnt, 3297 float min_pcnt,
3285 struct perf_env *env) 3298 struct perf_env *env,
3299 bool warn_lost_event)
3286{ 3300{
3287 struct perf_evsel *pos; 3301 struct perf_evsel *pos;
3288 struct perf_evsel_menu menu = { 3302 struct perf_evsel_menu menu = {
@@ -3309,13 +3323,15 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
3309 menu.b.width = line_len; 3323 menu.b.width = line_len;
3310 } 3324 }
3311 3325
3312 return perf_evsel_menu__run(&menu, nr_entries, help, hbt); 3326 return perf_evsel_menu__run(&menu, nr_entries, help,
3327 hbt, warn_lost_event);
3313} 3328}
3314 3329
3315int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 3330int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
3316 struct hist_browser_timer *hbt, 3331 struct hist_browser_timer *hbt,
3317 float min_pcnt, 3332 float min_pcnt,
3318 struct perf_env *env) 3333 struct perf_env *env,
3334 bool warn_lost_event)
3319{ 3335{
3320 int nr_entries = evlist->nr_entries; 3336 int nr_entries = evlist->nr_entries;
3321 3337
@@ -3325,7 +3341,7 @@ single_entry:
3325 3341
3326 return perf_evsel__hists_browse(first, nr_entries, help, 3342 return perf_evsel__hists_browse(first, nr_entries, help,
3327 false, hbt, min_pcnt, 3343 false, hbt, min_pcnt,
3328 env); 3344 env, warn_lost_event);
3329 } 3345 }
3330 3346
3331 if (symbol_conf.event_group) { 3347 if (symbol_conf.event_group) {
@@ -3342,5 +3358,6 @@ single_entry:
3342 } 3358 }
3343 3359
3344 return __perf_evlist__tui_browse_hists(evlist, nr_entries, help, 3360 return __perf_evlist__tui_browse_hists(evlist, nr_entries, help,
3345 hbt, min_pcnt, env); 3361 hbt, min_pcnt, env,
3362 warn_lost_event);
3346} 3363}
diff --git a/tools/perf/ui/browsers/hists.h b/tools/perf/ui/browsers/hists.h
index ba431777f559..9428bee076f2 100644
--- a/tools/perf/ui/browsers/hists.h
+++ b/tools/perf/ui/browsers/hists.h
@@ -28,7 +28,8 @@ struct hist_browser {
28 28
29struct hist_browser *hist_browser__new(struct hists *hists); 29struct hist_browser *hist_browser__new(struct hists *hists);
30void hist_browser__delete(struct hist_browser *browser); 30void hist_browser__delete(struct hist_browser *browser);
31int hist_browser__run(struct hist_browser *browser, const char *help); 31int hist_browser__run(struct hist_browser *browser, const char *help,
32 bool warn_lost_event);
32void hist_browser__init(struct hist_browser *browser, 33void hist_browser__init(struct hist_browser *browser,
33 struct hists *hists); 34 struct hists *hists);
34#endif /* _PERF_UI_BROWSER_HISTS_H_ */ 35#endif /* _PERF_UI_BROWSER_HISTS_H_ */
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 25dd1e0ecc58..6832fcb2e6ff 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -840,15 +840,11 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp)
840 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { 840 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
841 const char *name; 841 const char *name;
842 842
843 if (stats->nr_events[i] == 0)
844 continue;
845
846 name = perf_event__name(i); 843 name = perf_event__name(i);
847 if (!strcmp(name, "UNKNOWN")) 844 if (!strcmp(name, "UNKNOWN"))
848 continue; 845 continue;
849 846
850 ret += fprintf(fp, "%16s events: %10d\n", name, 847 ret += fprintf(fp, "%16s events: %10d\n", name, stats->nr_events[i]);
851 stats->nr_events[i]);
852 } 848 }
853 849
854 return ret; 850 return ret;
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index ea0a452550b0..8052373bcd6a 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -106,6 +106,7 @@ libperf-y += units.o
106libperf-y += time-utils.o 106libperf-y += time-utils.o
107libperf-y += expr-bison.o 107libperf-y += expr-bison.o
108libperf-y += branch.o 108libperf-y += branch.o
109libperf-y += mem2node.o
109 110
110libperf-$(CONFIG_LIBBPF) += bpf-loader.o 111libperf-$(CONFIG_LIBBPF) += bpf-loader.o
111libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o 112libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 28b233c3dcbe..3a428d7c59b9 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -14,6 +14,7 @@
14#include "sort.h" 14#include "sort.h"
15#include "build-id.h" 15#include "build-id.h"
16#include "color.h" 16#include "color.h"
17#include "config.h"
17#include "cache.h" 18#include "cache.h"
18#include "symbol.h" 19#include "symbol.h"
19#include "debug.h" 20#include "debug.h"
@@ -27,8 +28,25 @@
27#include <linux/bitops.h> 28#include <linux/bitops.h>
28#include <linux/kernel.h> 29#include <linux/kernel.h>
29 30
31/* FIXME: For the HE_COLORSET */
32#include "ui/browser.h"
33
34/*
35 * FIXME: Using the same values as slang.h,
36 * but that header may not be available everywhere
37 */
38#define LARROW_CHAR ((unsigned char)',')
39#define RARROW_CHAR ((unsigned char)'+')
40#define DARROW_CHAR ((unsigned char)'.')
41#define UARROW_CHAR ((unsigned char)'-')
42
30#include "sane_ctype.h" 43#include "sane_ctype.h"
31 44
45struct annotation_options annotation__default_options = {
46 .use_offset = true,
47 .jump_arrows = true,
48};
49
32const char *disassembler_style; 50const char *disassembler_style;
33const char *objdump_path; 51const char *objdump_path;
34static regex_t file_lineno; 52static regex_t file_lineno;
@@ -184,9 +202,13 @@ bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)
184 return arch->ins_is_fused(arch, ins1, ins2); 202 return arch->ins_is_fused(arch, ins1, ins2);
185} 203}
186 204
187static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *map) 205static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
188{ 206{
189 char *endptr, *tok, *name; 207 char *endptr, *tok, *name;
208 struct map *map = ms->map;
209 struct addr_map_symbol target = {
210 .map = map,
211 };
190 212
191 ops->target.addr = strtoull(ops->raw, &endptr, 16); 213 ops->target.addr = strtoull(ops->raw, &endptr, 16);
192 214
@@ -208,32 +230,36 @@ static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *
208 ops->target.name = strdup(name); 230 ops->target.name = strdup(name);
209 *tok = '>'; 231 *tok = '>';
210 232
211 return ops->target.name == NULL ? -1 : 0; 233 if (ops->target.name == NULL)
234 return -1;
235find_target:
236 target.addr = map__objdump_2mem(map, ops->target.addr);
212 237
213indirect_call: 238 if (map_groups__find_ams(&target) == 0 &&
214 tok = strchr(endptr, '*'); 239 map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
215 if (tok == NULL) { 240 ops->target.sym = target.sym;
216 struct symbol *sym = map__find_symbol(map, map->map_ip(map, ops->target.addr));
217 if (sym != NULL)
218 ops->target.name = strdup(sym->name);
219 else
220 ops->target.addr = 0;
221 return 0;
222 }
223 241
224 ops->target.addr = strtoull(tok + 1, NULL, 16);
225 return 0; 242 return 0;
243
244indirect_call:
245 tok = strchr(endptr, '*');
246 if (tok != NULL)
247 ops->target.addr = strtoull(tok + 1, NULL, 16);
248 goto find_target;
226} 249}
227 250
228static int call__scnprintf(struct ins *ins, char *bf, size_t size, 251static int call__scnprintf(struct ins *ins, char *bf, size_t size,
229 struct ins_operands *ops) 252 struct ins_operands *ops)
230{ 253{
231 if (ops->target.name) 254 if (ops->target.sym)
232 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.name); 255 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name);
233 256
234 if (ops->target.addr == 0) 257 if (ops->target.addr == 0)
235 return ins__raw_scnprintf(ins, bf, size, ops); 258 return ins__raw_scnprintf(ins, bf, size, ops);
236 259
260 if (ops->target.name)
261 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.name);
262
237 return scnprintf(bf, size, "%-6s *%" PRIx64, ins->name, ops->target.addr); 263 return scnprintf(bf, size, "%-6s *%" PRIx64, ins->name, ops->target.addr);
238} 264}
239 265
@@ -244,14 +270,29 @@ static struct ins_ops call_ops = {
244 270
245bool ins__is_call(const struct ins *ins) 271bool ins__is_call(const struct ins *ins)
246{ 272{
247 return ins->ops == &call_ops; 273 return ins->ops == &call_ops || ins->ops == &s390_call_ops;
248} 274}
249 275
250static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map *map __maybe_unused) 276static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map_symbol *ms)
251{ 277{
252 const char *s = strchr(ops->raw, '+'); 278 struct map *map = ms->map;
279 struct symbol *sym = ms->sym;
280 struct addr_map_symbol target = {
281 .map = map,
282 };
253 const char *c = strchr(ops->raw, ','); 283 const char *c = strchr(ops->raw, ',');
254 284 u64 start, end;
285 /*
286 * Examples of lines to parse for the _cpp_lex_token@@Base
287 * function:
288 *
289 * 1159e6c: jne 115aa32 <_cpp_lex_token@@Base+0xf92>
290 * 1159e8b: jne c469be <cpp_named_operator2name@@Base+0xa72>
291 *
292 * The first is a jump to an offset inside the same function,
293 * the second is to another function, i.e. that 0xa72 is an
294 * offset in the cpp_named_operator2name@@base function.
295 */
255 /* 296 /*
256 * skip over possible up to 2 operands to get to address, e.g.: 297 * skip over possible up to 2 operands to get to address, e.g.:
257 * tbnz w0, #26, ffff0000083cd190 <security_file_permission+0xd0> 298 * tbnz w0, #26, ffff0000083cd190 <security_file_permission+0xd0>
@@ -267,8 +308,36 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
267 ops->target.addr = strtoull(ops->raw, NULL, 16); 308 ops->target.addr = strtoull(ops->raw, NULL, 16);
268 } 309 }
269 310
270 if (s++ != NULL) { 311 target.addr = map__objdump_2mem(map, ops->target.addr);
271 ops->target.offset = strtoull(s, NULL, 16); 312 start = map->unmap_ip(map, sym->start),
313 end = map->unmap_ip(map, sym->end);
314
315 ops->target.outside = target.addr < start || target.addr > end;
316
317 /*
318 * FIXME: things like this in _cpp_lex_token (gcc's cc1 program):
319
320 cpp_named_operator2name@@Base+0xa72
321
322 * Point to a place that is after the cpp_named_operator2name
323 * boundaries, i.e. in the ELF symbol table for cc1
324 * cpp_named_operator2name is marked as being 32-bytes long, but it in
325 * fact is much larger than that, so we seem to need a symbols__find()
326 * routine that looks for >= current->start and < next_symbol->start,
327 * possibly just for C++ objects?
328 *
329 * For now lets just make some progress by marking jumps to outside the
330 * current function as call like.
331 *
332 * Actual navigation will come next, with further understanding of how
333 * the symbol searching and disassembly should be done.
334 */
335 if (map_groups__find_ams(&target) == 0 &&
336 map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
337 ops->target.sym = target.sym;
338
339 if (!ops->target.outside) {
340 ops->target.offset = target.addr - start;
272 ops->target.offset_avail = true; 341 ops->target.offset_avail = true;
273 } else { 342 } else {
274 ops->target.offset_avail = false; 343 ops->target.offset_avail = false;
@@ -280,11 +349,15 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
280static int jump__scnprintf(struct ins *ins, char *bf, size_t size, 349static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
281 struct ins_operands *ops) 350 struct ins_operands *ops)
282{ 351{
283 const char *c = strchr(ops->raw, ','); 352 const char *c;
284 353
285 if (!ops->target.addr || ops->target.offset < 0) 354 if (!ops->target.addr || ops->target.offset < 0)
286 return ins__raw_scnprintf(ins, bf, size, ops); 355 return ins__raw_scnprintf(ins, bf, size, ops);
287 356
357 if (ops->target.outside && ops->target.sym != NULL)
358 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name);
359
360 c = strchr(ops->raw, ',');
288 if (c != NULL) { 361 if (c != NULL) {
289 const char *c2 = strchr(c + 1, ','); 362 const char *c2 = strchr(c + 1, ',');
290 363
@@ -340,7 +413,7 @@ static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
340 return 0; 413 return 0;
341} 414}
342 415
343static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map *map) 416static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
344{ 417{
345 ops->locked.ops = zalloc(sizeof(*ops->locked.ops)); 418 ops->locked.ops = zalloc(sizeof(*ops->locked.ops));
346 if (ops->locked.ops == NULL) 419 if (ops->locked.ops == NULL)
@@ -355,7 +428,7 @@ static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map *
355 goto out_free_ops; 428 goto out_free_ops;
356 429
357 if (ops->locked.ins.ops->parse && 430 if (ops->locked.ins.ops->parse &&
358 ops->locked.ins.ops->parse(arch, ops->locked.ops, map) < 0) 431 ops->locked.ins.ops->parse(arch, ops->locked.ops, ms) < 0)
359 goto out_free_ops; 432 goto out_free_ops;
360 433
361 return 0; 434 return 0;
@@ -398,7 +471,7 @@ static struct ins_ops lock_ops = {
398 .scnprintf = lock__scnprintf, 471 .scnprintf = lock__scnprintf,
399}; 472};
400 473
401static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map *map __maybe_unused) 474static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms __maybe_unused)
402{ 475{
403 char *s = strchr(ops->raw, ','), *target, *comment, prev; 476 char *s = strchr(ops->raw, ','), *target, *comment, prev;
404 477
@@ -459,7 +532,7 @@ static struct ins_ops mov_ops = {
459 .scnprintf = mov__scnprintf, 532 .scnprintf = mov__scnprintf,
460}; 533};
461 534
462static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map *map __maybe_unused) 535static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map_symbol *ms __maybe_unused)
463{ 536{
464 char *target, *comment, *s, prev; 537 char *target, *comment, *s, prev;
465 538
@@ -826,6 +899,66 @@ int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
826 return err; 899 return err;
827} 900}
828 901
902static unsigned annotation__count_insn(struct annotation *notes, u64 start, u64 end)
903{
904 unsigned n_insn = 0;
905 u64 offset;
906
907 for (offset = start; offset <= end; offset++) {
908 if (notes->offsets[offset])
909 n_insn++;
910 }
911 return n_insn;
912}
913
914static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 end, struct cyc_hist *ch)
915{
916 unsigned n_insn;
917 u64 offset;
918
919 n_insn = annotation__count_insn(notes, start, end);
920 if (n_insn && ch->num && ch->cycles) {
921 float ipc = n_insn / ((double)ch->cycles / (double)ch->num);
922
923 /* Hide data when there are too many overlaps. */
924 if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2)
925 return;
926
927 for (offset = start; offset <= end; offset++) {
928 struct annotation_line *al = notes->offsets[offset];
929
930 if (al)
931 al->ipc = ipc;
932 }
933 }
934}
935
936void annotation__compute_ipc(struct annotation *notes, size_t size)
937{
938 u64 offset;
939
940 if (!notes->src || !notes->src->cycles_hist)
941 return;
942
943 pthread_mutex_lock(&notes->lock);
944 for (offset = 0; offset < size; ++offset) {
945 struct cyc_hist *ch;
946
947 ch = &notes->src->cycles_hist[offset];
948 if (ch && ch->cycles) {
949 struct annotation_line *al;
950
951 if (ch->have_start)
952 annotation__count_and_fill(notes, ch->start, offset, ch);
953 al = notes->offsets[offset];
954 if (al && ch->num_aggr)
955 al->cycles = ch->cycles_aggr / ch->num_aggr;
956 notes->have_cycles = true;
957 }
958 }
959 pthread_mutex_unlock(&notes->lock);
960}
961
829int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample, 962int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
830 int evidx) 963 int evidx)
831{ 964{
@@ -838,14 +971,14 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *samp
838 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip, sample); 971 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip, sample);
839} 972}
840 973
841static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map) 974static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map_symbol *ms)
842{ 975{
843 dl->ins.ops = ins__find(arch, dl->ins.name); 976 dl->ins.ops = ins__find(arch, dl->ins.name);
844 977
845 if (!dl->ins.ops) 978 if (!dl->ins.ops)
846 return; 979 return;
847 980
848 if (dl->ins.ops->parse && dl->ins.ops->parse(arch, &dl->ops, map) < 0) 981 if (dl->ins.ops->parse && dl->ins.ops->parse(arch, &dl->ops, ms) < 0)
849 dl->ins.ops = NULL; 982 dl->ins.ops = NULL;
850} 983}
851 984
@@ -882,7 +1015,7 @@ out_free_name:
882struct annotate_args { 1015struct annotate_args {
883 size_t privsize; 1016 size_t privsize;
884 struct arch *arch; 1017 struct arch *arch;
885 struct map *map; 1018 struct map_symbol ms;
886 struct perf_evsel *evsel; 1019 struct perf_evsel *evsel;
887 s64 offset; 1020 s64 offset;
888 char *line; 1021 char *line;
@@ -964,7 +1097,7 @@ static struct disasm_line *disasm_line__new(struct annotate_args *args)
964 if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0) 1097 if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)
965 goto out_free_line; 1098 goto out_free_line;
966 1099
967 disasm_line__init_ins(dl, args->arch, args->map); 1100 disasm_line__init_ins(dl, args->arch, &args->ms);
968 } 1101 }
969 } 1102 }
970 1103
@@ -1222,7 +1355,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,
1222 struct annotate_args *args, 1355 struct annotate_args *args,
1223 int *line_nr) 1356 int *line_nr)
1224{ 1357{
1225 struct map *map = args->map; 1358 struct map *map = args->ms.map;
1226 struct annotation *notes = symbol__annotation(sym); 1359 struct annotation *notes = symbol__annotation(sym);
1227 struct disasm_line *dl; 1360 struct disasm_line *dl;
1228 char *line = NULL, *parsed_line, *tmp, *tmp2; 1361 char *line = NULL, *parsed_line, *tmp, *tmp2;
@@ -1269,6 +1402,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,
1269 args->offset = offset; 1402 args->offset = offset;
1270 args->line = parsed_line; 1403 args->line = parsed_line;
1271 args->line_nr = *line_nr; 1404 args->line_nr = *line_nr;
1405 args->ms.sym = sym;
1272 1406
1273 dl = disasm_line__new(args); 1407 dl = disasm_line__new(args);
1274 free(line); 1408 free(line);
@@ -1277,14 +1411,14 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,
1277 if (dl == NULL) 1411 if (dl == NULL)
1278 return -1; 1412 return -1;
1279 1413
1280 if (!disasm_line__has_offset(dl)) { 1414 if (!disasm_line__has_local_offset(dl)) {
1281 dl->ops.target.offset = dl->ops.target.addr - 1415 dl->ops.target.offset = dl->ops.target.addr -
1282 map__rip_2objdump(map, sym->start); 1416 map__rip_2objdump(map, sym->start);
1283 dl->ops.target.offset_avail = true; 1417 dl->ops.target.offset_avail = true;
1284 } 1418 }
1285 1419
1286 /* kcore has no symbols, so add the call target name */ 1420 /* kcore has no symbols, so add the call target symbol */
1287 if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.name) { 1421 if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.sym) {
1288 struct addr_map_symbol target = { 1422 struct addr_map_symbol target = {
1289 .map = map, 1423 .map = map,
1290 .addr = dl->ops.target.addr, 1424 .addr = dl->ops.target.addr,
@@ -1292,7 +1426,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,
1292 1426
1293 if (!map_groups__find_ams(&target) && 1427 if (!map_groups__find_ams(&target) &&
1294 target.sym->start == target.al_addr) 1428 target.sym->start == target.al_addr)
1295 dl->ops.target.name = strdup(target.sym->name); 1429 dl->ops.target.sym = target.sym;
1296 } 1430 }
1297 1431
1298 annotation_line__add(&dl->al, &notes->src->source); 1432 annotation_line__add(&dl->al, &notes->src->source);
@@ -1421,9 +1555,9 @@ fallback:
1421 1555
1422static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) 1556static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1423{ 1557{
1424 struct map *map = args->map; 1558 struct map *map = args->ms.map;
1425 struct dso *dso = map->dso; 1559 struct dso *dso = map->dso;
1426 char command[PATH_MAX * 2]; 1560 char *command;
1427 FILE *file; 1561 FILE *file;
1428 char symfs_filename[PATH_MAX]; 1562 char symfs_filename[PATH_MAX];
1429 struct kcore_extract kce; 1563 struct kcore_extract kce;
@@ -1464,7 +1598,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1464 strcpy(symfs_filename, tmp); 1598 strcpy(symfs_filename, tmp);
1465 } 1599 }
1466 1600
1467 snprintf(command, sizeof(command), 1601 err = asprintf(&command,
1468 "%s %s%s --start-address=0x%016" PRIx64 1602 "%s %s%s --start-address=0x%016" PRIx64
1469 " --stop-address=0x%016" PRIx64 1603 " --stop-address=0x%016" PRIx64
1470 " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand", 1604 " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand",
@@ -1477,12 +1611,17 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1477 symbol_conf.annotate_src ? "-S" : "", 1611 symbol_conf.annotate_src ? "-S" : "",
1478 symfs_filename, symfs_filename); 1612 symfs_filename, symfs_filename);
1479 1613
1614 if (err < 0) {
1615 pr_err("Failure allocating memory for the command to run\n");
1616 goto out_remove_tmp;
1617 }
1618
1480 pr_debug("Executing: %s\n", command); 1619 pr_debug("Executing: %s\n", command);
1481 1620
1482 err = -1; 1621 err = -1;
1483 if (pipe(stdout_fd) < 0) { 1622 if (pipe(stdout_fd) < 0) {
1484 pr_err("Failure creating the pipe to run %s\n", command); 1623 pr_err("Failure creating the pipe to run %s\n", command);
1485 goto out_remove_tmp; 1624 goto out_free_command;
1486 } 1625 }
1487 1626
1488 pid = fork(); 1627 pid = fork();
@@ -1509,7 +1648,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1509 * If we were using debug info should retry with 1648 * If we were using debug info should retry with
1510 * original binary. 1649 * original binary.
1511 */ 1650 */
1512 goto out_remove_tmp; 1651 goto out_free_command;
1513 } 1652 }
1514 1653
1515 nline = 0; 1654 nline = 0;
@@ -1537,6 +1676,8 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1537 1676
1538 fclose(file); 1677 fclose(file);
1539 err = 0; 1678 err = 0;
1679out_free_command:
1680 free(command);
1540out_remove_tmp: 1681out_remove_tmp:
1541 close(stdout_fd[0]); 1682 close(stdout_fd[0]);
1542 1683
@@ -1550,7 +1691,7 @@ out:
1550 1691
1551out_close_stdout: 1692out_close_stdout:
1552 close(stdout_fd[1]); 1693 close(stdout_fd[1]);
1553 goto out_remove_tmp; 1694 goto out_free_command;
1554} 1695}
1555 1696
1556static void calc_percent(struct sym_hist *hist, 1697static void calc_percent(struct sym_hist *hist,
@@ -1613,7 +1754,6 @@ int symbol__annotate(struct symbol *sym, struct map *map,
1613{ 1754{
1614 struct annotate_args args = { 1755 struct annotate_args args = {
1615 .privsize = privsize, 1756 .privsize = privsize,
1616 .map = map,
1617 .evsel = evsel, 1757 .evsel = evsel,
1618 }; 1758 };
1619 struct perf_env *env = perf_evsel__env(evsel); 1759 struct perf_env *env = perf_evsel__env(evsel);
@@ -1639,6 +1779,9 @@ int symbol__annotate(struct symbol *sym, struct map *map,
1639 } 1779 }
1640 } 1780 }
1641 1781
1782 args.ms.map = map;
1783 args.ms.sym = sym;
1784
1642 return symbol__disassemble(sym, &args); 1785 return symbol__disassemble(sym, &args);
1643} 1786}
1644 1787
@@ -1879,6 +2022,103 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1879 return more; 2022 return more;
1880} 2023}
1881 2024
2025static void FILE__set_percent_color(void *fp __maybe_unused,
2026 double percent __maybe_unused,
2027 bool current __maybe_unused)
2028{
2029}
2030
2031static int FILE__set_jumps_percent_color(void *fp __maybe_unused,
2032 int nr __maybe_unused, bool current __maybe_unused)
2033{
2034 return 0;
2035}
2036
2037static int FILE__set_color(void *fp __maybe_unused, int color __maybe_unused)
2038{
2039 return 0;
2040}
2041
2042static void FILE__printf(void *fp, const char *fmt, ...)
2043{
2044 va_list args;
2045
2046 va_start(args, fmt);
2047 vfprintf(fp, fmt, args);
2048 va_end(args);
2049}
2050
2051static void FILE__write_graph(void *fp, int graph)
2052{
2053 const char *s;
2054 switch (graph) {
2055
2056 case DARROW_CHAR: s = "↓"; break;
2057 case UARROW_CHAR: s = "↑"; break;
2058 case LARROW_CHAR: s = "←"; break;
2059 case RARROW_CHAR: s = "→"; break;
2060 default: s = "?"; break;
2061 }
2062
2063 fputs(s, fp);
2064}
2065
2066int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp)
2067{
2068 struct annotation *notes = symbol__annotation(sym);
2069 struct annotation_write_ops ops = {
2070 .first_line = true,
2071 .obj = fp,
2072 .set_color = FILE__set_color,
2073 .set_percent_color = FILE__set_percent_color,
2074 .set_jumps_percent_color = FILE__set_jumps_percent_color,
2075 .printf = FILE__printf,
2076 .write_graph = FILE__write_graph,
2077 };
2078 struct annotation_line *al;
2079
2080 list_for_each_entry(al, &notes->src->source, node) {
2081 if (annotation_line__filter(al, notes))
2082 continue;
2083 annotation_line__write(al, notes, &ops);
2084 fputc('\n', fp);
2085 ops.first_line = false;
2086 }
2087
2088 return 0;
2089}
2090
2091int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel)
2092{
2093 const char *ev_name = perf_evsel__name(evsel);
2094 char buf[1024];
2095 char *filename;
2096 int err = -1;
2097 FILE *fp;
2098
2099 if (asprintf(&filename, "%s.annotation", ms->sym->name) < 0)
2100 return -1;
2101
2102 fp = fopen(filename, "w");
2103 if (fp == NULL)
2104 goto out_free_filename;
2105
2106 if (perf_evsel__is_group_event(evsel)) {
2107 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2108 ev_name = buf;
2109 }
2110
2111 fprintf(fp, "%s() %s\nEvent: %s\n\n",
2112 ms->sym->name, ms->map->dso->long_name, ev_name);
2113 symbol__annotate_fprintf2(ms->sym, fp);
2114
2115 fclose(fp);
2116 err = 0;
2117out_free_filename:
2118 free(filename);
2119 return err;
2120}
2121
1882void symbol__annotate_zero_histogram(struct symbol *sym, int evidx) 2122void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
1883{ 2123{
1884 struct annotation *notes = symbol__annotation(sym); 2124 struct annotation *notes = symbol__annotation(sym);
@@ -1938,8 +2178,109 @@ size_t disasm__fprintf(struct list_head *head, FILE *fp)
1938 return printed; 2178 return printed;
1939} 2179}
1940 2180
2181bool disasm_line__is_valid_local_jump(struct disasm_line *dl, struct symbol *sym)
2182{
2183 if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) ||
2184 !disasm_line__has_local_offset(dl) || dl->ops.target.offset < 0 ||
2185 dl->ops.target.offset >= (s64)symbol__size(sym))
2186 return false;
2187
2188 return true;
2189}
2190
2191void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym)
2192{
2193 u64 offset, size = symbol__size(sym);
2194
2195 /* PLT symbols contain external offsets */
2196 if (strstr(sym->name, "@plt"))
2197 return;
2198
2199 for (offset = 0; offset < size; ++offset) {
2200 struct annotation_line *al = notes->offsets[offset];
2201 struct disasm_line *dl;
2202
2203 dl = disasm_line(al);
2204
2205 if (!disasm_line__is_valid_local_jump(dl, sym))
2206 continue;
2207
2208 al = notes->offsets[dl->ops.target.offset];
2209
2210 /*
2211 * FIXME: Oops, no jump target? Buggy disassembler? Or do we
2212 * have to adjust to the previous offset?
2213 */
2214 if (al == NULL)
2215 continue;
2216
2217 if (++al->jump_sources > notes->max_jump_sources)
2218 notes->max_jump_sources = al->jump_sources;
2219
2220 ++notes->nr_jumps;
2221 }
2222}
2223
2224void annotation__set_offsets(struct annotation *notes, s64 size)
2225{
2226 struct annotation_line *al;
2227
2228 notes->max_line_len = 0;
2229
2230 list_for_each_entry(al, &notes->src->source, node) {
2231 size_t line_len = strlen(al->line);
2232
2233 if (notes->max_line_len < line_len)
2234 notes->max_line_len = line_len;
2235 al->idx = notes->nr_entries++;
2236 if (al->offset != -1) {
2237 al->idx_asm = notes->nr_asm_entries++;
2238 /*
2239 * FIXME: short term bandaid to cope with assembly
2240 * routines that comes with labels in the same column
2241 * as the address in objdump, sigh.
2242 *
2243 * E.g. copy_user_generic_unrolled
2244 */
2245 if (al->offset < size)
2246 notes->offsets[al->offset] = al;
2247 } else
2248 al->idx_asm = -1;
2249 }
2250}
2251
2252static inline int width_jumps(int n)
2253{
2254 if (n >= 100)
2255 return 5;
2256 if (n / 10)
2257 return 2;
2258 return 1;
2259}
2260
2261void annotation__init_column_widths(struct annotation *notes, struct symbol *sym)
2262{
2263 notes->widths.addr = notes->widths.target =
2264 notes->widths.min_addr = hex_width(symbol__size(sym));
2265 notes->widths.max_addr = hex_width(sym->end);
2266 notes->widths.jumps = width_jumps(notes->max_jump_sources);
2267}
2268
2269void annotation__update_column_widths(struct annotation *notes)
2270{
2271 if (notes->options->use_offset)
2272 notes->widths.target = notes->widths.min_addr;
2273 else
2274 notes->widths.target = notes->widths.max_addr;
2275
2276 notes->widths.addr = notes->widths.target;
2277
2278 if (notes->options->show_nr_jumps)
2279 notes->widths.addr += notes->widths.jumps + 1;
2280}
2281
1941static void annotation__calc_lines(struct annotation *notes, struct map *map, 2282static void annotation__calc_lines(struct annotation *notes, struct map *map,
1942 struct rb_root *root, u64 start) 2283 struct rb_root *root)
1943{ 2284{
1944 struct annotation_line *al; 2285 struct annotation_line *al;
1945 struct rb_root tmp_root = RB_ROOT; 2286 struct rb_root tmp_root = RB_ROOT;
@@ -1960,8 +2301,8 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
1960 if (percent_max <= 0.5) 2301 if (percent_max <= 0.5)
1961 continue; 2302 continue;
1962 2303
1963 al->path = get_srcline(map->dso, start + al->offset, NULL, 2304 al->path = get_srcline(map->dso, notes->start + al->offset, NULL,
1964 false, true, start + al->offset); 2305 false, true, notes->start + al->offset);
1965 insert_source_line(&tmp_root, al); 2306 insert_source_line(&tmp_root, al);
1966 } 2307 }
1967 2308
@@ -1972,9 +2313,40 @@ static void symbol__calc_lines(struct symbol *sym, struct map *map,
1972 struct rb_root *root) 2313 struct rb_root *root)
1973{ 2314{
1974 struct annotation *notes = symbol__annotation(sym); 2315 struct annotation *notes = symbol__annotation(sym);
1975 u64 start = map__rip_2objdump(map, sym->start);
1976 2316
1977 annotation__calc_lines(notes, map, root, start); 2317 annotation__calc_lines(notes, map, root);
2318}
2319
2320int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2321 struct perf_evsel *evsel, bool print_lines,
2322 bool full_paths)
2323{
2324 struct dso *dso = map->dso;
2325 struct rb_root source_line = RB_ROOT;
2326 struct annotation_options opts = annotation__default_options;
2327 const char *ev_name = perf_evsel__name(evsel);
2328 char buf[1024];
2329
2330 if (symbol__annotate2(sym, map, evsel, &opts, NULL) < 0)
2331 return -1;
2332
2333 if (print_lines) {
2334 srcline_full_filename = full_paths;
2335 symbol__calc_lines(sym, map, &source_line);
2336 print_summary(&source_line, dso->long_name);
2337 }
2338
2339 if (perf_evsel__is_group_event(evsel)) {
2340 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2341 ev_name = buf;
2342 }
2343
2344 fprintf(stdout, "%s() %s\nEvent: %s\n\n", sym->name, dso->long_name, ev_name);
2345 symbol__annotate_fprintf2(sym, stdout);
2346
2347 annotated_source__purge(symbol__annotation(sym)->src);
2348
2349 return 0;
1978} 2350}
1979 2351
1980int symbol__tty_annotate(struct symbol *sym, struct map *map, 2352int symbol__tty_annotate(struct symbol *sym, struct map *map,
@@ -2007,3 +2379,276 @@ bool ui__has_annotation(void)
2007{ 2379{
2008 return use_browser == 1 && perf_hpp_list.sym; 2380 return use_browser == 1 && perf_hpp_list.sym;
2009} 2381}
2382
2383
2384double annotation_line__max_percent(struct annotation_line *al, struct annotation *notes)
2385{
2386 double percent_max = 0.0;
2387 int i;
2388
2389 for (i = 0; i < notes->nr_events; i++) {
2390 if (al->samples[i].percent > percent_max)
2391 percent_max = al->samples[i].percent;
2392 }
2393
2394 return percent_max;
2395}
2396
2397static void disasm_line__write(struct disasm_line *dl, struct annotation *notes,
2398 void *obj, char *bf, size_t size,
2399 void (*obj__printf)(void *obj, const char *fmt, ...),
2400 void (*obj__write_graph)(void *obj, int graph))
2401{
2402 if (dl->ins.ops && dl->ins.ops->scnprintf) {
2403 if (ins__is_jump(&dl->ins)) {
2404 bool fwd;
2405
2406 if (dl->ops.target.outside)
2407 goto call_like;
2408 fwd = dl->ops.target.offset > dl->al.offset;
2409 obj__write_graph(obj, fwd ? DARROW_CHAR : UARROW_CHAR);
2410 obj__printf(obj, " ");
2411 } else if (ins__is_call(&dl->ins)) {
2412call_like:
2413 obj__write_graph(obj, RARROW_CHAR);
2414 obj__printf(obj, " ");
2415 } else if (ins__is_ret(&dl->ins)) {
2416 obj__write_graph(obj, LARROW_CHAR);
2417 obj__printf(obj, " ");
2418 } else {
2419 obj__printf(obj, " ");
2420 }
2421 } else {
2422 obj__printf(obj, " ");
2423 }
2424
2425 disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset);
2426}
2427
2428static void __annotation_line__write(struct annotation_line *al, struct annotation *notes,
2429 bool first_line, bool current_entry, bool change_color, int width,
2430 void *obj,
2431 int (*obj__set_color)(void *obj, int color),
2432 void (*obj__set_percent_color)(void *obj, double percent, bool current),
2433 int (*obj__set_jumps_percent_color)(void *obj, int nr, bool current),
2434 void (*obj__printf)(void *obj, const char *fmt, ...),
2435 void (*obj__write_graph)(void *obj, int graph))
2436
2437{
2438 double percent_max = annotation_line__max_percent(al, notes);
2439 int pcnt_width = annotation__pcnt_width(notes),
2440 cycles_width = annotation__cycles_width(notes);
2441 bool show_title = false;
2442 char bf[256];
2443 int printed;
2444
2445 if (first_line && (al->offset == -1 || percent_max == 0.0)) {
2446 if (notes->have_cycles) {
2447 if (al->ipc == 0.0 && al->cycles == 0)
2448 show_title = true;
2449 } else
2450 show_title = true;
2451 }
2452
2453 if (al->offset != -1 && percent_max != 0.0) {
2454 int i;
2455
2456 for (i = 0; i < notes->nr_events; i++) {
2457 obj__set_percent_color(obj, al->samples[i].percent, current_entry);
2458 if (notes->options->show_total_period) {
2459 obj__printf(obj, "%11" PRIu64 " ", al->samples[i].he.period);
2460 } else if (notes->options->show_nr_samples) {
2461 obj__printf(obj, "%6" PRIu64 " ",
2462 al->samples[i].he.nr_samples);
2463 } else {
2464 obj__printf(obj, "%6.2f ",
2465 al->samples[i].percent);
2466 }
2467 }
2468 } else {
2469 obj__set_percent_color(obj, 0, current_entry);
2470
2471 if (!show_title)
2472 obj__printf(obj, "%-*s", pcnt_width, " ");
2473 else {
2474 obj__printf(obj, "%-*s", pcnt_width,
2475 notes->options->show_total_period ? "Period" :
2476 notes->options->show_nr_samples ? "Samples" : "Percent");
2477 }
2478 }
2479
2480 if (notes->have_cycles) {
2481 if (al->ipc)
2482 obj__printf(obj, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->ipc);
2483 else if (!show_title)
2484 obj__printf(obj, "%*s", ANNOTATION__IPC_WIDTH, " ");
2485 else
2486 obj__printf(obj, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC");
2487
2488 if (al->cycles)
2489 obj__printf(obj, "%*" PRIu64 " ",
2490 ANNOTATION__CYCLES_WIDTH - 1, al->cycles);
2491 else if (!show_title)
2492 obj__printf(obj, "%*s", ANNOTATION__CYCLES_WIDTH, " ");
2493 else
2494 obj__printf(obj, "%*s ", ANNOTATION__CYCLES_WIDTH - 1, "Cycle");
2495 }
2496
2497 obj__printf(obj, " ");
2498
2499 if (!*al->line)
2500 obj__printf(obj, "%-*s", width - pcnt_width - cycles_width, " ");
2501 else if (al->offset == -1) {
2502 if (al->line_nr && notes->options->show_linenr)
2503 printed = scnprintf(bf, sizeof(bf), "%-*d ", notes->widths.addr + 1, al->line_nr);
2504 else
2505 printed = scnprintf(bf, sizeof(bf), "%-*s ", notes->widths.addr, " ");
2506 obj__printf(obj, bf);
2507 obj__printf(obj, "%-*s", width - printed - pcnt_width - cycles_width + 1, al->line);
2508 } else {
2509 u64 addr = al->offset;
2510 int color = -1;
2511
2512 if (!notes->options->use_offset)
2513 addr += notes->start;
2514
2515 if (!notes->options->use_offset) {
2516 printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr);
2517 } else {
2518 if (al->jump_sources) {
2519 if (notes->options->show_nr_jumps) {
2520 int prev;
2521 printed = scnprintf(bf, sizeof(bf), "%*d ",
2522 notes->widths.jumps,
2523 al->jump_sources);
2524 prev = obj__set_jumps_percent_color(obj, al->jump_sources,
2525 current_entry);
2526 obj__printf(obj, bf);
2527 obj__set_color(obj, prev);
2528 }
2529
2530 printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ",
2531 notes->widths.target, addr);
2532 } else {
2533 printed = scnprintf(bf, sizeof(bf), "%-*s ",
2534 notes->widths.addr, " ");
2535 }
2536 }
2537
2538 if (change_color)
2539 color = obj__set_color(obj, HE_COLORSET_ADDR);
2540 obj__printf(obj, bf);
2541 if (change_color)
2542 obj__set_color(obj, color);
2543
2544 disasm_line__write(disasm_line(al), notes, obj, bf, sizeof(bf), obj__printf, obj__write_graph);
2545
2546 obj__printf(obj, "%-*s", width - pcnt_width - cycles_width - 3 - printed, bf);
2547 }
2548
2549}
2550
2551void annotation_line__write(struct annotation_line *al, struct annotation *notes,
2552 struct annotation_write_ops *ops)
2553{
2554 __annotation_line__write(al, notes, ops->first_line, ops->current_entry,
2555 ops->change_color, ops->width, ops->obj,
2556 ops->set_color, ops->set_percent_color,
2557 ops->set_jumps_percent_color, ops->printf,
2558 ops->write_graph);
2559}
2560
2561int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *evsel,
2562 struct annotation_options *options, struct arch **parch)
2563{
2564 struct annotation *notes = symbol__annotation(sym);
2565 size_t size = symbol__size(sym);
2566 int nr_pcnt = 1, err;
2567
2568 notes->offsets = zalloc(size * sizeof(struct annotation_line *));
2569 if (notes->offsets == NULL)
2570 return -1;
2571
2572 if (perf_evsel__is_group_event(evsel))
2573 nr_pcnt = evsel->nr_members;
2574
2575 err = symbol__annotate(sym, map, evsel, 0, parch);
2576 if (err)
2577 goto out_free_offsets;
2578
2579 notes->options = options;
2580
2581 symbol__calc_percent(sym, evsel);
2582
2583 notes->start = map__rip_2objdump(map, sym->start);
2584
2585 annotation__set_offsets(notes, size);
2586 annotation__mark_jump_targets(notes, sym);
2587 annotation__compute_ipc(notes, size);
2588 annotation__init_column_widths(notes, sym);
2589 notes->nr_events = nr_pcnt;
2590
2591 annotation__update_column_widths(notes);
2592
2593 return 0;
2594
2595out_free_offsets:
2596 zfree(&notes->offsets);
2597 return -1;
2598}
2599
2600#define ANNOTATION__CFG(n) \
2601 { .name = #n, .value = &annotation__default_options.n, }
2602
2603/*
2604 * Keep the entries sorted, they are bsearch'ed
2605 */
2606static struct annotation_config {
2607 const char *name;
2608 bool *value;
2609} annotation__configs[] = {
2610 ANNOTATION__CFG(hide_src_code),
2611 ANNOTATION__CFG(jump_arrows),
2612 ANNOTATION__CFG(show_linenr),
2613 ANNOTATION__CFG(show_nr_jumps),
2614 ANNOTATION__CFG(show_nr_samples),
2615 ANNOTATION__CFG(show_total_period),
2616 ANNOTATION__CFG(use_offset),
2617};
2618
2619#undef ANNOTATION__CFG
2620
2621static int annotation_config__cmp(const void *name, const void *cfgp)
2622{
2623 const struct annotation_config *cfg = cfgp;
2624
2625 return strcmp(name, cfg->name);
2626}
2627
2628static int annotation__config(const char *var, const char *value,
2629 void *data __maybe_unused)
2630{
2631 struct annotation_config *cfg;
2632 const char *name;
2633
2634 if (!strstarts(var, "annotate."))
2635 return 0;
2636
2637 name = var + 9;
2638 cfg = bsearch(name, annotation__configs, ARRAY_SIZE(annotation__configs),
2639 sizeof(struct annotation_config), annotation_config__cmp);
2640
2641 if (cfg == NULL)
2642 pr_debug("%s variable unknown, ignoring...", var);
2643 else
2644 *cfg->value = perf_config_bool(name, value);
2645 return 0;
2646}
2647
2648void annotation_config__init(void)
2649{
2650 perf_config(annotation__config, NULL);
2651
2652 annotation__default_options.show_total_period = symbol_conf.show_total_period;
2653 annotation__default_options.show_nr_samples = symbol_conf.show_nr_samples;
2654}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index ce427445671f..ff7e3df31efa 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -24,9 +24,11 @@ struct ins_operands {
24 struct { 24 struct {
25 char *raw; 25 char *raw;
26 char *name; 26 char *name;
27 struct symbol *sym;
27 u64 addr; 28 u64 addr;
28 s64 offset; 29 s64 offset;
29 bool offset_avail; 30 bool offset_avail;
31 bool outside;
30 } target; 32 } target;
31 union { 33 union {
32 struct { 34 struct {
@@ -45,7 +47,7 @@ struct arch;
45 47
46struct ins_ops { 48struct ins_ops {
47 void (*free)(struct ins_operands *ops); 49 void (*free)(struct ins_operands *ops);
48 int (*parse)(struct arch *arch, struct ins_operands *ops, struct map *map); 50 int (*parse)(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms);
49 int (*scnprintf)(struct ins *ins, char *bf, size_t size, 51 int (*scnprintf)(struct ins *ins, char *bf, size_t size,
50 struct ins_operands *ops); 52 struct ins_operands *ops);
51}; 53};
@@ -57,6 +59,21 @@ bool ins__is_lock(const struct ins *ins);
57int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops); 59int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops);
58bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2); 60bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2);
59 61
62#define ANNOTATION__IPC_WIDTH 6
63#define ANNOTATION__CYCLES_WIDTH 6
64
65struct annotation_options {
66 bool hide_src_code,
67 use_offset,
68 jump_arrows,
69 show_linenr,
70 show_nr_jumps,
71 show_nr_samples,
72 show_total_period;
73};
74
75extern struct annotation_options annotation__default_options;
76
60struct annotation; 77struct annotation;
61 78
62struct sym_hist_entry { 79struct sym_hist_entry {
@@ -76,10 +93,13 @@ struct annotation_line {
76 s64 offset; 93 s64 offset;
77 char *line; 94 char *line;
78 int line_nr; 95 int line_nr;
96 int jump_sources;
79 float ipc; 97 float ipc;
80 u64 cycles; 98 u64 cycles;
81 size_t privsize; 99 size_t privsize;
82 char *path; 100 char *path;
101 u32 idx;
102 int idx_asm;
83 int samples_nr; 103 int samples_nr;
84 struct annotation_data samples[0]; 104 struct annotation_data samples[0];
85}; 105};
@@ -97,14 +117,40 @@ static inline struct disasm_line *disasm_line(struct annotation_line *al)
97 return al ? container_of(al, struct disasm_line, al) : NULL; 117 return al ? container_of(al, struct disasm_line, al) : NULL;
98} 118}
99 119
100static inline bool disasm_line__has_offset(const struct disasm_line *dl) 120/*
121 * Is this offset in the same function as the line it is used?
122 * asm functions jump to other functions, for instance.
123 */
124static inline bool disasm_line__has_local_offset(const struct disasm_line *dl)
101{ 125{
102 return dl->ops.target.offset_avail; 126 return dl->ops.target.offset_avail && !dl->ops.target.outside;
103} 127}
104 128
129/*
130 * Can we draw an arrow from the jump to its target, for instance? I.e.
131 * is the jump and its target in the same function?
132 */
133bool disasm_line__is_valid_local_jump(struct disasm_line *dl, struct symbol *sym);
134
105void disasm_line__free(struct disasm_line *dl); 135void disasm_line__free(struct disasm_line *dl);
106struct annotation_line * 136struct annotation_line *
107annotation_line__next(struct annotation_line *pos, struct list_head *head); 137annotation_line__next(struct annotation_line *pos, struct list_head *head);
138
139struct annotation_write_ops {
140 bool first_line, current_entry, change_color;
141 int width;
142 void *obj;
143 int (*set_color)(void *obj, int color);
144 void (*set_percent_color)(void *obj, double percent, bool current);
145 int (*set_jumps_percent_color)(void *obj, int nr, bool current);
146 void (*printf)(void *obj, const char *fmt, ...);
147 void (*write_graph)(void *obj, int graph);
148};
149
150double annotation_line__max_percent(struct annotation_line *al, struct annotation *notes);
151void annotation_line__write(struct annotation_line *al, struct annotation *notes,
152 struct annotation_write_ops *ops);
153
108int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); 154int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
109size_t disasm__fprintf(struct list_head *head, FILE *fp); 155size_t disasm__fprintf(struct list_head *head, FILE *fp);
110void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel); 156void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel);
@@ -150,9 +196,47 @@ struct annotated_source {
150struct annotation { 196struct annotation {
151 pthread_mutex_t lock; 197 pthread_mutex_t lock;
152 u64 max_coverage; 198 u64 max_coverage;
199 u64 start;
200 struct annotation_options *options;
201 struct annotation_line **offsets;
202 int nr_events;
203 int nr_jumps;
204 int max_jump_sources;
205 int nr_entries;
206 int nr_asm_entries;
207 u16 max_line_len;
208 struct {
209 u8 addr;
210 u8 jumps;
211 u8 target;
212 u8 min_addr;
213 u8 max_addr;
214 } widths;
215 bool have_cycles;
153 struct annotated_source *src; 216 struct annotated_source *src;
154}; 217};
155 218
219static inline int annotation__cycles_width(struct annotation *notes)
220{
221 return notes->have_cycles ? ANNOTATION__IPC_WIDTH + ANNOTATION__CYCLES_WIDTH : 0;
222}
223
224static inline int annotation__pcnt_width(struct annotation *notes)
225{
226 return (notes->options->show_total_period ? 12 : 7) * notes->nr_events;
227}
228
229static inline bool annotation_line__filter(struct annotation_line *al, struct annotation *notes)
230{
231 return notes->options->hide_src_code && al->offset == -1;
232}
233
234void annotation__set_offsets(struct annotation *notes, s64 size);
235void annotation__compute_ipc(struct annotation *notes, size_t size);
236void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym);
237void annotation__update_column_widths(struct annotation *notes);
238void annotation__init_column_widths(struct annotation *notes, struct symbol *sym);
239
156static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx) 240static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx)
157{ 241{
158 return (((void *)&notes->src->histograms) + 242 return (((void *)&notes->src->histograms) +
@@ -180,6 +264,10 @@ void symbol__annotate_zero_histograms(struct symbol *sym);
180int symbol__annotate(struct symbol *sym, struct map *map, 264int symbol__annotate(struct symbol *sym, struct map *map,
181 struct perf_evsel *evsel, size_t privsize, 265 struct perf_evsel *evsel, size_t privsize,
182 struct arch **parch); 266 struct arch **parch);
267int symbol__annotate2(struct symbol *sym, struct map *map,
268 struct perf_evsel *evsel,
269 struct annotation_options *options,
270 struct arch **parch);
183 271
184enum symbol_disassemble_errno { 272enum symbol_disassemble_errno {
185 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0, 273 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
@@ -204,16 +292,23 @@ int symbol__strerror_disassemble(struct symbol *sym, struct map *map,
204int symbol__annotate_printf(struct symbol *sym, struct map *map, 292int symbol__annotate_printf(struct symbol *sym, struct map *map,
205 struct perf_evsel *evsel, bool full_paths, 293 struct perf_evsel *evsel, bool full_paths,
206 int min_pcnt, int max_lines, int context); 294 int min_pcnt, int max_lines, int context);
295int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp);
207void symbol__annotate_zero_histogram(struct symbol *sym, int evidx); 296void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
208void symbol__annotate_decay_histogram(struct symbol *sym, int evidx); 297void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
209void annotated_source__purge(struct annotated_source *as); 298void annotated_source__purge(struct annotated_source *as);
210 299
300int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel);
301
211bool ui__has_annotation(void); 302bool ui__has_annotation(void);
212 303
213int symbol__tty_annotate(struct symbol *sym, struct map *map, 304int symbol__tty_annotate(struct symbol *sym, struct map *map,
214 struct perf_evsel *evsel, bool print_lines, 305 struct perf_evsel *evsel, bool print_lines,
215 bool full_paths, int min_pcnt, int max_lines); 306 bool full_paths, int min_pcnt, int max_lines);
216 307
308int symbol__tty_annotate2(struct symbol *sym, struct map *map,
309 struct perf_evsel *evsel, bool print_lines,
310 bool full_paths);
311
217#ifdef HAVE_SLANG_SUPPORT 312#ifdef HAVE_SLANG_SUPPORT
218int symbol__tui_annotate(struct symbol *sym, struct map *map, 313int symbol__tui_annotate(struct symbol *sym, struct map *map,
219 struct perf_evsel *evsel, 314 struct perf_evsel *evsel,
@@ -231,4 +326,6 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
231 326
232extern const char *disassembler_style; 327extern const char *disassembler_style;
233 328
329void annotation_config__init(void);
330
234#endif /* __PERF_ANNOTATE_H */ 331#endif /* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 9faf3b5367db..fb357a00dd86 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -60,6 +60,12 @@
60#include "sane_ctype.h" 60#include "sane_ctype.h"
61#include "symbol/kallsyms.h" 61#include "symbol/kallsyms.h"
62 62
63static bool auxtrace__dont_decode(struct perf_session *session)
64{
65 return !session->itrace_synth_opts ||
66 session->itrace_synth_opts->dont_decode;
67}
68
63int auxtrace_mmap__mmap(struct auxtrace_mmap *mm, 69int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
64 struct auxtrace_mmap_params *mp, 70 struct auxtrace_mmap_params *mp,
65 void *userpg, int fd) 71 void *userpg, int fd)
@@ -227,9 +233,9 @@ static void *auxtrace_copy_data(u64 size, struct perf_session *session)
227 return p; 233 return p;
228} 234}
229 235
230static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, 236static int auxtrace_queues__queue_buffer(struct auxtrace_queues *queues,
231 unsigned int idx, 237 unsigned int idx,
232 struct auxtrace_buffer *buffer) 238 struct auxtrace_buffer *buffer)
233{ 239{
234 struct auxtrace_queue *queue; 240 struct auxtrace_queue *queue;
235 int err; 241 int err;
@@ -280,7 +286,7 @@ static int auxtrace_queues__split_buffer(struct auxtrace_queues *queues,
280 return -ENOMEM; 286 return -ENOMEM;
281 b->size = BUFFER_LIMIT_FOR_32_BIT; 287 b->size = BUFFER_LIMIT_FOR_32_BIT;
282 b->consecutive = consecutive; 288 b->consecutive = consecutive;
283 err = auxtrace_queues__add_buffer(queues, idx, b); 289 err = auxtrace_queues__queue_buffer(queues, idx, b);
284 if (err) { 290 if (err) {
285 auxtrace_buffer__free(b); 291 auxtrace_buffer__free(b);
286 return err; 292 return err;
@@ -296,11 +302,14 @@ static int auxtrace_queues__split_buffer(struct auxtrace_queues *queues,
296 return 0; 302 return 0;
297} 303}
298 304
299static int auxtrace_queues__add_event_buffer(struct auxtrace_queues *queues, 305static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues,
300 struct perf_session *session, 306 struct perf_session *session,
301 unsigned int idx, 307 unsigned int idx,
302 struct auxtrace_buffer *buffer) 308 struct auxtrace_buffer *buffer,
309 struct auxtrace_buffer **buffer_ptr)
303{ 310{
311 int err;
312
304 if (session->one_mmap) { 313 if (session->one_mmap) {
305 buffer->data = buffer->data_offset - session->one_mmap_offset + 314 buffer->data = buffer->data_offset - session->one_mmap_offset +
306 session->one_mmap_addr; 315 session->one_mmap_addr;
@@ -311,14 +320,20 @@ static int auxtrace_queues__add_event_buffer(struct auxtrace_queues *queues,
311 buffer->data_needs_freeing = true; 320 buffer->data_needs_freeing = true;
312 } else if (BITS_PER_LONG == 32 && 321 } else if (BITS_PER_LONG == 32 &&
313 buffer->size > BUFFER_LIMIT_FOR_32_BIT) { 322 buffer->size > BUFFER_LIMIT_FOR_32_BIT) {
314 int err;
315
316 err = auxtrace_queues__split_buffer(queues, idx, buffer); 323 err = auxtrace_queues__split_buffer(queues, idx, buffer);
317 if (err) 324 if (err)
318 return err; 325 return err;
319 } 326 }
320 327
321 return auxtrace_queues__add_buffer(queues, idx, buffer); 328 err = auxtrace_queues__queue_buffer(queues, idx, buffer);
329 if (err)
330 return err;
331
332 /* FIXME: Doesn't work for split buffer */
333 if (buffer_ptr)
334 *buffer_ptr = buffer;
335
336 return 0;
322} 337}
323 338
324static bool filter_cpu(struct perf_session *session, int cpu) 339static bool filter_cpu(struct perf_session *session, int cpu)
@@ -353,13 +368,11 @@ int auxtrace_queues__add_event(struct auxtrace_queues *queues,
353 buffer->size = event->auxtrace.size; 368 buffer->size = event->auxtrace.size;
354 idx = event->auxtrace.idx; 369 idx = event->auxtrace.idx;
355 370
356 err = auxtrace_queues__add_event_buffer(queues, session, idx, buffer); 371 err = auxtrace_queues__add_buffer(queues, session, idx, buffer,
372 buffer_ptr);
357 if (err) 373 if (err)
358 goto out_err; 374 goto out_err;
359 375
360 if (buffer_ptr)
361 *buffer_ptr = buffer;
362
363 return 0; 376 return 0;
364 377
365out_err: 378out_err:
@@ -762,6 +775,9 @@ int auxtrace_queues__process_index(struct auxtrace_queues *queues,
762 size_t i; 775 size_t i;
763 int err; 776 int err;
764 777
778 if (auxtrace__dont_decode(session))
779 return 0;
780
765 list_for_each_entry(auxtrace_index, &session->auxtrace_index, list) { 781 list_for_each_entry(auxtrace_index, &session->auxtrace_index, list) {
766 for (i = 0; i < auxtrace_index->nr; i++) { 782 for (i = 0; i < auxtrace_index->nr; i++) {
767 ent = &auxtrace_index->entries[i]; 783 ent = &auxtrace_index->entries[i];
@@ -892,12 +908,6 @@ out_free:
892 return err; 908 return err;
893} 909}
894 910
895static bool auxtrace__dont_decode(struct perf_session *session)
896{
897 return !session->itrace_synth_opts ||
898 session->itrace_synth_opts->dont_decode;
899}
900
901int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused, 911int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
902 union perf_event *event, 912 union perf_event *event,
903 struct perf_session *session) 913 struct perf_session *session)
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 453c148d2158..e731f55da072 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -130,6 +130,7 @@ struct auxtrace_index {
130/** 130/**
131 * struct auxtrace - session callbacks to allow AUX area data decoding. 131 * struct auxtrace - session callbacks to allow AUX area data decoding.
132 * @process_event: lets the decoder see all session events 132 * @process_event: lets the decoder see all session events
133 * @process_auxtrace_event: process a PERF_RECORD_AUXTRACE event
133 * @flush_events: process any remaining data 134 * @flush_events: process any remaining data
134 * @free_events: free resources associated with event processing 135 * @free_events: free resources associated with event processing
135 * @free: free resources associated with the session 136 * @free: free resources associated with the session
@@ -301,6 +302,7 @@ struct auxtrace_mmap_params {
301 * @parse_snapshot_options: parse snapshot options 302 * @parse_snapshot_options: parse snapshot options
302 * @reference: provide a 64-bit reference number for auxtrace_event 303 * @reference: provide a 64-bit reference number for auxtrace_event
303 * @read_finish: called after reading from an auxtrace mmap 304 * @read_finish: called after reading from an auxtrace mmap
305 * @alignment: alignment (if any) for AUX area data
304 */ 306 */
305struct auxtrace_record { 307struct auxtrace_record {
306 int (*recording_options)(struct auxtrace_record *itr, 308 int (*recording_options)(struct auxtrace_record *itr,
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 7f8553630c4d..537eadd81914 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -316,7 +316,6 @@ static int machine__write_buildid_table(struct machine *machine,
316 struct feat_fd *fd) 316 struct feat_fd *fd)
317{ 317{
318 int err = 0; 318 int err = 0;
319 char nm[PATH_MAX];
320 struct dso *pos; 319 struct dso *pos;
321 u16 kmisc = PERF_RECORD_MISC_KERNEL, 320 u16 kmisc = PERF_RECORD_MISC_KERNEL,
322 umisc = PERF_RECORD_MISC_USER; 321 umisc = PERF_RECORD_MISC_USER;
@@ -338,9 +337,8 @@ static int machine__write_buildid_table(struct machine *machine,
338 name = pos->short_name; 337 name = pos->short_name;
339 name_len = pos->short_name_len; 338 name_len = pos->short_name_len;
340 } else if (dso__is_kcore(pos)) { 339 } else if (dso__is_kcore(pos)) {
341 machine__mmap_name(machine, nm, sizeof(nm)); 340 name = machine->mmap_name;
342 name = nm; 341 name_len = strlen(name);
343 name_len = strlen(nm);
344 } else { 342 } else {
345 name = pos->long_name; 343 name = pos->long_name;
346 name_len = pos->long_name_len; 344 name_len = pos->long_name_len;
@@ -813,12 +811,10 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine)
813 bool is_kallsyms = dso__is_kallsyms(dso); 811 bool is_kallsyms = dso__is_kallsyms(dso);
814 bool is_vdso = dso__is_vdso(dso); 812 bool is_vdso = dso__is_vdso(dso);
815 const char *name = dso->long_name; 813 const char *name = dso->long_name;
816 char nm[PATH_MAX];
817 814
818 if (dso__is_kcore(dso)) { 815 if (dso__is_kcore(dso)) {
819 is_kallsyms = true; 816 is_kallsyms = true;
820 machine__mmap_name(machine, nm, sizeof(nm)); 817 name = machine->mmap_name;
821 name = nm;
822 } 818 }
823 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name, 819 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
824 dso->nsinfo, is_kallsyms, is_vdso); 820 dso->nsinfo, is_kallsyms, is_vdso);
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 984f69144f87..decb91f9da82 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -71,7 +71,7 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
71 return -1; 71 return -1;
72} 72}
73 73
74static int open_cgroup(char *name) 74static int open_cgroup(const char *name)
75{ 75{
76 char path[PATH_MAX + 1]; 76 char path[PATH_MAX + 1];
77 char mnt[PATH_MAX + 1]; 77 char mnt[PATH_MAX + 1];
@@ -81,7 +81,7 @@ static int open_cgroup(char *name)
81 if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1)) 81 if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1))
82 return -1; 82 return -1;
83 83
84 snprintf(path, PATH_MAX, "%s/%s", mnt, name); 84 scnprintf(path, PATH_MAX, "%s/%s", mnt, name);
85 85
86 fd = open(path, O_RDONLY); 86 fd = open(path, O_RDONLY);
87 if (fd == -1) 87 if (fd == -1)
@@ -90,41 +90,64 @@ static int open_cgroup(char *name)
90 return fd; 90 return fd;
91} 91}
92 92
93static int add_cgroup(struct perf_evlist *evlist, char *str) 93static struct cgroup *evlist__find_cgroup(struct perf_evlist *evlist, const char *str)
94{ 94{
95 struct perf_evsel *counter; 95 struct perf_evsel *counter;
96 struct cgroup_sel *cgrp = NULL; 96 struct cgroup *cgrp = NULL;
97 int n;
98 /* 97 /*
99 * check if cgrp is already defined, if so we reuse it 98 * check if cgrp is already defined, if so we reuse it
100 */ 99 */
101 evlist__for_each_entry(evlist, counter) { 100 evlist__for_each_entry(evlist, counter) {
102 cgrp = counter->cgrp; 101 if (!counter->cgrp)
103 if (!cgrp)
104 continue; 102 continue;
105 if (!strcmp(cgrp->name, str)) { 103 if (!strcmp(counter->cgrp->name, str)) {
106 refcount_inc(&cgrp->refcnt); 104 cgrp = cgroup__get(counter->cgrp);
107 break; 105 break;
108 } 106 }
109
110 cgrp = NULL;
111 } 107 }
112 108
113 if (!cgrp) { 109 return cgrp;
114 cgrp = zalloc(sizeof(*cgrp)); 110}
115 if (!cgrp)
116 return -1;
117 111
118 cgrp->name = str; 112static struct cgroup *cgroup__new(const char *name)
119 refcount_set(&cgrp->refcnt, 1); 113{
114 struct cgroup *cgroup = zalloc(sizeof(*cgroup));
120 115
121 cgrp->fd = open_cgroup(str); 116 if (cgroup != NULL) {
122 if (cgrp->fd == -1) { 117 refcount_set(&cgroup->refcnt, 1);
123 free(cgrp); 118
124 return -1; 119 cgroup->name = strdup(name);
125 } 120 if (!cgroup->name)
121 goto out_err;
122 cgroup->fd = open_cgroup(name);
123 if (cgroup->fd == -1)
124 goto out_free_name;
126 } 125 }
127 126
127 return cgroup;
128
129out_free_name:
130 free(cgroup->name);
131out_err:
132 free(cgroup);
133 return NULL;
134}
135
136struct cgroup *evlist__findnew_cgroup(struct perf_evlist *evlist, const char *name)
137{
138 struct cgroup *cgroup = evlist__find_cgroup(evlist, name);
139
140 return cgroup ?: cgroup__new(name);
141}
142
143static int add_cgroup(struct perf_evlist *evlist, const char *str)
144{
145 struct perf_evsel *counter;
146 struct cgroup *cgrp = evlist__findnew_cgroup(evlist, str);
147 int n;
148
149 if (!cgrp)
150 return -1;
128 /* 151 /*
129 * find corresponding event 152 * find corresponding event
130 * if add cgroup N, then need to find event N 153 * if add cgroup N, then need to find event N
@@ -135,31 +158,58 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
135 goto found; 158 goto found;
136 n++; 159 n++;
137 } 160 }
138 if (refcount_dec_and_test(&cgrp->refcnt))
139 free(cgrp);
140 161
162 cgroup__put(cgrp);
141 return -1; 163 return -1;
142found: 164found:
143 counter->cgrp = cgrp; 165 counter->cgrp = cgrp;
144 return 0; 166 return 0;
145} 167}
146 168
147void close_cgroup(struct cgroup_sel *cgrp) 169static void cgroup__delete(struct cgroup *cgroup)
170{
171 close(cgroup->fd);
172 zfree(&cgroup->name);
173 free(cgroup);
174}
175
176void cgroup__put(struct cgroup *cgrp)
148{ 177{
149 if (cgrp && refcount_dec_and_test(&cgrp->refcnt)) { 178 if (cgrp && refcount_dec_and_test(&cgrp->refcnt)) {
150 close(cgrp->fd); 179 cgroup__delete(cgrp);
151 zfree(&cgrp->name);
152 free(cgrp);
153 } 180 }
154} 181}
155 182
156int parse_cgroups(const struct option *opt __maybe_unused, const char *str, 183struct cgroup *cgroup__get(struct cgroup *cgroup)
184{
185 if (cgroup)
186 refcount_inc(&cgroup->refcnt);
187 return cgroup;
188}
189
190static void evsel__set_default_cgroup(struct perf_evsel *evsel, struct cgroup *cgroup)
191{
192 if (evsel->cgrp == NULL)
193 evsel->cgrp = cgroup__get(cgroup);
194}
195
196void evlist__set_default_cgroup(struct perf_evlist *evlist, struct cgroup *cgroup)
197{
198 struct perf_evsel *evsel;
199
200 evlist__for_each_entry(evlist, evsel)
201 evsel__set_default_cgroup(evsel, cgroup);
202}
203
204int parse_cgroups(const struct option *opt, const char *str,
157 int unset __maybe_unused) 205 int unset __maybe_unused)
158{ 206{
159 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 207 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
208 struct perf_evsel *counter;
209 struct cgroup *cgrp = NULL;
160 const char *p, *e, *eos = str + strlen(str); 210 const char *p, *e, *eos = str + strlen(str);
161 char *s; 211 char *s;
162 int ret; 212 int ret, i;
163 213
164 if (list_empty(&evlist->entries)) { 214 if (list_empty(&evlist->entries)) {
165 fprintf(stderr, "must define events before cgroups\n"); 215 fprintf(stderr, "must define events before cgroups\n");
@@ -177,10 +227,9 @@ int parse_cgroups(const struct option *opt __maybe_unused, const char *str,
177 if (!s) 227 if (!s)
178 return -1; 228 return -1;
179 ret = add_cgroup(evlist, s); 229 ret = add_cgroup(evlist, s);
180 if (ret) { 230 free(s);
181 free(s); 231 if (ret)
182 return -1; 232 return -1;
183 }
184 } 233 }
185 /* nr_cgroups is increased een for empty cgroups */ 234 /* nr_cgroups is increased een for empty cgroups */
186 nr_cgroups++; 235 nr_cgroups++;
@@ -188,5 +237,18 @@ int parse_cgroups(const struct option *opt __maybe_unused, const char *str,
188 break; 237 break;
189 str = p+1; 238 str = p+1;
190 } 239 }
240 /* for the case one cgroup combine to multiple events */
241 i = 0;
242 if (nr_cgroups == 1) {
243 evlist__for_each_entry(evlist, counter) {
244 if (i == 0)
245 cgrp = counter->cgrp;
246 else {
247 counter->cgrp = cgrp;
248 refcount_inc(&cgrp->refcnt);
249 }
250 i++;
251 }
252 }
191 return 0; 253 return 0;
192} 254}
diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h
index afafc87e9201..f033a80c1b14 100644
--- a/tools/perf/util/cgroup.h
+++ b/tools/perf/util/cgroup.h
@@ -6,7 +6,7 @@
6 6
7struct option; 7struct option;
8 8
9struct cgroup_sel { 9struct cgroup {
10 char *name; 10 char *name;
11 int fd; 11 int fd;
12 refcount_t refcnt; 12 refcount_t refcnt;
@@ -14,7 +14,16 @@ struct cgroup_sel {
14 14
15 15
16extern int nr_cgroups; /* number of explicit cgroups defined */ 16extern int nr_cgroups; /* number of explicit cgroups defined */
17void close_cgroup(struct cgroup_sel *cgrp); 17
18struct cgroup *cgroup__get(struct cgroup *cgroup);
19void cgroup__put(struct cgroup *cgroup);
20
21struct perf_evlist;
22
23struct cgroup *evlist__findnew_cgroup(struct perf_evlist *evlist, const char *name);
24
25void evlist__set_default_cgroup(struct perf_evlist *evlist, struct cgroup *cgroup);
26
18int parse_cgroups(const struct option *opt, const char *str, int unset); 27int parse_cgroups(const struct option *opt, const char *str, int unset);
19 28
20#endif /* __CGROUP_H__ */ 29#endif /* __CGROUP_H__ */
diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
index 1fb01849f1c7..640af88331b4 100644
--- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
@@ -78,6 +78,8 @@ int cs_etm_decoder__reset(struct cs_etm_decoder *decoder)
78{ 78{
79 ocsd_datapath_resp_t dp_ret; 79 ocsd_datapath_resp_t dp_ret;
80 80
81 decoder->prev_return = OCSD_RESP_CONT;
82
81 dp_ret = ocsd_dt_process_data(decoder->dcd_tree, OCSD_OP_RESET, 83 dp_ret = ocsd_dt_process_data(decoder->dcd_tree, OCSD_OP_RESET,
82 0, 0, NULL, NULL); 84 0, 0, NULL, NULL);
83 if (OCSD_DATA_RESP_IS_FATAL(dp_ret)) 85 if (OCSD_DATA_RESP_IS_FATAL(dp_ret))
@@ -253,16 +255,16 @@ static void cs_etm_decoder__clear_buffer(struct cs_etm_decoder *decoder)
253 decoder->packet_count = 0; 255 decoder->packet_count = 0;
254 for (i = 0; i < MAX_BUFFER; i++) { 256 for (i = 0; i < MAX_BUFFER; i++) {
255 decoder->packet_buffer[i].start_addr = 0xdeadbeefdeadbeefUL; 257 decoder->packet_buffer[i].start_addr = 0xdeadbeefdeadbeefUL;
256 decoder->packet_buffer[i].end_addr = 0xdeadbeefdeadbeefUL; 258 decoder->packet_buffer[i].end_addr = 0xdeadbeefdeadbeefUL;
257 decoder->packet_buffer[i].exc = false; 259 decoder->packet_buffer[i].last_instr_taken_branch = false;
258 decoder->packet_buffer[i].exc_ret = false; 260 decoder->packet_buffer[i].exc = false;
259 decoder->packet_buffer[i].cpu = INT_MIN; 261 decoder->packet_buffer[i].exc_ret = false;
262 decoder->packet_buffer[i].cpu = INT_MIN;
260 } 263 }
261} 264}
262 265
263static ocsd_datapath_resp_t 266static ocsd_datapath_resp_t
264cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder, 267cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
265 const ocsd_generic_trace_elem *elem,
266 const u8 trace_chan_id, 268 const u8 trace_chan_id,
267 enum cs_etm_sample_type sample_type) 269 enum cs_etm_sample_type sample_type)
268{ 270{
@@ -278,18 +280,16 @@ cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
278 return OCSD_RESP_FATAL_SYS_ERR; 280 return OCSD_RESP_FATAL_SYS_ERR;
279 281
280 et = decoder->tail; 282 et = decoder->tail;
283 et = (et + 1) & (MAX_BUFFER - 1);
284 decoder->tail = et;
285 decoder->packet_count++;
286
281 decoder->packet_buffer[et].sample_type = sample_type; 287 decoder->packet_buffer[et].sample_type = sample_type;
282 decoder->packet_buffer[et].start_addr = elem->st_addr;
283 decoder->packet_buffer[et].end_addr = elem->en_addr;
284 decoder->packet_buffer[et].exc = false; 288 decoder->packet_buffer[et].exc = false;
285 decoder->packet_buffer[et].exc_ret = false; 289 decoder->packet_buffer[et].exc_ret = false;
286 decoder->packet_buffer[et].cpu = *((int *)inode->priv); 290 decoder->packet_buffer[et].cpu = *((int *)inode->priv);
287 291 decoder->packet_buffer[et].start_addr = 0xdeadbeefdeadbeefUL;
288 /* Wrap around if need be */ 292 decoder->packet_buffer[et].end_addr = 0xdeadbeefdeadbeefUL;
289 et = (et + 1) & (MAX_BUFFER - 1);
290
291 decoder->tail = et;
292 decoder->packet_count++;
293 293
294 if (decoder->packet_count == MAX_BUFFER - 1) 294 if (decoder->packet_count == MAX_BUFFER - 1)
295 return OCSD_RESP_WAIT; 295 return OCSD_RESP_WAIT;
@@ -297,6 +297,47 @@ cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
297 return OCSD_RESP_CONT; 297 return OCSD_RESP_CONT;
298} 298}
299 299
300static ocsd_datapath_resp_t
301cs_etm_decoder__buffer_range(struct cs_etm_decoder *decoder,
302 const ocsd_generic_trace_elem *elem,
303 const uint8_t trace_chan_id)
304{
305 int ret = 0;
306 struct cs_etm_packet *packet;
307
308 ret = cs_etm_decoder__buffer_packet(decoder, trace_chan_id,
309 CS_ETM_RANGE);
310 if (ret != OCSD_RESP_CONT && ret != OCSD_RESP_WAIT)
311 return ret;
312
313 packet = &decoder->packet_buffer[decoder->tail];
314
315 packet->start_addr = elem->st_addr;
316 packet->end_addr = elem->en_addr;
317 switch (elem->last_i_type) {
318 case OCSD_INSTR_BR:
319 case OCSD_INSTR_BR_INDIRECT:
320 packet->last_instr_taken_branch = elem->last_instr_exec;
321 break;
322 case OCSD_INSTR_ISB:
323 case OCSD_INSTR_DSB_DMB:
324 case OCSD_INSTR_OTHER:
325 default:
326 packet->last_instr_taken_branch = false;
327 break;
328 }
329
330 return ret;
331}
332
333static ocsd_datapath_resp_t
334cs_etm_decoder__buffer_trace_on(struct cs_etm_decoder *decoder,
335 const uint8_t trace_chan_id)
336{
337 return cs_etm_decoder__buffer_packet(decoder, trace_chan_id,
338 CS_ETM_TRACE_ON);
339}
340
300static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer( 341static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
301 const void *context, 342 const void *context,
302 const ocsd_trc_index_t indx __maybe_unused, 343 const ocsd_trc_index_t indx __maybe_unused,
@@ -313,12 +354,13 @@ static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
313 decoder->trace_on = false; 354 decoder->trace_on = false;
314 break; 355 break;
315 case OCSD_GEN_TRC_ELEM_TRACE_ON: 356 case OCSD_GEN_TRC_ELEM_TRACE_ON:
357 resp = cs_etm_decoder__buffer_trace_on(decoder,
358 trace_chan_id);
316 decoder->trace_on = true; 359 decoder->trace_on = true;
317 break; 360 break;
318 case OCSD_GEN_TRC_ELEM_INSTR_RANGE: 361 case OCSD_GEN_TRC_ELEM_INSTR_RANGE:
319 resp = cs_etm_decoder__buffer_packet(decoder, elem, 362 resp = cs_etm_decoder__buffer_range(decoder, elem,
320 trace_chan_id, 363 trace_chan_id);
321 CS_ETM_RANGE);
322 break; 364 break;
323 case OCSD_GEN_TRC_ELEM_EXCEPTION: 365 case OCSD_GEN_TRC_ELEM_EXCEPTION:
324 decoder->packet_buffer[decoder->tail].exc = true; 366 decoder->packet_buffer[decoder->tail].exc = true;
diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
index 3d2e6205d186..743f5f444304 100644
--- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
@@ -24,12 +24,14 @@ struct cs_etm_buffer {
24 24
25enum cs_etm_sample_type { 25enum cs_etm_sample_type {
26 CS_ETM_RANGE = 1 << 0, 26 CS_ETM_RANGE = 1 << 0,
27 CS_ETM_TRACE_ON = 1 << 1,
27}; 28};
28 29
29struct cs_etm_packet { 30struct cs_etm_packet {
30 enum cs_etm_sample_type sample_type; 31 enum cs_etm_sample_type sample_type;
31 u64 start_addr; 32 u64 start_addr;
32 u64 end_addr; 33 u64 end_addr;
34 u8 last_instr_taken_branch;
33 u8 exc; 35 u8 exc;
34 u8 exc_ret; 36 u8 exc_ret;
35 int cpu; 37 int cpu;
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index b9f0a53dfa65..1b0d422373be 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -32,6 +32,14 @@
32 32
33#define MAX_TIMESTAMP (~0ULL) 33#define MAX_TIMESTAMP (~0ULL)
34 34
35/*
36 * A64 instructions are always 4 bytes
37 *
38 * Only A64 is supported, so can use this constant for converting between
39 * addresses and instruction counts, calculting offsets etc
40 */
41#define A64_INSTR_SIZE 4
42
35struct cs_etm_auxtrace { 43struct cs_etm_auxtrace {
36 struct auxtrace auxtrace; 44 struct auxtrace auxtrace;
37 struct auxtrace_queues queues; 45 struct auxtrace_queues queues;
@@ -45,11 +53,15 @@ struct cs_etm_auxtrace {
45 u8 snapshot_mode; 53 u8 snapshot_mode;
46 u8 data_queued; 54 u8 data_queued;
47 u8 sample_branches; 55 u8 sample_branches;
56 u8 sample_instructions;
48 57
49 int num_cpu; 58 int num_cpu;
50 u32 auxtrace_type; 59 u32 auxtrace_type;
51 u64 branches_sample_type; 60 u64 branches_sample_type;
52 u64 branches_id; 61 u64 branches_id;
62 u64 instructions_sample_type;
63 u64 instructions_sample_period;
64 u64 instructions_id;
53 u64 **metadata; 65 u64 **metadata;
54 u64 kernel_start; 66 u64 kernel_start;
55 unsigned int pmu_type; 67 unsigned int pmu_type;
@@ -68,6 +80,12 @@ struct cs_etm_queue {
68 u64 time; 80 u64 time;
69 u64 timestamp; 81 u64 timestamp;
70 u64 offset; 82 u64 offset;
83 u64 period_instructions;
84 struct branch_stack *last_branch;
85 struct branch_stack *last_branch_rb;
86 size_t last_branch_pos;
87 struct cs_etm_packet *prev_packet;
88 struct cs_etm_packet *packet;
71}; 89};
72 90
73static int cs_etm__update_queues(struct cs_etm_auxtrace *etm); 91static int cs_etm__update_queues(struct cs_etm_auxtrace *etm);
@@ -174,6 +192,16 @@ static void cs_etm__free_queue(void *priv)
174{ 192{
175 struct cs_etm_queue *etmq = priv; 193 struct cs_etm_queue *etmq = priv;
176 194
195 if (!etmq)
196 return;
197
198 thread__zput(etmq->thread);
199 cs_etm_decoder__free(etmq->decoder);
200 zfree(&etmq->event_buf);
201 zfree(&etmq->last_branch);
202 zfree(&etmq->last_branch_rb);
203 zfree(&etmq->prev_packet);
204 zfree(&etmq->packet);
177 free(etmq); 205 free(etmq);
178} 206}
179 207
@@ -270,11 +298,35 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm,
270 struct cs_etm_decoder_params d_params; 298 struct cs_etm_decoder_params d_params;
271 struct cs_etm_trace_params *t_params; 299 struct cs_etm_trace_params *t_params;
272 struct cs_etm_queue *etmq; 300 struct cs_etm_queue *etmq;
301 size_t szp = sizeof(struct cs_etm_packet);
273 302
274 etmq = zalloc(sizeof(*etmq)); 303 etmq = zalloc(sizeof(*etmq));
275 if (!etmq) 304 if (!etmq)
276 return NULL; 305 return NULL;
277 306
307 etmq->packet = zalloc(szp);
308 if (!etmq->packet)
309 goto out_free;
310
311 if (etm->synth_opts.last_branch || etm->sample_branches) {
312 etmq->prev_packet = zalloc(szp);
313 if (!etmq->prev_packet)
314 goto out_free;
315 }
316
317 if (etm->synth_opts.last_branch) {
318 size_t sz = sizeof(struct branch_stack);
319
320 sz += etm->synth_opts.last_branch_sz *
321 sizeof(struct branch_entry);
322 etmq->last_branch = zalloc(sz);
323 if (!etmq->last_branch)
324 goto out_free;
325 etmq->last_branch_rb = zalloc(sz);
326 if (!etmq->last_branch_rb)
327 goto out_free;
328 }
329
278 etmq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE); 330 etmq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE);
279 if (!etmq->event_buf) 331 if (!etmq->event_buf)
280 goto out_free; 332 goto out_free;
@@ -329,6 +381,7 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm,
329 goto out_free_decoder; 381 goto out_free_decoder;
330 382
331 etmq->offset = 0; 383 etmq->offset = 0;
384 etmq->period_instructions = 0;
332 385
333 return etmq; 386 return etmq;
334 387
@@ -336,6 +389,10 @@ out_free_decoder:
336 cs_etm_decoder__free(etmq->decoder); 389 cs_etm_decoder__free(etmq->decoder);
337out_free: 390out_free:
338 zfree(&etmq->event_buf); 391 zfree(&etmq->event_buf);
392 zfree(&etmq->last_branch);
393 zfree(&etmq->last_branch_rb);
394 zfree(&etmq->prev_packet);
395 zfree(&etmq->packet);
339 free(etmq); 396 free(etmq);
340 397
341 return NULL; 398 return NULL;
@@ -389,6 +446,129 @@ static int cs_etm__update_queues(struct cs_etm_auxtrace *etm)
389 return 0; 446 return 0;
390} 447}
391 448
449static inline void cs_etm__copy_last_branch_rb(struct cs_etm_queue *etmq)
450{
451 struct branch_stack *bs_src = etmq->last_branch_rb;
452 struct branch_stack *bs_dst = etmq->last_branch;
453 size_t nr = 0;
454
455 /*
456 * Set the number of records before early exit: ->nr is used to
457 * determine how many branches to copy from ->entries.
458 */
459 bs_dst->nr = bs_src->nr;
460
461 /*
462 * Early exit when there is nothing to copy.
463 */
464 if (!bs_src->nr)
465 return;
466
467 /*
468 * As bs_src->entries is a circular buffer, we need to copy from it in
469 * two steps. First, copy the branches from the most recently inserted
470 * branch ->last_branch_pos until the end of bs_src->entries buffer.
471 */
472 nr = etmq->etm->synth_opts.last_branch_sz - etmq->last_branch_pos;
473 memcpy(&bs_dst->entries[0],
474 &bs_src->entries[etmq->last_branch_pos],
475 sizeof(struct branch_entry) * nr);
476
477 /*
478 * If we wrapped around at least once, the branches from the beginning
479 * of the bs_src->entries buffer and until the ->last_branch_pos element
480 * are older valid branches: copy them over. The total number of
481 * branches copied over will be equal to the number of branches asked by
482 * the user in last_branch_sz.
483 */
484 if (bs_src->nr >= etmq->etm->synth_opts.last_branch_sz) {
485 memcpy(&bs_dst->entries[nr],
486 &bs_src->entries[0],
487 sizeof(struct branch_entry) * etmq->last_branch_pos);
488 }
489}
490
491static inline void cs_etm__reset_last_branch_rb(struct cs_etm_queue *etmq)
492{
493 etmq->last_branch_pos = 0;
494 etmq->last_branch_rb->nr = 0;
495}
496
497static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
498{
499 /*
500 * The packet records the execution range with an exclusive end address
501 *
502 * A64 instructions are constant size, so the last executed
503 * instruction is A64_INSTR_SIZE before the end address
504 * Will need to do instruction level decode for T32 instructions as
505 * they can be variable size (not yet supported).
506 */
507 return packet->end_addr - A64_INSTR_SIZE;
508}
509
510static inline u64 cs_etm__instr_count(const struct cs_etm_packet *packet)
511{
512 /*
513 * Only A64 instructions are currently supported, so can get
514 * instruction count by dividing.
515 * Will need to do instruction level decode for T32 instructions as
516 * they can be variable size (not yet supported).
517 */
518 return (packet->end_addr - packet->start_addr) / A64_INSTR_SIZE;
519}
520
521static inline u64 cs_etm__instr_addr(const struct cs_etm_packet *packet,
522 u64 offset)
523{
524 /*
525 * Only A64 instructions are currently supported, so can get
526 * instruction address by muliplying.
527 * Will need to do instruction level decode for T32 instructions as
528 * they can be variable size (not yet supported).
529 */
530 return packet->start_addr + offset * A64_INSTR_SIZE;
531}
532
533static void cs_etm__update_last_branch_rb(struct cs_etm_queue *etmq)
534{
535 struct branch_stack *bs = etmq->last_branch_rb;
536 struct branch_entry *be;
537
538 /*
539 * The branches are recorded in a circular buffer in reverse
540 * chronological order: we start recording from the last element of the
541 * buffer down. After writing the first element of the stack, move the
542 * insert position back to the end of the buffer.
543 */
544 if (!etmq->last_branch_pos)
545 etmq->last_branch_pos = etmq->etm->synth_opts.last_branch_sz;
546
547 etmq->last_branch_pos -= 1;
548
549 be = &bs->entries[etmq->last_branch_pos];
550 be->from = cs_etm__last_executed_instr(etmq->prev_packet);
551 be->to = etmq->packet->start_addr;
552 /* No support for mispredict */
553 be->flags.mispred = 0;
554 be->flags.predicted = 1;
555
556 /*
557 * Increment bs->nr until reaching the number of last branches asked by
558 * the user on the command line.
559 */
560 if (bs->nr < etmq->etm->synth_opts.last_branch_sz)
561 bs->nr += 1;
562}
563
564static int cs_etm__inject_event(union perf_event *event,
565 struct perf_sample *sample, u64 type)
566{
567 event->header.size = perf_event__sample_event_size(sample, type, 0);
568 return perf_event__synthesize_sample(event, type, 0, sample);
569}
570
571
392static int 572static int
393cs_etm__get_trace(struct cs_etm_buffer *buff, struct cs_etm_queue *etmq) 573cs_etm__get_trace(struct cs_etm_buffer *buff, struct cs_etm_queue *etmq)
394{ 574{
@@ -453,35 +633,105 @@ static void cs_etm__set_pid_tid_cpu(struct cs_etm_auxtrace *etm,
453 } 633 }
454} 634}
455 635
636static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
637 u64 addr, u64 period)
638{
639 int ret = 0;
640 struct cs_etm_auxtrace *etm = etmq->etm;
641 union perf_event *event = etmq->event_buf;
642 struct perf_sample sample = {.ip = 0,};
643
644 event->sample.header.type = PERF_RECORD_SAMPLE;
645 event->sample.header.misc = PERF_RECORD_MISC_USER;
646 event->sample.header.size = sizeof(struct perf_event_header);
647
648 sample.ip = addr;
649 sample.pid = etmq->pid;
650 sample.tid = etmq->tid;
651 sample.id = etmq->etm->instructions_id;
652 sample.stream_id = etmq->etm->instructions_id;
653 sample.period = period;
654 sample.cpu = etmq->packet->cpu;
655 sample.flags = 0;
656 sample.insn_len = 1;
657 sample.cpumode = event->header.misc;
658
659 if (etm->synth_opts.last_branch) {
660 cs_etm__copy_last_branch_rb(etmq);
661 sample.branch_stack = etmq->last_branch;
662 }
663
664 if (etm->synth_opts.inject) {
665 ret = cs_etm__inject_event(event, &sample,
666 etm->instructions_sample_type);
667 if (ret)
668 return ret;
669 }
670
671 ret = perf_session__deliver_synth_event(etm->session, event, &sample);
672
673 if (ret)
674 pr_err(
675 "CS ETM Trace: failed to deliver instruction event, error %d\n",
676 ret);
677
678 if (etm->synth_opts.last_branch)
679 cs_etm__reset_last_branch_rb(etmq);
680
681 return ret;
682}
683
456/* 684/*
457 * The cs etm packet encodes an instruction range between a branch target 685 * The cs etm packet encodes an instruction range between a branch target
458 * and the next taken branch. Generate sample accordingly. 686 * and the next taken branch. Generate sample accordingly.
459 */ 687 */
460static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq, 688static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq)
461 struct cs_etm_packet *packet)
462{ 689{
463 int ret = 0; 690 int ret = 0;
464 struct cs_etm_auxtrace *etm = etmq->etm; 691 struct cs_etm_auxtrace *etm = etmq->etm;
465 struct perf_sample sample = {.ip = 0,}; 692 struct perf_sample sample = {.ip = 0,};
466 union perf_event *event = etmq->event_buf; 693 union perf_event *event = etmq->event_buf;
467 u64 start_addr = packet->start_addr; 694 struct dummy_branch_stack {
468 u64 end_addr = packet->end_addr; 695 u64 nr;
696 struct branch_entry entries;
697 } dummy_bs;
469 698
470 event->sample.header.type = PERF_RECORD_SAMPLE; 699 event->sample.header.type = PERF_RECORD_SAMPLE;
471 event->sample.header.misc = PERF_RECORD_MISC_USER; 700 event->sample.header.misc = PERF_RECORD_MISC_USER;
472 event->sample.header.size = sizeof(struct perf_event_header); 701 event->sample.header.size = sizeof(struct perf_event_header);
473 702
474 sample.ip = start_addr; 703 sample.ip = cs_etm__last_executed_instr(etmq->prev_packet);
475 sample.pid = etmq->pid; 704 sample.pid = etmq->pid;
476 sample.tid = etmq->tid; 705 sample.tid = etmq->tid;
477 sample.addr = end_addr; 706 sample.addr = etmq->packet->start_addr;
478 sample.id = etmq->etm->branches_id; 707 sample.id = etmq->etm->branches_id;
479 sample.stream_id = etmq->etm->branches_id; 708 sample.stream_id = etmq->etm->branches_id;
480 sample.period = 1; 709 sample.period = 1;
481 sample.cpu = packet->cpu; 710 sample.cpu = etmq->packet->cpu;
482 sample.flags = 0; 711 sample.flags = 0;
483 sample.cpumode = PERF_RECORD_MISC_USER; 712 sample.cpumode = PERF_RECORD_MISC_USER;
484 713
714 /*
715 * perf report cannot handle events without a branch stack
716 */
717 if (etm->synth_opts.last_branch) {
718 dummy_bs = (struct dummy_branch_stack){
719 .nr = 1,
720 .entries = {
721 .from = sample.ip,
722 .to = sample.addr,
723 },
724 };
725 sample.branch_stack = (struct branch_stack *)&dummy_bs;
726 }
727
728 if (etm->synth_opts.inject) {
729 ret = cs_etm__inject_event(event, &sample,
730 etm->branches_sample_type);
731 if (ret)
732 return ret;
733 }
734
485 ret = perf_session__deliver_synth_event(etm->session, event, &sample); 735 ret = perf_session__deliver_synth_event(etm->session, event, &sample);
486 736
487 if (ret) 737 if (ret)
@@ -578,6 +828,24 @@ static int cs_etm__synth_events(struct cs_etm_auxtrace *etm,
578 etm->sample_branches = true; 828 etm->sample_branches = true;
579 etm->branches_sample_type = attr.sample_type; 829 etm->branches_sample_type = attr.sample_type;
580 etm->branches_id = id; 830 etm->branches_id = id;
831 id += 1;
832 attr.sample_type &= ~(u64)PERF_SAMPLE_ADDR;
833 }
834
835 if (etm->synth_opts.last_branch)
836 attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
837
838 if (etm->synth_opts.instructions) {
839 attr.config = PERF_COUNT_HW_INSTRUCTIONS;
840 attr.sample_period = etm->synth_opts.period;
841 etm->instructions_sample_period = attr.sample_period;
842 err = cs_etm__synth_event(session, &attr, id);
843 if (err)
844 return err;
845 etm->sample_instructions = true;
846 etm->instructions_sample_type = attr.sample_type;
847 etm->instructions_id = id;
848 id += 1;
581 } 849 }
582 850
583 return 0; 851 return 0;
@@ -585,25 +853,108 @@ static int cs_etm__synth_events(struct cs_etm_auxtrace *etm,
585 853
586static int cs_etm__sample(struct cs_etm_queue *etmq) 854static int cs_etm__sample(struct cs_etm_queue *etmq)
587{ 855{
856 struct cs_etm_auxtrace *etm = etmq->etm;
857 struct cs_etm_packet *tmp;
588 int ret; 858 int ret;
589 struct cs_etm_packet packet; 859 u64 instrs_executed;
590 860
591 while (1) { 861 instrs_executed = cs_etm__instr_count(etmq->packet);
592 ret = cs_etm_decoder__get_packet(etmq->decoder, &packet); 862 etmq->period_instructions += instrs_executed;
593 if (ret <= 0) 863
864 /*
865 * Record a branch when the last instruction in
866 * PREV_PACKET is a branch.
867 */
868 if (etm->synth_opts.last_branch &&
869 etmq->prev_packet &&
870 etmq->prev_packet->sample_type == CS_ETM_RANGE &&
871 etmq->prev_packet->last_instr_taken_branch)
872 cs_etm__update_last_branch_rb(etmq);
873
874 if (etm->sample_instructions &&
875 etmq->period_instructions >= etm->instructions_sample_period) {
876 /*
877 * Emit instruction sample periodically
878 * TODO: allow period to be defined in cycles and clock time
879 */
880
881 /* Get number of instructions executed after the sample point */
882 u64 instrs_over = etmq->period_instructions -
883 etm->instructions_sample_period;
884
885 /*
886 * Calculate the address of the sampled instruction (-1 as
887 * sample is reported as though instruction has just been
888 * executed, but PC has not advanced to next instruction)
889 */
890 u64 offset = (instrs_executed - instrs_over - 1);
891 u64 addr = cs_etm__instr_addr(etmq->packet, offset);
892
893 ret = cs_etm__synth_instruction_sample(
894 etmq, addr, etm->instructions_sample_period);
895 if (ret)
896 return ret;
897
898 /* Carry remaining instructions into next sample period */
899 etmq->period_instructions = instrs_over;
900 }
901
902 if (etm->sample_branches &&
903 etmq->prev_packet &&
904 etmq->prev_packet->sample_type == CS_ETM_RANGE &&
905 etmq->prev_packet->last_instr_taken_branch) {
906 ret = cs_etm__synth_branch_sample(etmq);
907 if (ret)
594 return ret; 908 return ret;
909 }
595 910
911 if (etm->sample_branches || etm->synth_opts.last_branch) {
596 /* 912 /*
597 * If the packet contains an instruction range, generate an 913 * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
598 * instruction sequence event. 914 * the next incoming packet.
599 */ 915 */
600 if (packet.sample_type & CS_ETM_RANGE) 916 tmp = etmq->packet;
601 cs_etm__synth_branch_sample(etmq, &packet); 917 etmq->packet = etmq->prev_packet;
918 etmq->prev_packet = tmp;
602 } 919 }
603 920
604 return 0; 921 return 0;
605} 922}
606 923
924static int cs_etm__flush(struct cs_etm_queue *etmq)
925{
926 int err = 0;
927 struct cs_etm_packet *tmp;
928
929 if (etmq->etm->synth_opts.last_branch &&
930 etmq->prev_packet &&
931 etmq->prev_packet->sample_type == CS_ETM_RANGE) {
932 /*
933 * Generate a last branch event for the branches left in the
934 * circular buffer at the end of the trace.
935 *
936 * Use the address of the end of the last reported execution
937 * range
938 */
939 u64 addr = cs_etm__last_executed_instr(etmq->prev_packet);
940
941 err = cs_etm__synth_instruction_sample(
942 etmq, addr,
943 etmq->period_instructions);
944 etmq->period_instructions = 0;
945
946 /*
947 * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
948 * the next incoming packet.
949 */
950 tmp = etmq->packet;
951 etmq->packet = etmq->prev_packet;
952 etmq->prev_packet = tmp;
953 }
954
955 return err;
956}
957
607static int cs_etm__run_decoder(struct cs_etm_queue *etmq) 958static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
608{ 959{
609 struct cs_etm_auxtrace *etm = etmq->etm; 960 struct cs_etm_auxtrace *etm = etmq->etm;
@@ -615,45 +966,72 @@ static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
615 etm->kernel_start = machine__kernel_start(etm->machine); 966 etm->kernel_start = machine__kernel_start(etm->machine);
616 967
617 /* Go through each buffer in the queue and decode them one by one */ 968 /* Go through each buffer in the queue and decode them one by one */
618more: 969 while (1) {
619 buffer_used = 0; 970 buffer_used = 0;
620 memset(&buffer, 0, sizeof(buffer)); 971 memset(&buffer, 0, sizeof(buffer));
621 err = cs_etm__get_trace(&buffer, etmq); 972 err = cs_etm__get_trace(&buffer, etmq);
622 if (err <= 0) 973 if (err <= 0)
623 return err;
624 /*
625 * We cannot assume consecutive blocks in the data file are contiguous,
626 * reset the decoder to force re-sync.
627 */
628 err = cs_etm_decoder__reset(etmq->decoder);
629 if (err != 0)
630 return err;
631
632 /* Run trace decoder until buffer consumed or end of trace */
633 do {
634 processed = 0;
635
636 err = cs_etm_decoder__process_data_block(
637 etmq->decoder,
638 etmq->offset,
639 &buffer.buf[buffer_used],
640 buffer.len - buffer_used,
641 &processed);
642
643 if (err)
644 return err; 974 return err;
645
646 etmq->offset += processed;
647 buffer_used += processed;
648
649 /* 975 /*
650 * Nothing to do with an error condition, let's hope the next 976 * We cannot assume consecutive blocks in the data file are
651 * chunk will be better. 977 * contiguous, reset the decoder to force re-sync.
652 */ 978 */
653 err = cs_etm__sample(etmq); 979 err = cs_etm_decoder__reset(etmq->decoder);
654 } while (buffer.len > buffer_used); 980 if (err != 0)
981 return err;
982
983 /* Run trace decoder until buffer consumed or end of trace */
984 do {
985 processed = 0;
986 err = cs_etm_decoder__process_data_block(
987 etmq->decoder,
988 etmq->offset,
989 &buffer.buf[buffer_used],
990 buffer.len - buffer_used,
991 &processed);
992 if (err)
993 return err;
994
995 etmq->offset += processed;
996 buffer_used += processed;
997
998 /* Process each packet in this chunk */
999 while (1) {
1000 err = cs_etm_decoder__get_packet(etmq->decoder,
1001 etmq->packet);
1002 if (err <= 0)
1003 /*
1004 * Stop processing this chunk on
1005 * end of data or error
1006 */
1007 break;
1008
1009 switch (etmq->packet->sample_type) {
1010 case CS_ETM_RANGE:
1011 /*
1012 * If the packet contains an instruction
1013 * range, generate instruction sequence
1014 * events.
1015 */
1016 cs_etm__sample(etmq);
1017 break;
1018 case CS_ETM_TRACE_ON:
1019 /*
1020 * Discontinuity in trace, flush
1021 * previous branch stack
1022 */
1023 cs_etm__flush(etmq);
1024 break;
1025 default:
1026 break;
1027 }
1028 }
1029 } while (buffer.len > buffer_used);
655 1030
656goto more; 1031 if (err == 0)
1032 /* Flush any remaining branch stack entries */
1033 err = cs_etm__flush(etmq);
1034 }
657 1035
658 return err; 1036 return err;
659} 1037}
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index f3a71db83947..3d6459626c2a 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -232,7 +232,6 @@ int perf_quiet_option(void)
232 var++; 232 var++;
233 } 233 }
234 234
235 quiet = true;
236 return 0; 235 return 0;
237} 236}
238 237
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index 6d311868d850..4c842762e3f2 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -32,6 +32,10 @@ void perf_env__exit(struct perf_env *env)
32 for (i = 0; i < env->caches_cnt; i++) 32 for (i = 0; i < env->caches_cnt; i++)
33 cpu_cache_level__free(&env->caches[i]); 33 cpu_cache_level__free(&env->caches[i]);
34 zfree(&env->caches); 34 zfree(&env->caches);
35
36 for (i = 0; i < env->nr_memory_nodes; i++)
37 free(env->memory_nodes[i].set);
38 zfree(&env->memory_nodes);
35} 39}
36 40
37int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]) 41int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[])
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index bf970f57dce0..c4ef2e523367 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -27,6 +27,12 @@ struct numa_node {
27 struct cpu_map *map; 27 struct cpu_map *map;
28}; 28};
29 29
30struct memory_node {
31 u64 node;
32 u64 size;
33 unsigned long *set;
34};
35
30struct perf_env { 36struct perf_env {
31 char *hostname; 37 char *hostname;
32 char *os_release; 38 char *os_release;
@@ -43,6 +49,7 @@ struct perf_env {
43 int nr_sibling_cores; 49 int nr_sibling_cores;
44 int nr_sibling_threads; 50 int nr_sibling_threads;
45 int nr_numa_nodes; 51 int nr_numa_nodes;
52 int nr_memory_nodes;
46 int nr_pmu_mappings; 53 int nr_pmu_mappings;
47 int nr_groups; 54 int nr_groups;
48 char *cmdline; 55 char *cmdline;
@@ -54,6 +61,8 @@ struct perf_env {
54 struct cpu_cache_level *caches; 61 struct cpu_cache_level *caches;
55 int caches_cnt; 62 int caches_cnt;
56 struct numa_node *numa_nodes; 63 struct numa_node *numa_nodes;
64 struct memory_node *memory_nodes;
65 unsigned long long memory_bsize;
57}; 66};
58 67
59extern struct perf_env perf_env; 68extern struct perf_env perf_env;
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 44e603c27944..f0a6cbd033cc 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -894,8 +894,6 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
894 struct machine *machine) 894 struct machine *machine)
895{ 895{
896 size_t size; 896 size_t size;
897 const char *mmap_name;
898 char name_buff[PATH_MAX];
899 struct map *map = machine__kernel_map(machine); 897 struct map *map = machine__kernel_map(machine);
900 struct kmap *kmap; 898 struct kmap *kmap;
901 int err; 899 int err;
@@ -918,7 +916,6 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
918 return -1; 916 return -1;
919 } 917 }
920 918
921 mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff));
922 if (machine__is_host(machine)) { 919 if (machine__is_host(machine)) {
923 /* 920 /*
924 * kernel uses PERF_RECORD_MISC_USER for user space maps, 921 * kernel uses PERF_RECORD_MISC_USER for user space maps,
@@ -931,7 +928,7 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
931 928
932 kmap = map__kmap(map); 929 kmap = map__kmap(map);
933 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), 930 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
934 "%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1; 931 "%s%s", machine->mmap_name, kmap->ref_reloc_sym->name) + 1;
935 size = PERF_ALIGN(size, sizeof(u64)); 932 size = PERF_ALIGN(size, sizeof(u64));
936 event->mmap.header.type = PERF_RECORD_MMAP; 933 event->mmap.header.type = PERF_RECORD_MMAP;
937 event->mmap.header.size = (sizeof(event->mmap) - 934 event->mmap.header.size = (sizeof(event->mmap) -
@@ -1591,17 +1588,6 @@ int machine__resolve(struct machine *machine, struct addr_location *al,
1591 return -1; 1588 return -1;
1592 1589
1593 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); 1590 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
1594 /*
1595 * Have we already created the kernel maps for this machine?
1596 *
1597 * This should have happened earlier, when we processed the kernel MMAP
1598 * events, but for older perf.data files there was no such thing, so do
1599 * it now.
1600 */
1601 if (sample->cpumode == PERF_RECORD_MISC_KERNEL &&
1602 machine__kernel_map(machine) == NULL)
1603 machine__create_kernel_maps(machine);
1604
1605 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->ip, al); 1591 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->ip, al);
1606 dump_printf(" ...... dso: %s\n", 1592 dump_printf(" ...... dso: %s\n",
1607 al->map ? al->map->dso->long_name : 1593 al->map ? al->map->dso->long_name :
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index ac35cd214feb..a59281d64368 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -702,46 +702,6 @@ static int perf_evlist__resume(struct perf_evlist *evlist)
702 return perf_evlist__set_paused(evlist, false); 702 return perf_evlist__set_paused(evlist, false);
703} 703}
704 704
705union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, int idx)
706{
707 struct perf_mmap *md = &evlist->mmap[idx];
708
709 /*
710 * Check messup is required for forward overwritable ring buffer:
711 * memory pointed by md->prev can be overwritten in this case.
712 * No need for read-write ring buffer: kernel stop outputting when
713 * it hit md->prev (perf_mmap__consume()).
714 */
715 return perf_mmap__read_forward(md);
716}
717
718union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx)
719{
720 struct perf_mmap *md = &evlist->mmap[idx];
721
722 /*
723 * No need to check messup for backward ring buffer:
724 * We can always read arbitrary long data from a backward
725 * ring buffer unless we forget to pause it before reading.
726 */
727 return perf_mmap__read_backward(md);
728}
729
730union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
731{
732 return perf_evlist__mmap_read_forward(evlist, idx);
733}
734
735void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx)
736{
737 perf_mmap__read_catchup(&evlist->mmap[idx]);
738}
739
740void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
741{
742 perf_mmap__consume(&evlist->mmap[idx], false);
743}
744
745static void perf_evlist__munmap_nofree(struct perf_evlist *evlist) 705static void perf_evlist__munmap_nofree(struct perf_evlist *evlist)
746{ 706{
747 int i; 707 int i;
@@ -762,7 +722,8 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
762 zfree(&evlist->overwrite_mmap); 722 zfree(&evlist->overwrite_mmap);
763} 723}
764 724
765static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist) 725static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist,
726 bool overwrite)
766{ 727{
767 int i; 728 int i;
768 struct perf_mmap *map; 729 struct perf_mmap *map;
@@ -776,9 +737,10 @@ static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist)
776 737
777 for (i = 0; i < evlist->nr_mmaps; i++) { 738 for (i = 0; i < evlist->nr_mmaps; i++) {
778 map[i].fd = -1; 739 map[i].fd = -1;
740 map[i].overwrite = overwrite;
779 /* 741 /*
780 * When the perf_mmap() call is made we grab one refcount, plus 742 * When the perf_mmap() call is made we grab one refcount, plus
781 * one extra to let perf_evlist__mmap_consume() get the last 743 * one extra to let perf_mmap__consume() get the last
782 * events after all real references (perf_mmap__get()) are 744 * events after all real references (perf_mmap__get()) are
783 * dropped. 745 * dropped.
784 * 746 *
@@ -819,7 +781,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
819 maps = evlist->overwrite_mmap; 781 maps = evlist->overwrite_mmap;
820 782
821 if (!maps) { 783 if (!maps) {
822 maps = perf_evlist__alloc_mmap(evlist); 784 maps = perf_evlist__alloc_mmap(evlist, true);
823 if (!maps) 785 if (!maps)
824 return -1; 786 return -1;
825 evlist->overwrite_mmap = maps; 787 evlist->overwrite_mmap = maps;
@@ -1069,7 +1031,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
1069 struct mmap_params mp; 1031 struct mmap_params mp;
1070 1032
1071 if (!evlist->mmap) 1033 if (!evlist->mmap)
1072 evlist->mmap = perf_evlist__alloc_mmap(evlist); 1034 evlist->mmap = perf_evlist__alloc_mmap(evlist, false);
1073 if (!evlist->mmap) 1035 if (!evlist->mmap)
1074 return -ENOMEM; 1036 return -ENOMEM;
1075 1037
@@ -1103,11 +1065,30 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages)
1103 1065
1104int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) 1066int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
1105{ 1067{
1068 bool all_threads = (target->per_thread && target->system_wide);
1106 struct cpu_map *cpus; 1069 struct cpu_map *cpus;
1107 struct thread_map *threads; 1070 struct thread_map *threads;
1108 1071
1072 /*
1073 * If specify '-a' and '--per-thread' to perf record, perf record
1074 * will override '--per-thread'. target->per_thread = false and
1075 * target->system_wide = true.
1076 *
1077 * If specify '--per-thread' only to perf record,
1078 * target->per_thread = true and target->system_wide = false.
1079 *
1080 * So target->per_thread && target->system_wide is false.
1081 * For perf record, thread_map__new_str doesn't call
1082 * thread_map__new_all_cpus. That will keep perf record's
1083 * current behavior.
1084 *
1085 * For perf stat, it allows the case that target->per_thread and
1086 * target->system_wide are all true. It means to collect system-wide
1087 * per-thread data. thread_map__new_str will call
1088 * thread_map__new_all_cpus to enumerate all threads.
1089 */
1109 threads = thread_map__new_str(target->pid, target->tid, target->uid, 1090 threads = thread_map__new_str(target->pid, target->tid, target->uid,
1110 target->per_thread); 1091 all_threads);
1111 1092
1112 if (!threads) 1093 if (!threads)
1113 return -1; 1094 return -1;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 75f8e0ad5d76..6c41b2f78713 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -129,14 +129,6 @@ struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
129 129
130void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, enum bkw_mmap_state state); 130void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, enum bkw_mmap_state state);
131 131
132union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
133
134union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist,
135 int idx);
136union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist,
137 int idx);
138void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx);
139
140void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); 132void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
141 133
142int perf_evlist__open(struct perf_evlist *evlist); 134int perf_evlist__open(struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ff359c9ece2e..1ac8d9236efd 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -41,17 +41,7 @@
41 41
42#include "sane_ctype.h" 42#include "sane_ctype.h"
43 43
44static struct { 44struct perf_missing_features perf_missing_features;
45 bool sample_id_all;
46 bool exclude_guest;
47 bool mmap2;
48 bool cloexec;
49 bool clockid;
50 bool clockid_wrong;
51 bool lbr_flags;
52 bool write_backward;
53 bool group_read;
54} perf_missing_features;
55 45
56static clockid_t clockid; 46static clockid_t clockid;
57 47
@@ -254,6 +244,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
254 evsel->metric_name = NULL; 244 evsel->metric_name = NULL;
255 evsel->metric_events = NULL; 245 evsel->metric_events = NULL;
256 evsel->collect_stat = false; 246 evsel->collect_stat = false;
247 evsel->pmu_name = NULL;
257} 248}
258 249
259struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) 250struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
@@ -631,22 +622,34 @@ const char *perf_evsel__group_name(struct perf_evsel *evsel)
631 return evsel->group_name ?: "anon group"; 622 return evsel->group_name ?: "anon group";
632} 623}
633 624
625/*
626 * Returns the group details for the specified leader,
627 * with following rules.
628 *
629 * For record -e '{cycles,instructions}'
630 * 'anon group { cycles:u, instructions:u }'
631 *
632 * For record -e 'cycles,instructions' and report --group
633 * 'cycles:u, instructions:u'
634 */
634int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size) 635int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
635{ 636{
636 int ret; 637 int ret = 0;
637 struct perf_evsel *pos; 638 struct perf_evsel *pos;
638 const char *group_name = perf_evsel__group_name(evsel); 639 const char *group_name = perf_evsel__group_name(evsel);
639 640
640 ret = scnprintf(buf, size, "%s", group_name); 641 if (!evsel->forced_leader)
642 ret = scnprintf(buf, size, "%s { ", group_name);
641 643
642 ret += scnprintf(buf + ret, size - ret, " { %s", 644 ret += scnprintf(buf + ret, size - ret, "%s",
643 perf_evsel__name(evsel)); 645 perf_evsel__name(evsel));
644 646
645 for_each_group_member(pos, evsel) 647 for_each_group_member(pos, evsel)
646 ret += scnprintf(buf + ret, size - ret, ", %s", 648 ret += scnprintf(buf + ret, size - ret, ", %s",
647 perf_evsel__name(pos)); 649 perf_evsel__name(pos));
648 650
649 ret += scnprintf(buf + ret, size - ret, " }"); 651 if (!evsel->forced_leader)
652 ret += scnprintf(buf + ret, size - ret, " }");
650 653
651 return ret; 654 return ret;
652} 655}
@@ -1243,7 +1246,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)
1243 perf_evsel__free_fd(evsel); 1246 perf_evsel__free_fd(evsel);
1244 perf_evsel__free_id(evsel); 1247 perf_evsel__free_id(evsel);
1245 perf_evsel__free_config_terms(evsel); 1248 perf_evsel__free_config_terms(evsel);
1246 close_cgroup(evsel->cgrp); 1249 cgroup__put(evsel->cgrp);
1247 cpu_map__put(evsel->cpus); 1250 cpu_map__put(evsel->cpus);
1248 cpu_map__put(evsel->own_cpus); 1251 cpu_map__put(evsel->own_cpus);
1249 thread_map__put(evsel->threads); 1252 thread_map__put(evsel->threads);
@@ -1925,6 +1928,9 @@ try_fallback:
1925 goto fallback_missing_features; 1928 goto fallback_missing_features;
1926 } 1929 }
1927out_close: 1930out_close:
1931 if (err)
1932 threads->err_thread = thread;
1933
1928 do { 1934 do {
1929 while (--thread >= 0) { 1935 while (--thread >= 0) {
1930 close(FD(evsel, cpu, thread)); 1936 close(FD(evsel, cpu, thread));
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 846e41644525..d3ee3af618ef 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -30,7 +30,7 @@ struct perf_sample_id {
30 u64 period; 30 u64 period;
31}; 31};
32 32
33struct cgroup_sel; 33struct cgroup;
34 34
35/* 35/*
36 * The 'struct perf_evsel_config_term' is used to pass event 36 * The 'struct perf_evsel_config_term' is used to pass event
@@ -107,7 +107,7 @@ struct perf_evsel {
107 struct perf_stat_evsel *stats; 107 struct perf_stat_evsel *stats;
108 void *priv; 108 void *priv;
109 u64 db_id; 109 u64 db_id;
110 struct cgroup_sel *cgrp; 110 struct cgroup *cgrp;
111 void *handler; 111 void *handler;
112 struct cpu_map *cpus; 112 struct cpu_map *cpus;
113 struct cpu_map *own_cpus; 113 struct cpu_map *own_cpus;
@@ -125,6 +125,7 @@ struct perf_evsel {
125 bool per_pkg; 125 bool per_pkg;
126 bool precise_max; 126 bool precise_max;
127 bool ignore_missing_thread; 127 bool ignore_missing_thread;
128 bool forced_leader;
128 /* parse modifier helper */ 129 /* parse modifier helper */
129 int exclude_GH; 130 int exclude_GH;
130 int nr_members; 131 int nr_members;
@@ -142,6 +143,7 @@ struct perf_evsel {
142 struct perf_evsel **metric_events; 143 struct perf_evsel **metric_events;
143 bool collect_stat; 144 bool collect_stat;
144 bool weak_group; 145 bool weak_group;
146 const char *pmu_name;
145}; 147};
146 148
147union u64_swap { 149union u64_swap {
@@ -149,6 +151,20 @@ union u64_swap {
149 u32 val32[2]; 151 u32 val32[2];
150}; 152};
151 153
154struct perf_missing_features {
155 bool sample_id_all;
156 bool exclude_guest;
157 bool mmap2;
158 bool cloexec;
159 bool clockid;
160 bool clockid_wrong;
161 bool lbr_flags;
162 bool write_backward;
163 bool group_read;
164};
165
166extern struct perf_missing_features perf_missing_features;
167
152struct cpu_map; 168struct cpu_map;
153struct target; 169struct target;
154struct thread_map; 170struct thread_map;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a326e0d8b5b6..121df1683c36 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -17,6 +17,7 @@
17#include <sys/stat.h> 17#include <sys/stat.h>
18#include <sys/utsname.h> 18#include <sys/utsname.h>
19#include <linux/time64.h> 19#include <linux/time64.h>
20#include <dirent.h>
20 21
21#include "evlist.h" 22#include "evlist.h"
22#include "evsel.h" 23#include "evsel.h"
@@ -37,6 +38,7 @@
37#include "asm/bug.h" 38#include "asm/bug.h"
38#include "tool.h" 39#include "tool.h"
39#include "time-utils.h" 40#include "time-utils.h"
41#include "units.h"
40 42
41#include "sane_ctype.h" 43#include "sane_ctype.h"
42 44
@@ -132,6 +134,25 @@ int do_write(struct feat_fd *ff, const void *buf, size_t size)
132} 134}
133 135
134/* Return: 0 if succeded, -ERR if failed. */ 136/* Return: 0 if succeded, -ERR if failed. */
137static int do_write_bitmap(struct feat_fd *ff, unsigned long *set, u64 size)
138{
139 u64 *p = (u64 *) set;
140 int i, ret;
141
142 ret = do_write(ff, &size, sizeof(size));
143 if (ret < 0)
144 return ret;
145
146 for (i = 0; (u64) i < BITS_TO_U64(size); i++) {
147 ret = do_write(ff, p + i, sizeof(*p));
148 if (ret < 0)
149 return ret;
150 }
151
152 return 0;
153}
154
155/* Return: 0 if succeded, -ERR if failed. */
135int write_padded(struct feat_fd *ff, const void *bf, 156int write_padded(struct feat_fd *ff, const void *bf,
136 size_t count, size_t count_aligned) 157 size_t count, size_t count_aligned)
137{ 158{
@@ -243,6 +264,38 @@ static char *do_read_string(struct feat_fd *ff)
243 return NULL; 264 return NULL;
244} 265}
245 266
267/* Return: 0 if succeded, -ERR if failed. */
268static int do_read_bitmap(struct feat_fd *ff, unsigned long **pset, u64 *psize)
269{
270 unsigned long *set;
271 u64 size, *p;
272 int i, ret;
273
274 ret = do_read_u64(ff, &size);
275 if (ret)
276 return ret;
277
278 set = bitmap_alloc(size);
279 if (!set)
280 return -ENOMEM;
281
282 bitmap_zero(set, size);
283
284 p = (u64 *) set;
285
286 for (i = 0; (u64) i < BITS_TO_U64(size); i++) {
287 ret = do_read_u64(ff, p + i);
288 if (ret < 0) {
289 free(set);
290 return ret;
291 }
292 }
293
294 *pset = set;
295 *psize = size;
296 return 0;
297}
298
246static int write_tracing_data(struct feat_fd *ff, 299static int write_tracing_data(struct feat_fd *ff,
247 struct perf_evlist *evlist) 300 struct perf_evlist *evlist)
248{ 301{
@@ -1196,6 +1249,176 @@ static int write_sample_time(struct feat_fd *ff,
1196 sizeof(evlist->last_sample_time)); 1249 sizeof(evlist->last_sample_time));
1197} 1250}
1198 1251
1252
1253static int memory_node__read(struct memory_node *n, unsigned long idx)
1254{
1255 unsigned int phys, size = 0;
1256 char path[PATH_MAX];
1257 struct dirent *ent;
1258 DIR *dir;
1259
1260#define for_each_memory(mem, dir) \
1261 while ((ent = readdir(dir))) \
1262 if (strcmp(ent->d_name, ".") && \
1263 strcmp(ent->d_name, "..") && \
1264 sscanf(ent->d_name, "memory%u", &mem) == 1)
1265
1266 scnprintf(path, PATH_MAX,
1267 "%s/devices/system/node/node%lu",
1268 sysfs__mountpoint(), idx);
1269
1270 dir = opendir(path);
1271 if (!dir) {
1272 pr_warning("failed: cant' open memory sysfs data\n");
1273 return -1;
1274 }
1275
1276 for_each_memory(phys, dir) {
1277 size = max(phys, size);
1278 }
1279
1280 size++;
1281
1282 n->set = bitmap_alloc(size);
1283 if (!n->set) {
1284 closedir(dir);
1285 return -ENOMEM;
1286 }
1287
1288 bitmap_zero(n->set, size);
1289 n->node = idx;
1290 n->size = size;
1291
1292 rewinddir(dir);
1293
1294 for_each_memory(phys, dir) {
1295 set_bit(phys, n->set);
1296 }
1297
1298 closedir(dir);
1299 return 0;
1300}
1301
1302static int memory_node__sort(const void *a, const void *b)
1303{
1304 const struct memory_node *na = a;
1305 const struct memory_node *nb = b;
1306
1307 return na->node - nb->node;
1308}
1309
1310static int build_mem_topology(struct memory_node *nodes, u64 size, u64 *cntp)
1311{
1312 char path[PATH_MAX];
1313 struct dirent *ent;
1314 DIR *dir;
1315 u64 cnt = 0;
1316 int ret = 0;
1317
1318 scnprintf(path, PATH_MAX, "%s/devices/system/node/",
1319 sysfs__mountpoint());
1320
1321 dir = opendir(path);
1322 if (!dir) {
1323 pr_warning("failed: can't open node sysfs data\n");
1324 return -1;
1325 }
1326
1327 while (!ret && (ent = readdir(dir))) {
1328 unsigned int idx;
1329 int r;
1330
1331 if (!strcmp(ent->d_name, ".") ||
1332 !strcmp(ent->d_name, ".."))
1333 continue;
1334
1335 r = sscanf(ent->d_name, "node%u", &idx);
1336 if (r != 1)
1337 continue;
1338
1339 if (WARN_ONCE(cnt >= size,
1340 "failed to write MEM_TOPOLOGY, way too many nodes\n"))
1341 return -1;
1342
1343 ret = memory_node__read(&nodes[cnt++], idx);
1344 }
1345
1346 *cntp = cnt;
1347 closedir(dir);
1348
1349 if (!ret)
1350 qsort(nodes, cnt, sizeof(nodes[0]), memory_node__sort);
1351
1352 return ret;
1353}
1354
1355#define MAX_MEMORY_NODES 2000
1356
1357/*
1358 * The MEM_TOPOLOGY holds physical memory map for every
1359 * node in system. The format of data is as follows:
1360 *
1361 * 0 - version | for future changes
1362 * 8 - block_size_bytes | /sys/devices/system/memory/block_size_bytes
1363 * 16 - count | number of nodes
1364 *
1365 * For each node we store map of physical indexes for
1366 * each node:
1367 *
1368 * 32 - node id | node index
1369 * 40 - size | size of bitmap
1370 * 48 - bitmap | bitmap of memory indexes that belongs to node
1371 */
1372static int write_mem_topology(struct feat_fd *ff __maybe_unused,
1373 struct perf_evlist *evlist __maybe_unused)
1374{
1375 static struct memory_node nodes[MAX_MEMORY_NODES];
1376 u64 bsize, version = 1, i, nr;
1377 int ret;
1378
1379 ret = sysfs__read_xll("devices/system/memory/block_size_bytes",
1380 (unsigned long long *) &bsize);
1381 if (ret)
1382 return ret;
1383
1384 ret = build_mem_topology(&nodes[0], MAX_MEMORY_NODES, &nr);
1385 if (ret)
1386 return ret;
1387
1388 ret = do_write(ff, &version, sizeof(version));
1389 if (ret < 0)
1390 goto out;
1391
1392 ret = do_write(ff, &bsize, sizeof(bsize));
1393 if (ret < 0)
1394 goto out;
1395
1396 ret = do_write(ff, &nr, sizeof(nr));
1397 if (ret < 0)
1398 goto out;
1399
1400 for (i = 0; i < nr; i++) {
1401 struct memory_node *n = &nodes[i];
1402
1403 #define _W(v) \
1404 ret = do_write(ff, &n->v, sizeof(n->v)); \
1405 if (ret < 0) \
1406 goto out;
1407
1408 _W(node)
1409 _W(size)
1410
1411 #undef _W
1412
1413 ret = do_write_bitmap(ff, n->set, n->size);
1414 if (ret < 0)
1415 goto out;
1416 }
1417
1418out:
1419 return ret;
1420}
1421
1199static void print_hostname(struct feat_fd *ff, FILE *fp) 1422static void print_hostname(struct feat_fd *ff, FILE *fp)
1200{ 1423{
1201 fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname); 1424 fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname);
@@ -1543,6 +1766,35 @@ static void print_sample_time(struct feat_fd *ff, FILE *fp)
1543 fprintf(fp, "# sample duration : %10.3f ms\n", d); 1766 fprintf(fp, "# sample duration : %10.3f ms\n", d);
1544} 1767}
1545 1768
1769static void memory_node__fprintf(struct memory_node *n,
1770 unsigned long long bsize, FILE *fp)
1771{
1772 char buf_map[100], buf_size[50];
1773 unsigned long long size;
1774
1775 size = bsize * bitmap_weight(n->set, n->size);
1776 unit_number__scnprintf(buf_size, 50, size);
1777
1778 bitmap_scnprintf(n->set, n->size, buf_map, 100);
1779 fprintf(fp, "# %3" PRIu64 " [%s]: %s\n", n->node, buf_size, buf_map);
1780}
1781
1782static void print_mem_topology(struct feat_fd *ff, FILE *fp)
1783{
1784 struct memory_node *nodes;
1785 int i, nr;
1786
1787 nodes = ff->ph->env.memory_nodes;
1788 nr = ff->ph->env.nr_memory_nodes;
1789
1790 fprintf(fp, "# memory nodes (nr %d, block size 0x%llx):\n",
1791 nr, ff->ph->env.memory_bsize);
1792
1793 for (i = 0; i < nr; i++) {
1794 memory_node__fprintf(&nodes[i], ff->ph->env.memory_bsize, fp);
1795 }
1796}
1797
1546static int __event_process_build_id(struct build_id_event *bev, 1798static int __event_process_build_id(struct build_id_event *bev,
1547 char *filename, 1799 char *filename,
1548 struct perf_session *session) 1800 struct perf_session *session)
@@ -2205,6 +2457,58 @@ static int process_sample_time(struct feat_fd *ff, void *data __maybe_unused)
2205 return 0; 2457 return 0;
2206} 2458}
2207 2459
2460static int process_mem_topology(struct feat_fd *ff,
2461 void *data __maybe_unused)
2462{
2463 struct memory_node *nodes;
2464 u64 version, i, nr, bsize;
2465 int ret = -1;
2466
2467 if (do_read_u64(ff, &version))
2468 return -1;
2469
2470 if (version != 1)
2471 return -1;
2472
2473 if (do_read_u64(ff, &bsize))
2474 return -1;
2475
2476 if (do_read_u64(ff, &nr))
2477 return -1;
2478
2479 nodes = zalloc(sizeof(*nodes) * nr);
2480 if (!nodes)
2481 return -1;
2482
2483 for (i = 0; i < nr; i++) {
2484 struct memory_node n;
2485
2486 #define _R(v) \
2487 if (do_read_u64(ff, &n.v)) \
2488 goto out; \
2489
2490 _R(node)
2491 _R(size)
2492
2493 #undef _R
2494
2495 if (do_read_bitmap(ff, &n.set, &n.size))
2496 goto out;
2497
2498 nodes[i] = n;
2499 }
2500
2501 ff->ph->env.memory_bsize = bsize;
2502 ff->ph->env.memory_nodes = nodes;
2503 ff->ph->env.nr_memory_nodes = nr;
2504 ret = 0;
2505
2506out:
2507 if (ret)
2508 free(nodes);
2509 return ret;
2510}
2511
2208struct feature_ops { 2512struct feature_ops {
2209 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); 2513 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
2210 void (*print)(struct feat_fd *ff, FILE *fp); 2514 void (*print)(struct feat_fd *ff, FILE *fp);
@@ -2263,6 +2567,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
2263 FEAT_OPN(STAT, stat, false), 2567 FEAT_OPN(STAT, stat, false),
2264 FEAT_OPN(CACHE, cache, true), 2568 FEAT_OPN(CACHE, cache, true),
2265 FEAT_OPR(SAMPLE_TIME, sample_time, false), 2569 FEAT_OPR(SAMPLE_TIME, sample_time, false),
2570 FEAT_OPR(MEM_TOPOLOGY, mem_topology, true),
2266}; 2571};
2267 2572
2268struct header_print_data { 2573struct header_print_data {
@@ -2318,7 +2623,12 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
2318 if (ret == -1) 2623 if (ret == -1)
2319 return -1; 2624 return -1;
2320 2625
2321 fprintf(fp, "# captured on: %s", ctime(&st.st_ctime)); 2626 fprintf(fp, "# captured on : %s", ctime(&st.st_ctime));
2627
2628 fprintf(fp, "# header version : %u\n", header->version);
2629 fprintf(fp, "# data offset : %" PRIu64 "\n", header->data_offset);
2630 fprintf(fp, "# data size : %" PRIu64 "\n", header->data_size);
2631 fprintf(fp, "# feat offset : %" PRIu64 "\n", header->feat_offset);
2322 2632
2323 perf_header__process_sections(header, fd, &hd, 2633 perf_header__process_sections(header, fd, &hd,
2324 perf_file_section__fprintf_info); 2634 perf_file_section__fprintf_info);
@@ -3105,8 +3415,17 @@ int perf_event__synthesize_features(struct perf_tool *tool,
3105 return ret; 3415 return ret;
3106 } 3416 }
3107 } 3417 }
3418
3419 /* Send HEADER_LAST_FEATURE mark. */
3420 fe = ff.buf;
3421 fe->feat_id = HEADER_LAST_FEATURE;
3422 fe->header.type = PERF_RECORD_HEADER_FEATURE;
3423 fe->header.size = sizeof(*fe);
3424
3425 ret = process(tool, ff.buf, NULL, NULL);
3426
3108 free(ff.buf); 3427 free(ff.buf);
3109 return 0; 3428 return ret;
3110} 3429}
3111 3430
3112int perf_event__process_feature(struct perf_tool *tool, 3431int perf_event__process_feature(struct perf_tool *tool,
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index f28aaaa3a440..90d4577a92dc 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -36,6 +36,7 @@ enum {
36 HEADER_STAT, 36 HEADER_STAT,
37 HEADER_CACHE, 37 HEADER_CACHE,
38 HEADER_SAMPLE_TIME, 38 HEADER_SAMPLE_TIME,
39 HEADER_MEM_TOPOLOGY,
39 HEADER_LAST_FEATURE, 40 HEADER_LAST_FEATURE,
40 HEADER_FEAT_BITS = 256, 41 HEADER_FEAT_BITS = 256,
41}; 42};
@@ -174,4 +175,5 @@ int write_padded(struct feat_fd *fd, const void *bf,
174int get_cpuid(char *buffer, size_t sz); 175int get_cpuid(char *buffer, size_t sz);
175 176
176char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused); 177char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused);
178int strcmp_cpuid_str(const char *s1, const char *s2);
177#endif /* __PERF_HEADER_H */ 179#endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index b6140950301e..7d968892ee39 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -536,7 +536,7 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
536 * This mem info was allocated from sample__resolve_mem 536 * This mem info was allocated from sample__resolve_mem
537 * and will not be used anymore. 537 * and will not be used anymore.
538 */ 538 */
539 zfree(&entry->mem_info); 539 mem_info__zput(entry->mem_info);
540 540
541 /* If the map of an existing hist_entry has 541 /* If the map of an existing hist_entry has
542 * become out-of-date due to an exec() or 542 * become out-of-date due to an exec() or
@@ -879,7 +879,7 @@ iter_prepare_cumulative_entry(struct hist_entry_iter *iter,
879 * cumulated only one time to prevent entries more than 100% 879 * cumulated only one time to prevent entries more than 100%
880 * overhead. 880 * overhead.
881 */ 881 */
882 he_cache = malloc(sizeof(*he_cache) * (iter->max_stack + 1)); 882 he_cache = malloc(sizeof(*he_cache) * (callchain_cursor.nr + 1));
883 if (he_cache == NULL) 883 if (he_cache == NULL)
884 return -ENOMEM; 884 return -ENOMEM;
885 885
@@ -1045,8 +1045,6 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
1045 if (err) 1045 if (err)
1046 return err; 1046 return err;
1047 1047
1048 iter->max_stack = max_stack_depth;
1049
1050 err = iter->ops->prepare_entry(iter, al); 1048 err = iter->ops->prepare_entry(iter, al);
1051 if (err) 1049 if (err)
1052 goto out; 1050 goto out;
@@ -1141,7 +1139,7 @@ void hist_entry__delete(struct hist_entry *he)
1141 if (he->mem_info) { 1139 if (he->mem_info) {
1142 map__zput(he->mem_info->iaddr.map); 1140 map__zput(he->mem_info->iaddr.map);
1143 map__zput(he->mem_info->daddr.map); 1141 map__zput(he->mem_info->daddr.map);
1144 zfree(&he->mem_info); 1142 mem_info__zput(he->mem_info);
1145 } 1143 }
1146 1144
1147 zfree(&he->stat_acc); 1145 zfree(&he->stat_acc);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index f6630cb95eff..e869cad4d89f 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -107,7 +107,6 @@ struct hist_entry_iter {
107 int curr; 107 int curr;
108 108
109 bool hide_unresolved; 109 bool hide_unresolved;
110 int max_stack;
111 110
112 struct perf_evsel *evsel; 111 struct perf_evsel *evsel;
113 struct perf_sample *sample; 112 struct perf_sample *sample;
@@ -430,7 +429,8 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
430int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 429int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
431 struct hist_browser_timer *hbt, 430 struct hist_browser_timer *hbt,
432 float min_pcnt, 431 float min_pcnt,
433 struct perf_env *env); 432 struct perf_env *env,
433 bool warn_lost_event);
434int script_browse(const char *script_opt); 434int script_browse(const char *script_opt);
435#else 435#else
436static inline 436static inline
@@ -438,7 +438,8 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
438 const char *help __maybe_unused, 438 const char *help __maybe_unused,
439 struct hist_browser_timer *hbt __maybe_unused, 439 struct hist_browser_timer *hbt __maybe_unused,
440 float min_pcnt __maybe_unused, 440 float min_pcnt __maybe_unused,
441 struct perf_env *env __maybe_unused) 441 struct perf_env *env __maybe_unused,
442 bool warn_lost_event __maybe_unused)
442{ 443{
443 return 0; 444 return 0;
444} 445}
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index aa1593ce551d..f9157aed1289 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -1378,6 +1378,7 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder)
1378 intel_pt_clear_tx_flags(decoder); 1378 intel_pt_clear_tx_flags(decoder);
1379 decoder->have_tma = false; 1379 decoder->have_tma = false;
1380 decoder->cbr = 0; 1380 decoder->cbr = 0;
1381 decoder->timestamp_insn_cnt = 0;
1381 decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; 1382 decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
1382 decoder->overflow = true; 1383 decoder->overflow = true;
1383 return -EOVERFLOW; 1384 return -EOVERFLOW;
@@ -1616,6 +1617,7 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
1616 case INTEL_PT_PWRX: 1617 case INTEL_PT_PWRX:
1617 intel_pt_log("ERROR: Missing TIP after FUP\n"); 1618 intel_pt_log("ERROR: Missing TIP after FUP\n");
1618 decoder->pkt_state = INTEL_PT_STATE_ERR3; 1619 decoder->pkt_state = INTEL_PT_STATE_ERR3;
1620 decoder->pkt_step = 0;
1619 return -ENOENT; 1621 return -ENOENT;
1620 1622
1621 case INTEL_PT_OVF: 1623 case INTEL_PT_OVF:
@@ -2390,14 +2392,6 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
2390 return &decoder->state; 2392 return &decoder->state;
2391} 2393}
2392 2394
2393static bool intel_pt_at_psb(unsigned char *buf, size_t len)
2394{
2395 if (len < INTEL_PT_PSB_LEN)
2396 return false;
2397 return memmem(buf, INTEL_PT_PSB_LEN, INTEL_PT_PSB_STR,
2398 INTEL_PT_PSB_LEN);
2399}
2400
2401/** 2395/**
2402 * intel_pt_next_psb - move buffer pointer to the start of the next PSB packet. 2396 * intel_pt_next_psb - move buffer pointer to the start of the next PSB packet.
2403 * @buf: pointer to buffer pointer 2397 * @buf: pointer to buffer pointer
@@ -2486,6 +2480,7 @@ static unsigned char *intel_pt_last_psb(unsigned char *buf, size_t len)
2486 * @buf: buffer 2480 * @buf: buffer
2487 * @len: size of buffer 2481 * @len: size of buffer
2488 * @tsc: TSC value returned 2482 * @tsc: TSC value returned
2483 * @rem: returns remaining size when TSC is found
2489 * 2484 *
2490 * Find a TSC packet in @buf and return the TSC value. This function assumes 2485 * Find a TSC packet in @buf and return the TSC value. This function assumes
2491 * that @buf starts at a PSB and that PSB+ will contain TSC and so stops if a 2486 * that @buf starts at a PSB and that PSB+ will contain TSC and so stops if a
@@ -2493,7 +2488,8 @@ static unsigned char *intel_pt_last_psb(unsigned char *buf, size_t len)
2493 * 2488 *
2494 * Return: %true if TSC is found, false otherwise. 2489 * Return: %true if TSC is found, false otherwise.
2495 */ 2490 */
2496static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc) 2491static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc,
2492 size_t *rem)
2497{ 2493{
2498 struct intel_pt_pkt packet; 2494 struct intel_pt_pkt packet;
2499 int ret; 2495 int ret;
@@ -2504,6 +2500,7 @@ static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc)
2504 return false; 2500 return false;
2505 if (packet.type == INTEL_PT_TSC) { 2501 if (packet.type == INTEL_PT_TSC) {
2506 *tsc = packet.payload; 2502 *tsc = packet.payload;
2503 *rem = len;
2507 return true; 2504 return true;
2508 } 2505 }
2509 if (packet.type == INTEL_PT_PSBEND) 2506 if (packet.type == INTEL_PT_PSBEND)
@@ -2554,6 +2551,8 @@ static int intel_pt_tsc_cmp(uint64_t tsc1, uint64_t tsc2)
2554 * @len_a: size of first buffer 2551 * @len_a: size of first buffer
2555 * @buf_b: second buffer 2552 * @buf_b: second buffer
2556 * @len_b: size of second buffer 2553 * @len_b: size of second buffer
2554 * @consecutive: returns true if there is data in buf_b that is consecutive
2555 * to buf_a
2557 * 2556 *
2558 * If the trace contains TSC we can look at the last TSC of @buf_a and the 2557 * If the trace contains TSC we can look at the last TSC of @buf_a and the
2559 * first TSC of @buf_b in order to determine if the buffers overlap, and then 2558 * first TSC of @buf_b in order to determine if the buffers overlap, and then
@@ -2566,33 +2565,41 @@ static int intel_pt_tsc_cmp(uint64_t tsc1, uint64_t tsc2)
2566static unsigned char *intel_pt_find_overlap_tsc(unsigned char *buf_a, 2565static unsigned char *intel_pt_find_overlap_tsc(unsigned char *buf_a,
2567 size_t len_a, 2566 size_t len_a,
2568 unsigned char *buf_b, 2567 unsigned char *buf_b,
2569 size_t len_b) 2568 size_t len_b, bool *consecutive)
2570{ 2569{
2571 uint64_t tsc_a, tsc_b; 2570 uint64_t tsc_a, tsc_b;
2572 unsigned char *p; 2571 unsigned char *p;
2573 size_t len; 2572 size_t len, rem_a, rem_b;
2574 2573
2575 p = intel_pt_last_psb(buf_a, len_a); 2574 p = intel_pt_last_psb(buf_a, len_a);
2576 if (!p) 2575 if (!p)
2577 return buf_b; /* No PSB in buf_a => no overlap */ 2576 return buf_b; /* No PSB in buf_a => no overlap */
2578 2577
2579 len = len_a - (p - buf_a); 2578 len = len_a - (p - buf_a);
2580 if (!intel_pt_next_tsc(p, len, &tsc_a)) { 2579 if (!intel_pt_next_tsc(p, len, &tsc_a, &rem_a)) {
2581 /* The last PSB+ in buf_a is incomplete, so go back one more */ 2580 /* The last PSB+ in buf_a is incomplete, so go back one more */
2582 len_a -= len; 2581 len_a -= len;
2583 p = intel_pt_last_psb(buf_a, len_a); 2582 p = intel_pt_last_psb(buf_a, len_a);
2584 if (!p) 2583 if (!p)
2585 return buf_b; /* No full PSB+ => assume no overlap */ 2584 return buf_b; /* No full PSB+ => assume no overlap */
2586 len = len_a - (p - buf_a); 2585 len = len_a - (p - buf_a);
2587 if (!intel_pt_next_tsc(p, len, &tsc_a)) 2586 if (!intel_pt_next_tsc(p, len, &tsc_a, &rem_a))
2588 return buf_b; /* No TSC in buf_a => assume no overlap */ 2587 return buf_b; /* No TSC in buf_a => assume no overlap */
2589 } 2588 }
2590 2589
2591 while (1) { 2590 while (1) {
2592 /* Ignore PSB+ with no TSC */ 2591 /* Ignore PSB+ with no TSC */
2593 if (intel_pt_next_tsc(buf_b, len_b, &tsc_b) && 2592 if (intel_pt_next_tsc(buf_b, len_b, &tsc_b, &rem_b)) {
2594 intel_pt_tsc_cmp(tsc_a, tsc_b) < 0) 2593 int cmp = intel_pt_tsc_cmp(tsc_a, tsc_b);
2595 return buf_b; /* tsc_a < tsc_b => no overlap */ 2594
2595 /* Same TSC, so buffers are consecutive */
2596 if (!cmp && rem_b >= rem_a) {
2597 *consecutive = true;
2598 return buf_b + len_b - (rem_b - rem_a);
2599 }
2600 if (cmp < 0)
2601 return buf_b; /* tsc_a < tsc_b => no overlap */
2602 }
2596 2603
2597 if (!intel_pt_step_psb(&buf_b, &len_b)) 2604 if (!intel_pt_step_psb(&buf_b, &len_b))
2598 return buf_b + len_b; /* No PSB in buf_b => no data */ 2605 return buf_b + len_b; /* No PSB in buf_b => no data */
@@ -2606,6 +2613,8 @@ static unsigned char *intel_pt_find_overlap_tsc(unsigned char *buf_a,
2606 * @buf_b: second buffer 2613 * @buf_b: second buffer
2607 * @len_b: size of second buffer 2614 * @len_b: size of second buffer
2608 * @have_tsc: can use TSC packets to detect overlap 2615 * @have_tsc: can use TSC packets to detect overlap
2616 * @consecutive: returns true if there is data in buf_b that is consecutive
2617 * to buf_a
2609 * 2618 *
2610 * When trace samples or snapshots are recorded there is the possibility that 2619 * When trace samples or snapshots are recorded there is the possibility that
2611 * the data overlaps. Note that, for the purposes of decoding, data is only 2620 * the data overlaps. Note that, for the purposes of decoding, data is only
@@ -2616,7 +2625,7 @@ static unsigned char *intel_pt_find_overlap_tsc(unsigned char *buf_a,
2616 */ 2625 */
2617unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a, 2626unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a,
2618 unsigned char *buf_b, size_t len_b, 2627 unsigned char *buf_b, size_t len_b,
2619 bool have_tsc) 2628 bool have_tsc, bool *consecutive)
2620{ 2629{
2621 unsigned char *found; 2630 unsigned char *found;
2622 2631
@@ -2628,7 +2637,8 @@ unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a,
2628 return buf_b; /* No overlap */ 2637 return buf_b; /* No overlap */
2629 2638
2630 if (have_tsc) { 2639 if (have_tsc) {
2631 found = intel_pt_find_overlap_tsc(buf_a, len_a, buf_b, len_b); 2640 found = intel_pt_find_overlap_tsc(buf_a, len_a, buf_b, len_b,
2641 consecutive);
2632 if (found) 2642 if (found)
2633 return found; 2643 return found;
2634 } 2644 }
@@ -2643,28 +2653,16 @@ unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a,
2643 } 2653 }
2644 2654
2645 /* Now len_b >= len_a */ 2655 /* Now len_b >= len_a */
2646 if (len_b > len_a) {
2647 /* The leftover buffer 'b' must start at a PSB */
2648 while (!intel_pt_at_psb(buf_b + len_a, len_b - len_a)) {
2649 if (!intel_pt_step_psb(&buf_a, &len_a))
2650 return buf_b; /* No overlap */
2651 }
2652 }
2653
2654 while (1) { 2656 while (1) {
2655 /* Potential overlap so check the bytes */ 2657 /* Potential overlap so check the bytes */
2656 found = memmem(buf_a, len_a, buf_b, len_a); 2658 found = memmem(buf_a, len_a, buf_b, len_a);
2657 if (found) 2659 if (found) {
2660 *consecutive = true;
2658 return buf_b + len_a; 2661 return buf_b + len_a;
2662 }
2659 2663
2660 /* Try again at next PSB in buffer 'a' */ 2664 /* Try again at next PSB in buffer 'a' */
2661 if (!intel_pt_step_psb(&buf_a, &len_a)) 2665 if (!intel_pt_step_psb(&buf_a, &len_a))
2662 return buf_b; /* No overlap */ 2666 return buf_b; /* No overlap */
2663
2664 /* The leftover buffer 'b' must start at a PSB */
2665 while (!intel_pt_at_psb(buf_b + len_a, len_b - len_a)) {
2666 if (!intel_pt_step_psb(&buf_a, &len_a))
2667 return buf_b; /* No overlap */
2668 }
2669 } 2667 }
2670} 2668}
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 921b22e8ca0e..fc1752d50019 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -117,7 +117,7 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder);
117 117
118unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a, 118unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a,
119 unsigned char *buf_b, size_t len_b, 119 unsigned char *buf_b, size_t len_b,
120 bool have_tsc); 120 bool have_tsc, bool *consecutive);
121 121
122int intel_pt__strerror(int code, char *buf, size_t buflen); 122int intel_pt__strerror(int code, char *buf, size_t buflen);
123 123
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 3773d9c54f45..0effaff57020 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -132,6 +132,7 @@ struct intel_pt_queue {
132 struct intel_pt *pt; 132 struct intel_pt *pt;
133 unsigned int queue_nr; 133 unsigned int queue_nr;
134 struct auxtrace_buffer *buffer; 134 struct auxtrace_buffer *buffer;
135 struct auxtrace_buffer *old_buffer;
135 void *decoder; 136 void *decoder;
136 const struct intel_pt_state *state; 137 const struct intel_pt_state *state;
137 struct ip_callchain *chain; 138 struct ip_callchain *chain;
@@ -143,6 +144,7 @@ struct intel_pt_queue {
143 bool stop; 144 bool stop;
144 bool step_through_buffers; 145 bool step_through_buffers;
145 bool use_buffer_pid_tid; 146 bool use_buffer_pid_tid;
147 bool sync_switch;
146 pid_t pid, tid; 148 pid_t pid, tid;
147 int cpu; 149 int cpu;
148 int switch_state; 150 int switch_state;
@@ -207,49 +209,28 @@ static void intel_pt_dump_event(struct intel_pt *pt, unsigned char *buf,
207static int intel_pt_do_fix_overlap(struct intel_pt *pt, struct auxtrace_buffer *a, 209static int intel_pt_do_fix_overlap(struct intel_pt *pt, struct auxtrace_buffer *a,
208 struct auxtrace_buffer *b) 210 struct auxtrace_buffer *b)
209{ 211{
212 bool consecutive = false;
210 void *start; 213 void *start;
211 214
212 start = intel_pt_find_overlap(a->data, a->size, b->data, b->size, 215 start = intel_pt_find_overlap(a->data, a->size, b->data, b->size,
213 pt->have_tsc); 216 pt->have_tsc, &consecutive);
214 if (!start) 217 if (!start)
215 return -EINVAL; 218 return -EINVAL;
216 b->use_size = b->data + b->size - start; 219 b->use_size = b->data + b->size - start;
217 b->use_data = start; 220 b->use_data = start;
221 if (b->use_size && consecutive)
222 b->consecutive = true;
218 return 0; 223 return 0;
219} 224}
220 225
221static void intel_pt_use_buffer_pid_tid(struct intel_pt_queue *ptq,
222 struct auxtrace_queue *queue,
223 struct auxtrace_buffer *buffer)
224{
225 if (queue->cpu == -1 && buffer->cpu != -1)
226 ptq->cpu = buffer->cpu;
227
228 ptq->pid = buffer->pid;
229 ptq->tid = buffer->tid;
230
231 intel_pt_log("queue %u cpu %d pid %d tid %d\n",
232 ptq->queue_nr, ptq->cpu, ptq->pid, ptq->tid);
233
234 thread__zput(ptq->thread);
235
236 if (ptq->tid != -1) {
237 if (ptq->pid != -1)
238 ptq->thread = machine__findnew_thread(ptq->pt->machine,
239 ptq->pid,
240 ptq->tid);
241 else
242 ptq->thread = machine__find_thread(ptq->pt->machine, -1,
243 ptq->tid);
244 }
245}
246
247/* This function assumes data is processed sequentially only */ 226/* This function assumes data is processed sequentially only */
248static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data) 227static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
249{ 228{
250 struct intel_pt_queue *ptq = data; 229 struct intel_pt_queue *ptq = data;
251 struct auxtrace_buffer *buffer = ptq->buffer, *old_buffer = buffer; 230 struct auxtrace_buffer *buffer = ptq->buffer;
231 struct auxtrace_buffer *old_buffer = ptq->old_buffer;
252 struct auxtrace_queue *queue; 232 struct auxtrace_queue *queue;
233 bool might_overlap;
253 234
254 if (ptq->stop) { 235 if (ptq->stop) {
255 b->len = 0; 236 b->len = 0;
@@ -257,7 +238,7 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
257 } 238 }
258 239
259 queue = &ptq->pt->queues.queue_array[ptq->queue_nr]; 240 queue = &ptq->pt->queues.queue_array[ptq->queue_nr];
260next: 241
261 buffer = auxtrace_buffer__next(queue, buffer); 242 buffer = auxtrace_buffer__next(queue, buffer);
262 if (!buffer) { 243 if (!buffer) {
263 if (old_buffer) 244 if (old_buffer)
@@ -276,7 +257,8 @@ next:
276 return -ENOMEM; 257 return -ENOMEM;
277 } 258 }
278 259
279 if (ptq->pt->snapshot_mode && !buffer->consecutive && old_buffer && 260 might_overlap = ptq->pt->snapshot_mode || ptq->pt->sampling_mode;
261 if (might_overlap && !buffer->consecutive && old_buffer &&
280 intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer)) 262 intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer))
281 return -ENOMEM; 263 return -ENOMEM;
282 264
@@ -289,33 +271,24 @@ next:
289 } 271 }
290 b->ref_timestamp = buffer->reference; 272 b->ref_timestamp = buffer->reference;
291 273
292 /* 274 if (!old_buffer || (might_overlap && !buffer->consecutive)) {
293 * If in snapshot mode and the buffer has no usable data, get next
294 * buffer and again check overlap against old_buffer.
295 */
296 if (ptq->pt->snapshot_mode && !b->len)
297 goto next;
298
299 if (old_buffer)
300 auxtrace_buffer__drop_data(old_buffer);
301
302 if (!old_buffer || ptq->pt->sampling_mode || (ptq->pt->snapshot_mode &&
303 !buffer->consecutive)) {
304 b->consecutive = false; 275 b->consecutive = false;
305 b->trace_nr = buffer->buffer_nr + 1; 276 b->trace_nr = buffer->buffer_nr + 1;
306 } else { 277 } else {
307 b->consecutive = true; 278 b->consecutive = true;
308 } 279 }
309 280
310 if (ptq->use_buffer_pid_tid && (ptq->pid != buffer->pid ||
311 ptq->tid != buffer->tid))
312 intel_pt_use_buffer_pid_tid(ptq, queue, buffer);
313
314 if (ptq->step_through_buffers) 281 if (ptq->step_through_buffers)
315 ptq->stop = true; 282 ptq->stop = true;
316 283
317 if (!b->len) 284 if (b->len) {
285 if (old_buffer)
286 auxtrace_buffer__drop_data(old_buffer);
287 ptq->old_buffer = buffer;
288 } else {
289 auxtrace_buffer__drop_data(buffer);
318 return intel_pt_get_trace(b, data); 290 return intel_pt_get_trace(b, data);
291 }
319 292
320 return 0; 293 return 0;
321} 294}
@@ -954,16 +927,15 @@ static int intel_pt_setup_queue(struct intel_pt *pt,
954 ptq->cpu = queue->cpu; 927 ptq->cpu = queue->cpu;
955 ptq->tid = queue->tid; 928 ptq->tid = queue->tid;
956 929
957 if (pt->sampling_mode) { 930 if (pt->sampling_mode && !pt->snapshot_mode &&
958 if (pt->timeless_decoding) 931 pt->timeless_decoding)
959 ptq->step_through_buffers = true; 932 ptq->step_through_buffers = true;
960 if (pt->timeless_decoding || !pt->have_sched_switch) 933
961 ptq->use_buffer_pid_tid = true; 934 ptq->sync_switch = pt->sync_switch;
962 }
963 } 935 }
964 936
965 if (!ptq->on_heap && 937 if (!ptq->on_heap &&
966 (!pt->sync_switch || 938 (!ptq->sync_switch ||
967 ptq->switch_state != INTEL_PT_SS_EXPECTING_SWITCH_EVENT)) { 939 ptq->switch_state != INTEL_PT_SS_EXPECTING_SWITCH_EVENT)) {
968 const struct intel_pt_state *state; 940 const struct intel_pt_state *state;
969 int ret; 941 int ret;
@@ -1546,7 +1518,7 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
1546 if (pt->synth_opts.last_branch) 1518 if (pt->synth_opts.last_branch)
1547 intel_pt_update_last_branch_rb(ptq); 1519 intel_pt_update_last_branch_rb(ptq);
1548 1520
1549 if (!pt->sync_switch) 1521 if (!ptq->sync_switch)
1550 return 0; 1522 return 0;
1551 1523
1552 if (intel_pt_is_switch_ip(ptq, state->to_ip)) { 1524 if (intel_pt_is_switch_ip(ptq, state->to_ip)) {
@@ -1627,6 +1599,21 @@ static u64 intel_pt_switch_ip(struct intel_pt *pt, u64 *ptss_ip)
1627 return switch_ip; 1599 return switch_ip;
1628} 1600}
1629 1601
1602static void intel_pt_enable_sync_switch(struct intel_pt *pt)
1603{
1604 unsigned int i;
1605
1606 pt->sync_switch = true;
1607
1608 for (i = 0; i < pt->queues.nr_queues; i++) {
1609 struct auxtrace_queue *queue = &pt->queues.queue_array[i];
1610 struct intel_pt_queue *ptq = queue->priv;
1611
1612 if (ptq)
1613 ptq->sync_switch = true;
1614 }
1615}
1616
1630static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp) 1617static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
1631{ 1618{
1632 const struct intel_pt_state *state = ptq->state; 1619 const struct intel_pt_state *state = ptq->state;
@@ -1643,7 +1630,7 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
1643 if (pt->switch_ip) { 1630 if (pt->switch_ip) {
1644 intel_pt_log("switch_ip: %"PRIx64" ptss_ip: %"PRIx64"\n", 1631 intel_pt_log("switch_ip: %"PRIx64" ptss_ip: %"PRIx64"\n",
1645 pt->switch_ip, pt->ptss_ip); 1632 pt->switch_ip, pt->ptss_ip);
1646 pt->sync_switch = true; 1633 intel_pt_enable_sync_switch(pt);
1647 } 1634 }
1648 } 1635 }
1649 } 1636 }
@@ -1659,9 +1646,9 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
1659 if (state->err) { 1646 if (state->err) {
1660 if (state->err == INTEL_PT_ERR_NODATA) 1647 if (state->err == INTEL_PT_ERR_NODATA)
1661 return 1; 1648 return 1;
1662 if (pt->sync_switch && 1649 if (ptq->sync_switch &&
1663 state->from_ip >= pt->kernel_start) { 1650 state->from_ip >= pt->kernel_start) {
1664 pt->sync_switch = false; 1651 ptq->sync_switch = false;
1665 intel_pt_next_tid(pt, ptq); 1652 intel_pt_next_tid(pt, ptq);
1666 } 1653 }
1667 if (pt->synth_opts.errors) { 1654 if (pt->synth_opts.errors) {
@@ -1687,7 +1674,7 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
1687 state->timestamp, state->est_timestamp); 1674 state->timestamp, state->est_timestamp);
1688 ptq->timestamp = state->est_timestamp; 1675 ptq->timestamp = state->est_timestamp;
1689 /* Use estimated TSC in unknown switch state */ 1676 /* Use estimated TSC in unknown switch state */
1690 } else if (pt->sync_switch && 1677 } else if (ptq->sync_switch &&
1691 ptq->switch_state == INTEL_PT_SS_UNKNOWN && 1678 ptq->switch_state == INTEL_PT_SS_UNKNOWN &&
1692 intel_pt_is_switch_ip(ptq, state->to_ip) && 1679 intel_pt_is_switch_ip(ptq, state->to_ip) &&
1693 ptq->next_tid == -1) { 1680 ptq->next_tid == -1) {
@@ -1834,7 +1821,7 @@ static int intel_pt_sync_switch(struct intel_pt *pt, int cpu, pid_t tid,
1834 return 1; 1821 return 1;
1835 1822
1836 ptq = intel_pt_cpu_to_ptq(pt, cpu); 1823 ptq = intel_pt_cpu_to_ptq(pt, cpu);
1837 if (!ptq) 1824 if (!ptq || !ptq->sync_switch)
1838 return 1; 1825 return 1;
1839 1826
1840 switch (ptq->switch_state) { 1827 switch (ptq->switch_state) {
@@ -2075,9 +2062,6 @@ static int intel_pt_process_auxtrace_event(struct perf_session *session,
2075 struct intel_pt *pt = container_of(session->auxtrace, struct intel_pt, 2062 struct intel_pt *pt = container_of(session->auxtrace, struct intel_pt,
2076 auxtrace); 2063 auxtrace);
2077 2064
2078 if (pt->sampling_mode)
2079 return 0;
2080
2081 if (!pt->data_queued) { 2065 if (!pt->data_queued) {
2082 struct auxtrace_buffer *buffer; 2066 struct auxtrace_buffer *buffer;
2083 off_t data_offset; 2067 off_t data_offset;
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 4952b429caa7..1cca0a2fa641 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -433,6 +433,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
433 char serr[STRERR_BUFSIZE]; 433 char serr[STRERR_BUFSIZE];
434 char *kbuild_dir = NULL, *kbuild_include_opts = NULL; 434 char *kbuild_dir = NULL, *kbuild_include_opts = NULL;
435 const char *template = llvm_param.clang_bpf_cmd_template; 435 const char *template = llvm_param.clang_bpf_cmd_template;
436 char *command_echo, *command_out;
436 437
437 if (path[0] != '-' && realpath(path, abspath) == NULL) { 438 if (path[0] != '-' && realpath(path, abspath) == NULL) {
438 err = errno; 439 err = errno;
@@ -487,6 +488,16 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
487 (path[0] == '-') ? path : abspath); 488 (path[0] == '-') ? path : abspath);
488 489
489 pr_debug("llvm compiling command template: %s\n", template); 490 pr_debug("llvm compiling command template: %s\n", template);
491
492 if (asprintf(&command_echo, "echo -n \"%s\"", template) < 0)
493 goto errout;
494
495 err = read_from_pipe(command_echo, (void **) &command_out, NULL);
496 if (err)
497 goto errout;
498
499 pr_debug("llvm compiling command : %s\n", command_out);
500
490 err = read_from_pipe(template, &obj_buf, &obj_buf_sz); 501 err = read_from_pipe(template, &obj_buf, &obj_buf_sz);
491 if (err) { 502 if (err) {
492 pr_err("ERROR:\tunable to compile %s\n", path); 503 pr_err("ERROR:\tunable to compile %s\n", path);
@@ -497,6 +508,8 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
497 goto errout; 508 goto errout;
498 } 509 }
499 510
511 free(command_echo);
512 free(command_out);
500 free(kbuild_dir); 513 free(kbuild_dir);
501 free(kbuild_include_opts); 514 free(kbuild_include_opts);
502 515
@@ -509,6 +522,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
509 *p_obj_buf_sz = obj_buf_sz; 522 *p_obj_buf_sz = obj_buf_sz;
510 return 0; 523 return 0;
511errout: 524errout:
525 free(command_echo);
512 free(kbuild_dir); 526 free(kbuild_dir);
513 free(kbuild_include_opts); 527 free(kbuild_include_opts);
514 free(obj_buf); 528 free(obj_buf);
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index b05a67464c03..2eca8478e24f 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -48,8 +48,23 @@ static void machine__threads_init(struct machine *machine)
48 } 48 }
49} 49}
50 50
51static int machine__set_mmap_name(struct machine *machine)
52{
53 if (machine__is_host(machine))
54 machine->mmap_name = strdup("[kernel.kallsyms]");
55 else if (machine__is_default_guest(machine))
56 machine->mmap_name = strdup("[guest.kernel.kallsyms]");
57 else if (asprintf(&machine->mmap_name, "[guest.kernel.kallsyms.%d]",
58 machine->pid) < 0)
59 machine->mmap_name = NULL;
60
61 return machine->mmap_name ? 0 : -ENOMEM;
62}
63
51int machine__init(struct machine *machine, const char *root_dir, pid_t pid) 64int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
52{ 65{
66 int err = -ENOMEM;
67
53 memset(machine, 0, sizeof(*machine)); 68 memset(machine, 0, sizeof(*machine));
54 map_groups__init(&machine->kmaps, machine); 69 map_groups__init(&machine->kmaps, machine);
55 RB_CLEAR_NODE(&machine->rb_node); 70 RB_CLEAR_NODE(&machine->rb_node);
@@ -73,13 +88,16 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
73 if (machine->root_dir == NULL) 88 if (machine->root_dir == NULL)
74 return -ENOMEM; 89 return -ENOMEM;
75 90
91 if (machine__set_mmap_name(machine))
92 goto out;
93
76 if (pid != HOST_KERNEL_ID) { 94 if (pid != HOST_KERNEL_ID) {
77 struct thread *thread = machine__findnew_thread(machine, -1, 95 struct thread *thread = machine__findnew_thread(machine, -1,
78 pid); 96 pid);
79 char comm[64]; 97 char comm[64];
80 98
81 if (thread == NULL) 99 if (thread == NULL)
82 return -ENOMEM; 100 goto out;
83 101
84 snprintf(comm, sizeof(comm), "[guest/%d]", pid); 102 snprintf(comm, sizeof(comm), "[guest/%d]", pid);
85 thread__set_comm(thread, comm, 0); 103 thread__set_comm(thread, comm, 0);
@@ -87,7 +105,13 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
87 } 105 }
88 106
89 machine->current_tid = NULL; 107 machine->current_tid = NULL;
108 err = 0;
90 109
110out:
111 if (err) {
112 zfree(&machine->root_dir);
113 zfree(&machine->mmap_name);
114 }
91 return 0; 115 return 0;
92} 116}
93 117
@@ -119,7 +143,7 @@ struct machine *machine__new_kallsyms(void)
119 * ask for not using the kcore parsing code, once this one is fixed 143 * ask for not using the kcore parsing code, once this one is fixed
120 * to create a map per module. 144 * to create a map per module.
121 */ 145 */
122 if (machine && __machine__load_kallsyms(machine, "/proc/kallsyms", MAP__FUNCTION, true) <= 0) { 146 if (machine && machine__load_kallsyms(machine, "/proc/kallsyms", MAP__FUNCTION) <= 0) {
123 machine__delete(machine); 147 machine__delete(machine);
124 machine = NULL; 148 machine = NULL;
125 } 149 }
@@ -180,6 +204,7 @@ void machine__exit(struct machine *machine)
180 dsos__exit(&machine->dsos); 204 dsos__exit(&machine->dsos);
181 machine__exit_vdso(machine); 205 machine__exit_vdso(machine);
182 zfree(&machine->root_dir); 206 zfree(&machine->root_dir);
207 zfree(&machine->mmap_name);
183 zfree(&machine->current_tid); 208 zfree(&machine->current_tid);
184 209
185 for (i = 0; i < THREADS__TABLE_SIZE; i++) { 210 for (i = 0; i < THREADS__TABLE_SIZE; i++) {
@@ -322,20 +347,6 @@ void machines__process_guests(struct machines *machines,
322 } 347 }
323} 348}
324 349
325char *machine__mmap_name(struct machine *machine, char *bf, size_t size)
326{
327 if (machine__is_host(machine))
328 snprintf(bf, size, "[%s]", "kernel.kallsyms");
329 else if (machine__is_default_guest(machine))
330 snprintf(bf, size, "[%s]", "guest.kernel.kallsyms");
331 else {
332 snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms",
333 machine->pid);
334 }
335
336 return bf;
337}
338
339void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size) 350void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size)
340{ 351{
341 struct rb_node *node; 352 struct rb_node *node;
@@ -771,24 +782,18 @@ size_t machine__fprintf(struct machine *machine, FILE *fp)
771 782
772static struct dso *machine__get_kernel(struct machine *machine) 783static struct dso *machine__get_kernel(struct machine *machine)
773{ 784{
774 const char *vmlinux_name = NULL; 785 const char *vmlinux_name = machine->mmap_name;
775 struct dso *kernel; 786 struct dso *kernel;
776 787
777 if (machine__is_host(machine)) { 788 if (machine__is_host(machine)) {
778 vmlinux_name = symbol_conf.vmlinux_name; 789 if (symbol_conf.vmlinux_name)
779 if (!vmlinux_name) 790 vmlinux_name = symbol_conf.vmlinux_name;
780 vmlinux_name = DSO__NAME_KALLSYMS;
781 791
782 kernel = machine__findnew_kernel(machine, vmlinux_name, 792 kernel = machine__findnew_kernel(machine, vmlinux_name,
783 "[kernel]", DSO_TYPE_KERNEL); 793 "[kernel]", DSO_TYPE_KERNEL);
784 } else { 794 } else {
785 char bf[PATH_MAX]; 795 if (symbol_conf.default_guest_vmlinux_name)
786
787 if (machine__is_default_guest(machine))
788 vmlinux_name = symbol_conf.default_guest_vmlinux_name; 796 vmlinux_name = symbol_conf.default_guest_vmlinux_name;
789 if (!vmlinux_name)
790 vmlinux_name = machine__mmap_name(machine, bf,
791 sizeof(bf));
792 797
793 kernel = machine__findnew_kernel(machine, vmlinux_name, 798 kernel = machine__findnew_kernel(machine, vmlinux_name,
794 "[guest.kernel]", 799 "[guest.kernel]",
@@ -849,13 +854,10 @@ static int machine__get_running_kernel_start(struct machine *machine,
849 return 0; 854 return 0;
850} 855}
851 856
852int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) 857static int
858__machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
853{ 859{
854 int type; 860 int type;
855 u64 start = 0;
856
857 if (machine__get_running_kernel_start(machine, NULL, &start))
858 return -1;
859 861
860 /* In case of renewal the kernel map, destroy previous one */ 862 /* In case of renewal the kernel map, destroy previous one */
861 machine__destroy_kernel_maps(machine); 863 machine__destroy_kernel_maps(machine);
@@ -864,7 +866,7 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
864 struct kmap *kmap; 866 struct kmap *kmap;
865 struct map *map; 867 struct map *map;
866 868
867 machine->vmlinux_maps[type] = map__new2(start, kernel, type); 869 machine->vmlinux_maps[type] = map__new2(0, kernel, type);
868 if (machine->vmlinux_maps[type] == NULL) 870 if (machine->vmlinux_maps[type] == NULL)
869 return -1; 871 return -1;
870 872
@@ -987,11 +989,11 @@ int machines__create_kernel_maps(struct machines *machines, pid_t pid)
987 return machine__create_kernel_maps(machine); 989 return machine__create_kernel_maps(machine);
988} 990}
989 991
990int __machine__load_kallsyms(struct machine *machine, const char *filename, 992int machine__load_kallsyms(struct machine *machine, const char *filename,
991 enum map_type type, bool no_kcore) 993 enum map_type type)
992{ 994{
993 struct map *map = machine__kernel_map(machine); 995 struct map *map = machine__kernel_map(machine);
994 int ret = __dso__load_kallsyms(map->dso, filename, map, no_kcore); 996 int ret = __dso__load_kallsyms(map->dso, filename, map, true);
995 997
996 if (ret > 0) { 998 if (ret > 0) {
997 dso__set_loaded(map->dso, type); 999 dso__set_loaded(map->dso, type);
@@ -1006,12 +1008,6 @@ int __machine__load_kallsyms(struct machine *machine, const char *filename,
1006 return ret; 1008 return ret;
1007} 1009}
1008 1010
1009int machine__load_kallsyms(struct machine *machine, const char *filename,
1010 enum map_type type)
1011{
1012 return __machine__load_kallsyms(machine, filename, type, false);
1013}
1014
1015int machine__load_vmlinux_path(struct machine *machine, enum map_type type) 1011int machine__load_vmlinux_path(struct machine *machine, enum map_type type)
1016{ 1012{
1017 struct map *map = machine__kernel_map(machine); 1013 struct map *map = machine__kernel_map(machine);
@@ -1215,6 +1211,24 @@ static int machine__create_modules(struct machine *machine)
1215 return 0; 1211 return 0;
1216} 1212}
1217 1213
1214static void machine__set_kernel_mmap(struct machine *machine,
1215 u64 start, u64 end)
1216{
1217 int i;
1218
1219 for (i = 0; i < MAP__NR_TYPES; i++) {
1220 machine->vmlinux_maps[i]->start = start;
1221 machine->vmlinux_maps[i]->end = end;
1222
1223 /*
1224 * Be a bit paranoid here, some perf.data file came with
1225 * a zero sized synthesized MMAP event for the kernel.
1226 */
1227 if (start == 0 && end == 0)
1228 machine->vmlinux_maps[i]->end = ~0ULL;
1229 }
1230}
1231
1218int machine__create_kernel_maps(struct machine *machine) 1232int machine__create_kernel_maps(struct machine *machine)
1219{ 1233{
1220 struct dso *kernel = machine__get_kernel(machine); 1234 struct dso *kernel = machine__get_kernel(machine);
@@ -1239,40 +1253,22 @@ int machine__create_kernel_maps(struct machine *machine)
1239 "continuing anyway...\n", machine->pid); 1253 "continuing anyway...\n", machine->pid);
1240 } 1254 }
1241 1255
1242 /*
1243 * Now that we have all the maps created, just set the ->end of them:
1244 */
1245 map_groups__fixup_end(&machine->kmaps);
1246
1247 if (!machine__get_running_kernel_start(machine, &name, &addr)) { 1256 if (!machine__get_running_kernel_start(machine, &name, &addr)) {
1248 if (name && 1257 if (name &&
1249 maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) { 1258 maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) {
1250 machine__destroy_kernel_maps(machine); 1259 machine__destroy_kernel_maps(machine);
1251 return -1; 1260 return -1;
1252 } 1261 }
1262 machine__set_kernel_mmap(machine, addr, 0);
1253 } 1263 }
1254 1264
1265 /*
1266 * Now that we have all the maps created, just set the ->end of them:
1267 */
1268 map_groups__fixup_end(&machine->kmaps);
1255 return 0; 1269 return 0;
1256} 1270}
1257 1271
1258static void machine__set_kernel_mmap_len(struct machine *machine,
1259 union perf_event *event)
1260{
1261 int i;
1262
1263 for (i = 0; i < MAP__NR_TYPES; i++) {
1264 machine->vmlinux_maps[i]->start = event->mmap.start;
1265 machine->vmlinux_maps[i]->end = (event->mmap.start +
1266 event->mmap.len);
1267 /*
1268 * Be a bit paranoid here, some perf.data file came with
1269 * a zero sized synthesized MMAP event for the kernel.
1270 */
1271 if (machine->vmlinux_maps[i]->end == 0)
1272 machine->vmlinux_maps[i]->end = ~0ULL;
1273 }
1274}
1275
1276static bool machine__uses_kcore(struct machine *machine) 1272static bool machine__uses_kcore(struct machine *machine)
1277{ 1273{
1278 struct dso *dso; 1274 struct dso *dso;
@@ -1289,7 +1285,6 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1289 union perf_event *event) 1285 union perf_event *event)
1290{ 1286{
1291 struct map *map; 1287 struct map *map;
1292 char kmmap_prefix[PATH_MAX];
1293 enum dso_kernel_type kernel_type; 1288 enum dso_kernel_type kernel_type;
1294 bool is_kernel_mmap; 1289 bool is_kernel_mmap;
1295 1290
@@ -1297,15 +1292,14 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1297 if (machine__uses_kcore(machine)) 1292 if (machine__uses_kcore(machine))
1298 return 0; 1293 return 0;
1299 1294
1300 machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
1301 if (machine__is_host(machine)) 1295 if (machine__is_host(machine))
1302 kernel_type = DSO_TYPE_KERNEL; 1296 kernel_type = DSO_TYPE_KERNEL;
1303 else 1297 else
1304 kernel_type = DSO_TYPE_GUEST_KERNEL; 1298 kernel_type = DSO_TYPE_GUEST_KERNEL;
1305 1299
1306 is_kernel_mmap = memcmp(event->mmap.filename, 1300 is_kernel_mmap = memcmp(event->mmap.filename,
1307 kmmap_prefix, 1301 machine->mmap_name,
1308 strlen(kmmap_prefix) - 1) == 0; 1302 strlen(machine->mmap_name) - 1) == 0;
1309 if (event->mmap.filename[0] == '/' || 1303 if (event->mmap.filename[0] == '/' ||
1310 (!is_kernel_mmap && event->mmap.filename[0] == '[')) { 1304 (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
1311 map = machine__findnew_module_map(machine, event->mmap.start, 1305 map = machine__findnew_module_map(machine, event->mmap.start,
@@ -1316,7 +1310,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1316 map->end = map->start + event->mmap.len; 1310 map->end = map->start + event->mmap.len;
1317 } else if (is_kernel_mmap) { 1311 } else if (is_kernel_mmap) {
1318 const char *symbol_name = (event->mmap.filename + 1312 const char *symbol_name = (event->mmap.filename +
1319 strlen(kmmap_prefix)); 1313 strlen(machine->mmap_name));
1320 /* 1314 /*
1321 * Should be there already, from the build-id table in 1315 * Should be there already, from the build-id table in
1322 * the header. 1316 * the header.
@@ -1357,7 +1351,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1357 up_read(&machine->dsos.lock); 1351 up_read(&machine->dsos.lock);
1358 1352
1359 if (kernel == NULL) 1353 if (kernel == NULL)
1360 kernel = machine__findnew_dso(machine, kmmap_prefix); 1354 kernel = machine__findnew_dso(machine, machine->mmap_name);
1361 if (kernel == NULL) 1355 if (kernel == NULL)
1362 goto out_problem; 1356 goto out_problem;
1363 1357
@@ -1370,7 +1364,8 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1370 if (strstr(kernel->long_name, "vmlinux")) 1364 if (strstr(kernel->long_name, "vmlinux"))
1371 dso__set_short_name(kernel, "[kernel.vmlinux]", false); 1365 dso__set_short_name(kernel, "[kernel.vmlinux]", false);
1372 1366
1373 machine__set_kernel_mmap_len(machine, event); 1367 machine__set_kernel_mmap(machine, event->mmap.start,
1368 event->mmap.start + event->mmap.len);
1374 1369
1375 /* 1370 /*
1376 * Avoid using a zero address (kptr_restrict) for the ref reloc 1371 * Avoid using a zero address (kptr_restrict) for the ref reloc
@@ -1700,7 +1695,7 @@ static void ip__resolve_data(struct thread *thread,
1700struct mem_info *sample__resolve_mem(struct perf_sample *sample, 1695struct mem_info *sample__resolve_mem(struct perf_sample *sample,
1701 struct addr_location *al) 1696 struct addr_location *al)
1702{ 1697{
1703 struct mem_info *mi = zalloc(sizeof(*mi)); 1698 struct mem_info *mi = mem_info__new();
1704 1699
1705 if (!mi) 1700 if (!mi)
1706 return NULL; 1701 return NULL;
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 5ce860b64c74..66cc200ef86f 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -43,6 +43,7 @@ struct machine {
43 bool comm_exec; 43 bool comm_exec;
44 bool kptr_restrict_warned; 44 bool kptr_restrict_warned;
45 char *root_dir; 45 char *root_dir;
46 char *mmap_name;
46 struct threads threads[THREADS__TABLE_SIZE]; 47 struct threads threads[THREADS__TABLE_SIZE];
47 struct vdso_info *vdso_info; 48 struct vdso_info *vdso_info;
48 struct perf_env *env; 49 struct perf_env *env;
@@ -142,8 +143,6 @@ struct machine *machines__find(struct machines *machines, pid_t pid);
142struct machine *machines__findnew(struct machines *machines, pid_t pid); 143struct machine *machines__findnew(struct machines *machines, pid_t pid);
143 144
144void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size); 145void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size);
145char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
146
147void machines__set_comm_exec(struct machines *machines, bool comm_exec); 146void machines__set_comm_exec(struct machines *machines, bool comm_exec);
148 147
149struct machine *machine__new_host(void); 148struct machine *machine__new_host(void);
@@ -226,8 +225,6 @@ struct map *machine__findnew_module_map(struct machine *machine, u64 start,
226 const char *filename); 225 const char *filename);
227int arch__fix_module_text_start(u64 *start, const char *name); 226int arch__fix_module_text_start(u64 *start, const char *name);
228 227
229int __machine__load_kallsyms(struct machine *machine, const char *filename,
230 enum map_type type, bool no_kcore);
231int machine__load_kallsyms(struct machine *machine, const char *filename, 228int machine__load_kallsyms(struct machine *machine, const char *filename,
232 enum map_type type); 229 enum map_type type);
233int machine__load_vmlinux_path(struct machine *machine, enum map_type type); 230int machine__load_vmlinux_path(struct machine *machine, enum map_type type);
@@ -239,7 +236,6 @@ size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp,
239 bool (skip)(struct dso *dso, int parm), int parm); 236 bool (skip)(struct dso *dso, int parm), int parm);
240 237
241void machine__destroy_kernel_maps(struct machine *machine); 238void machine__destroy_kernel_maps(struct machine *machine);
242int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel);
243int machine__create_kernel_maps(struct machine *machine); 239int machine__create_kernel_maps(struct machine *machine);
244 240
245int machines__create_kernel_maps(struct machines *machines, pid_t pid); 241int machines__create_kernel_maps(struct machines *machines, pid_t pid);
diff --git a/tools/perf/util/mem2node.c b/tools/perf/util/mem2node.c
new file mode 100644
index 000000000000..c6fd81c02586
--- /dev/null
+++ b/tools/perf/util/mem2node.c
@@ -0,0 +1,134 @@
1#include <errno.h>
2#include <inttypes.h>
3#include <linux/bitmap.h>
4#include "mem2node.h"
5#include "util.h"
6
7struct phys_entry {
8 struct rb_node rb_node;
9 u64 start;
10 u64 end;
11 u64 node;
12};
13
14static void phys_entry__insert(struct phys_entry *entry, struct rb_root *root)
15{
16 struct rb_node **p = &root->rb_node;
17 struct rb_node *parent = NULL;
18 struct phys_entry *e;
19
20 while (*p != NULL) {
21 parent = *p;
22 e = rb_entry(parent, struct phys_entry, rb_node);
23
24 if (entry->start < e->start)
25 p = &(*p)->rb_left;
26 else
27 p = &(*p)->rb_right;
28 }
29
30 rb_link_node(&entry->rb_node, parent, p);
31 rb_insert_color(&entry->rb_node, root);
32}
33
34static void
35phys_entry__init(struct phys_entry *entry, u64 start, u64 bsize, u64 node)
36{
37 entry->start = start;
38 entry->end = start + bsize;
39 entry->node = node;
40 RB_CLEAR_NODE(&entry->rb_node);
41}
42
43int mem2node__init(struct mem2node *map, struct perf_env *env)
44{
45 struct memory_node *n, *nodes = &env->memory_nodes[0];
46 struct phys_entry *entries, *tmp_entries;
47 u64 bsize = env->memory_bsize;
48 int i, j = 0, max = 0;
49
50 memset(map, 0x0, sizeof(*map));
51 map->root = RB_ROOT;
52
53 for (i = 0; i < env->nr_memory_nodes; i++) {
54 n = &nodes[i];
55 max += bitmap_weight(n->set, n->size);
56 }
57
58 entries = zalloc(sizeof(*entries) * max);
59 if (!entries)
60 return -ENOMEM;
61
62 for (i = 0; i < env->nr_memory_nodes; i++) {
63 u64 bit;
64
65 n = &nodes[i];
66
67 for (bit = 0; bit < n->size; bit++) {
68 u64 start;
69
70 if (!test_bit(bit, n->set))
71 continue;
72
73 start = bit * bsize;
74
75 /*
76 * Merge nearby areas, we walk in order
77 * through the bitmap, so no need to sort.
78 */
79 if (j > 0) {
80 struct phys_entry *prev = &entries[j - 1];
81
82 if ((prev->end == start) &&
83 (prev->node == n->node)) {
84 prev->end += bsize;
85 continue;
86 }
87 }
88
89 phys_entry__init(&entries[j++], start, bsize, n->node);
90 }
91 }
92
93 /* Cut unused entries, due to merging. */
94 tmp_entries = realloc(entries, sizeof(*entries) * j);
95 if (tmp_entries)
96 entries = tmp_entries;
97
98 for (i = 0; i < j; i++) {
99 pr_debug("mem2node %03" PRIu64 " [0x%016" PRIx64 "-0x%016" PRIx64 "]\n",
100 entries[i].node, entries[i].start, entries[i].end);
101
102 phys_entry__insert(&entries[i], &map->root);
103 }
104
105 map->entries = entries;
106 return 0;
107}
108
109void mem2node__exit(struct mem2node *map)
110{
111 zfree(&map->entries);
112}
113
114int mem2node__node(struct mem2node *map, u64 addr)
115{
116 struct rb_node **p, *parent = NULL;
117 struct phys_entry *entry;
118
119 p = &map->root.rb_node;
120 while (*p != NULL) {
121 parent = *p;
122 entry = rb_entry(parent, struct phys_entry, rb_node);
123 if (addr < entry->start)
124 p = &(*p)->rb_left;
125 else if (addr >= entry->end)
126 p = &(*p)->rb_right;
127 else
128 goto out;
129 }
130
131 entry = NULL;
132out:
133 return entry ? (int) entry->node : -1;
134}
diff --git a/tools/perf/util/mem2node.h b/tools/perf/util/mem2node.h
new file mode 100644
index 000000000000..59c4752a2181
--- /dev/null
+++ b/tools/perf/util/mem2node.h
@@ -0,0 +1,19 @@
1#ifndef __MEM2NODE_H
2#define __MEM2NODE_H
3
4#include <linux/rbtree.h>
5#include "env.h"
6
7struct phys_entry;
8
9struct mem2node {
10 struct rb_root root;
11 struct phys_entry *entries;
12 int cnt;
13};
14
15int mem2node__init(struct mem2node *map, struct perf_env *env);
16void mem2node__exit(struct mem2node *map);
17int mem2node__node(struct mem2node *map, u64 addr);
18
19#endif /* __MEM2NODE_H */
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index 05076e683938..fc832676a798 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -22,29 +22,27 @@ size_t perf_mmap__mmap_len(struct perf_mmap *map)
22 22
23/* When check_messup is true, 'end' must points to a good entry */ 23/* When check_messup is true, 'end' must points to a good entry */
24static union perf_event *perf_mmap__read(struct perf_mmap *map, 24static union perf_event *perf_mmap__read(struct perf_mmap *map,
25 u64 start, u64 end, u64 *prev) 25 u64 *startp, u64 end)
26{ 26{
27 unsigned char *data = map->base + page_size; 27 unsigned char *data = map->base + page_size;
28 union perf_event *event = NULL; 28 union perf_event *event = NULL;
29 int diff = end - start; 29 int diff = end - *startp;
30 30
31 if (diff >= (int)sizeof(event->header)) { 31 if (diff >= (int)sizeof(event->header)) {
32 size_t size; 32 size_t size;
33 33
34 event = (union perf_event *)&data[start & map->mask]; 34 event = (union perf_event *)&data[*startp & map->mask];
35 size = event->header.size; 35 size = event->header.size;
36 36
37 if (size < sizeof(event->header) || diff < (int)size) { 37 if (size < sizeof(event->header) || diff < (int)size)
38 event = NULL; 38 return NULL;
39 goto broken_event;
40 }
41 39
42 /* 40 /*
43 * Event straddles the mmap boundary -- header should always 41 * Event straddles the mmap boundary -- header should always
44 * be inside due to u64 alignment of output. 42 * be inside due to u64 alignment of output.
45 */ 43 */
46 if ((start & map->mask) + size != ((start + size) & map->mask)) { 44 if ((*startp & map->mask) + size != ((*startp + size) & map->mask)) {
47 unsigned int offset = start; 45 unsigned int offset = *startp;
48 unsigned int len = min(sizeof(*event), size), cpy; 46 unsigned int len = min(sizeof(*event), size), cpy;
49 void *dst = map->event_copy; 47 void *dst = map->event_copy;
50 48
@@ -59,36 +57,27 @@ static union perf_event *perf_mmap__read(struct perf_mmap *map,
59 event = (union perf_event *)map->event_copy; 57 event = (union perf_event *)map->event_copy;
60 } 58 }
61 59
62 start += size; 60 *startp += size;
63 } 61 }
64 62
65broken_event:
66 if (prev)
67 *prev = start;
68
69 return event; 63 return event;
70} 64}
71 65
72union perf_event *perf_mmap__read_forward(struct perf_mmap *map) 66/*
73{ 67 * Read event from ring buffer one by one.
74 u64 head; 68 * Return one event for each call.
75 u64 old = map->prev; 69 *
76 70 * Usage:
77 /* 71 * perf_mmap__read_init()
78 * Check if event was unmapped due to a POLLHUP/POLLERR. 72 * while(event = perf_mmap__read_event()) {
79 */ 73 * //process the event
80 if (!refcount_read(&map->refcnt)) 74 * perf_mmap__consume()
81 return NULL; 75 * }
82 76 * perf_mmap__read_done()
83 head = perf_mmap__read_head(map); 77 */
84 78union perf_event *perf_mmap__read_event(struct perf_mmap *map)
85 return perf_mmap__read(map, old, head, &map->prev);
86}
87
88union perf_event *perf_mmap__read_backward(struct perf_mmap *map)
89{ 79{
90 u64 head, end; 80 union perf_event *event;
91 u64 start = map->prev;
92 81
93 /* 82 /*
94 * Check if event was unmapped due to a POLLHUP/POLLERR. 83 * Check if event was unmapped due to a POLLHUP/POLLERR.
@@ -96,40 +85,16 @@ union perf_event *perf_mmap__read_backward(struct perf_mmap *map)
96 if (!refcount_read(&map->refcnt)) 85 if (!refcount_read(&map->refcnt))
97 return NULL; 86 return NULL;
98 87
99 head = perf_mmap__read_head(map); 88 /* non-overwirte doesn't pause the ringbuffer */
100 if (!head) 89 if (!map->overwrite)
101 return NULL; 90 map->end = perf_mmap__read_head(map);
102
103 /*
104 * 'head' pointer starts from 0. Kernel minus sizeof(record) form
105 * it each time when kernel writes to it, so in fact 'head' is
106 * negative. 'end' pointer is made manually by adding the size of
107 * the ring buffer to 'head' pointer, means the validate data can
108 * read is the whole ring buffer. If 'end' is positive, the ring
109 * buffer has not fully filled, so we must adjust 'end' to 0.
110 *
111 * However, since both 'head' and 'end' is unsigned, we can't
112 * simply compare 'end' against 0. Here we compare '-head' and
113 * the size of the ring buffer, where -head is the number of bytes
114 * kernel write to the ring buffer.
115 */
116 if (-head < (u64)(map->mask + 1))
117 end = 0;
118 else
119 end = head + map->mask + 1;
120
121 return perf_mmap__read(map, start, end, &map->prev);
122}
123 91
124void perf_mmap__read_catchup(struct perf_mmap *map) 92 event = perf_mmap__read(map, &map->start, map->end);
125{
126 u64 head;
127 93
128 if (!refcount_read(&map->refcnt)) 94 if (!map->overwrite)
129 return; 95 map->prev = map->start;
130 96
131 head = perf_mmap__read_head(map); 97 return event;
132 map->prev = head;
133} 98}
134 99
135static bool perf_mmap__empty(struct perf_mmap *map) 100static bool perf_mmap__empty(struct perf_mmap *map)
@@ -150,9 +115,9 @@ void perf_mmap__put(struct perf_mmap *map)
150 perf_mmap__munmap(map); 115 perf_mmap__munmap(map);
151} 116}
152 117
153void perf_mmap__consume(struct perf_mmap *map, bool overwrite) 118void perf_mmap__consume(struct perf_mmap *map)
154{ 119{
155 if (!overwrite) { 120 if (!map->overwrite) {
156 u64 old = map->prev; 121 u64 old = map->prev;
157 122
158 perf_mmap__write_tail(map, old); 123 perf_mmap__write_tail(map, old);
@@ -202,7 +167,7 @@ void perf_mmap__munmap(struct perf_mmap *map)
202int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd) 167int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd)
203{ 168{
204 /* 169 /*
205 * The last one will be done at perf_evlist__mmap_consume(), so that we 170 * The last one will be done at perf_mmap__consume(), so that we
206 * make sure we don't prevent tools from consuming every last event in 171 * make sure we don't prevent tools from consuming every last event in
207 * the ring buffer. 172 * the ring buffer.
208 * 173 *
@@ -234,19 +199,18 @@ int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd)
234 return 0; 199 return 0;
235} 200}
236 201
237static int overwrite_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end) 202static int overwrite_rb_find_range(void *buf, int mask, u64 *start, u64 *end)
238{ 203{
239 struct perf_event_header *pheader; 204 struct perf_event_header *pheader;
240 u64 evt_head = head; 205 u64 evt_head = *start;
241 int size = mask + 1; 206 int size = mask + 1;
242 207
243 pr_debug2("overwrite_rb_find_range: buf=%p, head=%"PRIx64"\n", buf, head); 208 pr_debug2("%s: buf=%p, start=%"PRIx64"\n", __func__, buf, *start);
244 pheader = (struct perf_event_header *)(buf + (head & mask)); 209 pheader = (struct perf_event_header *)(buf + (*start & mask));
245 *start = head;
246 while (true) { 210 while (true) {
247 if (evt_head - head >= (unsigned int)size) { 211 if (evt_head - *start >= (unsigned int)size) {
248 pr_debug("Finished reading overwrite ring buffer: rewind\n"); 212 pr_debug("Finished reading overwrite ring buffer: rewind\n");
249 if (evt_head - head > (unsigned int)size) 213 if (evt_head - *start > (unsigned int)size)
250 evt_head -= pheader->size; 214 evt_head -= pheader->size;
251 *end = evt_head; 215 *end = evt_head;
252 return 0; 216 return 0;
@@ -267,45 +231,73 @@ static int overwrite_rb_find_range(void *buf, int mask, u64 head, u64 *start, u6
267 return -1; 231 return -1;
268} 232}
269 233
270int perf_mmap__push(struct perf_mmap *md, bool overwrite, 234/*
271 void *to, int push(void *to, void *buf, size_t size)) 235 * Report the start and end of the available data in ringbuffer
236 */
237static int __perf_mmap__read_init(struct perf_mmap *md)
272{ 238{
273 u64 head = perf_mmap__read_head(md); 239 u64 head = perf_mmap__read_head(md);
274 u64 old = md->prev; 240 u64 old = md->prev;
275 u64 end = head, start = old;
276 unsigned char *data = md->base + page_size; 241 unsigned char *data = md->base + page_size;
277 unsigned long size; 242 unsigned long size;
278 void *buf;
279 int rc = 0;
280 243
281 start = overwrite ? head : old; 244 md->start = md->overwrite ? head : old;
282 end = overwrite ? old : head; 245 md->end = md->overwrite ? old : head;
283 246
284 if (start == end) 247 if (md->start == md->end)
285 return 0; 248 return -EAGAIN;
286 249
287 size = end - start; 250 size = md->end - md->start;
288 if (size > (unsigned long)(md->mask) + 1) { 251 if (size > (unsigned long)(md->mask) + 1) {
289 if (!overwrite) { 252 if (!md->overwrite) {
290 WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n"); 253 WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
291 254
292 md->prev = head; 255 md->prev = head;
293 perf_mmap__consume(md, overwrite); 256 perf_mmap__consume(md);
294 return 0; 257 return -EAGAIN;
295 } 258 }
296 259
297 /* 260 /*
298 * Backward ring buffer is full. We still have a chance to read 261 * Backward ring buffer is full. We still have a chance to read
299 * most of data from it. 262 * most of data from it.
300 */ 263 */
301 if (overwrite_rb_find_range(data, md->mask, head, &start, &end)) 264 if (overwrite_rb_find_range(data, md->mask, &md->start, &md->end))
302 return -1; 265 return -EINVAL;
303 } 266 }
304 267
305 if ((start & md->mask) + size != (end & md->mask)) { 268 return 0;
306 buf = &data[start & md->mask]; 269}
307 size = md->mask + 1 - (start & md->mask); 270
308 start += size; 271int perf_mmap__read_init(struct perf_mmap *map)
272{
273 /*
274 * Check if event was unmapped due to a POLLHUP/POLLERR.
275 */
276 if (!refcount_read(&map->refcnt))
277 return -ENOENT;
278
279 return __perf_mmap__read_init(map);
280}
281
282int perf_mmap__push(struct perf_mmap *md, void *to,
283 int push(void *to, void *buf, size_t size))
284{
285 u64 head = perf_mmap__read_head(md);
286 unsigned char *data = md->base + page_size;
287 unsigned long size;
288 void *buf;
289 int rc = 0;
290
291 rc = perf_mmap__read_init(md);
292 if (rc < 0)
293 return (rc == -EAGAIN) ? 0 : -1;
294
295 size = md->end - md->start;
296
297 if ((md->start & md->mask) + size != (md->end & md->mask)) {
298 buf = &data[md->start & md->mask];
299 size = md->mask + 1 - (md->start & md->mask);
300 md->start += size;
309 301
310 if (push(to, buf, size) < 0) { 302 if (push(to, buf, size) < 0) {
311 rc = -1; 303 rc = -1;
@@ -313,9 +305,9 @@ int perf_mmap__push(struct perf_mmap *md, bool overwrite,
313 } 305 }
314 } 306 }
315 307
316 buf = &data[start & md->mask]; 308 buf = &data[md->start & md->mask];
317 size = end - start; 309 size = md->end - md->start;
318 start += size; 310 md->start += size;
319 311
320 if (push(to, buf, size) < 0) { 312 if (push(to, buf, size) < 0) {
321 rc = -1; 313 rc = -1;
@@ -323,7 +315,24 @@ int perf_mmap__push(struct perf_mmap *md, bool overwrite,
323 } 315 }
324 316
325 md->prev = head; 317 md->prev = head;
326 perf_mmap__consume(md, overwrite); 318 perf_mmap__consume(md);
327out: 319out:
328 return rc; 320 return rc;
329} 321}
322
323/*
324 * Mandatory for overwrite mode
325 * The direction of overwrite mode is backward.
326 * The last perf_mmap__read() will set tail to map->prev.
327 * Need to correct the map->prev to head which is the end of next read.
328 */
329void perf_mmap__read_done(struct perf_mmap *map)
330{
331 /*
332 * Check if event was unmapped due to a POLLHUP/POLLERR.
333 */
334 if (!refcount_read(&map->refcnt))
335 return;
336
337 map->prev = perf_mmap__read_head(map);
338}
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index e43d7b55a55f..d82294db1295 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -20,6 +20,9 @@ struct perf_mmap {
20 int fd; 20 int fd;
21 refcount_t refcnt; 21 refcount_t refcnt;
22 u64 prev; 22 u64 prev;
23 u64 start;
24 u64 end;
25 bool overwrite;
23 struct auxtrace_mmap auxtrace_mmap; 26 struct auxtrace_mmap auxtrace_mmap;
24 char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8); 27 char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8);
25}; 28};
@@ -63,9 +66,7 @@ void perf_mmap__munmap(struct perf_mmap *map);
63void perf_mmap__get(struct perf_mmap *map); 66void perf_mmap__get(struct perf_mmap *map);
64void perf_mmap__put(struct perf_mmap *map); 67void perf_mmap__put(struct perf_mmap *map);
65 68
66void perf_mmap__consume(struct perf_mmap *map, bool overwrite); 69void perf_mmap__consume(struct perf_mmap *map);
67
68void perf_mmap__read_catchup(struct perf_mmap *md);
69 70
70static inline u64 perf_mmap__read_head(struct perf_mmap *mm) 71static inline u64 perf_mmap__read_head(struct perf_mmap *mm)
71{ 72{
@@ -87,11 +88,14 @@ static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail)
87} 88}
88 89
89union perf_event *perf_mmap__read_forward(struct perf_mmap *map); 90union perf_event *perf_mmap__read_forward(struct perf_mmap *map);
90union perf_event *perf_mmap__read_backward(struct perf_mmap *map);
91 91
92int perf_mmap__push(struct perf_mmap *md, bool backward, 92union perf_event *perf_mmap__read_event(struct perf_mmap *map);
93 void *to, int push(void *to, void *buf, size_t size)); 93
94int perf_mmap__push(struct perf_mmap *md, void *to,
95 int push(void *to, void *buf, size_t size));
94 96
95size_t perf_mmap__mmap_len(struct perf_mmap *map); 97size_t perf_mmap__mmap_len(struct perf_mmap *map);
96 98
99int perf_mmap__read_init(struct perf_mmap *md);
100void perf_mmap__read_done(struct perf_mmap *map);
97#endif /*__PERF_MMAP_H */ 101#endif /*__PERF_MMAP_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 34589c427e52..2fb0272146d8 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -206,8 +206,8 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
206 206
207 for_each_event(sys_dirent, evt_dir, evt_dirent) { 207 for_each_event(sys_dirent, evt_dir, evt_dirent) {
208 208
209 snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, 209 scnprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
210 evt_dirent->d_name); 210 evt_dirent->d_name);
211 fd = open(evt_path, O_RDONLY); 211 fd = open(evt_path, O_RDONLY);
212 if (fd < 0) 212 if (fd < 0)
213 continue; 213 continue;
@@ -1217,7 +1217,7 @@ int parse_events_add_numeric(struct parse_events_state *parse_state,
1217 get_config_name(head_config), &config_terms); 1217 get_config_name(head_config), &config_terms);
1218} 1218}
1219 1219
1220static int __parse_events_add_pmu(struct parse_events_state *parse_state, 1220int parse_events_add_pmu(struct parse_events_state *parse_state,
1221 struct list_head *list, char *name, 1221 struct list_head *list, char *name,
1222 struct list_head *head_config, bool auto_merge_stats) 1222 struct list_head *head_config, bool auto_merge_stats)
1223{ 1223{
@@ -1247,7 +1247,12 @@ static int __parse_events_add_pmu(struct parse_events_state *parse_state,
1247 if (!head_config) { 1247 if (!head_config) {
1248 attr.type = pmu->type; 1248 attr.type = pmu->type;
1249 evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu, NULL, auto_merge_stats); 1249 evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu, NULL, auto_merge_stats);
1250 return evsel ? 0 : -ENOMEM; 1250 if (evsel) {
1251 evsel->pmu_name = name;
1252 return 0;
1253 } else {
1254 return -ENOMEM;
1255 }
1251 } 1256 }
1252 1257
1253 if (perf_pmu__check_alias(pmu, head_config, &info)) 1258 if (perf_pmu__check_alias(pmu, head_config, &info))
@@ -1276,18 +1281,12 @@ static int __parse_events_add_pmu(struct parse_events_state *parse_state,
1276 evsel->snapshot = info.snapshot; 1281 evsel->snapshot = info.snapshot;
1277 evsel->metric_expr = info.metric_expr; 1282 evsel->metric_expr = info.metric_expr;
1278 evsel->metric_name = info.metric_name; 1283 evsel->metric_name = info.metric_name;
1284 evsel->pmu_name = name;
1279 } 1285 }
1280 1286
1281 return evsel ? 0 : -ENOMEM; 1287 return evsel ? 0 : -ENOMEM;
1282} 1288}
1283 1289
1284int parse_events_add_pmu(struct parse_events_state *parse_state,
1285 struct list_head *list, char *name,
1286 struct list_head *head_config)
1287{
1288 return __parse_events_add_pmu(parse_state, list, name, head_config, false);
1289}
1290
1291int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 1290int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
1292 char *str, struct list_head **listp) 1291 char *str, struct list_head **listp)
1293{ 1292{
@@ -1317,8 +1316,8 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
1317 return -1; 1316 return -1;
1318 list_add_tail(&term->list, head); 1317 list_add_tail(&term->list, head);
1319 1318
1320 if (!__parse_events_add_pmu(parse_state, list, 1319 if (!parse_events_add_pmu(parse_state, list,
1321 pmu->name, head, true)) { 1320 pmu->name, head, true)) {
1322 pr_debug("%s -> %s/%s/\n", str, 1321 pr_debug("%s -> %s/%s/\n", str,
1323 pmu->name, alias->str); 1322 pmu->name, alias->str);
1324 ok++; 1323 ok++;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 88108cd11b4c..5015cfd58277 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -167,7 +167,7 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
167 void *ptr, char *type, u64 len); 167 void *ptr, char *type, u64 len);
168int parse_events_add_pmu(struct parse_events_state *parse_state, 168int parse_events_add_pmu(struct parse_events_state *parse_state,
169 struct list_head *list, char *name, 169 struct list_head *list, char *name,
170 struct list_head *head_config); 170 struct list_head *head_config, bool auto_merge_stats);
171 171
172int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 172int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
173 char *str, 173 char *str,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 655ecff636a8..a1a01b1ac8b8 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -175,7 +175,7 @@ bpf_source [^,{}]+\.c[a-zA-Z0-9._]*
175num_dec [0-9]+ 175num_dec [0-9]+
176num_hex 0x[a-fA-F0-9]+ 176num_hex 0x[a-fA-F0-9]+
177num_raw_hex [a-fA-F0-9]+ 177num_raw_hex [a-fA-F0-9]+
178name [a-zA-Z_*?][a-zA-Z0-9_*?.]* 178name [a-zA-Z_*?\[\]][a-zA-Z0-9_*?.\[\]]*
179name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]* 179name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]*
180drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)? 180drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)?
181/* If you add a modifier you need to update check_modifier() */ 181/* If you add a modifier you need to update check_modifier() */
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index e81a20ea8d7d..7afeb80cc39e 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -8,6 +8,7 @@
8 8
9#define YYDEBUG 1 9#define YYDEBUG 1
10 10
11#include <fnmatch.h>
11#include <linux/compiler.h> 12#include <linux/compiler.h>
12#include <linux/list.h> 13#include <linux/list.h>
13#include <linux/types.h> 14#include <linux/types.h>
@@ -231,9 +232,13 @@ PE_NAME opt_event_config
231 YYABORT; 232 YYABORT;
232 233
233 ALLOC_LIST(list); 234 ALLOC_LIST(list);
234 if (parse_events_add_pmu(_parse_state, list, $1, $2)) { 235 if (parse_events_add_pmu(_parse_state, list, $1, $2, false)) {
235 struct perf_pmu *pmu = NULL; 236 struct perf_pmu *pmu = NULL;
236 int ok = 0; 237 int ok = 0;
238 char *pattern;
239
240 if (asprintf(&pattern, "%s*", $1) < 0)
241 YYABORT;
237 242
238 while ((pmu = perf_pmu__scan(pmu)) != NULL) { 243 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
239 char *name = pmu->name; 244 char *name = pmu->name;
@@ -241,14 +246,19 @@ PE_NAME opt_event_config
241 if (!strncmp(name, "uncore_", 7) && 246 if (!strncmp(name, "uncore_", 7) &&
242 strncmp($1, "uncore_", 7)) 247 strncmp($1, "uncore_", 7))
243 name += 7; 248 name += 7;
244 if (!strncmp($1, name, strlen($1))) { 249 if (!fnmatch(pattern, name, 0)) {
245 if (parse_events_copy_term_list(orig_terms, &terms)) 250 if (parse_events_copy_term_list(orig_terms, &terms)) {
251 free(pattern);
246 YYABORT; 252 YYABORT;
247 if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms)) 253 }
254 if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms, true))
248 ok++; 255 ok++;
249 parse_events_terms__delete(terms); 256 parse_events_terms__delete(terms);
250 } 257 }
251 } 258 }
259
260 free(pattern);
261
252 if (!ok) 262 if (!ok)
253 YYABORT; 263 YYABORT;
254 } 264 }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 57e38fdf0b34..064bdcb7bd78 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -351,7 +351,7 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
351 if (pmu_alias_info_file(name)) 351 if (pmu_alias_info_file(name))
352 continue; 352 continue;
353 353
354 snprintf(path, PATH_MAX, "%s/%s", dir, name); 354 scnprintf(path, PATH_MAX, "%s/%s", dir, name);
355 355
356 file = fopen(path, "r"); 356 file = fopen(path, "r");
357 if (!file) { 357 if (!file) {
@@ -576,6 +576,34 @@ char * __weak get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
576 return NULL; 576 return NULL;
577} 577}
578 578
579/* Return zero when the cpuid from the mapfile.csv matches the
580 * cpuid string generated on this platform.
581 * Otherwise return non-zero.
582 */
583int __weak strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
584{
585 regex_t re;
586 regmatch_t pmatch[1];
587 int match;
588
589 if (regcomp(&re, mapcpuid, REG_EXTENDED) != 0) {
590 /* Warn unable to generate match particular string. */
591 pr_info("Invalid regular expression %s\n", mapcpuid);
592 return 1;
593 }
594
595 match = !regexec(&re, cpuid, 1, pmatch, 0);
596 regfree(&re);
597 if (match) {
598 size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
599
600 /* Verify the entire string matched. */
601 if (match_len == strlen(cpuid))
602 return 0;
603 }
604 return 1;
605}
606
579static char *perf_pmu__getcpuid(struct perf_pmu *pmu) 607static char *perf_pmu__getcpuid(struct perf_pmu *pmu)
580{ 608{
581 char *cpuid; 609 char *cpuid;
@@ -610,31 +638,14 @@ struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu)
610 638
611 i = 0; 639 i = 0;
612 for (;;) { 640 for (;;) {
613 regex_t re;
614 regmatch_t pmatch[1];
615 int match;
616
617 map = &pmu_events_map[i++]; 641 map = &pmu_events_map[i++];
618 if (!map->table) { 642 if (!map->table) {
619 map = NULL; 643 map = NULL;
620 break; 644 break;
621 } 645 }
622 646
623 if (regcomp(&re, map->cpuid, REG_EXTENDED) != 0) { 647 if (!strcmp_cpuid_str(map->cpuid, cpuid))
624 /* Warn unable to generate match particular string. */
625 pr_info("Invalid regular expression %s\n", map->cpuid);
626 break; 648 break;
627 }
628
629 match = !regexec(&re, cpuid, 1, pmatch, 0);
630 regfree(&re);
631 if (match) {
632 size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
633
634 /* Verify the entire string matched. */
635 if (match_len == strlen(cpuid))
636 break;
637 }
638 } 649 }
639 free(cpuid); 650 free(cpuid);
640 return map; 651 return map;
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index a5731de0e5eb..c37fbef1711d 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -423,20 +423,20 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
423 pr_warning("Failed to get the type of %s.\n", varname); 423 pr_warning("Failed to get the type of %s.\n", varname);
424 return -ENOENT; 424 return -ENOENT;
425 } 425 }
426 pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type)); 426 pr_debug2("Var real type: %s (%x)\n", dwarf_diename(&type),
427 (unsigned)dwarf_dieoffset(&type));
427 tag = dwarf_tag(&type); 428 tag = dwarf_tag(&type);
428 429
429 if (field->name[0] == '[' && 430 if (field->name[0] == '[' &&
430 (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) { 431 (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) {
431 if (field->next) 432 /* Save original type for next field or type */
432 /* Save original type for next field */ 433 memcpy(die_mem, &type, sizeof(*die_mem));
433 memcpy(die_mem, &type, sizeof(*die_mem));
434 /* Get the type of this array */ 434 /* Get the type of this array */
435 if (die_get_real_type(&type, &type) == NULL) { 435 if (die_get_real_type(&type, &type) == NULL) {
436 pr_warning("Failed to get the type of %s.\n", varname); 436 pr_warning("Failed to get the type of %s.\n", varname);
437 return -ENOENT; 437 return -ENOENT;
438 } 438 }
439 pr_debug2("Array real type: (%x)\n", 439 pr_debug2("Array real type: %s (%x)\n", dwarf_diename(&type),
440 (unsigned)dwarf_dieoffset(&type)); 440 (unsigned)dwarf_dieoffset(&type));
441 if (tag == DW_TAG_pointer_type) { 441 if (tag == DW_TAG_pointer_type) {
442 ref = zalloc(sizeof(struct probe_trace_arg_ref)); 442 ref = zalloc(sizeof(struct probe_trace_arg_ref));
@@ -448,9 +448,6 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
448 *ref_ptr = ref; 448 *ref_ptr = ref;
449 } 449 }
450 ref->offset += dwarf_bytesize(&type) * field->index; 450 ref->offset += dwarf_bytesize(&type) * field->index;
451 if (!field->next)
452 /* Save vr_die for converting types */
453 memcpy(die_mem, vr_die, sizeof(*die_mem));
454 goto next; 451 goto next;
455 } else if (tag == DW_TAG_pointer_type) { 452 } else if (tag == DW_TAG_pointer_type) {
456 /* Check the pointer and dereference */ 453 /* Check the pointer and dereference */
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index b1e999bd21ef..863b61478edd 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -12,6 +12,30 @@
12#include "print_binary.h" 12#include "print_binary.h"
13#include "thread_map.h" 13#include "thread_map.h"
14 14
15#if PY_MAJOR_VERSION < 3
16#define _PyUnicode_FromString(arg) \
17 PyString_FromString(arg)
18#define _PyUnicode_AsString(arg) \
19 PyString_AsString(arg)
20#define _PyUnicode_FromFormat(...) \
21 PyString_FromFormat(__VA_ARGS__)
22#define _PyLong_FromLong(arg) \
23 PyInt_FromLong(arg)
24
25#else
26
27#define _PyUnicode_FromString(arg) \
28 PyUnicode_FromString(arg)
29#define _PyUnicode_FromFormat(...) \
30 PyUnicode_FromFormat(__VA_ARGS__)
31#define _PyLong_FromLong(arg) \
32 PyLong_FromLong(arg)
33#endif
34
35#ifndef Py_TYPE
36#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
37#endif
38
15/* 39/*
16 * Provide these two so that we don't have to link against callchain.c and 40 * Provide these two so that we don't have to link against callchain.c and
17 * start dragging hist.c, etc. 41 * start dragging hist.c, etc.
@@ -49,7 +73,11 @@ int eprintf(int level, int var, const char *fmt, ...)
49# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, 73# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
50#endif 74#endif
51 75
76#if PY_MAJOR_VERSION < 3
52PyMODINIT_FUNC initperf(void); 77PyMODINIT_FUNC initperf(void);
78#else
79PyMODINIT_FUNC PyInit_perf(void);
80#endif
53 81
54#define member_def(type, member, ptype, help) \ 82#define member_def(type, member, ptype, help) \
55 { #member, ptype, \ 83 { #member, ptype, \
@@ -107,7 +135,7 @@ static PyObject *pyrf_mmap_event__repr(struct pyrf_event *pevent)
107 pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) { 135 pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) {
108 ret = PyErr_NoMemory(); 136 ret = PyErr_NoMemory();
109 } else { 137 } else {
110 ret = PyString_FromString(s); 138 ret = _PyUnicode_FromString(s);
111 free(s); 139 free(s);
112 } 140 }
113 return ret; 141 return ret;
@@ -138,7 +166,7 @@ static PyMemberDef pyrf_task_event__members[] = {
138 166
139static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent) 167static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent)
140{ 168{
141 return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, " 169 return _PyUnicode_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "
142 "ptid: %u, time: %" PRIu64 "}", 170 "ptid: %u, time: %" PRIu64 "}",
143 pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit", 171 pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit",
144 pevent->event.fork.pid, 172 pevent->event.fork.pid,
@@ -171,7 +199,7 @@ static PyMemberDef pyrf_comm_event__members[] = {
171 199
172static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent) 200static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent)
173{ 201{
174 return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }", 202 return _PyUnicode_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }",
175 pevent->event.comm.pid, 203 pevent->event.comm.pid,
176 pevent->event.comm.tid, 204 pevent->event.comm.tid,
177 pevent->event.comm.comm); 205 pevent->event.comm.comm);
@@ -202,7 +230,7 @@ static PyObject *pyrf_throttle_event__repr(struct pyrf_event *pevent)
202{ 230{
203 struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1); 231 struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1);
204 232
205 return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64 233 return _PyUnicode_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64
206 ", stream_id: %" PRIu64 " }", 234 ", stream_id: %" PRIu64 " }",
207 pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un", 235 pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un",
208 te->time, te->id, te->stream_id); 236 te->time, te->id, te->stream_id);
@@ -237,7 +265,7 @@ static PyObject *pyrf_lost_event__repr(struct pyrf_event *pevent)
237 pevent->event.lost.id, pevent->event.lost.lost) < 0) { 265 pevent->event.lost.id, pevent->event.lost.lost) < 0) {
238 ret = PyErr_NoMemory(); 266 ret = PyErr_NoMemory();
239 } else { 267 } else {
240 ret = PyString_FromString(s); 268 ret = _PyUnicode_FromString(s);
241 free(s); 269 free(s);
242 } 270 }
243 return ret; 271 return ret;
@@ -264,7 +292,7 @@ static PyMemberDef pyrf_read_event__members[] = {
264 292
265static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent) 293static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent)
266{ 294{
267 return PyString_FromFormat("{ type: read, pid: %u, tid: %u }", 295 return _PyUnicode_FromFormat("{ type: read, pid: %u, tid: %u }",
268 pevent->event.read.pid, 296 pevent->event.read.pid,
269 pevent->event.read.tid); 297 pevent->event.read.tid);
270 /* 298 /*
@@ -299,7 +327,7 @@ static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent)
299 if (asprintf(&s, "{ type: sample }") < 0) { 327 if (asprintf(&s, "{ type: sample }") < 0) {
300 ret = PyErr_NoMemory(); 328 ret = PyErr_NoMemory();
301 } else { 329 } else {
302 ret = PyString_FromString(s); 330 ret = _PyUnicode_FromString(s);
303 free(s); 331 free(s);
304 } 332 }
305 return ret; 333 return ret;
@@ -330,7 +358,7 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field)
330 } 358 }
331 if (field->flags & FIELD_IS_STRING && 359 if (field->flags & FIELD_IS_STRING &&
332 is_printable_array(data + offset, len)) { 360 is_printable_array(data + offset, len)) {
333 ret = PyString_FromString((char *)data + offset); 361 ret = _PyUnicode_FromString((char *)data + offset);
334 } else { 362 } else {
335 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len); 363 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len);
336 field->flags &= ~FIELD_IS_STRING; 364 field->flags &= ~FIELD_IS_STRING;
@@ -352,7 +380,7 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field)
352static PyObject* 380static PyObject*
353get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) 381get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
354{ 382{
355 const char *str = PyString_AsString(PyObject_Str(attr_name)); 383 const char *str = _PyUnicode_AsString(PyObject_Str(attr_name));
356 struct perf_evsel *evsel = pevent->evsel; 384 struct perf_evsel *evsel = pevent->evsel;
357 struct format_field *field; 385 struct format_field *field;
358 386
@@ -416,7 +444,7 @@ static PyObject *pyrf_context_switch_event__repr(struct pyrf_event *pevent)
416 !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) { 444 !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) {
417 ret = PyErr_NoMemory(); 445 ret = PyErr_NoMemory();
418 } else { 446 } else {
419 ret = PyString_FromString(s); 447 ret = _PyUnicode_FromString(s);
420 free(s); 448 free(s);
421 } 449 }
422 return ret; 450 return ret;
@@ -528,7 +556,7 @@ static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
528static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus) 556static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
529{ 557{
530 cpu_map__put(pcpus->cpus); 558 cpu_map__put(pcpus->cpus);
531 pcpus->ob_type->tp_free((PyObject*)pcpus); 559 Py_TYPE(pcpus)->tp_free((PyObject*)pcpus);
532} 560}
533 561
534static Py_ssize_t pyrf_cpu_map__length(PyObject *obj) 562static Py_ssize_t pyrf_cpu_map__length(PyObject *obj)
@@ -597,7 +625,7 @@ static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
597static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads) 625static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads)
598{ 626{
599 thread_map__put(pthreads->threads); 627 thread_map__put(pthreads->threads);
600 pthreads->ob_type->tp_free((PyObject*)pthreads); 628 Py_TYPE(pthreads)->tp_free((PyObject*)pthreads);
601} 629}
602 630
603static Py_ssize_t pyrf_thread_map__length(PyObject *obj) 631static Py_ssize_t pyrf_thread_map__length(PyObject *obj)
@@ -759,7 +787,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
759static void pyrf_evsel__delete(struct pyrf_evsel *pevsel) 787static void pyrf_evsel__delete(struct pyrf_evsel *pevsel)
760{ 788{
761 perf_evsel__exit(&pevsel->evsel); 789 perf_evsel__exit(&pevsel->evsel);
762 pevsel->ob_type->tp_free((PyObject*)pevsel); 790 Py_TYPE(pevsel)->tp_free((PyObject*)pevsel);
763} 791}
764 792
765static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, 793static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
@@ -850,7 +878,7 @@ static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
850static void pyrf_evlist__delete(struct pyrf_evlist *pevlist) 878static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
851{ 879{
852 perf_evlist__exit(&pevlist->evlist); 880 perf_evlist__exit(&pevlist->evlist);
853 pevlist->ob_type->tp_free((PyObject*)pevlist); 881 Py_TYPE(pevlist)->tp_free((PyObject*)pevlist);
854} 882}
855 883
856static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist, 884static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
@@ -902,12 +930,16 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
902 930
903 for (i = 0; i < evlist->pollfd.nr; ++i) { 931 for (i = 0; i < evlist->pollfd.nr; ++i) {
904 PyObject *file; 932 PyObject *file;
933#if PY_MAJOR_VERSION < 3
905 FILE *fp = fdopen(evlist->pollfd.entries[i].fd, "r"); 934 FILE *fp = fdopen(evlist->pollfd.entries[i].fd, "r");
906 935
907 if (fp == NULL) 936 if (fp == NULL)
908 goto free_list; 937 goto free_list;
909 938
910 file = PyFile_FromFile(fp, "perf", "r", NULL); 939 file = PyFile_FromFile(fp, "perf", "r", NULL);
940#else
941 file = PyFile_FromFd(evlist->pollfd.entries[i].fd, "perf", "r", -1, NULL, NULL, NULL, 1);
942#endif
911 if (file == NULL) 943 if (file == NULL)
912 goto free_list; 944 goto free_list;
913 945
@@ -951,13 +983,18 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
951 union perf_event *event; 983 union perf_event *event;
952 int sample_id_all = 1, cpu; 984 int sample_id_all = 1, cpu;
953 static char *kwlist[] = { "cpu", "sample_id_all", NULL }; 985 static char *kwlist[] = { "cpu", "sample_id_all", NULL };
986 struct perf_mmap *md;
954 int err; 987 int err;
955 988
956 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist, 989 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
957 &cpu, &sample_id_all)) 990 &cpu, &sample_id_all))
958 return NULL; 991 return NULL;
959 992
960 event = perf_evlist__mmap_read(evlist, cpu); 993 md = &evlist->mmap[cpu];
994 if (perf_mmap__read_init(md) < 0)
995 goto end;
996
997 event = perf_mmap__read_event(md);
961 if (event != NULL) { 998 if (event != NULL) {
962 PyObject *pyevent = pyrf_event__new(event); 999 PyObject *pyevent = pyrf_event__new(event);
963 struct pyrf_event *pevent = (struct pyrf_event *)pyevent; 1000 struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
@@ -967,22 +1004,24 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
967 return PyErr_NoMemory(); 1004 return PyErr_NoMemory();
968 1005
969 evsel = perf_evlist__event2evsel(evlist, event); 1006 evsel = perf_evlist__event2evsel(evlist, event);
970 if (!evsel) 1007 if (!evsel) {
1008 Py_INCREF(Py_None);
971 return Py_None; 1009 return Py_None;
1010 }
972 1011
973 pevent->evsel = evsel; 1012 pevent->evsel = evsel;
974 1013
975 err = perf_evsel__parse_sample(evsel, event, &pevent->sample); 1014 err = perf_evsel__parse_sample(evsel, event, &pevent->sample);
976 1015
977 /* Consume the even only after we parsed it out. */ 1016 /* Consume the even only after we parsed it out. */
978 perf_evlist__mmap_consume(evlist, cpu); 1017 perf_mmap__consume(md);
979 1018
980 if (err) 1019 if (err)
981 return PyErr_Format(PyExc_OSError, 1020 return PyErr_Format(PyExc_OSError,
982 "perf: can't parse sample, err=%d", err); 1021 "perf: can't parse sample, err=%d", err);
983 return pyevent; 1022 return pyevent;
984 } 1023 }
985 1024end:
986 Py_INCREF(Py_None); 1025 Py_INCREF(Py_None);
987 return Py_None; 1026 return Py_None;
988} 1027}
@@ -1194,9 +1233,9 @@ static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel,
1194 1233
1195 tp_format = trace_event__tp_format(sys, name); 1234 tp_format = trace_event__tp_format(sys, name);
1196 if (IS_ERR(tp_format)) 1235 if (IS_ERR(tp_format))
1197 return PyInt_FromLong(-1); 1236 return _PyLong_FromLong(-1);
1198 1237
1199 return PyInt_FromLong(tp_format->id); 1238 return _PyLong_FromLong(tp_format->id);
1200} 1239}
1201 1240
1202static PyMethodDef perf__methods[] = { 1241static PyMethodDef perf__methods[] = {
@@ -1209,11 +1248,31 @@ static PyMethodDef perf__methods[] = {
1209 { .ml_name = NULL, } 1248 { .ml_name = NULL, }
1210}; 1249};
1211 1250
1251#if PY_MAJOR_VERSION < 3
1212PyMODINIT_FUNC initperf(void) 1252PyMODINIT_FUNC initperf(void)
1253#else
1254PyMODINIT_FUNC PyInit_perf(void)
1255#endif
1213{ 1256{
1214 PyObject *obj; 1257 PyObject *obj;
1215 int i; 1258 int i;
1216 PyObject *dict, *module = Py_InitModule("perf", perf__methods); 1259 PyObject *dict;
1260#if PY_MAJOR_VERSION < 3
1261 PyObject *module = Py_InitModule("perf", perf__methods);
1262#else
1263 static struct PyModuleDef moduledef = {
1264 PyModuleDef_HEAD_INIT,
1265 "perf", /* m_name */
1266 "", /* m_doc */
1267 -1, /* m_size */
1268 perf__methods, /* m_methods */
1269 NULL, /* m_reload */
1270 NULL, /* m_traverse */
1271 NULL, /* m_clear */
1272 NULL, /* m_free */
1273 };
1274 PyObject *module = PyModule_Create(&moduledef);
1275#endif
1217 1276
1218 if (module == NULL || 1277 if (module == NULL ||
1219 pyrf_event__setup_types() < 0 || 1278 pyrf_event__setup_types() < 0 ||
@@ -1221,7 +1280,11 @@ PyMODINIT_FUNC initperf(void)
1221 pyrf_evsel__setup_types() < 0 || 1280 pyrf_evsel__setup_types() < 0 ||
1222 pyrf_thread_map__setup_types() < 0 || 1281 pyrf_thread_map__setup_types() < 0 ||
1223 pyrf_cpu_map__setup_types() < 0) 1282 pyrf_cpu_map__setup_types() < 0)
1283#if PY_MAJOR_VERSION < 3
1224 return; 1284 return;
1285#else
1286 return module;
1287#endif
1225 1288
1226 /* The page_size is placed in util object. */ 1289 /* The page_size is placed in util object. */
1227 page_size = sysconf(_SC_PAGE_SIZE); 1290 page_size = sysconf(_SC_PAGE_SIZE);
@@ -1270,7 +1333,7 @@ PyMODINIT_FUNC initperf(void)
1270 goto error; 1333 goto error;
1271 1334
1272 for (i = 0; perf__constants[i].name != NULL; i++) { 1335 for (i = 0; perf__constants[i].name != NULL; i++) {
1273 obj = PyInt_FromLong(perf__constants[i].value); 1336 obj = _PyLong_FromLong(perf__constants[i].value);
1274 if (obj == NULL) 1337 if (obj == NULL)
1275 goto error; 1338 goto error;
1276 PyDict_SetItemString(dict, perf__constants[i].name, obj); 1339 PyDict_SetItemString(dict, perf__constants[i].name, obj);
@@ -1280,6 +1343,9 @@ PyMODINIT_FUNC initperf(void)
1280error: 1343error:
1281 if (PyErr_Occurred()) 1344 if (PyErr_Occurred())
1282 PyErr_SetString(PyExc_ImportError, "perf: Init failed!"); 1345 PyErr_SetString(PyExc_ImportError, "perf: Init failed!");
1346#if PY_MAJOR_VERSION >= 3
1347 return module;
1348#endif
1283} 1349}
1284 1350
1285/* 1351/*
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index 1e97937b03a9..9cfc7bf16531 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -5,6 +5,7 @@
5#include "parse-events.h" 5#include "parse-events.h"
6#include <errno.h> 6#include <errno.h>
7#include <api/fs/fs.h> 7#include <api/fs/fs.h>
8#include <subcmd/parse-options.h>
8#include "util.h" 9#include "util.h"
9#include "cloexec.h" 10#include "cloexec.h"
10 11
@@ -137,6 +138,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
137 struct perf_evsel *evsel; 138 struct perf_evsel *evsel;
138 bool use_sample_identifier = false; 139 bool use_sample_identifier = false;
139 bool use_comm_exec; 140 bool use_comm_exec;
141 bool sample_id = opts->sample_id;
140 142
141 /* 143 /*
142 * Set the evsel leader links before we configure attributes, 144 * Set the evsel leader links before we configure attributes,
@@ -163,8 +165,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
163 * match the id. 165 * match the id.
164 */ 166 */
165 use_sample_identifier = perf_can_sample_identifier(); 167 use_sample_identifier = perf_can_sample_identifier();
166 evlist__for_each_entry(evlist, evsel) 168 sample_id = true;
167 perf_evsel__set_sample_id(evsel, use_sample_identifier);
168 } else if (evlist->nr_entries > 1) { 169 } else if (evlist->nr_entries > 1) {
169 struct perf_evsel *first = perf_evlist__first(evlist); 170 struct perf_evsel *first = perf_evlist__first(evlist);
170 171
@@ -174,6 +175,10 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
174 use_sample_identifier = perf_can_sample_identifier(); 175 use_sample_identifier = perf_can_sample_identifier();
175 break; 176 break;
176 } 177 }
178 sample_id = true;
179 }
180
181 if (sample_id) {
177 evlist__for_each_entry(evlist, evsel) 182 evlist__for_each_entry(evlist, evsel)
178 perf_evsel__set_sample_id(evsel, use_sample_identifier); 183 perf_evsel__set_sample_id(evsel, use_sample_identifier);
179 } 184 }
@@ -215,11 +220,21 @@ static int record_opts__config_freq(struct record_opts *opts)
215 * User specified frequency is over current maximum. 220 * User specified frequency is over current maximum.
216 */ 221 */
217 if (user_freq && (max_rate < opts->freq)) { 222 if (user_freq && (max_rate < opts->freq)) {
218 pr_err("Maximum frequency rate (%u) reached.\n" 223 if (opts->strict_freq) {
219 "Please use -F freq option with lower value or consider\n" 224 pr_err("error: Maximum frequency rate (%'u Hz) exceeded.\n"
220 "tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n", 225 " Please use -F freq option with a lower value or consider\n"
221 max_rate); 226 " tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n",
222 return -1; 227 max_rate);
228 return -1;
229 } else {
230 pr_warning("warning: Maximum frequency rate (%'u Hz) exceeded, throttling from %'u Hz to %'u Hz.\n"
231 " The limit can be raised via /proc/sys/kernel/perf_event_max_sample_rate.\n"
232 " The kernel will lower it when perf's interrupts take too long.\n"
233 " Use --strict-freq to disable this throttling, refusing to record.\n",
234 max_rate, opts->freq, max_rate);
235
236 opts->freq = max_rate;
237 }
223 } 238 }
224 239
225 /* 240 /*
@@ -287,3 +302,25 @@ out_delete:
287 perf_evlist__delete(temp_evlist); 302 perf_evlist__delete(temp_evlist);
288 return ret; 303 return ret;
289} 304}
305
306int record__parse_freq(const struct option *opt, const char *str, int unset __maybe_unused)
307{
308 unsigned int freq;
309 struct record_opts *opts = opt->value;
310
311 if (!str)
312 return -EINVAL;
313
314 if (strcasecmp(str, "max") == 0) {
315 if (get_max_rate(&freq)) {
316 pr_err("couldn't read /proc/sys/kernel/perf_event_max_sample_rate\n");
317 return -1;
318 }
319 pr_info("info: Using a maximum frequency rate of %'d Hz\n", freq);
320 } else {
321 freq = atoi(str);
322 }
323
324 opts->user_freq = freq;
325 return 0;
326}
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index ea070883c593..10dd5fce082b 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -49,7 +49,37 @@
49#include "print_binary.h" 49#include "print_binary.h"
50#include "stat.h" 50#include "stat.h"
51 51
52#if PY_MAJOR_VERSION < 3
53#define _PyUnicode_FromString(arg) \
54 PyString_FromString(arg)
55#define _PyUnicode_FromStringAndSize(arg1, arg2) \
56 PyString_FromStringAndSize((arg1), (arg2))
57#define _PyBytes_FromStringAndSize(arg1, arg2) \
58 PyString_FromStringAndSize((arg1), (arg2))
59#define _PyLong_FromLong(arg) \
60 PyInt_FromLong(arg)
61#define _PyLong_AsLong(arg) \
62 PyInt_AsLong(arg)
63#define _PyCapsule_New(arg1, arg2, arg3) \
64 PyCObject_FromVoidPtr((arg1), (arg2))
65
52PyMODINIT_FUNC initperf_trace_context(void); 66PyMODINIT_FUNC initperf_trace_context(void);
67#else
68#define _PyUnicode_FromString(arg) \
69 PyUnicode_FromString(arg)
70#define _PyUnicode_FromStringAndSize(arg1, arg2) \
71 PyUnicode_FromStringAndSize((arg1), (arg2))
72#define _PyBytes_FromStringAndSize(arg1, arg2) \
73 PyBytes_FromStringAndSize((arg1), (arg2))
74#define _PyLong_FromLong(arg) \
75 PyLong_FromLong(arg)
76#define _PyLong_AsLong(arg) \
77 PyLong_AsLong(arg)
78#define _PyCapsule_New(arg1, arg2, arg3) \
79 PyCapsule_New((arg1), (arg2), (arg3))
80
81PyMODINIT_FUNC PyInit_perf_trace_context(void);
82#endif
53 83
54#define TRACE_EVENT_TYPE_MAX \ 84#define TRACE_EVENT_TYPE_MAX \
55 ((1 << (sizeof(unsigned short) * 8)) - 1) 85 ((1 << (sizeof(unsigned short) * 8)) - 1)
@@ -135,7 +165,7 @@ static int get_argument_count(PyObject *handler)
135 PyObject *arg_count_obj = PyObject_GetAttrString(code_obj, 165 PyObject *arg_count_obj = PyObject_GetAttrString(code_obj,
136 "co_argcount"); 166 "co_argcount");
137 if (arg_count_obj) { 167 if (arg_count_obj) {
138 arg_count = (int) PyInt_AsLong(arg_count_obj); 168 arg_count = (int) _PyLong_AsLong(arg_count_obj);
139 Py_DECREF(arg_count_obj); 169 Py_DECREF(arg_count_obj);
140 } 170 }
141 Py_DECREF(code_obj); 171 Py_DECREF(code_obj);
@@ -182,10 +212,10 @@ static void define_value(enum print_arg_type field_type,
182 212
183 value = eval_flag(field_value); 213 value = eval_flag(field_value);
184 214
185 PyTuple_SetItem(t, n++, PyString_FromString(ev_name)); 215 PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name));
186 PyTuple_SetItem(t, n++, PyString_FromString(field_name)); 216 PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name));
187 PyTuple_SetItem(t, n++, PyInt_FromLong(value)); 217 PyTuple_SetItem(t, n++, _PyLong_FromLong(value));
188 PyTuple_SetItem(t, n++, PyString_FromString(field_str)); 218 PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_str));
189 219
190 try_call_object(handler_name, t); 220 try_call_object(handler_name, t);
191 221
@@ -223,10 +253,10 @@ static void define_field(enum print_arg_type field_type,
223 if (!t) 253 if (!t)
224 Py_FatalError("couldn't create Python tuple"); 254 Py_FatalError("couldn't create Python tuple");
225 255
226 PyTuple_SetItem(t, n++, PyString_FromString(ev_name)); 256 PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name));
227 PyTuple_SetItem(t, n++, PyString_FromString(field_name)); 257 PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name));
228 if (field_type == PRINT_FLAGS) 258 if (field_type == PRINT_FLAGS)
229 PyTuple_SetItem(t, n++, PyString_FromString(delim)); 259 PyTuple_SetItem(t, n++, _PyUnicode_FromString(delim));
230 260
231 try_call_object(handler_name, t); 261 try_call_object(handler_name, t);
232 262
@@ -325,12 +355,12 @@ static PyObject *get_field_numeric_entry(struct event_format *event,
325 if (field->flags & FIELD_IS_SIGNED) { 355 if (field->flags & FIELD_IS_SIGNED) {
326 if ((long long)val >= LONG_MIN && 356 if ((long long)val >= LONG_MIN &&
327 (long long)val <= LONG_MAX) 357 (long long)val <= LONG_MAX)
328 obj = PyInt_FromLong(val); 358 obj = _PyLong_FromLong(val);
329 else 359 else
330 obj = PyLong_FromLongLong(val); 360 obj = PyLong_FromLongLong(val);
331 } else { 361 } else {
332 if (val <= LONG_MAX) 362 if (val <= LONG_MAX)
333 obj = PyInt_FromLong(val); 363 obj = _PyLong_FromLong(val);
334 else 364 else
335 obj = PyLong_FromUnsignedLongLong(val); 365 obj = PyLong_FromUnsignedLongLong(val);
336 } 366 }
@@ -389,9 +419,9 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
389 pydict_set_item_string_decref(pysym, "end", 419 pydict_set_item_string_decref(pysym, "end",
390 PyLong_FromUnsignedLongLong(node->sym->end)); 420 PyLong_FromUnsignedLongLong(node->sym->end));
391 pydict_set_item_string_decref(pysym, "binding", 421 pydict_set_item_string_decref(pysym, "binding",
392 PyInt_FromLong(node->sym->binding)); 422 _PyLong_FromLong(node->sym->binding));
393 pydict_set_item_string_decref(pysym, "name", 423 pydict_set_item_string_decref(pysym, "name",
394 PyString_FromStringAndSize(node->sym->name, 424 _PyUnicode_FromStringAndSize(node->sym->name,
395 node->sym->namelen)); 425 node->sym->namelen));
396 pydict_set_item_string_decref(pyelem, "sym", pysym); 426 pydict_set_item_string_decref(pyelem, "sym", pysym);
397 } 427 }
@@ -406,7 +436,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
406 dsoname = map->dso->name; 436 dsoname = map->dso->name;
407 } 437 }
408 pydict_set_item_string_decref(pyelem, "dso", 438 pydict_set_item_string_decref(pyelem, "dso",
409 PyString_FromString(dsoname)); 439 _PyUnicode_FromString(dsoname));
410 } 440 }
411 441
412 callchain_cursor_advance(&callchain_cursor); 442 callchain_cursor_advance(&callchain_cursor);
@@ -483,16 +513,16 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,
483 if (!dict_sample) 513 if (!dict_sample)
484 Py_FatalError("couldn't create Python dictionary"); 514 Py_FatalError("couldn't create Python dictionary");
485 515
486 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); 516 pydict_set_item_string_decref(dict, "ev_name", _PyUnicode_FromString(perf_evsel__name(evsel)));
487 pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( 517 pydict_set_item_string_decref(dict, "attr", _PyUnicode_FromStringAndSize(
488 (const char *)&evsel->attr, sizeof(evsel->attr))); 518 (const char *)&evsel->attr, sizeof(evsel->attr)));
489 519
490 pydict_set_item_string_decref(dict_sample, "pid", 520 pydict_set_item_string_decref(dict_sample, "pid",
491 PyInt_FromLong(sample->pid)); 521 _PyLong_FromLong(sample->pid));
492 pydict_set_item_string_decref(dict_sample, "tid", 522 pydict_set_item_string_decref(dict_sample, "tid",
493 PyInt_FromLong(sample->tid)); 523 _PyLong_FromLong(sample->tid));
494 pydict_set_item_string_decref(dict_sample, "cpu", 524 pydict_set_item_string_decref(dict_sample, "cpu",
495 PyInt_FromLong(sample->cpu)); 525 _PyLong_FromLong(sample->cpu));
496 pydict_set_item_string_decref(dict_sample, "ip", 526 pydict_set_item_string_decref(dict_sample, "ip",
497 PyLong_FromUnsignedLongLong(sample->ip)); 527 PyLong_FromUnsignedLongLong(sample->ip));
498 pydict_set_item_string_decref(dict_sample, "time", 528 pydict_set_item_string_decref(dict_sample, "time",
@@ -504,17 +534,17 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,
504 set_sample_read_in_dict(dict_sample, sample, evsel); 534 set_sample_read_in_dict(dict_sample, sample, evsel);
505 pydict_set_item_string_decref(dict, "sample", dict_sample); 535 pydict_set_item_string_decref(dict, "sample", dict_sample);
506 536
507 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( 537 pydict_set_item_string_decref(dict, "raw_buf", _PyBytes_FromStringAndSize(
508 (const char *)sample->raw_data, sample->raw_size)); 538 (const char *)sample->raw_data, sample->raw_size));
509 pydict_set_item_string_decref(dict, "comm", 539 pydict_set_item_string_decref(dict, "comm",
510 PyString_FromString(thread__comm_str(al->thread))); 540 _PyUnicode_FromString(thread__comm_str(al->thread)));
511 if (al->map) { 541 if (al->map) {
512 pydict_set_item_string_decref(dict, "dso", 542 pydict_set_item_string_decref(dict, "dso",
513 PyString_FromString(al->map->dso->name)); 543 _PyUnicode_FromString(al->map->dso->name));
514 } 544 }
515 if (al->sym) { 545 if (al->sym) {
516 pydict_set_item_string_decref(dict, "symbol", 546 pydict_set_item_string_decref(dict, "symbol",
517 PyString_FromString(al->sym->name)); 547 _PyUnicode_FromString(al->sym->name));
518 } 548 }
519 549
520 pydict_set_item_string_decref(dict, "callchain", callchain); 550 pydict_set_item_string_decref(dict, "callchain", callchain);
@@ -574,9 +604,9 @@ static void python_process_tracepoint(struct perf_sample *sample,
574 scripting_context->event_data = data; 604 scripting_context->event_data = data;
575 scripting_context->pevent = evsel->tp_format->pevent; 605 scripting_context->pevent = evsel->tp_format->pevent;
576 606
577 context = PyCObject_FromVoidPtr(scripting_context, NULL); 607 context = _PyCapsule_New(scripting_context, NULL, NULL);
578 608
579 PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); 609 PyTuple_SetItem(t, n++, _PyUnicode_FromString(handler_name));
580 PyTuple_SetItem(t, n++, context); 610 PyTuple_SetItem(t, n++, context);
581 611
582 /* ip unwinding */ 612 /* ip unwinding */
@@ -585,18 +615,18 @@ static void python_process_tracepoint(struct perf_sample *sample,
585 Py_INCREF(callchain); 615 Py_INCREF(callchain);
586 616
587 if (!dict) { 617 if (!dict) {
588 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 618 PyTuple_SetItem(t, n++, _PyLong_FromLong(cpu));
589 PyTuple_SetItem(t, n++, PyInt_FromLong(s)); 619 PyTuple_SetItem(t, n++, _PyLong_FromLong(s));
590 PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); 620 PyTuple_SetItem(t, n++, _PyLong_FromLong(ns));
591 PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); 621 PyTuple_SetItem(t, n++, _PyLong_FromLong(pid));
592 PyTuple_SetItem(t, n++, PyString_FromString(comm)); 622 PyTuple_SetItem(t, n++, _PyUnicode_FromString(comm));
593 PyTuple_SetItem(t, n++, callchain); 623 PyTuple_SetItem(t, n++, callchain);
594 } else { 624 } else {
595 pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); 625 pydict_set_item_string_decref(dict, "common_cpu", _PyLong_FromLong(cpu));
596 pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); 626 pydict_set_item_string_decref(dict, "common_s", _PyLong_FromLong(s));
597 pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); 627 pydict_set_item_string_decref(dict, "common_ns", _PyLong_FromLong(ns));
598 pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); 628 pydict_set_item_string_decref(dict, "common_pid", _PyLong_FromLong(pid));
599 pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); 629 pydict_set_item_string_decref(dict, "common_comm", _PyUnicode_FromString(comm));
600 pydict_set_item_string_decref(dict, "common_callchain", callchain); 630 pydict_set_item_string_decref(dict, "common_callchain", callchain);
601 } 631 }
602 for (field = event->format.fields; field; field = field->next) { 632 for (field = event->format.fields; field; field = field->next) {
@@ -615,7 +645,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
615 } 645 }
616 if (field->flags & FIELD_IS_STRING && 646 if (field->flags & FIELD_IS_STRING &&
617 is_printable_array(data + offset, len)) { 647 is_printable_array(data + offset, len)) {
618 obj = PyString_FromString((char *) data + offset); 648 obj = _PyUnicode_FromString((char *) data + offset);
619 } else { 649 } else {
620 obj = PyByteArray_FromStringAndSize((const char *) data + offset, len); 650 obj = PyByteArray_FromStringAndSize((const char *) data + offset, len);
621 field->flags &= ~FIELD_IS_STRING; 651 field->flags &= ~FIELD_IS_STRING;
@@ -668,7 +698,7 @@ static PyObject *tuple_new(unsigned int sz)
668static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val) 698static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val)
669{ 699{
670#if BITS_PER_LONG == 64 700#if BITS_PER_LONG == 64
671 return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); 701 return PyTuple_SetItem(t, pos, _PyLong_FromLong(val));
672#endif 702#endif
673#if BITS_PER_LONG == 32 703#if BITS_PER_LONG == 32
674 return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val)); 704 return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val));
@@ -677,12 +707,12 @@ static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val)
677 707
678static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val) 708static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val)
679{ 709{
680 return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); 710 return PyTuple_SetItem(t, pos, _PyLong_FromLong(val));
681} 711}
682 712
683static int tuple_set_string(PyObject *t, unsigned int pos, const char *s) 713static int tuple_set_string(PyObject *t, unsigned int pos, const char *s)
684{ 714{
685 return PyTuple_SetItem(t, pos, PyString_FromString(s)); 715 return PyTuple_SetItem(t, pos, _PyUnicode_FromString(s));
686} 716}
687 717
688static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel) 718static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel)
@@ -1029,8 +1059,8 @@ process_stat(struct perf_evsel *counter, int cpu, int thread, u64 tstamp,
1029 return; 1059 return;
1030 } 1060 }
1031 1061
1032 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 1062 PyTuple_SetItem(t, n++, _PyLong_FromLong(cpu));
1033 PyTuple_SetItem(t, n++, PyInt_FromLong(thread)); 1063 PyTuple_SetItem(t, n++, _PyLong_FromLong(thread));
1034 1064
1035 tuple_set_u64(t, n++, tstamp); 1065 tuple_set_u64(t, n++, tstamp);
1036 tuple_set_u64(t, n++, count->val); 1066 tuple_set_u64(t, n++, count->val);
@@ -1212,27 +1242,58 @@ static void set_table_handlers(struct tables *tables)
1212 SET_TABLE_HANDLER(call_return); 1242 SET_TABLE_HANDLER(call_return);
1213} 1243}
1214 1244
1245#if PY_MAJOR_VERSION < 3
1246static void _free_command_line(const char **command_line, int num)
1247{
1248 free(command_line);
1249}
1250#else
1251static void _free_command_line(wchar_t **command_line, int num)
1252{
1253 int i;
1254 for (i = 0; i < num; i++)
1255 PyMem_RawFree(command_line[i]);
1256 free(command_line);
1257}
1258#endif
1259
1260
1215/* 1261/*
1216 * Start trace script 1262 * Start trace script
1217 */ 1263 */
1218static int python_start_script(const char *script, int argc, const char **argv) 1264static int python_start_script(const char *script, int argc, const char **argv)
1219{ 1265{
1220 struct tables *tables = &tables_global; 1266 struct tables *tables = &tables_global;
1267#if PY_MAJOR_VERSION < 3
1221 const char **command_line; 1268 const char **command_line;
1269#else
1270 wchar_t **command_line;
1271#endif
1222 char buf[PATH_MAX]; 1272 char buf[PATH_MAX];
1223 int i, err = 0; 1273 int i, err = 0;
1224 FILE *fp; 1274 FILE *fp;
1225 1275
1276#if PY_MAJOR_VERSION < 3
1226 command_line = malloc((argc + 1) * sizeof(const char *)); 1277 command_line = malloc((argc + 1) * sizeof(const char *));
1227 command_line[0] = script; 1278 command_line[0] = script;
1228 for (i = 1; i < argc + 1; i++) 1279 for (i = 1; i < argc + 1; i++)
1229 command_line[i] = argv[i - 1]; 1280 command_line[i] = argv[i - 1];
1281#else
1282 command_line = malloc((argc + 1) * sizeof(wchar_t *));
1283 command_line[0] = Py_DecodeLocale(script, NULL);
1284 for (i = 1; i < argc + 1; i++)
1285 command_line[i] = Py_DecodeLocale(argv[i - 1], NULL);
1286#endif
1230 1287
1231 Py_Initialize(); 1288 Py_Initialize();
1232 1289
1290#if PY_MAJOR_VERSION < 3
1233 initperf_trace_context(); 1291 initperf_trace_context();
1234
1235 PySys_SetArgv(argc + 1, (char **)command_line); 1292 PySys_SetArgv(argc + 1, (char **)command_line);
1293#else
1294 PyInit_perf_trace_context();
1295 PySys_SetArgv(argc + 1, command_line);
1296#endif
1236 1297
1237 fp = fopen(script, "r"); 1298 fp = fopen(script, "r");
1238 if (!fp) { 1299 if (!fp) {
@@ -1262,12 +1323,12 @@ static int python_start_script(const char *script, int argc, const char **argv)
1262 goto error; 1323 goto error;
1263 } 1324 }
1264 1325
1265 free(command_line); 1326 _free_command_line(command_line, argc + 1);
1266 1327
1267 return err; 1328 return err;
1268error: 1329error:
1269 Py_Finalize(); 1330 Py_Finalize();
1270 free(command_line); 1331 _free_command_line(command_line, argc + 1);
1271 1332
1272 return err; 1333 return err;
1273} 1334}
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index af415febbc46..001be4f9d3b9 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -1,4 +1,4 @@
1#!/usr/bin/python2 1#!/usr/bin/python
2 2
3from os import getenv 3from os import getenv
4 4
@@ -28,6 +28,8 @@ class install_lib(_install_lib):
28cflags = getenv('CFLAGS', '').split() 28cflags = getenv('CFLAGS', '').split()
29# switch off several checks (need to be at the end of cflags list) 29# switch off several checks (need to be at the end of cflags list)
30cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' ] 30cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' ]
31if cc != "clang":
32 cflags += ['-Wno-cast-function-type' ]
31 33
32src_perf = getenv('srctree') + '/tools/perf' 34src_perf = getenv('srctree') + '/tools/perf'
33build_lib = getenv('PYTHON_EXTBUILD_LIB') 35build_lib = getenv('PYTHON_EXTBUILD_LIB')
@@ -35,11 +37,11 @@ build_tmp = getenv('PYTHON_EXTBUILD_TMP')
35libtraceevent = getenv('LIBTRACEEVENT') 37libtraceevent = getenv('LIBTRACEEVENT')
36libapikfs = getenv('LIBAPI') 38libapikfs = getenv('LIBAPI')
37 39
38ext_sources = [f.strip() for f in file('util/python-ext-sources') 40ext_sources = [f.strip() for f in open('util/python-ext-sources')
39 if len(f.strip()) > 0 and f[0] != '#'] 41 if len(f.strip()) > 0 and f[0] != '#']
40 42
41# use full paths with source files 43# use full paths with source files
42ext_sources = map(lambda x: '%s/%s' % (src_perf, x) , ext_sources) 44ext_sources = list(map(lambda x: '%s/%s' % (src_perf, x) , ext_sources))
43 45
44perf = Extension('perf', 46perf = Extension('perf',
45 sources = ext_sources, 47 sources = ext_sources,
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 2da4d0456a03..e8514f651865 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -111,17 +111,20 @@ struct sort_entry sort_thread = {
111 111
112/* --sort comm */ 112/* --sort comm */
113 113
114/*
115 * We can't use pointer comparison in functions below,
116 * because it gives different results based on pointer
117 * values, which could break some sorting assumptions.
118 */
114static int64_t 119static int64_t
115sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) 120sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
116{ 121{
117 /* Compare the addr that should be unique among comm */
118 return strcmp(comm__str(right->comm), comm__str(left->comm)); 122 return strcmp(comm__str(right->comm), comm__str(left->comm));
119} 123}
120 124
121static int64_t 125static int64_t
122sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) 126sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
123{ 127{
124 /* Compare the addr that should be unique among comm */
125 return strcmp(comm__str(right->comm), comm__str(left->comm)); 128 return strcmp(comm__str(right->comm), comm__str(left->comm));
126} 129}
127 130
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 32235657c1ac..a0061e0b0fad 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -92,7 +92,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
92}; 92};
93#undef ID 93#undef ID
94 94
95void perf_stat_evsel_id_init(struct perf_evsel *evsel) 95static void perf_stat_evsel_id_init(struct perf_evsel *evsel)
96{ 96{
97 struct perf_stat_evsel *ps = evsel->stats; 97 struct perf_stat_evsel *ps = evsel->stats;
98 int i; 98 int i;
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index dbc6f7134f61..8f56ba4fd258 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -90,6 +90,8 @@ struct perf_stat_config {
90 bool scale; 90 bool scale;
91 FILE *output; 91 FILE *output;
92 unsigned int interval; 92 unsigned int interval;
93 unsigned int timeout;
94 int times;
93 struct runtime_stat *stats; 95 struct runtime_stat *stats;
94 int stats_num; 96 int stats_num;
95}; 97};
@@ -126,8 +128,6 @@ bool __perf_evsel_stat__is(struct perf_evsel *evsel,
126#define perf_stat_evsel__is(evsel, id) \ 128#define perf_stat_evsel__is(evsel, id) \
127 __perf_evsel_stat__is(evsel, PERF_STAT_EVSEL_ID__ ## id) 129 __perf_evsel_stat__is(evsel, PERF_STAT_EVSEL_ID__ ## id)
128 130
129void perf_stat_evsel_id_init(struct perf_evsel *evsel);
130
131extern struct runtime_stat rt_stat; 131extern struct runtime_stat rt_stat;
132extern struct stats walltime_nsecs_stats; 132extern struct stats walltime_nsecs_stats;
133 133
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index cc065d4bfafc..62b2dd2253eb 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1582,7 +1582,7 @@ int dso__load(struct dso *dso, struct map *map)
1582 bool next_slot = false; 1582 bool next_slot = false;
1583 bool is_reg; 1583 bool is_reg;
1584 bool nsexit; 1584 bool nsexit;
1585 int sirc; 1585 int sirc = -1;
1586 1586
1587 enum dso_binary_type symtab_type = binary_type_symtab[i]; 1587 enum dso_binary_type symtab_type = binary_type_symtab[i];
1588 1588
@@ -1600,16 +1600,14 @@ int dso__load(struct dso *dso, struct map *map)
1600 nsinfo__mountns_exit(&nsc); 1600 nsinfo__mountns_exit(&nsc);
1601 1601
1602 is_reg = is_regular_file(name); 1602 is_reg = is_regular_file(name);
1603 sirc = symsrc__init(ss, dso, name, symtab_type); 1603 if (is_reg)
1604 sirc = symsrc__init(ss, dso, name, symtab_type);
1604 1605
1605 if (nsexit) 1606 if (nsexit)
1606 nsinfo__mountns_enter(dso->nsinfo, &nsc); 1607 nsinfo__mountns_enter(dso->nsinfo, &nsc);
1607 1608
1608 if (!is_reg || sirc < 0) { 1609 if (!is_reg || sirc < 0)
1609 if (sirc >= 0)
1610 symsrc__destroy(ss);
1611 continue; 1610 continue;
1612 }
1613 1611
1614 if (!syms_ss && symsrc__has_symtab(ss)) { 1612 if (!syms_ss && symsrc__has_symtab(ss)) {
1615 syms_ss = ss; 1613 syms_ss = ss;
@@ -1960,8 +1958,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map)
1960 pr_debug("Using %s for symbols\n", kallsyms_filename); 1958 pr_debug("Using %s for symbols\n", kallsyms_filename);
1961 if (err > 0 && !dso__is_kcore(dso)) { 1959 if (err > 0 && !dso__is_kcore(dso)) {
1962 dso->binary_type = DSO_BINARY_TYPE__GUEST_KALLSYMS; 1960 dso->binary_type = DSO_BINARY_TYPE__GUEST_KALLSYMS;
1963 machine__mmap_name(machine, path, sizeof(path)); 1961 dso__set_long_name(dso, machine->mmap_name, false);
1964 dso__set_long_name(dso, strdup(path), true);
1965 map__fixup_start(map); 1962 map__fixup_start(map);
1966 map__fixup_end(map); 1963 map__fixup_end(map);
1967 } 1964 }
@@ -2224,3 +2221,25 @@ int symbol__config_symfs(const struct option *opt __maybe_unused,
2224 free(bf); 2221 free(bf);
2225 return 0; 2222 return 0;
2226} 2223}
2224
2225struct mem_info *mem_info__get(struct mem_info *mi)
2226{
2227 if (mi)
2228 refcount_inc(&mi->refcnt);
2229 return mi;
2230}
2231
2232void mem_info__put(struct mem_info *mi)
2233{
2234 if (mi && refcount_dec_and_test(&mi->refcnt))
2235 free(mi);
2236}
2237
2238struct mem_info *mem_info__new(void)
2239{
2240 struct mem_info *mi = zalloc(sizeof(*mi));
2241
2242 if (mi)
2243 refcount_set(&mi->refcnt, 1);
2244 return mi;
2245}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 0563f33c1eb3..70c16741f50a 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -200,9 +200,10 @@ struct branch_info {
200}; 200};
201 201
202struct mem_info { 202struct mem_info {
203 struct addr_map_symbol iaddr; 203 struct addr_map_symbol iaddr;
204 struct addr_map_symbol daddr; 204 struct addr_map_symbol daddr;
205 union perf_mem_data_src data_src; 205 union perf_mem_data_src data_src;
206 refcount_t refcnt;
206}; 207};
207 208
208struct addr_location { 209struct addr_location {
@@ -389,4 +390,16 @@ int sdt_notes__get_count(struct list_head *start);
389#define SDT_NOTE_NAME "stapsdt" 390#define SDT_NOTE_NAME "stapsdt"
390#define NR_ADDR 3 391#define NR_ADDR 3
391 392
393struct mem_info *mem_info__new(void);
394struct mem_info *mem_info__get(struct mem_info *mi);
395void mem_info__put(struct mem_info *mi);
396
397static inline void __mem_info__zput(struct mem_info **mi)
398{
399 mem_info__put(*mi);
400 *mi = NULL;
401}
402
403#define mem_info__zput(mi) __mem_info__zput(&mi)
404
392#endif /* __PERF_SYMBOL */ 405#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 303bdb84ab5a..895122d638dd 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -30,6 +30,14 @@ static const char **syscalltbl_native = syscalltbl_x86_64;
30#include <asm/syscalls_64.c> 30#include <asm/syscalls_64.c>
31const int syscalltbl_native_max_id = SYSCALLTBL_S390_64_MAX_ID; 31const int syscalltbl_native_max_id = SYSCALLTBL_S390_64_MAX_ID;
32static const char **syscalltbl_native = syscalltbl_s390_64; 32static const char **syscalltbl_native = syscalltbl_s390_64;
33#elif defined(__powerpc64__)
34#include <asm/syscalls_64.c>
35const int syscalltbl_native_max_id = SYSCALLTBL_POWERPC_64_MAX_ID;
36static const char **syscalltbl_native = syscalltbl_powerpc_64;
37#elif defined(__powerpc__)
38#include <asm/syscalls_32.c>
39const int syscalltbl_native_max_id = SYSCALLTBL_POWERPC_32_MAX_ID;
40static const char **syscalltbl_native = syscalltbl_powerpc_32;
33#endif 41#endif
34 42
35struct syscall { 43struct syscall {
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 40cfa36c022a..14d44c3235b8 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -26,7 +26,6 @@ struct thread {
26 pid_t ppid; 26 pid_t ppid;
27 int cpu; 27 int cpu;
28 refcount_t refcnt; 28 refcount_t refcnt;
29 char shortname[3];
30 bool comm_set; 29 bool comm_set;
31 int comm_len; 30 int comm_len;
32 bool dead; /* if set thread has exited */ 31 bool dead; /* if set thread has exited */
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 3e1038f6491c..5d467d8ae9ab 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -32,6 +32,7 @@ static void thread_map__reset(struct thread_map *map, int start, int nr)
32 size_t size = (nr - start) * sizeof(map->map[0]); 32 size_t size = (nr - start) * sizeof(map->map[0]);
33 33
34 memset(&map->map[start], 0, size); 34 memset(&map->map[start], 0, size);
35 map->err_thread = -1;
35} 36}
36 37
37static struct thread_map *thread_map__realloc(struct thread_map *map, int nr) 38static struct thread_map *thread_map__realloc(struct thread_map *map, int nr)
@@ -323,7 +324,7 @@ out_free_threads:
323} 324}
324 325
325struct thread_map *thread_map__new_str(const char *pid, const char *tid, 326struct thread_map *thread_map__new_str(const char *pid, const char *tid,
326 uid_t uid, bool per_thread) 327 uid_t uid, bool all_threads)
327{ 328{
328 if (pid) 329 if (pid)
329 return thread_map__new_by_pid_str(pid); 330 return thread_map__new_by_pid_str(pid);
@@ -331,7 +332,7 @@ struct thread_map *thread_map__new_str(const char *pid, const char *tid,
331 if (!tid && uid != UINT_MAX) 332 if (!tid && uid != UINT_MAX)
332 return thread_map__new_by_uid(uid); 333 return thread_map__new_by_uid(uid);
333 334
334 if (per_thread) 335 if (all_threads)
335 return thread_map__new_all_cpus(); 336 return thread_map__new_all_cpus();
336 337
337 return thread_map__new_by_tid_str(tid); 338 return thread_map__new_by_tid_str(tid);
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 0a806b99e73c..2f689c90a8c6 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -14,6 +14,7 @@ struct thread_map_data {
14struct thread_map { 14struct thread_map {
15 refcount_t refcnt; 15 refcount_t refcnt;
16 int nr; 16 int nr;
17 int err_thread;
17 struct thread_map_data map[]; 18 struct thread_map_data map[];
18}; 19};
19 20
@@ -31,7 +32,7 @@ struct thread_map *thread_map__get(struct thread_map *map);
31void thread_map__put(struct thread_map *map); 32void thread_map__put(struct thread_map *map);
32 33
33struct thread_map *thread_map__new_str(const char *pid, 34struct thread_map *thread_map__new_str(const char *pid,
34 const char *tid, uid_t uid, bool per_thread); 35 const char *tid, uid_t uid, bool all_threads);
35 36
36struct thread_map *thread_map__new_by_tid_str(const char *tid_str); 37struct thread_map *thread_map__new_by_tid_str(const char *tid_str);
37 38
diff --git a/tools/perf/util/trigger.h b/tools/perf/util/trigger.h
index 370138e7e35c..88223bc7c82b 100644
--- a/tools/perf/util/trigger.h
+++ b/tools/perf/util/trigger.h
@@ -12,7 +12,7 @@
12 * States and transits: 12 * States and transits:
13 * 13 *
14 * 14 *
15 * OFF--(on)--> READY --(hit)--> HIT 15 * OFF--> ON --> READY --(hit)--> HIT
16 * ^ | 16 * ^ |
17 * | (ready) 17 * | (ready)
18 * | | 18 * | |
@@ -27,8 +27,9 @@ struct trigger {
27 volatile enum { 27 volatile enum {
28 TRIGGER_ERROR = -2, 28 TRIGGER_ERROR = -2,
29 TRIGGER_OFF = -1, 29 TRIGGER_OFF = -1,
30 TRIGGER_READY = 0, 30 TRIGGER_ON = 0,
31 TRIGGER_HIT = 1, 31 TRIGGER_READY = 1,
32 TRIGGER_HIT = 2,
32 } state; 33 } state;
33 const char *name; 34 const char *name;
34}; 35};
@@ -50,7 +51,7 @@ static inline bool trigger_is_error(struct trigger *t)
50static inline void trigger_on(struct trigger *t) 51static inline void trigger_on(struct trigger *t)
51{ 52{
52 TRIGGER_WARN_ONCE(t, TRIGGER_OFF); 53 TRIGGER_WARN_ONCE(t, TRIGGER_OFF);
53 t->state = TRIGGER_READY; 54 t->state = TRIGGER_ON;
54} 55}
55 56
56static inline void trigger_ready(struct trigger *t) 57static inline void trigger_ready(struct trigger *t)
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index 1e9c974faf67..7bdd239c795c 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -50,7 +50,7 @@ static int __report_module(struct addr_location *al, u64 ip,
50 50
51 if (!mod) 51 if (!mod)
52 mod = dwfl_report_elf(ui->dwfl, dso->short_name, 52 mod = dwfl_report_elf(ui->dwfl, dso->short_name,
53 dso->long_name, -1, al->map->start, 53 (dso->symsrc_filename ? dso->symsrc_filename : dso->long_name), -1, al->map->start,
54 false); 54 false);
55 55
56 return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1; 56 return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1;
@@ -236,7 +236,8 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
236 if (err) 236 if (err)
237 goto out; 237 goto out;
238 238
239 if (!dwfl_attach_state(ui->dwfl, EM_NONE, thread->tid, &callbacks, ui)) 239 err = !dwfl_attach_state(ui->dwfl, EM_NONE, thread->tid, &callbacks, ui);
240 if (err)
240 goto out; 241 goto out;
241 242
242 err = dwfl_getthread_frames(ui->dwfl, thread->tid, frame_callback, ui); 243 err = dwfl_getthread_frames(ui->dwfl, thread->tid, frame_callback, ui);
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 443892dabedb..1019bbc5dbd8 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -340,35 +340,15 @@ size_t hex_width(u64 v)
340 return n; 340 return n;
341} 341}
342 342
343static int hex(char ch)
344{
345 if ((ch >= '0') && (ch <= '9'))
346 return ch - '0';
347 if ((ch >= 'a') && (ch <= 'f'))
348 return ch - 'a' + 10;
349 if ((ch >= 'A') && (ch <= 'F'))
350 return ch - 'A' + 10;
351 return -1;
352}
353
354/* 343/*
355 * While we find nice hex chars, build a long_val. 344 * While we find nice hex chars, build a long_val.
356 * Return number of chars processed. 345 * Return number of chars processed.
357 */ 346 */
358int hex2u64(const char *ptr, u64 *long_val) 347int hex2u64(const char *ptr, u64 *long_val)
359{ 348{
360 const char *p = ptr; 349 char *p;
361 *long_val = 0;
362
363 while (*p) {
364 const int hex_val = hex(*p);
365 350
366 if (hex_val < 0) 351 *long_val = strtoull(ptr, &p, 16);
367 break;
368
369 *long_val = (*long_val << 4) | hex_val;
370 p++;
371 }
372 352
373 return p - ptr; 353 return p - ptr;
374} 354}
diff --git a/tools/power/acpi/Makefile.config b/tools/power/acpi/Makefile.config
index a1883bbb0144..2cccbba64418 100644
--- a/tools/power/acpi/Makefile.config
+++ b/tools/power/acpi/Makefile.config
@@ -56,9 +56,6 @@ INSTALL_SCRIPT = ${INSTALL_PROGRAM}
56# to compile vs uClibc, that can be done here as well. 56# to compile vs uClibc, that can be done here as well.
57CROSS = #/usr/i386-linux-uclibc/usr/bin/i386-uclibc- 57CROSS = #/usr/i386-linux-uclibc/usr/bin/i386-uclibc-
58CROSS_COMPILE ?= $(CROSS) 58CROSS_COMPILE ?= $(CROSS)
59CC = $(CROSS_COMPILE)gcc
60LD = $(CROSS_COMPILE)gcc
61STRIP = $(CROSS_COMPILE)strip
62HOSTCC = gcc 59HOSTCC = gcc
63 60
64# check if compiler option is supported 61# check if compiler option is supported
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index fcb3ed0be5f8..dd614463d4d6 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -42,6 +42,24 @@ EXTRA_WARNINGS += -Wformat
42 42
43CC_NO_CLANG := $(shell $(CC) -dM -E -x c /dev/null | grep -Fq "__clang__"; echo $$?) 43CC_NO_CLANG := $(shell $(CC) -dM -E -x c /dev/null | grep -Fq "__clang__"; echo $$?)
44 44
45# Makefiles suck: This macro sets a default value of $(2) for the
46# variable named by $(1), unless the variable has been set by
47# environment or command line. This is necessary for CC and AR
48# because make sets default values, so the simpler ?= approach
49# won't work as expected.
50define allow-override
51 $(if $(or $(findstring environment,$(origin $(1))),\
52 $(findstring command line,$(origin $(1)))),,\
53 $(eval $(1) = $(2)))
54endef
55
56# Allow setting various cross-compile vars or setting CROSS_COMPILE as a prefix.
57$(call allow-override,CC,$(CROSS_COMPILE)gcc)
58$(call allow-override,AR,$(CROSS_COMPILE)ar)
59$(call allow-override,LD,$(CROSS_COMPILE)ld)
60$(call allow-override,CXX,$(CROSS_COMPILE)g++)
61$(call allow-override,STRIP,$(CROSS_COMPILE)strip)
62
45ifeq ($(CC_NO_CLANG), 1) 63ifeq ($(CC_NO_CLANG), 1)
46EXTRA_WARNINGS += -Wstrict-aliasing=3 64EXTRA_WARNINGS += -Wstrict-aliasing=3
47endif 65endif
diff --git a/tools/spi/Makefile b/tools/spi/Makefile
index 90615e10c79a..815d15589177 100644
--- a/tools/spi/Makefile
+++ b/tools/spi/Makefile
@@ -11,8 +11,6 @@ endif
11# (this improves performance and avoids hard-to-debug behaviour); 11# (this improves performance and avoids hard-to-debug behaviour);
12MAKEFLAGS += -r 12MAKEFLAGS += -r
13 13
14CC = $(CROSS_COMPILE)gcc
15LD = $(CROSS_COMPILE)ld
16CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include 14CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
17 15
18ALL_TARGETS := spidev_test spidev_fdx 16ALL_TARGETS := spidev_test spidev_fdx
diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c
index 44ef9eba5a7a..6c645eb77d42 100644
--- a/tools/testing/radix-tree/idr-test.c
+++ b/tools/testing/radix-tree/idr-test.c
@@ -178,6 +178,55 @@ void idr_get_next_test(int base)
178 idr_destroy(&idr); 178 idr_destroy(&idr);
179} 179}
180 180
181int idr_u32_cb(int id, void *ptr, void *data)
182{
183 BUG_ON(id < 0);
184 BUG_ON(ptr != DUMMY_PTR);
185 return 0;
186}
187
188void idr_u32_test1(struct idr *idr, u32 handle)
189{
190 static bool warned = false;
191 u32 id = handle;
192 int sid = 0;
193 void *ptr;
194
195 BUG_ON(idr_alloc_u32(idr, DUMMY_PTR, &id, id, GFP_KERNEL));
196 BUG_ON(id != handle);
197 BUG_ON(idr_alloc_u32(idr, DUMMY_PTR, &id, id, GFP_KERNEL) != -ENOSPC);
198 BUG_ON(id != handle);
199 if (!warned && id > INT_MAX)
200 printk("vvv Ignore these warnings\n");
201 ptr = idr_get_next(idr, &sid);
202 if (id > INT_MAX) {
203 BUG_ON(ptr != NULL);
204 BUG_ON(sid != 0);
205 } else {
206 BUG_ON(ptr != DUMMY_PTR);
207 BUG_ON(sid != id);
208 }
209 idr_for_each(idr, idr_u32_cb, NULL);
210 if (!warned && id > INT_MAX) {
211 printk("^^^ Warnings over\n");
212 warned = true;
213 }
214 BUG_ON(idr_remove(idr, id) != DUMMY_PTR);
215 BUG_ON(!idr_is_empty(idr));
216}
217
218void idr_u32_test(int base)
219{
220 DEFINE_IDR(idr);
221 idr_init_base(&idr, base);
222 idr_u32_test1(&idr, 10);
223 idr_u32_test1(&idr, 0x7fffffff);
224 idr_u32_test1(&idr, 0x80000000);
225 idr_u32_test1(&idr, 0x80000001);
226 idr_u32_test1(&idr, 0xffe00000);
227 idr_u32_test1(&idr, 0xffffffff);
228}
229
181void idr_checks(void) 230void idr_checks(void)
182{ 231{
183 unsigned long i; 232 unsigned long i;
@@ -248,6 +297,9 @@ void idr_checks(void)
248 idr_get_next_test(0); 297 idr_get_next_test(0);
249 idr_get_next_test(1); 298 idr_get_next_test(1);
250 idr_get_next_test(4); 299 idr_get_next_test(4);
300 idr_u32_test(4);
301 idr_u32_test(1);
302 idr_u32_test(0);
251} 303}
252 304
253/* 305/*
diff --git a/tools/testing/radix-tree/linux.c b/tools/testing/radix-tree/linux.c
index 6903ccf35595..44a0d1ad4408 100644
--- a/tools/testing/radix-tree/linux.c
+++ b/tools/testing/radix-tree/linux.c
@@ -29,7 +29,7 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, int flags)
29{ 29{
30 struct radix_tree_node *node; 30 struct radix_tree_node *node;
31 31
32 if (flags & __GFP_NOWARN) 32 if (!(flags & __GFP_DIRECT_RECLAIM))
33 return NULL; 33 return NULL;
34 34
35 pthread_mutex_lock(&cachep->lock); 35 pthread_mutex_lock(&cachep->lock);
@@ -73,10 +73,17 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp)
73 73
74void *kmalloc(size_t size, gfp_t gfp) 74void *kmalloc(size_t size, gfp_t gfp)
75{ 75{
76 void *ret = malloc(size); 76 void *ret;
77
78 if (!(gfp & __GFP_DIRECT_RECLAIM))
79 return NULL;
80
81 ret = malloc(size);
77 uatomic_inc(&nr_allocated); 82 uatomic_inc(&nr_allocated);
78 if (kmalloc_verbose) 83 if (kmalloc_verbose)
79 printf("Allocating %p from malloc\n", ret); 84 printf("Allocating %p from malloc\n", ret);
85 if (gfp & __GFP_ZERO)
86 memset(ret, 0, size);
80 return ret; 87 return ret;
81} 88}
82 89
diff --git a/tools/testing/radix-tree/linux/compiler_types.h b/tools/testing/radix-tree/linux/compiler_types.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/radix-tree/linux/compiler_types.h
diff --git a/tools/testing/radix-tree/linux/gfp.h b/tools/testing/radix-tree/linux/gfp.h
index e9fff59dfd8a..e3201ccf54c3 100644
--- a/tools/testing/radix-tree/linux/gfp.h
+++ b/tools/testing/radix-tree/linux/gfp.h
@@ -11,6 +11,7 @@
11#define __GFP_IO 0x40u 11#define __GFP_IO 0x40u
12#define __GFP_FS 0x80u 12#define __GFP_FS 0x80u
13#define __GFP_NOWARN 0x200u 13#define __GFP_NOWARN 0x200u
14#define __GFP_ZERO 0x8000u
14#define __GFP_ATOMIC 0x80000u 15#define __GFP_ATOMIC 0x80000u
15#define __GFP_ACCOUNT 0x100000u 16#define __GFP_ACCOUNT 0x100000u
16#define __GFP_DIRECT_RECLAIM 0x400000u 17#define __GFP_DIRECT_RECLAIM 0x400000u
diff --git a/tools/testing/radix-tree/linux/slab.h b/tools/testing/radix-tree/linux/slab.h
index 979baeec7e70..a037def0dec6 100644
--- a/tools/testing/radix-tree/linux/slab.h
+++ b/tools/testing/radix-tree/linux/slab.h
@@ -3,6 +3,7 @@
3#define SLAB_H 3#define SLAB_H
4 4
5#include <linux/types.h> 5#include <linux/types.h>
6#include <linux/gfp.h>
6 7
7#define SLAB_HWCACHE_ALIGN 1 8#define SLAB_HWCACHE_ALIGN 1
8#define SLAB_PANIC 2 9#define SLAB_PANIC 2
@@ -11,6 +12,11 @@
11void *kmalloc(size_t size, gfp_t); 12void *kmalloc(size_t size, gfp_t);
12void kfree(void *); 13void kfree(void *);
13 14
15static inline void *kzalloc(size_t size, gfp_t gfp)
16{
17 return kmalloc(size, gfp | __GFP_ZERO);
18}
19
14void *kmem_cache_alloc(struct kmem_cache *cachep, int flags); 20void *kmem_cache_alloc(struct kmem_cache *cachep, int flags);
15void kmem_cache_free(struct kmem_cache *cachep, void *objp); 21void kmem_cache_free(struct kmem_cache *cachep, void *objp);
16 22
diff --git a/tools/testing/selftests/android/Makefile b/tools/testing/selftests/android/Makefile
index 1a7492268993..f6304d2be90c 100644
--- a/tools/testing/selftests/android/Makefile
+++ b/tools/testing/selftests/android/Makefile
@@ -11,11 +11,11 @@ all:
11 BUILD_TARGET=$(OUTPUT)/$$DIR; \ 11 BUILD_TARGET=$(OUTPUT)/$$DIR; \
12 mkdir $$BUILD_TARGET -p; \ 12 mkdir $$BUILD_TARGET -p; \
13 make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\ 13 make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
14 #SUBDIR test prog name should be in the form: SUBDIR_test.sh 14 #SUBDIR test prog name should be in the form: SUBDIR_test.sh \
15 TEST=$$DIR"_test.sh"; \ 15 TEST=$$DIR"_test.sh"; \
16 if [ -e $$DIR/$$TEST ]; then 16 if [ -e $$DIR/$$TEST ]; then \
17 rsync -a $$DIR/$$TEST $$BUILD_TARGET/; 17 rsync -a $$DIR/$$TEST $$BUILD_TARGET/; \
18 fi 18 fi \
19 done 19 done
20 20
21override define RUN_TESTS 21override define RUN_TESTS
diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore
index cc15af2e54fe..9cf83f895d98 100644
--- a/tools/testing/selftests/bpf/.gitignore
+++ b/tools/testing/selftests/bpf/.gitignore
@@ -11,3 +11,4 @@ test_progs
11test_tcpbpf_user 11test_tcpbpf_user
12test_verifier_log 12test_verifier_log
13feature 13feature
14test_libbpf_open
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
index 436c4c72414f..9e03a4c356a4 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -126,6 +126,8 @@ static void test_hashmap_sizes(int task, void *data)
126 fd = bpf_create_map(BPF_MAP_TYPE_HASH, i, j, 126 fd = bpf_create_map(BPF_MAP_TYPE_HASH, i, j,
127 2, map_flags); 127 2, map_flags);
128 if (fd < 0) { 128 if (fd < 0) {
129 if (errno == ENOMEM)
130 return;
129 printf("Failed to create hashmap key=%d value=%d '%s'\n", 131 printf("Failed to create hashmap key=%d value=%d '%s'\n",
130 i, j, strerror(errno)); 132 i, j, strerror(errno));
131 exit(1); 133 exit(1);
diff --git a/tools/testing/selftests/bpf/test_tcpbpf_kern.c b/tools/testing/selftests/bpf/test_tcpbpf_kern.c
index 57119ad57a3f..3e645ee41ed5 100644
--- a/tools/testing/selftests/bpf/test_tcpbpf_kern.c
+++ b/tools/testing/selftests/bpf/test_tcpbpf_kern.c
@@ -5,7 +5,6 @@
5#include <linux/if_ether.h> 5#include <linux/if_ether.h>
6#include <linux/if_packet.h> 6#include <linux/if_packet.h>
7#include <linux/ip.h> 7#include <linux/ip.h>
8#include <linux/in6.h>
9#include <linux/types.h> 8#include <linux/types.h>
10#include <linux/socket.h> 9#include <linux/socket.h>
11#include <linux/tcp.h> 10#include <linux/tcp.h>
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index c0f16e93f9bd..437c0b1c9d21 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -2587,6 +2587,32 @@ static struct bpf_test tests[] = {
2587 .result = ACCEPT, 2587 .result = ACCEPT,
2588 }, 2588 },
2589 { 2589 {
2590 "runtime/jit: pass negative index to tail_call",
2591 .insns = {
2592 BPF_MOV64_IMM(BPF_REG_3, -1),
2593 BPF_LD_MAP_FD(BPF_REG_2, 0),
2594 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
2595 BPF_FUNC_tail_call),
2596 BPF_MOV64_IMM(BPF_REG_0, 0),
2597 BPF_EXIT_INSN(),
2598 },
2599 .fixup_prog = { 1 },
2600 .result = ACCEPT,
2601 },
2602 {
2603 "runtime/jit: pass > 32bit index to tail_call",
2604 .insns = {
2605 BPF_LD_IMM64(BPF_REG_3, 0x100000000ULL),
2606 BPF_LD_MAP_FD(BPF_REG_2, 0),
2607 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
2608 BPF_FUNC_tail_call),
2609 BPF_MOV64_IMM(BPF_REG_0, 0),
2610 BPF_EXIT_INSN(),
2611 },
2612 .fixup_prog = { 2 },
2613 .result = ACCEPT,
2614 },
2615 {
2590 "stack pointer arithmetic", 2616 "stack pointer arithmetic",
2591 .insns = { 2617 .insns = {
2592 BPF_MOV64_IMM(BPF_REG_1, 4), 2618 BPF_MOV64_IMM(BPF_REG_1, 4),
@@ -11137,6 +11163,64 @@ static struct bpf_test tests[] = {
11137 .result = REJECT, 11163 .result = REJECT,
11138 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 11164 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
11139 }, 11165 },
11166 {
11167 "xadd/w check unaligned stack",
11168 .insns = {
11169 BPF_MOV64_IMM(BPF_REG_0, 1),
11170 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
11171 BPF_STX_XADD(BPF_W, BPF_REG_10, BPF_REG_0, -7),
11172 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
11173 BPF_EXIT_INSN(),
11174 },
11175 .result = REJECT,
11176 .errstr = "misaligned stack access off",
11177 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
11178 },
11179 {
11180 "xadd/w check unaligned map",
11181 .insns = {
11182 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
11183 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
11184 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
11185 BPF_LD_MAP_FD(BPF_REG_1, 0),
11186 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
11187 BPF_FUNC_map_lookup_elem),
11188 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
11189 BPF_EXIT_INSN(),
11190 BPF_MOV64_IMM(BPF_REG_1, 1),
11191 BPF_STX_XADD(BPF_W, BPF_REG_0, BPF_REG_1, 3),
11192 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, 3),
11193 BPF_EXIT_INSN(),
11194 },
11195 .fixup_map1 = { 3 },
11196 .result = REJECT,
11197 .errstr = "misaligned value access off",
11198 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
11199 },
11200 {
11201 "xadd/w check unaligned pkt",
11202 .insns = {
11203 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
11204 offsetof(struct xdp_md, data)),
11205 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
11206 offsetof(struct xdp_md, data_end)),
11207 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
11208 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
11209 BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 2),
11210 BPF_MOV64_IMM(BPF_REG_0, 99),
11211 BPF_JMP_IMM(BPF_JA, 0, 0, 6),
11212 BPF_MOV64_IMM(BPF_REG_0, 1),
11213 BPF_ST_MEM(BPF_W, BPF_REG_2, 0, 0),
11214 BPF_ST_MEM(BPF_W, BPF_REG_2, 3, 0),
11215 BPF_STX_XADD(BPF_W, BPF_REG_2, BPF_REG_0, 1),
11216 BPF_STX_XADD(BPF_W, BPF_REG_2, BPF_REG_0, 2),
11217 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_2, 1),
11218 BPF_EXIT_INSN(),
11219 },
11220 .result = REJECT,
11221 .errstr = "BPF_XADD stores into R2 packet",
11222 .prog_type = BPF_PROG_TYPE_XDP,
11223 },
11140}; 11224};
11141 11225
11142static int probe_filter_length(const struct bpf_insn *fp) 11226static int probe_filter_length(const struct bpf_insn *fp)
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc
new file mode 100644
index 000000000000..5ba73035e1d9
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc
@@ -0,0 +1,46 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3# description: Kprobe event string type argument
4
5[ -f kprobe_events ] || exit_unsupported # this is configurable
6
7echo 0 > events/enable
8echo > kprobe_events
9
10case `uname -m` in
11x86_64)
12 ARG2=%si
13 OFFS=8
14;;
15i[3456]86)
16 ARG2=%cx
17 OFFS=4
18;;
19aarch64)
20 ARG2=%x1
21 OFFS=8
22;;
23arm*)
24 ARG2=%r1
25 OFFS=4
26;;
27*)
28 echo "Please implement other architecture here"
29 exit_untested
30esac
31
32: "Test get argument (1)"
33echo "p:testprobe create_trace_kprobe arg1=+0(+0(${ARG2})):string" > kprobe_events
34echo 1 > events/kprobes/testprobe/enable
35! echo test >> kprobe_events
36tail -n 1 trace | grep -qe "testprobe.* arg1=\"test\""
37
38echo 0 > events/kprobes/testprobe/enable
39: "Test get argument (2)"
40echo "p:testprobe create_trace_kprobe arg1=+0(+0(${ARG2})):string arg2=+0(+${OFFS}(${ARG2})):string" > kprobe_events
41echo 1 > events/kprobes/testprobe/enable
42! echo test1 test2 >> kprobe_events
43tail -n 1 trace | grep -qe "testprobe.* arg1=\"test1\" arg2=\"test2\""
44
45echo 0 > events/enable
46echo > kprobe_events
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc
new file mode 100644
index 000000000000..231bcd2c4eb5
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc
@@ -0,0 +1,97 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3# description: Kprobe event argument syntax
4
5[ -f kprobe_events ] || exit_unsupported # this is configurable
6
7grep "x8/16/32/64" README > /dev/null || exit_unsupported # version issue
8
9echo 0 > events/enable
10echo > kprobe_events
11
12PROBEFUNC="vfs_read"
13GOODREG=
14BADREG=
15GOODSYM="_sdata"
16if ! grep -qw ${GOODSYM} /proc/kallsyms ; then
17 GOODSYM=$PROBEFUNC
18fi
19BADSYM="deaqswdefr"
20SYMADDR=0x`grep -w ${GOODSYM} /proc/kallsyms | cut -f 1 -d " "`
21GOODTYPE="x16"
22BADTYPE="y16"
23
24case `uname -m` in
25x86_64|i[3456]86)
26 GOODREG=%ax
27 BADREG=%ex
28;;
29aarch64)
30 GOODREG=%x0
31 BADREG=%ax
32;;
33arm*)
34 GOODREG=%r0
35 BADREG=%ax
36;;
37esac
38
39test_goodarg() # Good-args
40{
41 while [ "$1" ]; do
42 echo "p ${PROBEFUNC} $1" > kprobe_events
43 shift 1
44 done;
45}
46
47test_badarg() # Bad-args
48{
49 while [ "$1" ]; do
50 ! echo "p ${PROBEFUNC} $1" > kprobe_events
51 shift 1
52 done;
53}
54
55echo > kprobe_events
56
57: "Register access"
58test_goodarg ${GOODREG}
59test_badarg ${BADREG}
60
61: "Symbol access"
62test_goodarg "@${GOODSYM}" "@${SYMADDR}" "@${GOODSYM}+10" "@${GOODSYM}-10"
63test_badarg "@" "@${BADSYM}" "@${GOODSYM}*10" "@${GOODSYM}/10" \
64 "@${GOODSYM}%10" "@${GOODSYM}&10" "@${GOODSYM}|10"
65
66: "Stack access"
67test_goodarg "\$stack" "\$stack0" "\$stack1"
68test_badarg "\$stackp" "\$stack0+10" "\$stack1-10"
69
70: "Retval access"
71echo "r ${PROBEFUNC} \$retval" > kprobe_events
72! echo "p ${PROBEFUNC} \$retval" > kprobe_events
73
74: "Comm access"
75test_goodarg "\$comm"
76
77: "Indirect memory access"
78test_goodarg "+0(${GOODREG})" "-0(${GOODREG})" "+10(\$stack)" \
79 "+0(\$stack1)" "+10(@${GOODSYM}-10)" "+0(+10(+20(\$stack)))"
80test_badarg "+(${GOODREG})" "(${GOODREG}+10)" "-(${GOODREG})" "(${GOODREG})" \
81 "+10(\$comm)" "+0(${GOODREG})+10"
82
83: "Name assignment"
84test_goodarg "varname=${GOODREG}"
85test_badarg "varname=varname2=${GOODREG}"
86
87: "Type syntax"
88test_goodarg "${GOODREG}:${GOODTYPE}"
89test_badarg "${GOODREG}::${GOODTYPE}" "${GOODREG}:${BADTYPE}" \
90 "${GOODTYPE}:${GOODREG}"
91
92: "Combination check"
93
94test_goodarg "\$comm:string" "+0(\$stack):string"
95test_badarg "\$comm:x64" "\$stack:string" "${GOODREG}:string"
96
97echo > kprobe_events
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/probepoint.tc b/tools/testing/selftests/ftrace/test.d/kprobe/probepoint.tc
new file mode 100644
index 000000000000..4fda01a08da4
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/probepoint.tc
@@ -0,0 +1,43 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3# description: Kprobe events - probe points
4
5[ -f kprobe_events ] || exit_unsupported # this is configurable
6
7TARGET_FUNC=create_trace_kprobe
8
9dec_addr() { # hexaddr
10 printf "%d" "0x"`echo $1 | tail -c 8`
11}
12
13set_offs() { # prev target next
14 A1=`dec_addr $1`
15 A2=`dec_addr $2`
16 A3=`dec_addr $3`
17 TARGET="0x$2" # an address
18 PREV=`expr $A1 - $A2` # offset to previous symbol
19 NEXT=+`expr $A3 - $A2` # offset to next symbol
20 OVERFLOW=+`printf "0x%x" ${PREV}` # overflow offset to previous symbol
21}
22
23# We have to decode symbol addresses to get correct offsets.
24# If the offset is not an instruction boundary, it cause -EILSEQ.
25set_offs `grep -A1 -B1 ${TARGET_FUNC} /proc/kallsyms | cut -f 1 -d " " | xargs`
26
27UINT_TEST=no
28# printf "%x" -1 returns (unsigned long)-1.
29if [ `printf "%x" -1 | wc -c` != 9 ]; then
30 UINT_TEST=yes
31fi
32
33echo 0 > events/enable
34echo > kprobe_events
35echo "p:testprobe ${TARGET_FUNC}" > kprobe_events
36echo "p:testprobe ${TARGET}" > kprobe_events
37echo "p:testprobe ${TARGET_FUNC}${NEXT}" > kprobe_events
38! echo "p:testprobe ${TARGET_FUNC}${PREV}" > kprobe_events
39if [ "${UINT_TEST}" = yes ]; then
40! echo "p:testprobe ${TARGET_FUNC}${OVERFLOW}" > kprobe_events
41fi
42echo > kprobe_events
43clear_trace
diff --git a/tools/testing/selftests/futex/Makefile b/tools/testing/selftests/futex/Makefile
index cea4adcd42b8..a63e8453984d 100644
--- a/tools/testing/selftests/futex/Makefile
+++ b/tools/testing/selftests/futex/Makefile
@@ -12,9 +12,9 @@ all:
12 BUILD_TARGET=$(OUTPUT)/$$DIR; \ 12 BUILD_TARGET=$(OUTPUT)/$$DIR; \
13 mkdir $$BUILD_TARGET -p; \ 13 mkdir $$BUILD_TARGET -p; \
14 make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\ 14 make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
15 if [ -e $$DIR/$(TEST_PROGS) ]; then 15 if [ -e $$DIR/$(TEST_PROGS) ]; then \
16 rsync -a $$DIR/$(TEST_PROGS) $$BUILD_TARGET/; 16 rsync -a $$DIR/$(TEST_PROGS) $$BUILD_TARGET/; \
17 fi 17 fi \
18 done 18 done
19 19
20override define RUN_TESTS 20override define RUN_TESTS
diff --git a/tools/testing/selftests/memfd/Makefile b/tools/testing/selftests/memfd/Makefile
index a5276a91dfbf..0862e6f47a38 100644
--- a/tools/testing/selftests/memfd/Makefile
+++ b/tools/testing/selftests/memfd/Makefile
@@ -5,6 +5,7 @@ CFLAGS += -I../../../../include/
5CFLAGS += -I../../../../usr/include/ 5CFLAGS += -I../../../../usr/include/
6 6
7TEST_PROGS := run_tests.sh 7TEST_PROGS := run_tests.sh
8TEST_FILES := run_fuse_test.sh
8TEST_GEN_FILES := memfd_test fuse_mnt fuse_test 9TEST_GEN_FILES := memfd_test fuse_mnt fuse_test
9 10
10fuse_mnt.o: CFLAGS += $(shell pkg-config fuse --cflags) 11fuse_mnt.o: CFLAGS += $(shell pkg-config fuse --cflags)
diff --git a/tools/testing/selftests/memfd/config b/tools/testing/selftests/memfd/config
new file mode 100644
index 000000000000..835c7f4dadcd
--- /dev/null
+++ b/tools/testing/selftests/memfd/config
@@ -0,0 +1 @@
CONFIG_FUSE_FS=m
diff --git a/tools/testing/selftests/memory-hotplug/Makefile b/tools/testing/selftests/memory-hotplug/Makefile
index 86636d207adf..686da510f989 100644
--- a/tools/testing/selftests/memory-hotplug/Makefile
+++ b/tools/testing/selftests/memory-hotplug/Makefile
@@ -4,8 +4,9 @@ all:
4include ../lib.mk 4include ../lib.mk
5 5
6TEST_PROGS := mem-on-off-test.sh 6TEST_PROGS := mem-on-off-test.sh
7override RUN_TESTS := ./mem-on-off-test.sh -r 2 && echo "selftests: memory-hotplug [PASS]" || echo "selftests: memory-hotplug [FAIL]" 7override RUN_TESTS := @./mem-on-off-test.sh -r 2 && echo "selftests: memory-hotplug [PASS]" || echo "selftests: memory-hotplug [FAIL]"
8override EMIT_TESTS := echo "$(RUN_TESTS)" 8
9override EMIT_TESTS := echo "$(subst @,,$(RUN_TESTS))"
9 10
10run_full_test: 11run_full_test:
11 @/bin/bash ./mem-on-off-test.sh && echo "memory-hotplug selftests: [PASS]" || echo "memory-hotplug selftests: [FAIL]" 12 @/bin/bash ./mem-on-off-test.sh && echo "memory-hotplug selftests: [PASS]" || echo "memory-hotplug selftests: [FAIL]"
diff --git a/tools/testing/selftests/powerpc/mm/subpage_prot.c b/tools/testing/selftests/powerpc/mm/subpage_prot.c
index 35ade7406dcd..3ae77ba93208 100644
--- a/tools/testing/selftests/powerpc/mm/subpage_prot.c
+++ b/tools/testing/selftests/powerpc/mm/subpage_prot.c
@@ -135,6 +135,16 @@ static int run_test(void *addr, unsigned long size)
135 return 0; 135 return 0;
136} 136}
137 137
138static int syscall_available(void)
139{
140 int rc;
141
142 errno = 0;
143 rc = syscall(__NR_subpage_prot, 0, 0, 0);
144
145 return rc == 0 || (errno != ENOENT && errno != ENOSYS);
146}
147
138int test_anon(void) 148int test_anon(void)
139{ 149{
140 unsigned long align; 150 unsigned long align;
@@ -145,6 +155,8 @@ int test_anon(void)
145 void *mallocblock; 155 void *mallocblock;
146 unsigned long mallocsize; 156 unsigned long mallocsize;
147 157
158 SKIP_IF(!syscall_available());
159
148 if (getpagesize() != 0x10000) { 160 if (getpagesize() != 0x10000) {
149 fprintf(stderr, "Kernel page size must be 64K!\n"); 161 fprintf(stderr, "Kernel page size must be 64K!\n");
150 return 1; 162 return 1;
@@ -180,6 +192,8 @@ int test_file(void)
180 off_t filesize; 192 off_t filesize;
181 int fd; 193 int fd;
182 194
195 SKIP_IF(!syscall_available());
196
183 fd = open(file_name, O_RDWR); 197 fd = open(file_name, O_RDWR);
184 if (fd == -1) { 198 if (fd == -1) {
185 perror("failed to open file"); 199 perror("failed to open file");
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index a23453943ad2..5c72ff978f27 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -16,7 +16,7 @@ $(OUTPUT)/tm-syscall: tm-syscall-asm.S
16$(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include 16$(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include
17$(OUTPUT)/tm-tmspr: CFLAGS += -pthread 17$(OUTPUT)/tm-tmspr: CFLAGS += -pthread
18$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64 18$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64
19$(OUTPUT)/tm-resched-dscr: ../pmu/lib.o 19$(OUTPUT)/tm-resched-dscr: ../pmu/lib.c
20$(OUTPUT)/tm-unavailable: CFLAGS += -O0 -pthread -m64 -Wno-error=uninitialized -mvsx 20$(OUTPUT)/tm-unavailable: CFLAGS += -O0 -pthread -m64 -Wno-error=uninitialized -mvsx
21$(OUTPUT)/tm-trap: CFLAGS += -O0 -pthread -m64 21$(OUTPUT)/tm-trap: CFLAGS += -O0 -pthread -m64
22 22
diff --git a/tools/testing/selftests/powerpc/tm/tm-trap.c b/tools/testing/selftests/powerpc/tm/tm-trap.c
index 5d92c23ee6cb..179d592f0073 100644
--- a/tools/testing/selftests/powerpc/tm/tm-trap.c
+++ b/tools/testing/selftests/powerpc/tm/tm-trap.c
@@ -255,6 +255,8 @@ int tm_trap_test(void)
255 255
256 struct sigaction trap_sa; 256 struct sigaction trap_sa;
257 257
258 SKIP_IF(!have_htm());
259
258 trap_sa.sa_flags = SA_SIGINFO; 260 trap_sa.sa_flags = SA_SIGINFO;
259 trap_sa.sa_sigaction = trap_signal_handler; 261 trap_sa.sa_sigaction = trap_signal_handler;
260 sigaction(SIGTRAP, &trap_sa, NULL); 262 sigaction(SIGTRAP, &trap_sa, NULL);
diff --git a/tools/testing/selftests/pstore/config b/tools/testing/selftests/pstore/config
index 6a8e5a9bfc10..d148f9f89fb6 100644
--- a/tools/testing/selftests/pstore/config
+++ b/tools/testing/selftests/pstore/config
@@ -2,3 +2,4 @@ CONFIG_MISC_FILESYSTEMS=y
2CONFIG_PSTORE=y 2CONFIG_PSTORE=y
3CONFIG_PSTORE_PMSG=y 3CONFIG_PSTORE_PMSG=y
4CONFIG_PSTORE_CONSOLE=y 4CONFIG_PSTORE_CONSOLE=y
5CONFIG_PSTORE_RAM=m
diff --git a/tools/testing/selftests/rcutorture/bin/functions.sh b/tools/testing/selftests/rcutorture/bin/functions.sh
index 07a13779eece..65f6655026f0 100644
--- a/tools/testing/selftests/rcutorture/bin/functions.sh
+++ b/tools/testing/selftests/rcutorture/bin/functions.sh
@@ -136,6 +136,9 @@ identify_boot_image () {
136 qemu-system-x86_64|qemu-system-i386) 136 qemu-system-x86_64|qemu-system-i386)
137 echo arch/x86/boot/bzImage 137 echo arch/x86/boot/bzImage
138 ;; 138 ;;
139 qemu-system-aarch64)
140 echo arch/arm64/boot/Image
141 ;;
139 *) 142 *)
140 echo vmlinux 143 echo vmlinux
141 ;; 144 ;;
@@ -158,6 +161,9 @@ identify_qemu () {
158 elif echo $u | grep -q "Intel 80386" 161 elif echo $u | grep -q "Intel 80386"
159 then 162 then
160 echo qemu-system-i386 163 echo qemu-system-i386
164 elif echo $u | grep -q aarch64
165 then
166 echo qemu-system-aarch64
161 elif uname -a | grep -q ppc64 167 elif uname -a | grep -q ppc64
162 then 168 then
163 echo qemu-system-ppc64 169 echo qemu-system-ppc64
@@ -176,16 +182,20 @@ identify_qemu () {
176# Output arguments for the qemu "-append" string based on CPU type 182# Output arguments for the qemu "-append" string based on CPU type
177# and the TORTURE_QEMU_INTERACTIVE environment variable. 183# and the TORTURE_QEMU_INTERACTIVE environment variable.
178identify_qemu_append () { 184identify_qemu_append () {
185 local console=ttyS0
179 case "$1" in 186 case "$1" in
180 qemu-system-x86_64|qemu-system-i386) 187 qemu-system-x86_64|qemu-system-i386)
181 echo noapic selinux=0 initcall_debug debug 188 echo noapic selinux=0 initcall_debug debug
182 ;; 189 ;;
190 qemu-system-aarch64)
191 console=ttyAMA0
192 ;;
183 esac 193 esac
184 if test -n "$TORTURE_QEMU_INTERACTIVE" 194 if test -n "$TORTURE_QEMU_INTERACTIVE"
185 then 195 then
186 echo root=/dev/sda 196 echo root=/dev/sda
187 else 197 else
188 echo console=ttyS0 198 echo console=$console
189 fi 199 fi
190} 200}
191 201
@@ -197,6 +207,9 @@ identify_qemu_args () {
197 case "$1" in 207 case "$1" in
198 qemu-system-x86_64|qemu-system-i386) 208 qemu-system-x86_64|qemu-system-i386)
199 ;; 209 ;;
210 qemu-system-aarch64)
211 echo -machine virt,gic-version=host -cpu host
212 ;;
200 qemu-system-ppc64) 213 qemu-system-ppc64)
201 echo -enable-kvm -M pseries -nodefaults 214 echo -enable-kvm -M pseries -nodefaults
202 echo -device spapr-vscsi 215 echo -device spapr-vscsi
@@ -254,7 +267,7 @@ specify_qemu_cpus () {
254 echo $2 267 echo $2
255 else 268 else
256 case "$1" in 269 case "$1" in
257 qemu-system-x86_64|qemu-system-i386) 270 qemu-system-x86_64|qemu-system-i386|qemu-system-aarch64)
258 echo $2 -smp $3 271 echo $2 -smp $3
259 ;; 272 ;;
260 qemu-system-ppc64) 273 qemu-system-ppc64)
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh
index 963f71289d22..8948f7926b21 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh
@@ -39,30 +39,31 @@ sed -e 's/us : / : /' |
39tr -d '\015' | 39tr -d '\015' |
40awk ' 40awk '
41$8 == "start" { 41$8 == "start" {
42 if (starttask != "") 42 if (startseq != "")
43 nlost++; 43 nlost++;
44 starttask = $1; 44 starttask = $1;
45 starttime = $3; 45 starttime = $3;
46 startseq = $7; 46 startseq = $7;
47 seqtask[startseq] = starttask;
47} 48}
48 49
49$8 == "end" { 50$8 == "end" {
50 if (starttask == $1 && startseq == $7) { 51 if (startseq == $7) {
51 curgpdur = $3 - starttime; 52 curgpdur = $3 - starttime;
52 gptimes[++n] = curgpdur; 53 gptimes[++n] = curgpdur;
53 gptaskcnt[starttask]++; 54 gptaskcnt[starttask]++;
54 sum += curgpdur; 55 sum += curgpdur;
55 if (curgpdur > 1000) 56 if (curgpdur > 1000)
56 print "Long GP " starttime "us to " $3 "us (" curgpdur "us)"; 57 print "Long GP " starttime "us to " $3 "us (" curgpdur "us)";
57 starttask = ""; 58 startseq = "";
58 } else { 59 } else {
59 # Lost a message or some such, reset. 60 # Lost a message or some such, reset.
60 starttask = ""; 61 startseq = "";
61 nlost++; 62 nlost++;
62 } 63 }
63} 64}
64 65
65$8 == "done" { 66$8 == "done" && seqtask[$7] != $1 {
66 piggybackcnt[$1]++; 67 piggybackcnt[$1]++;
67} 68}
68 69
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
index 1b78a12740e5..5f8fbb0d7c17 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
@@ -177,8 +177,8 @@ then
177 exit 0 177 exit 0
178fi 178fi
179echo "NOTE: $QEMU either did not run or was interactive" > $resdir/console.log 179echo "NOTE: $QEMU either did not run or was interactive" > $resdir/console.log
180echo $QEMU $qemu_args -m 512 -kernel $KERNEL -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd 180echo $QEMU $qemu_args -m $TORTURE_QEMU_MEM -kernel $KERNEL -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd
181( $QEMU $qemu_args -m 512 -kernel $KERNEL -append "$qemu_append $boot_args"& echo $! > $resdir/qemu_pid; wait `cat $resdir/qemu_pid`; echo $? > $resdir/qemu-retval ) & 181( $QEMU $qemu_args -m $TORTURE_QEMU_MEM -kernel $KERNEL -append "$qemu_append $boot_args"& echo $! > $resdir/qemu_pid; wait `cat $resdir/qemu_pid`; echo $? > $resdir/qemu-retval ) &
182commandcompleted=0 182commandcompleted=0
183sleep 10 # Give qemu's pid a chance to reach the file 183sleep 10 # Give qemu's pid a chance to reach the file
184if test -s "$resdir/qemu_pid" 184if test -s "$resdir/qemu_pid"
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh
index 7d1f607f0f76..56610dbbdf73 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm.sh
@@ -1,10 +1,8 @@
1#!/bin/bash 1#!/bin/bash
2# 2#
3# Run a series of 14 tests under KVM. These are not particularly 3# Run a series of tests under KVM. By default, this series is specified
4# well-selected or well-tuned, but are the current set. 4# by the relevant CFLIST file, but can be overridden by the --configs
5# 5# command-line argument.
6# Edit the definitions below to set the locations of the various directories,
7# as well as the test duration.
8# 6#
9# Usage: kvm.sh [ options ] 7# Usage: kvm.sh [ options ]
10# 8#
@@ -44,6 +42,7 @@ TORTURE_BOOT_IMAGE=""
44TORTURE_INITRD="$KVM/initrd"; export TORTURE_INITRD 42TORTURE_INITRD="$KVM/initrd"; export TORTURE_INITRD
45TORTURE_KCONFIG_ARG="" 43TORTURE_KCONFIG_ARG=""
46TORTURE_KMAKE_ARG="" 44TORTURE_KMAKE_ARG=""
45TORTURE_QEMU_MEM=512
47TORTURE_SHUTDOWN_GRACE=180 46TORTURE_SHUTDOWN_GRACE=180
48TORTURE_SUITE=rcu 47TORTURE_SUITE=rcu
49resdir="" 48resdir=""
@@ -70,6 +69,7 @@ usage () {
70 echo " --kconfig Kconfig-options" 69 echo " --kconfig Kconfig-options"
71 echo " --kmake-arg kernel-make-arguments" 70 echo " --kmake-arg kernel-make-arguments"
72 echo " --mac nn:nn:nn:nn:nn:nn" 71 echo " --mac nn:nn:nn:nn:nn:nn"
72 echo " --memory megabytes | nnnG"
73 echo " --no-initrd" 73 echo " --no-initrd"
74 echo " --qemu-args qemu-arguments" 74 echo " --qemu-args qemu-arguments"
75 echo " --qemu-cmd qemu-system-..." 75 echo " --qemu-cmd qemu-system-..."
@@ -147,6 +147,11 @@ do
147 TORTURE_QEMU_MAC=$2 147 TORTURE_QEMU_MAC=$2
148 shift 148 shift
149 ;; 149 ;;
150 --memory)
151 checkarg --memory "(memory size)" $# "$2" '^[0-9]\+[MG]\?$' error
152 TORTURE_QEMU_MEM=$2
153 shift
154 ;;
150 --no-initrd) 155 --no-initrd)
151 TORTURE_INITRD=""; export TORTURE_INITRD 156 TORTURE_INITRD=""; export TORTURE_INITRD
152 ;; 157 ;;
@@ -174,6 +179,12 @@ do
174 checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\|rcuperf\)$' '^--' 179 checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\|rcuperf\)$' '^--'
175 TORTURE_SUITE=$2 180 TORTURE_SUITE=$2
176 shift 181 shift
182 if test "$TORTURE_SUITE" = rcuperf
183 then
184 # If you really want jitter for rcuperf, specify
185 # it after specifying rcuperf. (But why?)
186 jitter=0
187 fi
177 ;; 188 ;;
178 *) 189 *)
179 echo Unknown argument $1 190 echo Unknown argument $1
@@ -288,6 +299,7 @@ TORTURE_KMAKE_ARG="$TORTURE_KMAKE_ARG"; export TORTURE_KMAKE_ARG
288TORTURE_QEMU_CMD="$TORTURE_QEMU_CMD"; export TORTURE_QEMU_CMD 299TORTURE_QEMU_CMD="$TORTURE_QEMU_CMD"; export TORTURE_QEMU_CMD
289TORTURE_QEMU_INTERACTIVE="$TORTURE_QEMU_INTERACTIVE"; export TORTURE_QEMU_INTERACTIVE 300TORTURE_QEMU_INTERACTIVE="$TORTURE_QEMU_INTERACTIVE"; export TORTURE_QEMU_INTERACTIVE
290TORTURE_QEMU_MAC="$TORTURE_QEMU_MAC"; export TORTURE_QEMU_MAC 301TORTURE_QEMU_MAC="$TORTURE_QEMU_MAC"; export TORTURE_QEMU_MAC
302TORTURE_QEMU_MEM="$TORTURE_QEMU_MEM"; export TORTURE_QEMU_MEM
291TORTURE_SHUTDOWN_GRACE="$TORTURE_SHUTDOWN_GRACE"; export TORTURE_SHUTDOWN_GRACE 303TORTURE_SHUTDOWN_GRACE="$TORTURE_SHUTDOWN_GRACE"; export TORTURE_SHUTDOWN_GRACE
292TORTURE_SUITE="$TORTURE_SUITE"; export TORTURE_SUITE 304TORTURE_SUITE="$TORTURE_SUITE"; export TORTURE_SUITE
293if ! test -e $resdir 305if ! test -e $resdir
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TASKS03 b/tools/testing/selftests/rcutorture/configs/rcu/TASKS03
index c70c51d5ded1..28568b72a31b 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TASKS03
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TASKS03
@@ -9,5 +9,4 @@ CONFIG_PREEMPT=y
9CONFIG_HZ_PERIODIC=n 9CONFIG_HZ_PERIODIC=n
10CONFIG_NO_HZ_IDLE=n 10CONFIG_NO_HZ_IDLE=n
11CONFIG_NO_HZ_FULL=y 11CONFIG_NO_HZ_FULL=y
12CONFIG_NO_HZ_FULL_ALL=y
13#CHECK#CONFIG_RCU_EXPERT=n 12#CHECK#CONFIG_RCU_EXPERT=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot b/tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot
index cd2a188eeb6d..838297c58318 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot
@@ -1 +1 @@
rcutorture.torture_type=tasks rcutorture.torture_type=tasks nohz_full=1
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04 b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
index 27d22695d64c..24c9f6012e35 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE04
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
@@ -7,7 +7,6 @@ CONFIG_PREEMPT=n
7CONFIG_HZ_PERIODIC=n 7CONFIG_HZ_PERIODIC=n
8CONFIG_NO_HZ_IDLE=n 8CONFIG_NO_HZ_IDLE=n
9CONFIG_NO_HZ_FULL=y 9CONFIG_NO_HZ_FULL=y
10CONFIG_NO_HZ_FULL_ALL=y
11CONFIG_RCU_FAST_NO_HZ=y 10CONFIG_RCU_FAST_NO_HZ=y
12CONFIG_RCU_TRACE=y 11CONFIG_RCU_TRACE=y
13CONFIG_HOTPLUG_CPU=n 12CONFIG_HOTPLUG_CPU=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot
index e34c33430447..e6071bb96c7d 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot
@@ -1 +1 @@
rcutorture.torture_type=rcu_bh rcutree.rcu_fanout_leaf=4 rcutorture.torture_type=rcu_bh rcutree.rcu_fanout_leaf=4 nohz_full=1-7
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE07 b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
index 0f4759f4232e..d7afb271a586 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE07
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
@@ -7,7 +7,6 @@ CONFIG_PREEMPT=n
7CONFIG_HZ_PERIODIC=n 7CONFIG_HZ_PERIODIC=n
8CONFIG_NO_HZ_IDLE=n 8CONFIG_NO_HZ_IDLE=n
9CONFIG_NO_HZ_FULL=y 9CONFIG_NO_HZ_FULL=y
10CONFIG_NO_HZ_FULL_ALL=n
11CONFIG_RCU_FAST_NO_HZ=n 10CONFIG_RCU_FAST_NO_HZ=n
12CONFIG_RCU_TRACE=y 11CONFIG_RCU_TRACE=y
13CONFIG_HOTPLUG_CPU=y 12CONFIG_HOTPLUG_CPU=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh
index b9603115d7c7..d36b8fd6f0fc 100644
--- a/tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh
+++ b/tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh
@@ -20,32 +20,10 @@
20# 20#
21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
22 22
23# rcuperf_param_nreaders bootparam-string
24#
25# Adds nreaders rcuperf module parameter if not already specified.
26rcuperf_param_nreaders () {
27 if ! echo "$1" | grep -q "rcuperf.nreaders"
28 then
29 echo rcuperf.nreaders=-1
30 fi
31}
32
33# rcuperf_param_nwriters bootparam-string
34#
35# Adds nwriters rcuperf module parameter if not already specified.
36rcuperf_param_nwriters () {
37 if ! echo "$1" | grep -q "rcuperf.nwriters"
38 then
39 echo rcuperf.nwriters=-1
40 fi
41}
42
43# per_version_boot_params bootparam-string config-file seconds 23# per_version_boot_params bootparam-string config-file seconds
44# 24#
45# Adds per-version torture-module parameters to kernels supporting them. 25# Adds per-version torture-module parameters to kernels supporting them.
46per_version_boot_params () { 26per_version_boot_params () {
47 echo $1 `rcuperf_param_nreaders "$1"` \ 27 echo $1 rcuperf.shutdown=1 \
48 `rcuperf_param_nwriters "$1"` \
49 rcuperf.shutdown=1 \
50 rcuperf.verbose=1 28 rcuperf.verbose=1
51} 29}
diff --git a/tools/testing/selftests/rcutorture/doc/rcu-test-image.txt b/tools/testing/selftests/rcutorture/doc/rcu-test-image.txt
index 66efb59a1bd1..449cf579d6f9 100644
--- a/tools/testing/selftests/rcutorture/doc/rcu-test-image.txt
+++ b/tools/testing/selftests/rcutorture/doc/rcu-test-image.txt
@@ -1,4 +1,4 @@
1This document describes one way to created the rcu-test-image file 1This document describes one way to create the rcu-test-image file
2that contains the filesystem used by the guest-OS kernel. There are 2that contains the filesystem used by the guest-OS kernel. There are
3probably much better ways of doing this, and this filesystem could no 3probably much better ways of doing this, and this filesystem could no
4doubt be smaller. It is probably also possible to simply download 4doubt be smaller. It is probably also possible to simply download
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 0b457e8e0f0c..5df609950a66 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -141,6 +141,15 @@ struct seccomp_data {
141#define SECCOMP_FILTER_FLAG_LOG 2 141#define SECCOMP_FILTER_FLAG_LOG 2
142#endif 142#endif
143 143
144#ifndef PTRACE_SECCOMP_GET_METADATA
145#define PTRACE_SECCOMP_GET_METADATA 0x420d
146
147struct seccomp_metadata {
148 __u64 filter_off; /* Input: which filter */
149 __u64 flags; /* Output: filter's flags */
150};
151#endif
152
144#ifndef seccomp 153#ifndef seccomp
145int seccomp(unsigned int op, unsigned int flags, void *args) 154int seccomp(unsigned int op, unsigned int flags, void *args)
146{ 155{
@@ -2845,6 +2854,58 @@ TEST(get_action_avail)
2845 EXPECT_EQ(errno, EOPNOTSUPP); 2854 EXPECT_EQ(errno, EOPNOTSUPP);
2846} 2855}
2847 2856
2857TEST(get_metadata)
2858{
2859 pid_t pid;
2860 int pipefd[2];
2861 char buf;
2862 struct seccomp_metadata md;
2863
2864 ASSERT_EQ(0, pipe(pipefd));
2865
2866 pid = fork();
2867 ASSERT_GE(pid, 0);
2868 if (pid == 0) {
2869 struct sock_filter filter[] = {
2870 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2871 };
2872 struct sock_fprog prog = {
2873 .len = (unsigned short)ARRAY_SIZE(filter),
2874 .filter = filter,
2875 };
2876
2877 /* one with log, one without */
2878 ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER,
2879 SECCOMP_FILTER_FLAG_LOG, &prog));
2880 ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog));
2881
2882 ASSERT_EQ(0, close(pipefd[0]));
2883 ASSERT_EQ(1, write(pipefd[1], "1", 1));
2884 ASSERT_EQ(0, close(pipefd[1]));
2885
2886 while (1)
2887 sleep(100);
2888 }
2889
2890 ASSERT_EQ(0, close(pipefd[1]));
2891 ASSERT_EQ(1, read(pipefd[0], &buf, 1));
2892
2893 ASSERT_EQ(0, ptrace(PTRACE_ATTACH, pid));
2894 ASSERT_EQ(pid, waitpid(pid, NULL, 0));
2895
2896 md.filter_off = 0;
2897 ASSERT_EQ(sizeof(md), ptrace(PTRACE_SECCOMP_GET_METADATA, pid, sizeof(md), &md));
2898 EXPECT_EQ(md.flags, SECCOMP_FILTER_FLAG_LOG);
2899 EXPECT_EQ(md.filter_off, 0);
2900
2901 md.filter_off = 1;
2902 ASSERT_EQ(sizeof(md), ptrace(PTRACE_SECCOMP_GET_METADATA, pid, sizeof(md), &md));
2903 EXPECT_EQ(md.flags, 0);
2904 EXPECT_EQ(md.filter_off, 1);
2905
2906 ASSERT_EQ(0, kill(pid, SIGKILL));
2907}
2908
2848/* 2909/*
2849 * TODO: 2910 * TODO:
2850 * - add microbenchmarks 2911 * - add microbenchmarks
diff --git a/tools/testing/selftests/sync/Makefile b/tools/testing/selftests/sync/Makefile
index b3c8ba3cb668..d0121a8a3523 100644
--- a/tools/testing/selftests/sync/Makefile
+++ b/tools/testing/selftests/sync/Makefile
@@ -30,7 +30,7 @@ $(TEST_CUSTOM_PROGS): $(TESTS) $(OBJS)
30 $(CC) -o $(TEST_CUSTOM_PROGS) $(OBJS) $(TESTS) $(CFLAGS) $(LDFLAGS) 30 $(CC) -o $(TEST_CUSTOM_PROGS) $(OBJS) $(TESTS) $(CFLAGS) $(LDFLAGS)
31 31
32$(OBJS): $(OUTPUT)/%.o: %.c 32$(OBJS): $(OUTPUT)/%.o: %.c
33 $(CC) -c $^ -o $@ 33 $(CC) -c $^ -o $@ $(CFLAGS)
34 34
35$(TESTS): $(OUTPUT)/%.o: %.c 35$(TESTS): $(OUTPUT)/%.o: %.c
36 $(CC) -c $^ -o $@ 36 $(CC) -c $^ -o $@
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json b/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json
index e34075059c26..90bba48c3f07 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json
@@ -315,7 +315,7 @@
315 "cmdUnderTest": "$TC actions ls action skbmod", 315 "cmdUnderTest": "$TC actions ls action skbmod",
316 "expExitCode": "0", 316 "expExitCode": "0",
317 "verifyCmd": "$TC actions get action skbmod index 4", 317 "verifyCmd": "$TC actions get action skbmod index 4",
318 "matchPattern": "action order [0-9]*: skbmod pipe set etype 0x0031", 318 "matchPattern": "action order [0-9]*: skbmod pipe set etype 0x31",
319 "matchCount": "1", 319 "matchCount": "1",
320 "teardown": [ 320 "teardown": [
321 "$TC actions flush action skbmod" 321 "$TC actions flush action skbmod"
diff --git a/tools/testing/selftests/vDSO/Makefile b/tools/testing/selftests/vDSO/Makefile
index 3d5a62ff7d31..f5d7a7851e21 100644
--- a/tools/testing/selftests/vDSO/Makefile
+++ b/tools/testing/selftests/vDSO/Makefile
@@ -1,4 +1,6 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2include ../lib.mk
3
2ifndef CROSS_COMPILE 4ifndef CROSS_COMPILE
3CFLAGS := -std=gnu99 5CFLAGS := -std=gnu99
4CFLAGS_vdso_standalone_test_x86 := -nostdlib -fno-asynchronous-unwind-tables -fno-stack-protector 6CFLAGS_vdso_standalone_test_x86 := -nostdlib -fno-asynchronous-unwind-tables -fno-stack-protector
@@ -6,16 +8,14 @@ ifeq ($(CONFIG_X86_32),y)
6LDLIBS += -lgcc_s 8LDLIBS += -lgcc_s
7endif 9endif
8 10
9TEST_PROGS := vdso_test vdso_standalone_test_x86 11TEST_PROGS := $(OUTPUT)/vdso_test $(OUTPUT)/vdso_standalone_test_x86
10 12
11all: $(TEST_PROGS) 13all: $(TEST_PROGS)
12vdso_test: parse_vdso.c vdso_test.c 14$(OUTPUT)/vdso_test: parse_vdso.c vdso_test.c
13vdso_standalone_test_x86: vdso_standalone_test_x86.c parse_vdso.c 15$(OUTPUT)/vdso_standalone_test_x86: vdso_standalone_test_x86.c parse_vdso.c
14 $(CC) $(CFLAGS) $(CFLAGS_vdso_standalone_test_x86) \ 16 $(CC) $(CFLAGS) $(CFLAGS_vdso_standalone_test_x86) \
15 vdso_standalone_test_x86.c parse_vdso.c \ 17 vdso_standalone_test_x86.c parse_vdso.c \
16 -o vdso_standalone_test_x86 18 -o $@
17 19
18include ../lib.mk 20EXTRA_CLEAN := $(TEST_PROGS)
19clean:
20 rm -fr $(TEST_PROGS)
21endif 21endif
diff --git a/tools/testing/selftests/vm/.gitignore b/tools/testing/selftests/vm/.gitignore
index 63c94d776e89..342c7bc9dc8c 100644
--- a/tools/testing/selftests/vm/.gitignore
+++ b/tools/testing/selftests/vm/.gitignore
@@ -11,3 +11,4 @@ mlock-intersect-test
11mlock-random-test 11mlock-random-test
12virtual_address_range 12virtual_address_range
13gup_benchmark 13gup_benchmark
14va_128TBswitch
diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests
index d2561895a021..22d564673830 100755
--- a/tools/testing/selftests/vm/run_vmtests
+++ b/tools/testing/selftests/vm/run_vmtests
@@ -2,25 +2,33 @@
2# SPDX-License-Identifier: GPL-2.0 2# SPDX-License-Identifier: GPL-2.0
3#please run as root 3#please run as root
4 4
5#we need 256M, below is the size in kB
6needmem=262144
7mnt=./huge 5mnt=./huge
8exitcode=0 6exitcode=0
9 7
10#get pagesize and freepages from /proc/meminfo 8#get huge pagesize and freepages from /proc/meminfo
11while read name size unit; do 9while read name size unit; do
12 if [ "$name" = "HugePages_Free:" ]; then 10 if [ "$name" = "HugePages_Free:" ]; then
13 freepgs=$size 11 freepgs=$size
14 fi 12 fi
15 if [ "$name" = "Hugepagesize:" ]; then 13 if [ "$name" = "Hugepagesize:" ]; then
16 pgsize=$size 14 hpgsize_KB=$size
17 fi 15 fi
18done < /proc/meminfo 16done < /proc/meminfo
19 17
18# Simple hugetlbfs tests have a hardcoded minimum requirement of
19# huge pages totaling 256MB (262144KB) in size. The userfaultfd
20# hugetlb test requires a minimum of 2 * nr_cpus huge pages. Take
21# both of these requirements into account and attempt to increase
22# number of huge pages available.
23nr_cpus=$(nproc)
24hpgsize_MB=$((hpgsize_KB / 1024))
25half_ufd_size_MB=$((((nr_cpus * hpgsize_MB + 127) / 128) * 128))
26needmem_KB=$((half_ufd_size_MB * 2 * 1024))
27
20#set proper nr_hugepages 28#set proper nr_hugepages
21if [ -n "$freepgs" ] && [ -n "$pgsize" ]; then 29if [ -n "$freepgs" ] && [ -n "$hpgsize_KB" ]; then
22 nr_hugepgs=`cat /proc/sys/vm/nr_hugepages` 30 nr_hugepgs=`cat /proc/sys/vm/nr_hugepages`
23 needpgs=`expr $needmem / $pgsize` 31 needpgs=$((needmem_KB / hpgsize_KB))
24 tries=2 32 tries=2
25 while [ $tries -gt 0 ] && [ $freepgs -lt $needpgs ]; do 33 while [ $tries -gt 0 ] && [ $freepgs -lt $needpgs ]; do
26 lackpgs=$(( $needpgs - $freepgs )) 34 lackpgs=$(( $needpgs - $freepgs ))
@@ -107,8 +115,9 @@ fi
107echo "---------------------------" 115echo "---------------------------"
108echo "running userfaultfd_hugetlb" 116echo "running userfaultfd_hugetlb"
109echo "---------------------------" 117echo "---------------------------"
110# 256MB total huge pages == 128MB src and 128MB dst 118# Test requires source and destination huge pages. Size of source
111./userfaultfd hugetlb 128 32 $mnt/ufd_test_file 119# (half_ufd_size_MB) is passed as argument to test.
120./userfaultfd hugetlb $half_ufd_size_MB 32 $mnt/ufd_test_file
112if [ $? -ne 0 ]; then 121if [ $? -ne 0 ]; then
113 echo "[FAIL]" 122 echo "[FAIL]"
114 exitcode=1 123 exitcode=1
diff --git a/tools/usb/Makefile b/tools/usb/Makefile
index 4e6506078494..01d758d73b6d 100644
--- a/tools/usb/Makefile
+++ b/tools/usb/Makefile
@@ -1,7 +1,6 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2# Makefile for USB tools 2# Makefile for USB tools
3 3
4CC = $(CROSS_COMPILE)gcc
5PTHREAD_LIBS = -lpthread 4PTHREAD_LIBS = -lpthread
6WARNINGS = -Wall -Wextra 5WARNINGS = -Wall -Wextra
7CFLAGS = $(WARNINGS) -g -I../include 6CFLAGS = $(WARNINGS) -g -I../include
diff --git a/tools/vm/Makefile b/tools/vm/Makefile
index be320b905ea7..20f6cf04377f 100644
--- a/tools/vm/Makefile
+++ b/tools/vm/Makefile
@@ -6,7 +6,6 @@ TARGETS=page-types slabinfo page_owner_sort
6LIB_DIR = ../lib/api 6LIB_DIR = ../lib/api
7LIBS = $(LIB_DIR)/libapi.a 7LIBS = $(LIB_DIR)/libapi.a
8 8
9CC = $(CROSS_COMPILE)gcc
10CFLAGS = -Wall -Wextra -I../lib/ 9CFLAGS = -Wall -Wextra -I../lib/
11LDFLAGS = $(LIBS) 10LDFLAGS = $(LIBS)
12 11
diff --git a/tools/wmi/Makefile b/tools/wmi/Makefile
index e664f1167388..e0e87239126b 100644
--- a/tools/wmi/Makefile
+++ b/tools/wmi/Makefile
@@ -2,7 +2,6 @@ PREFIX ?= /usr
2SBINDIR ?= sbin 2SBINDIR ?= sbin
3INSTALL ?= install 3INSTALL ?= install
4CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include 4CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include
5CC = $(CROSS_COMPILE)gcc
6 5
7TARGET = dell-smbios-example 6TARGET = dell-smbios-example
8 7