aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2017-05-03 13:28:27 -0400
committerIngo Molnar <mingo@kernel.org>2017-05-03 13:28:27 -0400
commit12c1c2fd780a9a5581105fcb6f251466cf35af2a (patch)
treece613b7dfdb64d93a26765cdcf20b0f5deab9ef7
parent33b88e708e7dfa58dc896da2a98f5719d2eb315c (diff)
parent4341ec6b3db4c3e903d6c44958722918baec1e59 (diff)
Merge tag 'perf-core-for-mingo-4.12-20170503' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: Fixes: - Support setting probes in versioned user space symbols, such as pthread_create@@GLIBC_2.1, picking the default one, more work needed to make it possible to set it on the other versions, as the 'perf probe' syntax already uses @ for other purposes. (Paul Clarke) - Do not special case address zero as an error for routines that return addresses (symbol lookup), instead use the return as the success/error indication and pass a pointer to return the address, fixing 'perf test vmlinux' (the one that compares address between vmlinux and kallsyms) on s/390, where the '_text' address is equal to zero (Arnaldo Carvalho de Melo) Infrastructure changes: - More header sanitization, moving stuff out of util.h into more appropriate headers and objects and sometimes creating new ones (Arnaldo Carvalho de Melo) - Refactor a duplicated code for obtaining config file name (Taeung Song) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--Documentation/trace/kprobetrace.txt5
-rw-r--r--arch/um/include/shared/os.h4
-rw-r--r--arch/x86/entry/syscalls/syscall_32.tbl1
-rw-r--r--arch/x86/events/amd/iommu.c325
-rw-r--r--arch/x86/events/amd/iommu.h18
-rw-r--r--arch/x86/events/amd/uncore.c77
-rw-r--r--arch/x86/events/intel/bts.c16
-rw-r--r--arch/x86/events/intel/core.c24
-rw-r--r--arch/x86/events/intel/ds.c2
-rw-r--r--arch/x86/events/intel/pt.c129
-rw-r--r--arch/x86/events/intel/pt.h2
-rw-r--r--arch/x86/events/perf_event.h1
-rw-r--r--arch/x86/include/asm/cpufeatures.h1
-rw-r--r--arch/x86/include/asm/kprobes.h7
-rw-r--r--arch/x86/include/asm/msr-index.h11
-rw-r--r--arch/x86/include/asm/processor.h2
-rw-r--r--arch/x86/include/asm/proto.h4
-rw-r--r--arch/x86/include/asm/thread_info.h6
-rw-r--r--arch/x86/include/asm/tlbflush.h10
-rw-r--r--arch/x86/include/uapi/asm/prctl.h11
-rw-r--r--arch/x86/kernel/cpu/intel.c40
-rw-r--r--arch/x86/kernel/kprobes/common.h4
-rw-r--r--arch/x86/kernel/kprobes/core.c149
-rw-r--r--arch/x86/kernel/kprobes/ftrace.c2
-rw-r--r--arch/x86/kernel/kprobes/opt.c13
-rw-r--r--arch/x86/kernel/process.c151
-rw-r--r--arch/x86/kernel/process_32.c7
-rw-r--r--arch/x86/kernel/process_64.c48
-rw-r--r--arch/x86/kernel/ptrace.c8
-rw-r--r--arch/x86/um/Makefile2
-rw-r--r--arch/x86/um/asm/ptrace.h2
-rw-r--r--arch/x86/um/os-Linux/prctl.c4
-rw-r--r--arch/x86/um/syscalls_32.c7
-rw-r--r--arch/x86/um/syscalls_64.c20
-rw-r--r--drivers/hwtracing/coresight/coresight-etb10.c9
-rw-r--r--drivers/hwtracing/coresight/coresight-etm-perf.c9
-rw-r--r--drivers/hwtracing/coresight/coresight-priv.h2
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc-etf.c7
-rw-r--r--drivers/iommu/amd_iommu.c6
-rw-r--r--drivers/iommu/amd_iommu_init.c101
-rw-r--r--drivers/iommu/amd_iommu_proto.h8
-rw-r--r--drivers/iommu/amd_iommu_types.h3
-rw-r--r--fs/exec.c1
-rw-r--r--include/linux/compat.h2
-rw-r--r--include/linux/coresight.h2
-rw-r--r--include/linux/kprobes.h2
-rw-r--r--include/linux/perf_event.h17
-rw-r--r--include/linux/thread_info.h4
-rw-r--r--include/uapi/linux/perf_event.h33
-rw-r--r--kernel/events/core.c139
-rw-r--r--kernel/events/ring_buffer.c34
-rw-r--r--kernel/fork.c2
-rw-r--r--kernel/kprobes.c46
-rw-r--r--kernel/nsproxy.c3
-rw-r--r--kernel/trace/Kconfig2
-rw-r--r--kernel/trace/trace.c1
-rw-r--r--kernel/trace/trace_kprobe.c9
-rw-r--r--tools/arch/arm/include/uapi/asm/kvm.h13
-rw-r--r--tools/arch/arm64/include/uapi/asm/kvm.h13
-rw-r--r--tools/arch/powerpc/include/uapi/asm/kvm.h22
-rw-r--r--tools/arch/x86/include/asm/atomic.h7
-rw-r--r--tools/arch/x86/include/asm/cmpxchg.h89
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h9
-rw-r--r--tools/arch/x86/lib/memcpy_64.S2
-rw-r--r--tools/build/Makefile.feature1
-rw-r--r--tools/build/feature/Makefile18
-rw-r--r--tools/build/feature/test-all.c5
-rw-r--r--tools/build/feature/test-sched_getcpu.c7
-rw-r--r--tools/include/asm-generic/atomic-gcc.h8
-rw-r--r--tools/include/linux/atomic.h6
-rw-r--r--tools/include/linux/bug.h10
-rw-r--r--tools/include/linux/compiler-gcc.h7
-rw-r--r--tools/include/linux/compiler.h9
-rw-r--r--tools/include/linux/hashtable.h4
-rw-r--r--tools/include/linux/kernel.h7
-rw-r--r--tools/include/linux/log2.h3
-rw-r--r--tools/include/linux/refcount.h151
-rw-r--r--tools/include/linux/string.h2
-rw-r--r--tools/include/linux/types.h1
-rw-r--r--tools/include/uapi/linux/fcntl.h72
-rw-r--r--tools/include/uapi/linux/perf_event.h33
-rw-r--r--tools/include/uapi/linux/stat.h177
-rw-r--r--tools/lib/api/fs/fs.c29
-rw-r--r--tools/lib/api/fs/fs.h1
-rw-r--r--tools/lib/string.c9
-rw-r--r--tools/lib/subcmd/help.c1
-rw-r--r--tools/lib/subcmd/help.h1
-rw-r--r--tools/lib/subcmd/parse-options.c1
-rw-r--r--tools/lib/subcmd/subcmd-util.h9
-rw-r--r--tools/lib/symbol/kallsyms.c1
-rw-r--r--tools/objtool/builtin-check.c3
-rw-r--r--tools/objtool/objtool.c3
-rw-r--r--tools/perf/.gitignore2
-rw-r--r--tools/perf/Build1
-rw-r--r--tools/perf/Documentation/perf-ftrace.txt18
-rw-r--r--tools/perf/Documentation/perf-list.txt8
-rw-r--r--tools/perf/Documentation/perf-record.txt3
-rw-r--r--tools/perf/Documentation/perf-report.txt13
-rw-r--r--tools/perf/Documentation/perf-sched.txt4
-rw-r--r--tools/perf/Documentation/perf-script.txt16
-rw-r--r--tools/perf/Documentation/perf-stat.txt6
-rw-r--r--tools/perf/Documentation/perf-trace.txt3
-rw-r--r--tools/perf/Documentation/perf.data-file-format.txt19
-rw-r--r--tools/perf/MANIFEST5
-rw-r--r--tools/perf/Makefile.config39
-rw-r--r--tools/perf/arch/arm/util/cs-etm.c1
-rw-r--r--tools/perf/arch/arm/util/dwarf-regs.c4
-rw-r--r--tools/perf/arch/arm/util/unwind-libdw.c1
-rw-r--r--tools/perf/arch/arm64/util/dwarf-regs.c5
-rw-r--r--tools/perf/arch/arm64/util/unwind-libunwind.c2
-rw-r--r--tools/perf/arch/common.c2
-rw-r--r--tools/perf/arch/powerpc/util/dwarf-regs.c5
-rw-r--r--tools/perf/arch/powerpc/util/kvm-stat.c1
-rw-r--r--tools/perf/arch/powerpc/util/perf_regs.c112
-rw-r--r--tools/perf/arch/powerpc/util/sym-handling.c26
-rw-r--r--tools/perf/arch/s390/annotate/instructions.c30
-rw-r--r--tools/perf/arch/s390/util/kvm-stat.c1
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_64.tbl1
-rw-r--r--tools/perf/arch/x86/tests/intel-cqm.c3
-rw-r--r--tools/perf/arch/x86/tests/perf-time-to-tsc.c2
-rw-r--r--tools/perf/arch/x86/util/auxtrace.c1
-rw-r--r--tools/perf/arch/x86/util/intel-bts.c1
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c1
-rw-r--r--tools/perf/arch/x86/util/kvm-stat.c1
-rw-r--r--tools/perf/arch/x86/util/perf_regs.c227
-rw-r--r--tools/perf/arch/x86/util/unwind-libdw.c1
-rw-r--r--tools/perf/bench/bench.h20
-rw-r--r--tools/perf/bench/futex-hash.c4
-rw-r--r--tools/perf/bench/futex-lock-pi.c4
-rw-r--r--tools/perf/bench/futex-requeue.c4
-rw-r--r--tools/perf/bench/futex-wake-parallel.c4
-rw-r--r--tools/perf/bench/futex-wake.c4
-rw-r--r--tools/perf/bench/futex.h10
-rw-r--r--tools/perf/bench/mem-functions.c5
-rw-r--r--tools/perf/bench/numa.c7
-rw-r--r--tools/perf/bench/sched-messaging.c3
-rw-r--r--tools/perf/bench/sched-pipe.c2
-rw-r--r--tools/perf/builtin-annotate.c6
-rw-r--r--tools/perf/builtin-bench.c12
-rw-r--r--tools/perf/builtin-buildid-cache.c18
-rw-r--r--tools/perf/builtin-buildid-list.c4
-rw-r--r--tools/perf/builtin-c2c.c13
-rw-r--r--tools/perf/builtin-config.c21
-rw-r--r--tools/perf/builtin-data.c9
-rw-r--r--tools/perf/builtin-diff.c5
-rw-r--r--tools/perf/builtin-evlist.c2
-rw-r--r--tools/perf/builtin-ftrace.c157
-rw-r--r--tools/perf/builtin-help.c25
-rw-r--r--tools/perf/builtin-inject.c20
-rw-r--r--tools/perf/builtin-kallsyms.c3
-rw-r--r--tools/perf/builtin-kmem.c10
-rw-r--r--tools/perf/builtin-kvm.c39
-rw-r--r--tools/perf/builtin-list.c16
-rw-r--r--tools/perf/builtin-lock.c32
-rw-r--r--tools/perf/builtin-mem.c12
-rw-r--r--tools/perf/builtin-probe.c12
-rw-r--r--tools/perf/builtin-record.c44
-rw-r--r--tools/perf/builtin-report.c17
-rw-r--r--tools/perf/builtin-sched.c37
-rw-r--r--tools/perf/builtin-script.c326
-rw-r--r--tools/perf/builtin-stat.c224
-rw-r--r--tools/perf/builtin-timechart.c28
-rw-r--r--tools/perf/builtin-top.c8
-rw-r--r--tools/perf/builtin-trace.c96
-rw-r--r--tools/perf/builtin-version.c6
-rw-r--r--tools/perf/builtin.h62
-rwxr-xr-xtools/perf/check-headers.sh2
-rw-r--r--tools/perf/command-list.txt1
-rw-r--r--tools/perf/perf.c130
-rw-r--r--tools/perf/perf.h1
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwell/uncore.json278
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellde/uncore-cache.json28
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellde/uncore-memory.json29
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellde/uncore-power.json26
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/uncore-cache.json28
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/uncore-interconnect.json6
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/uncore-memory.json21
-rw-r--r--tools/perf/pmu-events/arch/x86/broadwellx/uncore-power.json26
-rw-r--r--tools/perf/pmu-events/arch/x86/haswell/uncore.json374
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/uncore-cache.json28
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/uncore-interconnect.json6
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/uncore-memory.json21
-rw-r--r--tools/perf/pmu-events/arch/x86/haswellx/uncore-power.json26
-rw-r--r--tools/perf/pmu-events/arch/x86/ivybridge/uncore.json314
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/uncore-cache.json22
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/uncore-interconnect.json12
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/uncore-memory.json19
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json53
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/uncore-cache.json13
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/uncore-interconnect.json12
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/uncore-memory.json21
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json53
-rw-r--r--tools/perf/pmu-events/arch/x86/mapfile.csv1
-rw-r--r--tools/perf/pmu-events/arch/x86/sandybridge/uncore.json314
-rw-r--r--tools/perf/pmu-events/arch/x86/skylake/uncore.json254
-rw-r--r--tools/perf/pmu-events/jevents.c28
-rw-r--r--tools/perf/pmu-events/jevents.h3
-rw-r--r--tools/perf/pmu-events/pmu-events.h2
-rw-r--r--tools/perf/tests/Build1
-rw-r--r--tools/perf/tests/attr.c6
-rw-r--r--tools/perf/tests/backward-ring-buffer.c1
-rw-r--r--tools/perf/tests/bpf.c4
-rw-r--r--tools/perf/tests/builtin-test.c9
-rw-r--r--tools/perf/tests/clang.c1
-rw-r--r--tools/perf/tests/code-reading.c7
-rw-r--r--tools/perf/tests/cpumap.c2
-rw-r--r--tools/perf/tests/dso-data.c2
-rw-r--r--tools/perf/tests/dwarf-unwind.c1
-rw-r--r--tools/perf/tests/event-times.c3
-rw-r--r--tools/perf/tests/evsel-roundtrip-name.c2
-rw-r--r--tools/perf/tests/expr.c56
-rw-r--r--tools/perf/tests/hists_common.c2
-rw-r--r--tools/perf/tests/hists_cumulate.c2
-rw-r--r--tools/perf/tests/hists_filter.c2
-rw-r--r--tools/perf/tests/hists_link.c2
-rw-r--r--tools/perf/tests/hists_output.c2
-rw-r--r--tools/perf/tests/is_printable_array.c3
-rw-r--r--tools/perf/tests/mmap-basic.c3
-rw-r--r--tools/perf/tests/mmap-thread-lookup.c2
-rw-r--r--tools/perf/tests/openat-syscall-all-cpus.c6
-rw-r--r--tools/perf/tests/openat-syscall-tp-fields.c1
-rw-r--r--tools/perf/tests/openat-syscall.c5
-rw-r--r--tools/perf/tests/parse-events.c8
-rw-r--r--tools/perf/tests/parse-no-sample-id-all.c1
-rw-r--r--tools/perf/tests/perf-record.c2
-rw-r--r--tools/perf/tests/pmu.c2
-rw-r--r--tools/perf/tests/sample-parsing.c2
-rw-r--r--tools/perf/tests/sdt.c4
-rw-r--r--tools/perf/tests/sw-clock.c2
-rw-r--r--tools/perf/tests/switch-tracking.c1
-rw-r--r--tools/perf/tests/task-exit.c1
-rw-r--r--tools/perf/tests/tests.h1
-rw-r--r--tools/perf/tests/thread-map.c6
-rw-r--r--tools/perf/tests/thread-mg-share.c12
-rw-r--r--tools/perf/tests/unit_number__scnprintf.c3
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c1
-rw-r--r--tools/perf/trace/beauty/Build1
-rw-r--r--tools/perf/trace/beauty/beauty.h24
-rw-r--r--tools/perf/trace/beauty/signum.c1
-rw-r--r--tools/perf/trace/beauty/statx.c72
-rw-r--r--tools/perf/ui/browser.c4
-rw-r--r--tools/perf/ui/browsers/annotate.c3
-rw-r--r--tools/perf/ui/browsers/header.c2
-rw-r--r--tools/perf/ui/browsers/hists.c193
-rw-r--r--tools/perf/ui/browsers/map.c2
-rw-r--r--tools/perf/ui/gtk/annotate.c3
-rw-r--r--tools/perf/ui/gtk/hists.c2
-rw-r--r--tools/perf/ui/hist.c1
-rw-r--r--tools/perf/ui/setup.c4
-rw-r--r--tools/perf/ui/stdio/hist.c91
-rw-r--r--tools/perf/ui/tui/setup.c1
-rw-r--r--tools/perf/util/Build12
-rw-r--r--tools/perf/util/alias.c78
-rw-r--r--tools/perf/util/annotate.c89
-rw-r--r--tools/perf/util/annotate.h2
-rw-r--r--tools/perf/util/auxtrace.c10
-rw-r--r--tools/perf/util/auxtrace.h1
-rw-r--r--tools/perf/util/bpf-loader.c3
-rw-r--r--tools/perf/util/bpf-loader.h2
-rw-r--r--tools/perf/util/bpf-prologue.c1
-rw-r--r--tools/perf/util/bpf-prologue.h2
-rw-r--r--tools/perf/util/build-id.c20
-rw-r--r--tools/perf/util/build-id.h8
-rw-r--r--tools/perf/util/c++/clang-c.h1
-rw-r--r--tools/perf/util/cache.h1
-rw-r--r--tools/perf/util/callchain.c271
-rw-r--r--tools/perf/util/callchain.h3
-rw-r--r--tools/perf/util/cgroup.c11
-rw-r--r--tools/perf/util/cgroup.h4
-rw-r--r--tools/perf/util/cloexec.c1
-rw-r--r--tools/perf/util/cloexec.h6
-rw-r--r--tools/perf/util/color.h2
-rw-r--r--tools/perf/util/comm.c17
-rw-r--r--tools/perf/util/compress.h12
-rw-r--r--tools/perf/util/config.c61
-rw-r--r--tools/perf/util/counts.c2
-rw-r--r--tools/perf/util/cpumap.c65
-rw-r--r--tools/perf/util/cpumap.h5
-rw-r--r--tools/perf/util/ctype.c2
-rw-r--r--tools/perf/util/data-convert-bt.c5
-rw-r--r--tools/perf/util/data.c1
-rw-r--r--tools/perf/util/debug.c37
-rw-r--r--tools/perf/util/debug.h3
-rw-r--r--tools/perf/util/demangle-java.c2
-rw-r--r--tools/perf/util/drv_configs.c1
-rw-r--r--tools/perf/util/dso.c14
-rw-r--r--tools/perf/util/dso.h4
-rw-r--r--tools/perf/util/dump-insn.c14
-rw-r--r--tools/perf/util/dump-insn.h22
-rw-r--r--tools/perf/util/dwarf-aux.c3
-rw-r--r--tools/perf/util/dwarf-regs.c1
-rw-r--r--tools/perf/util/env.c1
-rw-r--r--tools/perf/util/event.c189
-rw-r--r--tools/perf/util/event.h34
-rw-r--r--tools/perf/util/evlist.c36
-rw-r--r--tools/perf/util/evlist.h6
-rw-r--r--tools/perf/util/evsel.c25
-rw-r--r--tools/perf/util/evsel.h5
-rw-r--r--tools/perf/util/evsel_fprintf.c2
-rw-r--r--tools/perf/util/expr.h25
-rw-r--r--tools/perf/util/expr.y173
-rw-r--r--tools/perf/util/header.c21
-rw-r--r--tools/perf/util/help-unknown-cmd.c9
-rw-r--r--tools/perf/util/hist.c18
-rw-r--r--tools/perf/util/hist.h2
-rw-r--r--tools/perf/util/intel-bts.c2
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c26
-rw-r--r--tools/perf/util/intel-pt.c2
-rw-r--r--tools/perf/util/jitdump.c7
-rw-r--r--tools/perf/util/llvm-utils.c1
-rw-r--r--tools/perf/util/lzma.c2
-rw-r--r--tools/perf/util/machine.c75
-rw-r--r--tools/perf/util/machine.h3
-rw-r--r--tools/perf/util/map.c20
-rw-r--r--tools/perf/util/map.h15
-rw-r--r--tools/perf/util/mem-events.c3
-rw-r--r--tools/perf/util/memswap.c24
-rw-r--r--tools/perf/util/memswap.h7
-rw-r--r--tools/perf/util/namespaces.c37
-rw-r--r--tools/perf/util/namespaces.h26
-rw-r--r--tools/perf/util/ordered-events.c5
-rw-r--r--tools/perf/util/parse-events.c92
-rw-r--r--tools/perf/util/parse-events.h30
-rw-r--r--tools/perf/util/parse-events.y73
-rw-r--r--tools/perf/util/path.c28
-rw-r--r--tools/perf/util/path.h9
-rw-r--r--tools/perf/util/perf-hooks.c1
-rw-r--r--tools/perf/util/perf_regs.c6
-rw-r--r--tools/perf/util/perf_regs.h7
-rw-r--r--tools/perf/util/pmu.c38
-rw-r--r--tools/perf/util/pmu.h6
-rw-r--r--tools/perf/util/print_binary.c55
-rw-r--r--tools/perf/util/print_binary.h28
-rw-r--r--tools/perf/util/probe-event.c29
-rw-r--r--tools/perf/util/probe-event.h7
-rw-r--r--tools/perf/util/probe-file.c218
-rw-r--r--tools/perf/util/probe-file.h8
-rw-r--r--tools/perf/util/probe-finder.c3
-rw-r--r--tools/perf/util/probe-finder.h2
-rw-r--r--tools/perf/util/python-ext-sources2
-rw-r--r--tools/perf/util/python.c14
-rw-r--r--tools/perf/util/quote.c1
-rw-r--r--tools/perf/util/record.c1
-rw-r--r--tools/perf/util/sane_ctype.h51
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c5
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c2
-rw-r--r--tools/perf/util/session.c55
-rw-r--r--tools/perf/util/session.h4
-rw-r--r--tools/perf/util/sort.c109
-rw-r--r--tools/perf/util/sort.h16
-rw-r--r--tools/perf/util/srcline.c248
-rw-r--r--tools/perf/util/srcline.h34
-rw-r--r--tools/perf/util/stat-shadow.c197
-rw-r--r--tools/perf/util/stat.c2
-rw-r--r--tools/perf/util/stat.h2
-rw-r--r--tools/perf/util/strbuf.c10
-rw-r--r--tools/perf/util/strfilter.c5
-rw-r--r--tools/perf/util/string.c24
-rw-r--r--tools/perf/util/string2.h42
-rw-r--r--tools/perf/util/strlist.c1
-rw-r--r--tools/perf/util/symbol-elf.c33
-rw-r--r--tools/perf/util/symbol-minimal.c8
-rw-r--r--tools/perf/util/symbol.c75
-rw-r--r--tools/perf/util/symbol.h19
-rw-r--r--tools/perf/util/term.c6
-rw-r--r--tools/perf/util/thread-stack.c1
-rw-r--r--tools/perf/util/thread.c52
-rw-r--r--tools/perf/util/thread.h10
-rw-r--r--tools/perf/util/thread_map.c22
-rw-r--r--tools/perf/util/thread_map.h4
-rw-r--r--tools/perf/util/time-utils.c25
-rw-r--r--tools/perf/util/time-utils.h7
-rw-r--r--tools/perf/util/tool.h2
-rw-r--r--tools/perf/util/top.h2
-rw-r--r--tools/perf/util/trace-event-parse.c3
-rw-r--r--tools/perf/util/trace-event-read.c4
-rw-r--r--tools/perf/util/units.c68
-rw-r--r--tools/perf/util/units.h17
-rw-r--r--tools/perf/util/unwind-libdw.c1
-rw-r--r--tools/perf/util/unwind-libdw.h6
-rw-r--r--tools/perf/util/unwind-libunwind-local.c2
-rw-r--r--tools/perf/util/unwind.h9
-rw-r--r--tools/perf/util/util.c327
-rw-r--r--tools/perf/util/util.h299
-rw-r--r--tools/perf/util/values.c63
-rw-r--r--tools/perf/util/vdso.c2
-rw-r--r--tools/perf/util/xyarray.c2
-rw-r--r--tools/perf/util/zlib.c1
-rw-r--r--tools/scripts/Makefile.include9
389 files changed, 8610 insertions, 2446 deletions
diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt
index 41ef9d8efe95..5ea85059db3b 100644
--- a/Documentation/trace/kprobetrace.txt
+++ b/Documentation/trace/kprobetrace.txt
@@ -8,8 +8,9 @@ Overview
8-------- 8--------
9These events are similar to tracepoint based events. Instead of Tracepoint, 9These events are similar to tracepoint based events. Instead of Tracepoint,
10this is based on kprobes (kprobe and kretprobe). So it can probe wherever 10this is based on kprobes (kprobe and kretprobe). So it can probe wherever
11kprobes can probe (this means, all functions body except for __kprobes 11kprobes can probe (this means, all functions except those with
12functions). Unlike the Tracepoint based event, this can be added and removed 12__kprobes/nokprobe_inline annotation and those marked NOKPROBE_SYMBOL).
13Unlike the Tracepoint based event, this can be added and removed
13dynamically, on the fly. 14dynamically, on the fly.
14 15
15To enable this feature, build your kernel with CONFIG_KPROBE_EVENTS=y. 16To enable this feature, build your kernel with CONFIG_KPROBE_EVENTS=y.
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
index de5d572225f3..cd1fa97776c3 100644
--- a/arch/um/include/shared/os.h
+++ b/arch/um/include/shared/os.h
@@ -302,8 +302,8 @@ extern int ignore_sigio_fd(int fd);
302extern void maybe_sigio_broken(int fd, int read); 302extern void maybe_sigio_broken(int fd, int read);
303extern void sigio_broken(int fd, int read); 303extern void sigio_broken(int fd, int read);
304 304
305/* sys-x86_64/prctl.c */ 305/* prctl.c */
306extern int os_arch_prctl(int pid, int code, unsigned long *addr); 306extern int os_arch_prctl(int pid, int option, unsigned long *arg2);
307 307
308/* tty.c */ 308/* tty.c */
309extern int get_pty(void); 309extern int get_pty(void);
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index 9ba050fe47f3..0af59fa789ea 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -390,3 +390,4 @@
390381 i386 pkey_alloc sys_pkey_alloc 390381 i386 pkey_alloc sys_pkey_alloc
391382 i386 pkey_free sys_pkey_free 391382 i386 pkey_free sys_pkey_free
392383 i386 statx sys_statx 392383 i386 statx sys_statx
393384 i386 arch_prctl sys_arch_prctl compat_sys_arch_prctl
diff --git a/arch/x86/events/amd/iommu.c b/arch/x86/events/amd/iommu.c
index b28200dea715..3641e24fdac5 100644
--- a/arch/x86/events/amd/iommu.c
+++ b/arch/x86/events/amd/iommu.c
@@ -11,6 +11,8 @@
11 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
12 */ 12 */
13 13
14#define pr_fmt(fmt) "perf/amd_iommu: " fmt
15
14#include <linux/perf_event.h> 16#include <linux/perf_event.h>
15#include <linux/init.h> 17#include <linux/init.h>
16#include <linux/cpumask.h> 18#include <linux/cpumask.h>
@@ -21,44 +23,42 @@
21 23
22#define COUNTER_SHIFT 16 24#define COUNTER_SHIFT 16
23 25
24#define _GET_BANK(ev) ((u8)(ev->hw.extra_reg.reg >> 8)) 26/* iommu pmu conf masks */
25#define _GET_CNTR(ev) ((u8)(ev->hw.extra_reg.reg)) 27#define GET_CSOURCE(x) ((x)->conf & 0xFFULL)
28#define GET_DEVID(x) (((x)->conf >> 8) & 0xFFFFULL)
29#define GET_DOMID(x) (((x)->conf >> 24) & 0xFFFFULL)
30#define GET_PASID(x) (((x)->conf >> 40) & 0xFFFFFULL)
26 31
27/* iommu pmu config masks */ 32/* iommu pmu conf1 masks */
28#define _GET_CSOURCE(ev) ((ev->hw.config & 0xFFULL)) 33#define GET_DEVID_MASK(x) ((x)->conf1 & 0xFFFFULL)
29#define _GET_DEVID(ev) ((ev->hw.config >> 8) & 0xFFFFULL) 34#define GET_DOMID_MASK(x) (((x)->conf1 >> 16) & 0xFFFFULL)
30#define _GET_PASID(ev) ((ev->hw.config >> 24) & 0xFFFFULL) 35#define GET_PASID_MASK(x) (((x)->conf1 >> 32) & 0xFFFFFULL)
31#define _GET_DOMID(ev) ((ev->hw.config >> 40) & 0xFFFFULL)
32#define _GET_DEVID_MASK(ev) ((ev->hw.extra_reg.config) & 0xFFFFULL)
33#define _GET_PASID_MASK(ev) ((ev->hw.extra_reg.config >> 16) & 0xFFFFULL)
34#define _GET_DOMID_MASK(ev) ((ev->hw.extra_reg.config >> 32) & 0xFFFFULL)
35 36
36static struct perf_amd_iommu __perf_iommu; 37#define IOMMU_NAME_SIZE 16
37 38
38struct perf_amd_iommu { 39struct perf_amd_iommu {
40 struct list_head list;
39 struct pmu pmu; 41 struct pmu pmu;
42 struct amd_iommu *iommu;
43 char name[IOMMU_NAME_SIZE];
40 u8 max_banks; 44 u8 max_banks;
41 u8 max_counters; 45 u8 max_counters;
42 u64 cntr_assign_mask; 46 u64 cntr_assign_mask;
43 raw_spinlock_t lock; 47 raw_spinlock_t lock;
44 const struct attribute_group *attr_groups[4];
45}; 48};
46 49
47#define format_group attr_groups[0] 50static LIST_HEAD(perf_amd_iommu_list);
48#define cpumask_group attr_groups[1]
49#define events_group attr_groups[2]
50#define null_group attr_groups[3]
51 51
52/*--------------------------------------------- 52/*---------------------------------------------
53 * sysfs format attributes 53 * sysfs format attributes
54 *---------------------------------------------*/ 54 *---------------------------------------------*/
55PMU_FORMAT_ATTR(csource, "config:0-7"); 55PMU_FORMAT_ATTR(csource, "config:0-7");
56PMU_FORMAT_ATTR(devid, "config:8-23"); 56PMU_FORMAT_ATTR(devid, "config:8-23");
57PMU_FORMAT_ATTR(pasid, "config:24-39"); 57PMU_FORMAT_ATTR(domid, "config:24-39");
58PMU_FORMAT_ATTR(domid, "config:40-55"); 58PMU_FORMAT_ATTR(pasid, "config:40-59");
59PMU_FORMAT_ATTR(devid_mask, "config1:0-15"); 59PMU_FORMAT_ATTR(devid_mask, "config1:0-15");
60PMU_FORMAT_ATTR(pasid_mask, "config1:16-31"); 60PMU_FORMAT_ATTR(domid_mask, "config1:16-31");
61PMU_FORMAT_ATTR(domid_mask, "config1:32-47"); 61PMU_FORMAT_ATTR(pasid_mask, "config1:32-51");
62 62
63static struct attribute *iommu_format_attrs[] = { 63static struct attribute *iommu_format_attrs[] = {
64 &format_attr_csource.attr, 64 &format_attr_csource.attr,
@@ -79,6 +79,10 @@ static struct attribute_group amd_iommu_format_group = {
79/*--------------------------------------------- 79/*---------------------------------------------
80 * sysfs events attributes 80 * sysfs events attributes
81 *---------------------------------------------*/ 81 *---------------------------------------------*/
82static struct attribute_group amd_iommu_events_group = {
83 .name = "events",
84};
85
82struct amd_iommu_event_desc { 86struct amd_iommu_event_desc {
83 struct kobj_attribute attr; 87 struct kobj_attribute attr;
84 const char *event; 88 const char *event;
@@ -150,30 +154,34 @@ static struct attribute_group amd_iommu_cpumask_group = {
150 154
151/*---------------------------------------------*/ 155/*---------------------------------------------*/
152 156
153static int get_next_avail_iommu_bnk_cntr(struct perf_amd_iommu *perf_iommu) 157static int get_next_avail_iommu_bnk_cntr(struct perf_event *event)
154{ 158{
159 struct perf_amd_iommu *piommu = container_of(event->pmu, struct perf_amd_iommu, pmu);
160 int max_cntrs = piommu->max_counters;
161 int max_banks = piommu->max_banks;
162 u32 shift, bank, cntr;
155 unsigned long flags; 163 unsigned long flags;
156 int shift, bank, cntr, retval; 164 int retval;
157 int max_banks = perf_iommu->max_banks;
158 int max_cntrs = perf_iommu->max_counters;
159 165
160 raw_spin_lock_irqsave(&perf_iommu->lock, flags); 166 raw_spin_lock_irqsave(&piommu->lock, flags);
161 167
162 for (bank = 0, shift = 0; bank < max_banks; bank++) { 168 for (bank = 0, shift = 0; bank < max_banks; bank++) {
163 for (cntr = 0; cntr < max_cntrs; cntr++) { 169 for (cntr = 0; cntr < max_cntrs; cntr++) {
164 shift = bank + (bank*3) + cntr; 170 shift = bank + (bank*3) + cntr;
165 if (perf_iommu->cntr_assign_mask & (1ULL<<shift)) { 171 if (piommu->cntr_assign_mask & BIT_ULL(shift)) {
166 continue; 172 continue;
167 } else { 173 } else {
168 perf_iommu->cntr_assign_mask |= (1ULL<<shift); 174 piommu->cntr_assign_mask |= BIT_ULL(shift);
169 retval = ((u16)((u16)bank<<8) | (u8)(cntr)); 175 event->hw.iommu_bank = bank;
176 event->hw.iommu_cntr = cntr;
177 retval = 0;
170 goto out; 178 goto out;
171 } 179 }
172 } 180 }
173 } 181 }
174 retval = -ENOSPC; 182 retval = -ENOSPC;
175out: 183out:
176 raw_spin_unlock_irqrestore(&perf_iommu->lock, flags); 184 raw_spin_unlock_irqrestore(&piommu->lock, flags);
177 return retval; 185 return retval;
178} 186}
179 187
@@ -202,8 +210,6 @@ static int clear_avail_iommu_bnk_cntr(struct perf_amd_iommu *perf_iommu,
202static int perf_iommu_event_init(struct perf_event *event) 210static int perf_iommu_event_init(struct perf_event *event)
203{ 211{
204 struct hw_perf_event *hwc = &event->hw; 212 struct hw_perf_event *hwc = &event->hw;
205 struct perf_amd_iommu *perf_iommu;
206 u64 config, config1;
207 213
208 /* test the event attr type check for PMU enumeration */ 214 /* test the event attr type check for PMU enumeration */
209 if (event->attr.type != event->pmu->type) 215 if (event->attr.type != event->pmu->type)
@@ -225,80 +231,62 @@ static int perf_iommu_event_init(struct perf_event *event)
225 if (event->cpu < 0) 231 if (event->cpu < 0)
226 return -EINVAL; 232 return -EINVAL;
227 233
228 perf_iommu = &__perf_iommu;
229
230 if (event->pmu != &perf_iommu->pmu)
231 return -ENOENT;
232
233 if (perf_iommu) {
234 config = event->attr.config;
235 config1 = event->attr.config1;
236 } else {
237 return -EINVAL;
238 }
239
240 /* integrate with iommu base devid (0000), assume one iommu */
241 perf_iommu->max_banks =
242 amd_iommu_pc_get_max_banks(IOMMU_BASE_DEVID);
243 perf_iommu->max_counters =
244 amd_iommu_pc_get_max_counters(IOMMU_BASE_DEVID);
245 if ((perf_iommu->max_banks == 0) || (perf_iommu->max_counters == 0))
246 return -EINVAL;
247
248 /* update the hw_perf_event struct with the iommu config data */ 234 /* update the hw_perf_event struct with the iommu config data */
249 hwc->config = config; 235 hwc->conf = event->attr.config;
250 hwc->extra_reg.config = config1; 236 hwc->conf1 = event->attr.config1;
251 237
252 return 0; 238 return 0;
253} 239}
254 240
241static inline struct amd_iommu *perf_event_2_iommu(struct perf_event *ev)
242{
243 return (container_of(ev->pmu, struct perf_amd_iommu, pmu))->iommu;
244}
245
255static void perf_iommu_enable_event(struct perf_event *ev) 246static void perf_iommu_enable_event(struct perf_event *ev)
256{ 247{
257 u8 csource = _GET_CSOURCE(ev); 248 struct amd_iommu *iommu = perf_event_2_iommu(ev);
258 u16 devid = _GET_DEVID(ev); 249 struct hw_perf_event *hwc = &ev->hw;
250 u8 bank = hwc->iommu_bank;
251 u8 cntr = hwc->iommu_cntr;
259 u64 reg = 0ULL; 252 u64 reg = 0ULL;
260 253
261 reg = csource; 254 reg = GET_CSOURCE(hwc);
262 amd_iommu_pc_get_set_reg_val(devid, 255 amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_COUNTER_SRC_REG, &reg);
263 _GET_BANK(ev), _GET_CNTR(ev) ,
264 IOMMU_PC_COUNTER_SRC_REG, &reg, true);
265 256
266 reg = 0ULL | devid | (_GET_DEVID_MASK(ev) << 32); 257 reg = GET_DEVID_MASK(hwc);
258 reg = GET_DEVID(hwc) | (reg << 32);
267 if (reg) 259 if (reg)
268 reg |= (1UL << 31); 260 reg |= BIT(31);
269 amd_iommu_pc_get_set_reg_val(devid, 261 amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_DEVID_MATCH_REG, &reg);
270 _GET_BANK(ev), _GET_CNTR(ev) ,
271 IOMMU_PC_DEVID_MATCH_REG, &reg, true);
272 262
273 reg = 0ULL | _GET_PASID(ev) | (_GET_PASID_MASK(ev) << 32); 263 reg = GET_PASID_MASK(hwc);
264 reg = GET_PASID(hwc) | (reg << 32);
274 if (reg) 265 if (reg)
275 reg |= (1UL << 31); 266 reg |= BIT(31);
276 amd_iommu_pc_get_set_reg_val(devid, 267 amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_PASID_MATCH_REG, &reg);
277 _GET_BANK(ev), _GET_CNTR(ev) ,
278 IOMMU_PC_PASID_MATCH_REG, &reg, true);
279 268
280 reg = 0ULL | _GET_DOMID(ev) | (_GET_DOMID_MASK(ev) << 32); 269 reg = GET_DOMID_MASK(hwc);
270 reg = GET_DOMID(hwc) | (reg << 32);
281 if (reg) 271 if (reg)
282 reg |= (1UL << 31); 272 reg |= BIT(31);
283 amd_iommu_pc_get_set_reg_val(devid, 273 amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_DOMID_MATCH_REG, &reg);
284 _GET_BANK(ev), _GET_CNTR(ev) ,
285 IOMMU_PC_DOMID_MATCH_REG, &reg, true);
286} 274}
287 275
288static void perf_iommu_disable_event(struct perf_event *event) 276static void perf_iommu_disable_event(struct perf_event *event)
289{ 277{
278 struct amd_iommu *iommu = perf_event_2_iommu(event);
279 struct hw_perf_event *hwc = &event->hw;
290 u64 reg = 0ULL; 280 u64 reg = 0ULL;
291 281
292 amd_iommu_pc_get_set_reg_val(_GET_DEVID(event), 282 amd_iommu_pc_set_reg(iommu, hwc->iommu_bank, hwc->iommu_cntr,
293 _GET_BANK(event), _GET_CNTR(event), 283 IOMMU_PC_COUNTER_SRC_REG, &reg);
294 IOMMU_PC_COUNTER_SRC_REG, &reg, true);
295} 284}
296 285
297static void perf_iommu_start(struct perf_event *event, int flags) 286static void perf_iommu_start(struct perf_event *event, int flags)
298{ 287{
299 struct hw_perf_event *hwc = &event->hw; 288 struct hw_perf_event *hwc = &event->hw;
300 289
301 pr_debug("perf: amd_iommu:perf_iommu_start\n");
302 if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED))) 290 if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
303 return; 291 return;
304 292
@@ -306,10 +294,11 @@ static void perf_iommu_start(struct perf_event *event, int flags)
306 hwc->state = 0; 294 hwc->state = 0;
307 295
308 if (flags & PERF_EF_RELOAD) { 296 if (flags & PERF_EF_RELOAD) {
309 u64 prev_raw_count = local64_read(&hwc->prev_count); 297 u64 prev_raw_count = local64_read(&hwc->prev_count);
310 amd_iommu_pc_get_set_reg_val(_GET_DEVID(event), 298 struct amd_iommu *iommu = perf_event_2_iommu(event);
311 _GET_BANK(event), _GET_CNTR(event), 299
312 IOMMU_PC_COUNTER_REG, &prev_raw_count, true); 300 amd_iommu_pc_set_reg(iommu, hwc->iommu_bank, hwc->iommu_cntr,
301 IOMMU_PC_COUNTER_REG, &prev_raw_count);
313 } 302 }
314 303
315 perf_iommu_enable_event(event); 304 perf_iommu_enable_event(event);
@@ -319,37 +308,30 @@ static void perf_iommu_start(struct perf_event *event, int flags)
319 308
320static void perf_iommu_read(struct perf_event *event) 309static void perf_iommu_read(struct perf_event *event)
321{ 310{
322 u64 count = 0ULL; 311 u64 count, prev, delta;
323 u64 prev_raw_count = 0ULL;
324 u64 delta = 0ULL;
325 struct hw_perf_event *hwc = &event->hw; 312 struct hw_perf_event *hwc = &event->hw;
326 pr_debug("perf: amd_iommu:perf_iommu_read\n"); 313 struct amd_iommu *iommu = perf_event_2_iommu(event);
327 314
328 amd_iommu_pc_get_set_reg_val(_GET_DEVID(event), 315 if (amd_iommu_pc_get_reg(iommu, hwc->iommu_bank, hwc->iommu_cntr,
329 _GET_BANK(event), _GET_CNTR(event), 316 IOMMU_PC_COUNTER_REG, &count))
330 IOMMU_PC_COUNTER_REG, &count, false); 317 return;
331 318
332 /* IOMMU pc counter register is only 48 bits */ 319 /* IOMMU pc counter register is only 48 bits */
333 count &= 0xFFFFFFFFFFFFULL; 320 count &= GENMASK_ULL(47, 0);
334 321
335 prev_raw_count = local64_read(&hwc->prev_count); 322 prev = local64_read(&hwc->prev_count);
336 if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, 323 if (local64_cmpxchg(&hwc->prev_count, prev, count) != prev)
337 count) != prev_raw_count)
338 return; 324 return;
339 325
340 /* Handling 48-bit counter overflowing */ 326 /* Handle 48-bit counter overflow */
341 delta = (count << COUNTER_SHIFT) - (prev_raw_count << COUNTER_SHIFT); 327 delta = (count << COUNTER_SHIFT) - (prev << COUNTER_SHIFT);
342 delta >>= COUNTER_SHIFT; 328 delta >>= COUNTER_SHIFT;
343 local64_add(delta, &event->count); 329 local64_add(delta, &event->count);
344
345} 330}
346 331
347static void perf_iommu_stop(struct perf_event *event, int flags) 332static void perf_iommu_stop(struct perf_event *event, int flags)
348{ 333{
349 struct hw_perf_event *hwc = &event->hw; 334 struct hw_perf_event *hwc = &event->hw;
350 u64 config;
351
352 pr_debug("perf: amd_iommu:perf_iommu_stop\n");
353 335
354 if (hwc->state & PERF_HES_UPTODATE) 336 if (hwc->state & PERF_HES_UPTODATE)
355 return; 337 return;
@@ -361,7 +343,6 @@ static void perf_iommu_stop(struct perf_event *event, int flags)
361 if (hwc->state & PERF_HES_UPTODATE) 343 if (hwc->state & PERF_HES_UPTODATE)
362 return; 344 return;
363 345
364 config = hwc->config;
365 perf_iommu_read(event); 346 perf_iommu_read(event);
366 hwc->state |= PERF_HES_UPTODATE; 347 hwc->state |= PERF_HES_UPTODATE;
367} 348}
@@ -369,17 +350,12 @@ static void perf_iommu_stop(struct perf_event *event, int flags)
369static int perf_iommu_add(struct perf_event *event, int flags) 350static int perf_iommu_add(struct perf_event *event, int flags)
370{ 351{
371 int retval; 352 int retval;
372 struct perf_amd_iommu *perf_iommu =
373 container_of(event->pmu, struct perf_amd_iommu, pmu);
374 353
375 pr_debug("perf: amd_iommu:perf_iommu_add\n");
376 event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED; 354 event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
377 355
378 /* request an iommu bank/counter */ 356 /* request an iommu bank/counter */
379 retval = get_next_avail_iommu_bnk_cntr(perf_iommu); 357 retval = get_next_avail_iommu_bnk_cntr(event);
380 if (retval != -ENOSPC) 358 if (retval)
381 event->hw.extra_reg.reg = (u16)retval;
382 else
383 return retval; 359 return retval;
384 360
385 if (flags & PERF_EF_START) 361 if (flags & PERF_EF_START)
@@ -390,115 +366,124 @@ static int perf_iommu_add(struct perf_event *event, int flags)
390 366
391static void perf_iommu_del(struct perf_event *event, int flags) 367static void perf_iommu_del(struct perf_event *event, int flags)
392{ 368{
369 struct hw_perf_event *hwc = &event->hw;
393 struct perf_amd_iommu *perf_iommu = 370 struct perf_amd_iommu *perf_iommu =
394 container_of(event->pmu, struct perf_amd_iommu, pmu); 371 container_of(event->pmu, struct perf_amd_iommu, pmu);
395 372
396 pr_debug("perf: amd_iommu:perf_iommu_del\n");
397 perf_iommu_stop(event, PERF_EF_UPDATE); 373 perf_iommu_stop(event, PERF_EF_UPDATE);
398 374
399 /* clear the assigned iommu bank/counter */ 375 /* clear the assigned iommu bank/counter */
400 clear_avail_iommu_bnk_cntr(perf_iommu, 376 clear_avail_iommu_bnk_cntr(perf_iommu,
401 _GET_BANK(event), 377 hwc->iommu_bank, hwc->iommu_cntr);
402 _GET_CNTR(event));
403 378
404 perf_event_update_userpage(event); 379 perf_event_update_userpage(event);
405} 380}
406 381
407static __init int _init_events_attrs(struct perf_amd_iommu *perf_iommu) 382static __init int _init_events_attrs(void)
408{ 383{
409 struct attribute **attrs;
410 struct attribute_group *attr_group;
411 int i = 0, j; 384 int i = 0, j;
385 struct attribute **attrs;
412 386
413 while (amd_iommu_v2_event_descs[i].attr.attr.name) 387 while (amd_iommu_v2_event_descs[i].attr.attr.name)
414 i++; 388 i++;
415 389
416 attr_group = kzalloc(sizeof(struct attribute *) 390 attrs = kzalloc(sizeof(struct attribute **) * (i + 1), GFP_KERNEL);
417 * (i + 1) + sizeof(*attr_group), GFP_KERNEL); 391 if (!attrs)
418 if (!attr_group)
419 return -ENOMEM; 392 return -ENOMEM;
420 393
421 attrs = (struct attribute **)(attr_group + 1);
422 for (j = 0; j < i; j++) 394 for (j = 0; j < i; j++)
423 attrs[j] = &amd_iommu_v2_event_descs[j].attr.attr; 395 attrs[j] = &amd_iommu_v2_event_descs[j].attr.attr;
424 396
425 attr_group->name = "events"; 397 amd_iommu_events_group.attrs = attrs;
426 attr_group->attrs = attrs;
427 perf_iommu->events_group = attr_group;
428
429 return 0; 398 return 0;
430} 399}
431 400
432static __init void amd_iommu_pc_exit(void) 401const struct attribute_group *amd_iommu_attr_groups[] = {
433{ 402 &amd_iommu_format_group,
434 if (__perf_iommu.events_group != NULL) { 403 &amd_iommu_cpumask_group,
435 kfree(__perf_iommu.events_group); 404 &amd_iommu_events_group,
436 __perf_iommu.events_group = NULL; 405 NULL,
437 } 406};
438} 407
408static struct pmu iommu_pmu = {
409 .event_init = perf_iommu_event_init,
410 .add = perf_iommu_add,
411 .del = perf_iommu_del,
412 .start = perf_iommu_start,
413 .stop = perf_iommu_stop,
414 .read = perf_iommu_read,
415 .task_ctx_nr = perf_invalid_context,
416 .attr_groups = amd_iommu_attr_groups,
417};
439 418
440static __init int _init_perf_amd_iommu( 419static __init int init_one_iommu(unsigned int idx)
441 struct perf_amd_iommu *perf_iommu, char *name)
442{ 420{
421 struct perf_amd_iommu *perf_iommu;
443 int ret; 422 int ret;
444 423
424 perf_iommu = kzalloc(sizeof(struct perf_amd_iommu), GFP_KERNEL);
425 if (!perf_iommu)
426 return -ENOMEM;
427
445 raw_spin_lock_init(&perf_iommu->lock); 428 raw_spin_lock_init(&perf_iommu->lock);
446 429
447 /* Init format attributes */ 430 perf_iommu->pmu = iommu_pmu;
448 perf_iommu->format_group = &amd_iommu_format_group; 431 perf_iommu->iommu = get_amd_iommu(idx);
432 perf_iommu->max_banks = amd_iommu_pc_get_max_banks(idx);
433 perf_iommu->max_counters = amd_iommu_pc_get_max_counters(idx);
449 434
450 /* Init cpumask attributes to only core 0 */ 435 if (!perf_iommu->iommu ||
451 cpumask_set_cpu(0, &iommu_cpumask); 436 !perf_iommu->max_banks ||
452 perf_iommu->cpumask_group = &amd_iommu_cpumask_group; 437 !perf_iommu->max_counters) {
453 438 kfree(perf_iommu);
454 /* Init events attributes */ 439 return -EINVAL;
455 if (_init_events_attrs(perf_iommu) != 0) 440 }
456 pr_err("perf: amd_iommu: Only support raw events.\n");
457 441
458 /* Init null attributes */ 442 snprintf(perf_iommu->name, IOMMU_NAME_SIZE, "amd_iommu_%u", idx);
459 perf_iommu->null_group = NULL;
460 perf_iommu->pmu.attr_groups = perf_iommu->attr_groups;
461 443
462 ret = perf_pmu_register(&perf_iommu->pmu, name, -1); 444 ret = perf_pmu_register(&perf_iommu->pmu, perf_iommu->name, -1);
463 if (ret) { 445 if (!ret) {
464 pr_err("perf: amd_iommu: Failed to initialized.\n"); 446 pr_info("Detected AMD IOMMU #%d (%d banks, %d counters/bank).\n",
465 amd_iommu_pc_exit(); 447 idx, perf_iommu->max_banks, perf_iommu->max_counters);
448 list_add_tail(&perf_iommu->list, &perf_amd_iommu_list);
466 } else { 449 } else {
467 pr_info("perf: amd_iommu: Detected. (%d banks, %d counters/bank)\n", 450 pr_warn("Error initializing IOMMU %d.\n", idx);
468 amd_iommu_pc_get_max_banks(IOMMU_BASE_DEVID), 451 kfree(perf_iommu);
469 amd_iommu_pc_get_max_counters(IOMMU_BASE_DEVID));
470 } 452 }
471
472 return ret; 453 return ret;
473} 454}
474 455
475static struct perf_amd_iommu __perf_iommu = {
476 .pmu = {
477 .task_ctx_nr = perf_invalid_context,
478 .event_init = perf_iommu_event_init,
479 .add = perf_iommu_add,
480 .del = perf_iommu_del,
481 .start = perf_iommu_start,
482 .stop = perf_iommu_stop,
483 .read = perf_iommu_read,
484 },
485 .max_banks = 0x00,
486 .max_counters = 0x00,
487 .cntr_assign_mask = 0ULL,
488 .format_group = NULL,
489 .cpumask_group = NULL,
490 .events_group = NULL,
491 .null_group = NULL,
492};
493
494static __init int amd_iommu_pc_init(void) 456static __init int amd_iommu_pc_init(void)
495{ 457{
458 unsigned int i, cnt = 0;
459 int ret;
460
496 /* Make sure the IOMMU PC resource is available */ 461 /* Make sure the IOMMU PC resource is available */
497 if (!amd_iommu_pc_supported()) 462 if (!amd_iommu_pc_supported())
498 return -ENODEV; 463 return -ENODEV;
499 464
500 _init_perf_amd_iommu(&__perf_iommu, "amd_iommu"); 465 ret = _init_events_attrs();
466 if (ret)
467 return ret;
468
469 /*
470 * An IOMMU PMU is specific to an IOMMU, and can function independently.
471 * So we go through all IOMMUs and ignore the one that fails init
472 * unless all IOMMU are failing.
473 */
474 for (i = 0; i < amd_iommu_get_num_iommus(); i++) {
475 ret = init_one_iommu(i);
476 if (!ret)
477 cnt++;
478 }
479
480 if (!cnt) {
481 kfree(amd_iommu_events_group.attrs);
482 return -ENODEV;
483 }
501 484
485 /* Init cpumask attributes to only core 0 */
486 cpumask_set_cpu(0, &iommu_cpumask);
502 return 0; 487 return 0;
503} 488}
504 489
diff --git a/arch/x86/events/amd/iommu.h b/arch/x86/events/amd/iommu.h
index 845d173278e3..62e0702c4374 100644
--- a/arch/x86/events/amd/iommu.h
+++ b/arch/x86/events/amd/iommu.h
@@ -24,17 +24,23 @@
24#define PC_MAX_SPEC_BNKS 64 24#define PC_MAX_SPEC_BNKS 64
25#define PC_MAX_SPEC_CNTRS 16 25#define PC_MAX_SPEC_CNTRS 16
26 26
27/* iommu pc reg masks*/ 27struct amd_iommu;
28#define IOMMU_BASE_DEVID 0x0000
29 28
30/* amd_iommu_init.c external support functions */ 29/* amd_iommu_init.c external support functions */
30extern int amd_iommu_get_num_iommus(void);
31
31extern bool amd_iommu_pc_supported(void); 32extern bool amd_iommu_pc_supported(void);
32 33
33extern u8 amd_iommu_pc_get_max_banks(u16 devid); 34extern u8 amd_iommu_pc_get_max_banks(unsigned int idx);
35
36extern u8 amd_iommu_pc_get_max_counters(unsigned int idx);
37
38extern int amd_iommu_pc_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr,
39 u8 fxn, u64 *value);
34 40
35extern u8 amd_iommu_pc_get_max_counters(u16 devid); 41extern int amd_iommu_pc_get_reg(struct amd_iommu *iommu, u8 bank, u8 cntr,
42 u8 fxn, u64 *value);
36 43
37extern int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, 44extern struct amd_iommu *get_amd_iommu(int idx);
38 u8 fxn, u64 *value, bool is_write);
39 45
40#endif /*_PERF_EVENT_AMD_IOMMU_H_*/ 46#endif /*_PERF_EVENT_AMD_IOMMU_H_*/
diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c
index 4d1f7f2d9aff..ad44af0dd667 100644
--- a/arch/x86/events/amd/uncore.c
+++ b/arch/x86/events/amd/uncore.c
@@ -30,6 +30,9 @@
30 30
31#define COUNTER_SHIFT 16 31#define COUNTER_SHIFT 16
32 32
33#undef pr_fmt
34#define pr_fmt(fmt) "amd_uncore: " fmt
35
33static int num_counters_llc; 36static int num_counters_llc;
34static int num_counters_nb; 37static int num_counters_nb;
35 38
@@ -509,51 +512,34 @@ static int __init amd_uncore_init(void)
509 int ret = -ENODEV; 512 int ret = -ENODEV;
510 513
511 if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) 514 if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
512 goto fail_nodev; 515 return -ENODEV;
513
514 switch(boot_cpu_data.x86) {
515 case 23:
516 /* Family 17h: */
517 num_counters_nb = NUM_COUNTERS_NB;
518 num_counters_llc = NUM_COUNTERS_L3;
519 /*
520 * For Family17h, the NorthBridge counters are
521 * re-purposed as Data Fabric counters. Also, support is
522 * added for L3 counters. The pmus are exported based on
523 * family as either L2 or L3 and NB or DF.
524 */
525 amd_nb_pmu.name = "amd_df";
526 amd_llc_pmu.name = "amd_l3";
527 format_attr_event_df.show = &event_show_df;
528 format_attr_event_l3.show = &event_show_l3;
529 break;
530 case 22:
531 /* Family 16h - may change: */
532 num_counters_nb = NUM_COUNTERS_NB;
533 num_counters_llc = NUM_COUNTERS_L2;
534 amd_nb_pmu.name = "amd_nb";
535 amd_llc_pmu.name = "amd_l2";
536 format_attr_event_df = format_attr_event;
537 format_attr_event_l3 = format_attr_event;
538 break;
539 default:
540 /*
541 * All prior families have the same number of
542 * NorthBridge and Last Level Cache counters
543 */
544 num_counters_nb = NUM_COUNTERS_NB;
545 num_counters_llc = NUM_COUNTERS_L2;
546 amd_nb_pmu.name = "amd_nb";
547 amd_llc_pmu.name = "amd_l2";
548 format_attr_event_df = format_attr_event;
549 format_attr_event_l3 = format_attr_event;
550 break;
551 }
552 amd_nb_pmu.attr_groups = amd_uncore_attr_groups_df;
553 amd_llc_pmu.attr_groups = amd_uncore_attr_groups_l3;
554 516
555 if (!boot_cpu_has(X86_FEATURE_TOPOEXT)) 517 if (!boot_cpu_has(X86_FEATURE_TOPOEXT))
556 goto fail_nodev; 518 return -ENODEV;
519
520 if (boot_cpu_data.x86 == 0x17) {
521 /*
522 * For F17h, the Northbridge counters are repurposed as Data
523 * Fabric counters. Also, L3 counters are supported too. The PMUs
524 * are exported based on family as either L2 or L3 and NB or DF.
525 */
526 num_counters_nb = NUM_COUNTERS_NB;
527 num_counters_llc = NUM_COUNTERS_L3;
528 amd_nb_pmu.name = "amd_df";
529 amd_llc_pmu.name = "amd_l3";
530 format_attr_event_df.show = &event_show_df;
531 format_attr_event_l3.show = &event_show_l3;
532 } else {
533 num_counters_nb = NUM_COUNTERS_NB;
534 num_counters_llc = NUM_COUNTERS_L2;
535 amd_nb_pmu.name = "amd_nb";
536 amd_llc_pmu.name = "amd_l2";
537 format_attr_event_df = format_attr_event;
538 format_attr_event_l3 = format_attr_event;
539 }
540
541 amd_nb_pmu.attr_groups = amd_uncore_attr_groups_df;
542 amd_llc_pmu.attr_groups = amd_uncore_attr_groups_l3;
557 543
558 if (boot_cpu_has(X86_FEATURE_PERFCTR_NB)) { 544 if (boot_cpu_has(X86_FEATURE_PERFCTR_NB)) {
559 amd_uncore_nb = alloc_percpu(struct amd_uncore *); 545 amd_uncore_nb = alloc_percpu(struct amd_uncore *);
@@ -565,7 +551,7 @@ static int __init amd_uncore_init(void)
565 if (ret) 551 if (ret)
566 goto fail_nb; 552 goto fail_nb;
567 553
568 pr_info("perf: AMD NB counters detected\n"); 554 pr_info("AMD NB counters detected\n");
569 ret = 0; 555 ret = 0;
570 } 556 }
571 557
@@ -579,7 +565,7 @@ static int __init amd_uncore_init(void)
579 if (ret) 565 if (ret)
580 goto fail_llc; 566 goto fail_llc;
581 567
582 pr_info("perf: AMD LLC counters detected\n"); 568 pr_info("AMD LLC counters detected\n");
583 ret = 0; 569 ret = 0;
584 } 570 }
585 571
@@ -615,7 +601,6 @@ fail_nb:
615 if (amd_uncore_nb) 601 if (amd_uncore_nb)
616 free_percpu(amd_uncore_nb); 602 free_percpu(amd_uncore_nb);
617 603
618fail_nodev:
619 return ret; 604 return ret;
620} 605}
621device_initcall(amd_uncore_init); 606device_initcall(amd_uncore_init);
diff --git a/arch/x86/events/intel/bts.c b/arch/x86/events/intel/bts.c
index 982c9e31daca..8ae8c5ce3a1f 100644
--- a/arch/x86/events/intel/bts.c
+++ b/arch/x86/events/intel/bts.c
@@ -63,7 +63,6 @@ struct bts_buffer {
63 unsigned int cur_buf; 63 unsigned int cur_buf;
64 bool snapshot; 64 bool snapshot;
65 local_t data_size; 65 local_t data_size;
66 local_t lost;
67 local_t head; 66 local_t head;
68 unsigned long end; 67 unsigned long end;
69 void **data_pages; 68 void **data_pages;
@@ -199,7 +198,8 @@ static void bts_update(struct bts_ctx *bts)
199 return; 198 return;
200 199
201 if (ds->bts_index >= ds->bts_absolute_maximum) 200 if (ds->bts_index >= ds->bts_absolute_maximum)
202 local_inc(&buf->lost); 201 perf_aux_output_flag(&bts->handle,
202 PERF_AUX_FLAG_TRUNCATED);
203 203
204 /* 204 /*
205 * old and head are always in the same physical buffer, so we 205 * old and head are always in the same physical buffer, so we
@@ -276,7 +276,7 @@ static void bts_event_start(struct perf_event *event, int flags)
276 return; 276 return;
277 277
278fail_end_stop: 278fail_end_stop:
279 perf_aux_output_end(&bts->handle, 0, false); 279 perf_aux_output_end(&bts->handle, 0);
280 280
281fail_stop: 281fail_stop:
282 event->hw.state = PERF_HES_STOPPED; 282 event->hw.state = PERF_HES_STOPPED;
@@ -319,9 +319,8 @@ static void bts_event_stop(struct perf_event *event, int flags)
319 bts->handle.head = 319 bts->handle.head =
320 local_xchg(&buf->data_size, 320 local_xchg(&buf->data_size,
321 buf->nr_pages << PAGE_SHIFT); 321 buf->nr_pages << PAGE_SHIFT);
322 322 perf_aux_output_end(&bts->handle,
323 perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0), 323 local_xchg(&buf->data_size, 0));
324 !!local_xchg(&buf->lost, 0));
325 } 324 }
326 325
327 cpuc->ds->bts_index = bts->ds_back.bts_buffer_base; 326 cpuc->ds->bts_index = bts->ds_back.bts_buffer_base;
@@ -484,8 +483,7 @@ int intel_bts_interrupt(void)
484 if (old_head == local_read(&buf->head)) 483 if (old_head == local_read(&buf->head))
485 return handled; 484 return handled;
486 485
487 perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0), 486 perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0));
488 !!local_xchg(&buf->lost, 0));
489 487
490 buf = perf_aux_output_begin(&bts->handle, event); 488 buf = perf_aux_output_begin(&bts->handle, event);
491 if (buf) 489 if (buf)
@@ -500,7 +498,7 @@ int intel_bts_interrupt(void)
500 * cleared handle::event 498 * cleared handle::event
501 */ 499 */
502 barrier(); 500 barrier();
503 perf_aux_output_end(&bts->handle, 0, false); 501 perf_aux_output_end(&bts->handle, 0);
504 } 502 }
505 } 503 }
506 504
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index eb1484c86bb4..a6d91d4e37a1 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -1553,6 +1553,27 @@ static __initconst const u64 slm_hw_cache_event_ids
1553 }, 1553 },
1554}; 1554};
1555 1555
1556EVENT_ATTR_STR(topdown-total-slots, td_total_slots_glm, "event=0x3c");
1557EVENT_ATTR_STR(topdown-total-slots.scale, td_total_slots_scale_glm, "3");
1558/* UOPS_NOT_DELIVERED.ANY */
1559EVENT_ATTR_STR(topdown-fetch-bubbles, td_fetch_bubbles_glm, "event=0x9c");
1560/* ISSUE_SLOTS_NOT_CONSUMED.RECOVERY */
1561EVENT_ATTR_STR(topdown-recovery-bubbles, td_recovery_bubbles_glm, "event=0xca,umask=0x02");
1562/* UOPS_RETIRED.ANY */
1563EVENT_ATTR_STR(topdown-slots-retired, td_slots_retired_glm, "event=0xc2");
1564/* UOPS_ISSUED.ANY */
1565EVENT_ATTR_STR(topdown-slots-issued, td_slots_issued_glm, "event=0x0e");
1566
1567static struct attribute *glm_events_attrs[] = {
1568 EVENT_PTR(td_total_slots_glm),
1569 EVENT_PTR(td_total_slots_scale_glm),
1570 EVENT_PTR(td_fetch_bubbles_glm),
1571 EVENT_PTR(td_recovery_bubbles_glm),
1572 EVENT_PTR(td_slots_issued_glm),
1573 EVENT_PTR(td_slots_retired_glm),
1574 NULL
1575};
1576
1556static struct extra_reg intel_glm_extra_regs[] __read_mostly = { 1577static struct extra_reg intel_glm_extra_regs[] __read_mostly = {
1557 /* must define OFFCORE_RSP_X first, see intel_fixup_er() */ 1578 /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
1558 INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x760005ffbfull, RSP_0), 1579 INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x760005ffbfull, RSP_0),
@@ -2130,7 +2151,7 @@ again:
2130 * counters from the GLOBAL_STATUS mask and we always process PEBS 2151 * counters from the GLOBAL_STATUS mask and we always process PEBS
2131 * events via drain_pebs(). 2152 * events via drain_pebs().
2132 */ 2153 */
2133 status &= ~cpuc->pebs_enabled; 2154 status &= ~(cpuc->pebs_enabled & PEBS_COUNTER_MASK);
2134 2155
2135 /* 2156 /*
2136 * PEBS overflow sets bit 62 in the global status register 2157 * PEBS overflow sets bit 62 in the global status register
@@ -3750,6 +3771,7 @@ __init int intel_pmu_init(void)
3750 x86_pmu.pebs_prec_dist = true; 3771 x86_pmu.pebs_prec_dist = true;
3751 x86_pmu.lbr_pt_coexist = true; 3772 x86_pmu.lbr_pt_coexist = true;
3752 x86_pmu.flags |= PMU_FL_HAS_RSP_1; 3773 x86_pmu.flags |= PMU_FL_HAS_RSP_1;
3774 x86_pmu.cpu_events = glm_events_attrs;
3753 pr_cont("Goldmont events, "); 3775 pr_cont("Goldmont events, ");
3754 break; 3776 break;
3755 3777
diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
index 9dfeeeca0ea8..c6d23ffe422d 100644
--- a/arch/x86/events/intel/ds.c
+++ b/arch/x86/events/intel/ds.c
@@ -1222,7 +1222,7 @@ get_next_pebs_record_by_bit(void *base, void *top, int bit)
1222 1222
1223 /* clear non-PEBS bit and re-check */ 1223 /* clear non-PEBS bit and re-check */
1224 pebs_status = p->status & cpuc->pebs_enabled; 1224 pebs_status = p->status & cpuc->pebs_enabled;
1225 pebs_status &= (1ULL << MAX_PEBS_EVENTS) - 1; 1225 pebs_status &= PEBS_COUNTER_MASK;
1226 if (pebs_status == (1 << bit)) 1226 if (pebs_status == (1 << bit))
1227 return at; 1227 return at;
1228 } 1228 }
diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
index 5900471ee508..ae8324d65e61 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
@@ -28,6 +28,7 @@
28#include <asm/insn.h> 28#include <asm/insn.h>
29#include <asm/io.h> 29#include <asm/io.h>
30#include <asm/intel_pt.h> 30#include <asm/intel_pt.h>
31#include <asm/intel-family.h>
31 32
32#include "../perf_event.h" 33#include "../perf_event.h"
33#include "pt.h" 34#include "pt.h"
@@ -98,6 +99,7 @@ static struct attribute_group pt_cap_group = {
98 .name = "caps", 99 .name = "caps",
99}; 100};
100 101
102PMU_FORMAT_ATTR(pt, "config:0" );
101PMU_FORMAT_ATTR(cyc, "config:1" ); 103PMU_FORMAT_ATTR(cyc, "config:1" );
102PMU_FORMAT_ATTR(pwr_evt, "config:4" ); 104PMU_FORMAT_ATTR(pwr_evt, "config:4" );
103PMU_FORMAT_ATTR(fup_on_ptw, "config:5" ); 105PMU_FORMAT_ATTR(fup_on_ptw, "config:5" );
@@ -105,11 +107,13 @@ PMU_FORMAT_ATTR(mtc, "config:9" );
105PMU_FORMAT_ATTR(tsc, "config:10" ); 107PMU_FORMAT_ATTR(tsc, "config:10" );
106PMU_FORMAT_ATTR(noretcomp, "config:11" ); 108PMU_FORMAT_ATTR(noretcomp, "config:11" );
107PMU_FORMAT_ATTR(ptw, "config:12" ); 109PMU_FORMAT_ATTR(ptw, "config:12" );
110PMU_FORMAT_ATTR(branch, "config:13" );
108PMU_FORMAT_ATTR(mtc_period, "config:14-17" ); 111PMU_FORMAT_ATTR(mtc_period, "config:14-17" );
109PMU_FORMAT_ATTR(cyc_thresh, "config:19-22" ); 112PMU_FORMAT_ATTR(cyc_thresh, "config:19-22" );
110PMU_FORMAT_ATTR(psb_period, "config:24-27" ); 113PMU_FORMAT_ATTR(psb_period, "config:24-27" );
111 114
112static struct attribute *pt_formats_attr[] = { 115static struct attribute *pt_formats_attr[] = {
116 &format_attr_pt.attr,
113 &format_attr_cyc.attr, 117 &format_attr_cyc.attr,
114 &format_attr_pwr_evt.attr, 118 &format_attr_pwr_evt.attr,
115 &format_attr_fup_on_ptw.attr, 119 &format_attr_fup_on_ptw.attr,
@@ -117,6 +121,7 @@ static struct attribute *pt_formats_attr[] = {
117 &format_attr_tsc.attr, 121 &format_attr_tsc.attr,
118 &format_attr_noretcomp.attr, 122 &format_attr_noretcomp.attr,
119 &format_attr_ptw.attr, 123 &format_attr_ptw.attr,
124 &format_attr_branch.attr,
120 &format_attr_mtc_period.attr, 125 &format_attr_mtc_period.attr,
121 &format_attr_cyc_thresh.attr, 126 &format_attr_cyc_thresh.attr,
122 &format_attr_psb_period.attr, 127 &format_attr_psb_period.attr,
@@ -197,6 +202,19 @@ static int __init pt_pmu_hw_init(void)
197 pt_pmu.tsc_art_den = eax; 202 pt_pmu.tsc_art_den = eax;
198 } 203 }
199 204
205 /* model-specific quirks */
206 switch (boot_cpu_data.x86_model) {
207 case INTEL_FAM6_BROADWELL_CORE:
208 case INTEL_FAM6_BROADWELL_XEON_D:
209 case INTEL_FAM6_BROADWELL_GT3E:
210 case INTEL_FAM6_BROADWELL_X:
211 /* not setting BRANCH_EN will #GP, erratum BDM106 */
212 pt_pmu.branch_en_always_on = true;
213 break;
214 default:
215 break;
216 }
217
200 if (boot_cpu_has(X86_FEATURE_VMX)) { 218 if (boot_cpu_has(X86_FEATURE_VMX)) {
201 /* 219 /*
202 * Intel SDM, 36.5 "Tracing post-VMXON" says that 220 * Intel SDM, 36.5 "Tracing post-VMXON" says that
@@ -263,8 +281,20 @@ fail:
263#define RTIT_CTL_PTW (RTIT_CTL_PTW_EN | \ 281#define RTIT_CTL_PTW (RTIT_CTL_PTW_EN | \
264 RTIT_CTL_FUP_ON_PTW) 282 RTIT_CTL_FUP_ON_PTW)
265 283
266#define PT_CONFIG_MASK (RTIT_CTL_TSC_EN | \ 284/*
285 * Bit 0 (TraceEn) in the attr.config is meaningless as the
286 * corresponding bit in the RTIT_CTL can only be controlled
287 * by the driver; therefore, repurpose it to mean: pass
288 * through the bit that was previously assumed to be always
289 * on for PT, thereby allowing the user to *not* set it if
290 * they so wish. See also pt_event_valid() and pt_config().
291 */
292#define RTIT_CTL_PASSTHROUGH RTIT_CTL_TRACEEN
293
294#define PT_CONFIG_MASK (RTIT_CTL_TRACEEN | \
295 RTIT_CTL_TSC_EN | \
267 RTIT_CTL_DISRETC | \ 296 RTIT_CTL_DISRETC | \
297 RTIT_CTL_BRANCH_EN | \
268 RTIT_CTL_CYC_PSB | \ 298 RTIT_CTL_CYC_PSB | \
269 RTIT_CTL_MTC | \ 299 RTIT_CTL_MTC | \
270 RTIT_CTL_PWR_EVT_EN | \ 300 RTIT_CTL_PWR_EVT_EN | \
@@ -332,6 +362,33 @@ static bool pt_event_valid(struct perf_event *event)
332 return false; 362 return false;
333 } 363 }
334 364
365 /*
366 * Setting bit 0 (TraceEn in RTIT_CTL MSR) in the attr.config
367 * clears the assomption that BranchEn must always be enabled,
368 * as was the case with the first implementation of PT.
369 * If this bit is not set, the legacy behavior is preserved
370 * for compatibility with the older userspace.
371 *
372 * Re-using bit 0 for this purpose is fine because it is never
373 * directly set by the user; previous attempts at setting it in
374 * the attr.config resulted in -EINVAL.
375 */
376 if (config & RTIT_CTL_PASSTHROUGH) {
377 /*
378 * Disallow not setting BRANCH_EN where BRANCH_EN is
379 * always required.
380 */
381 if (pt_pmu.branch_en_always_on &&
382 !(config & RTIT_CTL_BRANCH_EN))
383 return false;
384 } else {
385 /*
386 * Disallow BRANCH_EN without the PASSTHROUGH.
387 */
388 if (config & RTIT_CTL_BRANCH_EN)
389 return false;
390 }
391
335 return true; 392 return true;
336} 393}
337 394
@@ -411,6 +468,7 @@ static u64 pt_config_filters(struct perf_event *event)
411 468
412static void pt_config(struct perf_event *event) 469static void pt_config(struct perf_event *event)
413{ 470{
471 struct pt *pt = this_cpu_ptr(&pt_ctx);
414 u64 reg; 472 u64 reg;
415 473
416 if (!event->hw.itrace_started) { 474 if (!event->hw.itrace_started) {
@@ -419,7 +477,20 @@ static void pt_config(struct perf_event *event)
419 } 477 }
420 478
421 reg = pt_config_filters(event); 479 reg = pt_config_filters(event);
422 reg |= RTIT_CTL_TOPA | RTIT_CTL_BRANCH_EN | RTIT_CTL_TRACEEN; 480 reg |= RTIT_CTL_TOPA | RTIT_CTL_TRACEEN;
481
482 /*
483 * Previously, we had BRANCH_EN on by default, but now that PT has
484 * grown features outside of branch tracing, it is useful to allow
485 * the user to disable it. Setting bit 0 in the event's attr.config
486 * allows BRANCH_EN to pass through instead of being always on. See
487 * also the comment in pt_event_valid().
488 */
489 if (event->attr.config & BIT(0)) {
490 reg |= event->attr.config & RTIT_CTL_BRANCH_EN;
491 } else {
492 reg |= RTIT_CTL_BRANCH_EN;
493 }
423 494
424 if (!event->attr.exclude_kernel) 495 if (!event->attr.exclude_kernel)
425 reg |= RTIT_CTL_OS; 496 reg |= RTIT_CTL_OS;
@@ -429,11 +500,15 @@ static void pt_config(struct perf_event *event)
429 reg |= (event->attr.config & PT_CONFIG_MASK); 500 reg |= (event->attr.config & PT_CONFIG_MASK);
430 501
431 event->hw.config = reg; 502 event->hw.config = reg;
432 wrmsrl(MSR_IA32_RTIT_CTL, reg); 503 if (READ_ONCE(pt->vmx_on))
504 perf_aux_output_flag(&pt->handle, PERF_AUX_FLAG_PARTIAL);
505 else
506 wrmsrl(MSR_IA32_RTIT_CTL, reg);
433} 507}
434 508
435static void pt_config_stop(struct perf_event *event) 509static void pt_config_stop(struct perf_event *event)
436{ 510{
511 struct pt *pt = this_cpu_ptr(&pt_ctx);
437 u64 ctl = READ_ONCE(event->hw.config); 512 u64 ctl = READ_ONCE(event->hw.config);
438 513
439 /* may be already stopped by a PMI */ 514 /* may be already stopped by a PMI */
@@ -441,7 +516,8 @@ static void pt_config_stop(struct perf_event *event)
441 return; 516 return;
442 517
443 ctl &= ~RTIT_CTL_TRACEEN; 518 ctl &= ~RTIT_CTL_TRACEEN;
444 wrmsrl(MSR_IA32_RTIT_CTL, ctl); 519 if (!READ_ONCE(pt->vmx_on))
520 wrmsrl(MSR_IA32_RTIT_CTL, ctl);
445 521
446 WRITE_ONCE(event->hw.config, ctl); 522 WRITE_ONCE(event->hw.config, ctl);
447 523
@@ -753,7 +829,8 @@ static void pt_handle_status(struct pt *pt)
753 */ 829 */
754 if (!pt_cap_get(PT_CAP_topa_multiple_entries) || 830 if (!pt_cap_get(PT_CAP_topa_multiple_entries) ||
755 buf->output_off == sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) { 831 buf->output_off == sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) {
756 local_inc(&buf->lost); 832 perf_aux_output_flag(&pt->handle,
833 PERF_AUX_FLAG_TRUNCATED);
757 advance++; 834 advance++;
758 } 835 }
759 } 836 }
@@ -846,8 +923,10 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
846 923
847 /* can't stop in the middle of an output region */ 924 /* can't stop in the middle of an output region */
848 if (buf->output_off + handle->size + 1 < 925 if (buf->output_off + handle->size + 1 <
849 sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) 926 sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) {
927 perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
850 return -EINVAL; 928 return -EINVAL;
929 }
851 930
852 931
853 /* single entry ToPA is handled by marking all regions STOP=1 INT=1 */ 932 /* single entry ToPA is handled by marking all regions STOP=1 INT=1 */
@@ -1171,12 +1250,6 @@ void intel_pt_interrupt(void)
1171 if (!READ_ONCE(pt->handle_nmi)) 1250 if (!READ_ONCE(pt->handle_nmi))
1172 return; 1251 return;
1173 1252
1174 /*
1175 * If VMX is on and PT does not support it, don't touch anything.
1176 */
1177 if (READ_ONCE(pt->vmx_on))
1178 return;
1179
1180 if (!event) 1253 if (!event)
1181 return; 1254 return;
1182 1255
@@ -1192,8 +1265,7 @@ void intel_pt_interrupt(void)
1192 1265
1193 pt_update_head(pt); 1266 pt_update_head(pt);
1194 1267
1195 perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0), 1268 perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0));
1196 local_xchg(&buf->lost, 0));
1197 1269
1198 if (!event->hw.state) { 1270 if (!event->hw.state) {
1199 int ret; 1271 int ret;
@@ -1208,7 +1280,7 @@ void intel_pt_interrupt(void)
1208 /* snapshot counters don't use PMI, so it's safe */ 1280 /* snapshot counters don't use PMI, so it's safe */
1209 ret = pt_buffer_reset_markers(buf, &pt->handle); 1281 ret = pt_buffer_reset_markers(buf, &pt->handle);
1210 if (ret) { 1282 if (ret) {
1211 perf_aux_output_end(&pt->handle, 0, true); 1283 perf_aux_output_end(&pt->handle, 0);
1212 return; 1284 return;
1213 } 1285 }
1214 1286
@@ -1237,12 +1309,19 @@ void intel_pt_handle_vmx(int on)
1237 local_irq_save(flags); 1309 local_irq_save(flags);
1238 WRITE_ONCE(pt->vmx_on, on); 1310 WRITE_ONCE(pt->vmx_on, on);
1239 1311
1240 if (on) { 1312 /*
1241 /* prevent pt_config_stop() from writing RTIT_CTL */ 1313 * If an AUX transaction is in progress, it will contain
1242 event = pt->handle.event; 1314 * gap(s), so flag it PARTIAL to inform the user.
1243 if (event) 1315 */
1244 event->hw.config = 0; 1316 event = pt->handle.event;
1245 } 1317 if (event)
1318 perf_aux_output_flag(&pt->handle,
1319 PERF_AUX_FLAG_PARTIAL);
1320
1321 /* Turn PTs back on */
1322 if (!on && event)
1323 wrmsrl(MSR_IA32_RTIT_CTL, event->hw.config);
1324
1246 local_irq_restore(flags); 1325 local_irq_restore(flags);
1247} 1326}
1248EXPORT_SYMBOL_GPL(intel_pt_handle_vmx); 1327EXPORT_SYMBOL_GPL(intel_pt_handle_vmx);
@@ -1257,9 +1336,6 @@ static void pt_event_start(struct perf_event *event, int mode)
1257 struct pt *pt = this_cpu_ptr(&pt_ctx); 1336 struct pt *pt = this_cpu_ptr(&pt_ctx);
1258 struct pt_buffer *buf; 1337 struct pt_buffer *buf;
1259 1338
1260 if (READ_ONCE(pt->vmx_on))
1261 return;
1262
1263 buf = perf_aux_output_begin(&pt->handle, event); 1339 buf = perf_aux_output_begin(&pt->handle, event);
1264 if (!buf) 1340 if (!buf)
1265 goto fail_stop; 1341 goto fail_stop;
@@ -1280,7 +1356,7 @@ static void pt_event_start(struct perf_event *event, int mode)
1280 return; 1356 return;
1281 1357
1282fail_end_stop: 1358fail_end_stop:
1283 perf_aux_output_end(&pt->handle, 0, true); 1359 perf_aux_output_end(&pt->handle, 0);
1284fail_stop: 1360fail_stop:
1285 hwc->state = PERF_HES_STOPPED; 1361 hwc->state = PERF_HES_STOPPED;
1286} 1362}
@@ -1321,8 +1397,7 @@ static void pt_event_stop(struct perf_event *event, int mode)
1321 pt->handle.head = 1397 pt->handle.head =
1322 local_xchg(&buf->data_size, 1398 local_xchg(&buf->data_size,
1323 buf->nr_pages << PAGE_SHIFT); 1399 buf->nr_pages << PAGE_SHIFT);
1324 perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0), 1400 perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0));
1325 local_xchg(&buf->lost, 0));
1326 } 1401 }
1327} 1402}
1328 1403
diff --git a/arch/x86/events/intel/pt.h b/arch/x86/events/intel/pt.h
index 53473c21b554..0eb41d07b79a 100644
--- a/arch/x86/events/intel/pt.h
+++ b/arch/x86/events/intel/pt.h
@@ -110,6 +110,7 @@ struct pt_pmu {
110 struct pmu pmu; 110 struct pmu pmu;
111 u32 caps[PT_CPUID_REGS_NUM * PT_CPUID_LEAVES]; 111 u32 caps[PT_CPUID_REGS_NUM * PT_CPUID_LEAVES];
112 bool vmx; 112 bool vmx;
113 bool branch_en_always_on;
113 unsigned long max_nonturbo_ratio; 114 unsigned long max_nonturbo_ratio;
114 unsigned int tsc_art_num; 115 unsigned int tsc_art_num;
115 unsigned int tsc_art_den; 116 unsigned int tsc_art_den;
@@ -143,7 +144,6 @@ struct pt_buffer {
143 size_t output_off; 144 size_t output_off;
144 unsigned long nr_pages; 145 unsigned long nr_pages;
145 local_t data_size; 146 local_t data_size;
146 local_t lost;
147 local64_t head; 147 local64_t head;
148 bool snapshot; 148 bool snapshot;
149 unsigned long stop_pos, intr_pos; 149 unsigned long stop_pos, intr_pos;
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
index bcbb1d2ae10b..be3d36254040 100644
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -79,6 +79,7 @@ struct amd_nb {
79 79
80/* The maximal number of PEBS events: */ 80/* The maximal number of PEBS events: */
81#define MAX_PEBS_EVENTS 8 81#define MAX_PEBS_EVENTS 8
82#define PEBS_COUNTER_MASK ((1ULL << MAX_PEBS_EVENTS) - 1)
82 83
83/* 84/*
84 * Flags PEBS can handle without an PMI. 85 * Flags PEBS can handle without an PMI.
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index b04bb6dfed7f..0fe00446f9ca 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -187,6 +187,7 @@
187 * Reuse free bits when adding new feature flags! 187 * Reuse free bits when adding new feature flags!
188 */ 188 */
189#define X86_FEATURE_RING3MWAIT ( 7*32+ 0) /* Ring 3 MONITOR/MWAIT */ 189#define X86_FEATURE_RING3MWAIT ( 7*32+ 0) /* Ring 3 MONITOR/MWAIT */
190#define X86_FEATURE_CPUID_FAULT ( 7*32+ 1) /* Intel CPUID faulting */
190#define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */ 191#define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */
191#define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */ 192#define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */
192#define X86_FEATURE_CAT_L3 ( 7*32+ 4) /* Cache Allocation Technology L3 */ 193#define X86_FEATURE_CAT_L3 ( 7*32+ 4) /* Cache Allocation Technology L3 */
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index 200581691c6e..34b984c60790 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -72,14 +72,13 @@ struct arch_specific_insn {
72 /* copy of the original instruction */ 72 /* copy of the original instruction */
73 kprobe_opcode_t *insn; 73 kprobe_opcode_t *insn;
74 /* 74 /*
75 * boostable = -1: This instruction type is not boostable. 75 * boostable = false: This instruction type is not boostable.
76 * boostable = 0: This instruction type is boostable. 76 * boostable = true: This instruction has been boosted: we have
77 * boostable = 1: This instruction has been boosted: we have
78 * added a relative jump after the instruction copy in insn, 77 * added a relative jump after the instruction copy in insn,
79 * so no single-step and fixup are needed (unless there's 78 * so no single-step and fixup are needed (unless there's
80 * a post_handler or break_handler). 79 * a post_handler or break_handler).
81 */ 80 */
82 int boostable; 81 bool boostable;
83 bool if_modifier; 82 bool if_modifier;
84}; 83};
85 84
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index d8b5f8ab8ef9..673f9ac50f6d 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -45,6 +45,8 @@
45#define MSR_IA32_PERFCTR1 0x000000c2 45#define MSR_IA32_PERFCTR1 0x000000c2
46#define MSR_FSB_FREQ 0x000000cd 46#define MSR_FSB_FREQ 0x000000cd
47#define MSR_PLATFORM_INFO 0x000000ce 47#define MSR_PLATFORM_INFO 0x000000ce
48#define MSR_PLATFORM_INFO_CPUID_FAULT_BIT 31
49#define MSR_PLATFORM_INFO_CPUID_FAULT BIT_ULL(MSR_PLATFORM_INFO_CPUID_FAULT_BIT)
48 50
49#define MSR_PKG_CST_CONFIG_CONTROL 0x000000e2 51#define MSR_PKG_CST_CONFIG_CONTROL 0x000000e2
50#define NHM_C3_AUTO_DEMOTE (1UL << 25) 52#define NHM_C3_AUTO_DEMOTE (1UL << 25)
@@ -127,6 +129,7 @@
127 129
128/* DEBUGCTLMSR bits (others vary by model): */ 130/* DEBUGCTLMSR bits (others vary by model): */
129#define DEBUGCTLMSR_LBR (1UL << 0) /* last branch recording */ 131#define DEBUGCTLMSR_LBR (1UL << 0) /* last branch recording */
132#define DEBUGCTLMSR_BTF_SHIFT 1
130#define DEBUGCTLMSR_BTF (1UL << 1) /* single-step on branches */ 133#define DEBUGCTLMSR_BTF (1UL << 1) /* single-step on branches */
131#define DEBUGCTLMSR_TR (1UL << 6) 134#define DEBUGCTLMSR_TR (1UL << 6)
132#define DEBUGCTLMSR_BTS (1UL << 7) 135#define DEBUGCTLMSR_BTS (1UL << 7)
@@ -552,10 +555,12 @@
552#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT 39 555#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT 39
553#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE (1ULL << MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT) 556#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE (1ULL << MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT)
554 557
555/* MISC_FEATURE_ENABLES non-architectural features */ 558/* MISC_FEATURES_ENABLES non-architectural features */
556#define MSR_MISC_FEATURE_ENABLES 0x00000140 559#define MSR_MISC_FEATURES_ENABLES 0x00000140
557 560
558#define MSR_MISC_FEATURE_ENABLES_RING3MWAIT_BIT 1 561#define MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT 0
562#define MSR_MISC_FEATURES_ENABLES_CPUID_FAULT BIT_ULL(MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT)
563#define MSR_MISC_FEATURES_ENABLES_RING3MWAIT_BIT 1
559 564
560#define MSR_IA32_TSC_DEADLINE 0x000006E0 565#define MSR_IA32_TSC_DEADLINE 0x000006E0
561 566
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index f385eca5407a..a80c1b3997ed 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -884,6 +884,8 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_ip,
884extern int get_tsc_mode(unsigned long adr); 884extern int get_tsc_mode(unsigned long adr);
885extern int set_tsc_mode(unsigned int val); 885extern int set_tsc_mode(unsigned int val);
886 886
887DECLARE_PER_CPU(u64, msr_misc_features_shadow);
888
887/* Register/unregister a process' MPX related resource */ 889/* Register/unregister a process' MPX related resource */
888#define MPX_ENABLE_MANAGEMENT() mpx_enable_management() 890#define MPX_ENABLE_MANAGEMENT() mpx_enable_management()
889#define MPX_DISABLE_MANAGEMENT() mpx_disable_management() 891#define MPX_DISABLE_MANAGEMENT() mpx_disable_management()
diff --git a/arch/x86/include/asm/proto.h b/arch/x86/include/asm/proto.h
index 9b9b30b19441..8d3964fc5f91 100644
--- a/arch/x86/include/asm/proto.h
+++ b/arch/x86/include/asm/proto.h
@@ -9,6 +9,7 @@ void syscall_init(void);
9 9
10#ifdef CONFIG_X86_64 10#ifdef CONFIG_X86_64
11void entry_SYSCALL_64(void); 11void entry_SYSCALL_64(void);
12long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2);
12#endif 13#endif
13 14
14#ifdef CONFIG_X86_32 15#ifdef CONFIG_X86_32
@@ -30,6 +31,7 @@ void x86_report_nx(void);
30 31
31extern int reboot_force; 32extern int reboot_force;
32 33
33long do_arch_prctl(struct task_struct *task, int code, unsigned long addr); 34long do_arch_prctl_common(struct task_struct *task, int option,
35 unsigned long cpuid_enabled);
34 36
35#endif /* _ASM_X86_PROTO_H */ 37#endif /* _ASM_X86_PROTO_H */
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index ad6f5eb07a95..9fc44b95f7cb 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -87,6 +87,7 @@ struct thread_info {
87#define TIF_SECCOMP 8 /* secure computing */ 87#define TIF_SECCOMP 8 /* secure computing */
88#define TIF_USER_RETURN_NOTIFY 11 /* notify kernel of userspace return */ 88#define TIF_USER_RETURN_NOTIFY 11 /* notify kernel of userspace return */
89#define TIF_UPROBE 12 /* breakpointed or singlestepping */ 89#define TIF_UPROBE 12 /* breakpointed or singlestepping */
90#define TIF_NOCPUID 15 /* CPUID is not accessible in userland */
90#define TIF_NOTSC 16 /* TSC is not accessible in userland */ 91#define TIF_NOTSC 16 /* TSC is not accessible in userland */
91#define TIF_IA32 17 /* IA32 compatibility process */ 92#define TIF_IA32 17 /* IA32 compatibility process */
92#define TIF_NOHZ 19 /* in adaptive nohz mode */ 93#define TIF_NOHZ 19 /* in adaptive nohz mode */
@@ -110,6 +111,7 @@ struct thread_info {
110#define _TIF_SECCOMP (1 << TIF_SECCOMP) 111#define _TIF_SECCOMP (1 << TIF_SECCOMP)
111#define _TIF_USER_RETURN_NOTIFY (1 << TIF_USER_RETURN_NOTIFY) 112#define _TIF_USER_RETURN_NOTIFY (1 << TIF_USER_RETURN_NOTIFY)
112#define _TIF_UPROBE (1 << TIF_UPROBE) 113#define _TIF_UPROBE (1 << TIF_UPROBE)
114#define _TIF_NOCPUID (1 << TIF_NOCPUID)
113#define _TIF_NOTSC (1 << TIF_NOTSC) 115#define _TIF_NOTSC (1 << TIF_NOTSC)
114#define _TIF_IA32 (1 << TIF_IA32) 116#define _TIF_IA32 (1 << TIF_IA32)
115#define _TIF_NOHZ (1 << TIF_NOHZ) 117#define _TIF_NOHZ (1 << TIF_NOHZ)
@@ -138,7 +140,7 @@ struct thread_info {
138 140
139/* flags to check in __switch_to() */ 141/* flags to check in __switch_to() */
140#define _TIF_WORK_CTXSW \ 142#define _TIF_WORK_CTXSW \
141 (_TIF_IO_BITMAP|_TIF_NOTSC|_TIF_BLOCKSTEP) 143 (_TIF_IO_BITMAP|_TIF_NOCPUID|_TIF_NOTSC|_TIF_BLOCKSTEP)
142 144
143#define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY) 145#define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY)
144#define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW) 146#define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW)
@@ -239,6 +241,8 @@ static inline int arch_within_stack_frames(const void * const stack,
239extern void arch_task_cache_init(void); 241extern void arch_task_cache_init(void);
240extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); 242extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
241extern void arch_release_task_struct(struct task_struct *tsk); 243extern void arch_release_task_struct(struct task_struct *tsk);
244extern void arch_setup_new_exec(void);
245#define arch_setup_new_exec arch_setup_new_exec
242#endif /* !__ASSEMBLY__ */ 246#endif /* !__ASSEMBLY__ */
243 247
244#endif /* _ASM_X86_THREAD_INFO_H */ 248#endif /* _ASM_X86_THREAD_INFO_H */
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index fc5abff9b7fd..75d002bdb3f3 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -110,6 +110,16 @@ static inline void cr4_clear_bits(unsigned long mask)
110 } 110 }
111} 111}
112 112
113static inline void cr4_toggle_bits(unsigned long mask)
114{
115 unsigned long cr4;
116
117 cr4 = this_cpu_read(cpu_tlbstate.cr4);
118 cr4 ^= mask;
119 this_cpu_write(cpu_tlbstate.cr4, cr4);
120 __write_cr4(cr4);
121}
122
113/* Read the CR4 shadow. */ 123/* Read the CR4 shadow. */
114static inline unsigned long cr4_read_shadow(void) 124static inline unsigned long cr4_read_shadow(void)
115{ 125{
diff --git a/arch/x86/include/uapi/asm/prctl.h b/arch/x86/include/uapi/asm/prctl.h
index 835aa51c7f6e..c45765517092 100644
--- a/arch/x86/include/uapi/asm/prctl.h
+++ b/arch/x86/include/uapi/asm/prctl.h
@@ -1,10 +1,13 @@
1#ifndef _ASM_X86_PRCTL_H 1#ifndef _ASM_X86_PRCTL_H
2#define _ASM_X86_PRCTL_H 2#define _ASM_X86_PRCTL_H
3 3
4#define ARCH_SET_GS 0x1001 4#define ARCH_SET_GS 0x1001
5#define ARCH_SET_FS 0x1002 5#define ARCH_SET_FS 0x1002
6#define ARCH_GET_FS 0x1003 6#define ARCH_GET_FS 0x1003
7#define ARCH_GET_GS 0x1004 7#define ARCH_GET_GS 0x1004
8
9#define ARCH_GET_CPUID 0x1011
10#define ARCH_SET_CPUID 0x1012
8 11
9#define ARCH_MAP_VDSO_X32 0x2001 12#define ARCH_MAP_VDSO_X32 0x2001
10#define ARCH_MAP_VDSO_32 0x2002 13#define ARCH_MAP_VDSO_32 0x2002
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 063197771b8d..dfa90a3a5145 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -90,16 +90,12 @@ static void probe_xeon_phi_r3mwait(struct cpuinfo_x86 *c)
90 return; 90 return;
91 } 91 }
92 92
93 if (ring3mwait_disabled) { 93 if (ring3mwait_disabled)
94 msr_clear_bit(MSR_MISC_FEATURE_ENABLES,
95 MSR_MISC_FEATURE_ENABLES_RING3MWAIT_BIT);
96 return; 94 return;
97 }
98
99 msr_set_bit(MSR_MISC_FEATURE_ENABLES,
100 MSR_MISC_FEATURE_ENABLES_RING3MWAIT_BIT);
101 95
102 set_cpu_cap(c, X86_FEATURE_RING3MWAIT); 96 set_cpu_cap(c, X86_FEATURE_RING3MWAIT);
97 this_cpu_or(msr_misc_features_shadow,
98 1UL << MSR_MISC_FEATURES_ENABLES_RING3MWAIT_BIT);
103 99
104 if (c == &boot_cpu_data) 100 if (c == &boot_cpu_data)
105 ELF_HWCAP2 |= HWCAP2_RING3MWAIT; 101 ELF_HWCAP2 |= HWCAP2_RING3MWAIT;
@@ -488,6 +484,34 @@ static void intel_bsp_resume(struct cpuinfo_x86 *c)
488 init_intel_energy_perf(c); 484 init_intel_energy_perf(c);
489} 485}
490 486
487static void init_cpuid_fault(struct cpuinfo_x86 *c)
488{
489 u64 msr;
490
491 if (!rdmsrl_safe(MSR_PLATFORM_INFO, &msr)) {
492 if (msr & MSR_PLATFORM_INFO_CPUID_FAULT)
493 set_cpu_cap(c, X86_FEATURE_CPUID_FAULT);
494 }
495}
496
497static void init_intel_misc_features(struct cpuinfo_x86 *c)
498{
499 u64 msr;
500
501 if (rdmsrl_safe(MSR_MISC_FEATURES_ENABLES, &msr))
502 return;
503
504 /* Clear all MISC features */
505 this_cpu_write(msr_misc_features_shadow, 0);
506
507 /* Check features and update capabilities and shadow control bits */
508 init_cpuid_fault(c);
509 probe_xeon_phi_r3mwait(c);
510
511 msr = this_cpu_read(msr_misc_features_shadow);
512 wrmsrl(MSR_MISC_FEATURES_ENABLES, msr);
513}
514
491static void init_intel(struct cpuinfo_x86 *c) 515static void init_intel(struct cpuinfo_x86 *c)
492{ 516{
493 unsigned int l2 = 0; 517 unsigned int l2 = 0;
@@ -602,7 +626,7 @@ static void init_intel(struct cpuinfo_x86 *c)
602 626
603 init_intel_energy_perf(c); 627 init_intel_energy_perf(c);
604 628
605 probe_xeon_phi_r3mwait(c); 629 init_intel_misc_features(c);
606} 630}
607 631
608#ifdef CONFIG_X86_32 632#ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/kprobes/common.h b/arch/x86/kernel/kprobes/common.h
index d688826e5736..db2182d63ed0 100644
--- a/arch/x86/kernel/kprobes/common.h
+++ b/arch/x86/kernel/kprobes/common.h
@@ -67,7 +67,7 @@
67#endif 67#endif
68 68
69/* Ensure if the instruction can be boostable */ 69/* Ensure if the instruction can be boostable */
70extern int can_boost(kprobe_opcode_t *instruction, void *addr); 70extern int can_boost(struct insn *insn, void *orig_addr);
71/* Recover instruction if given address is probed */ 71/* Recover instruction if given address is probed */
72extern unsigned long recover_probed_instruction(kprobe_opcode_t *buf, 72extern unsigned long recover_probed_instruction(kprobe_opcode_t *buf,
73 unsigned long addr); 73 unsigned long addr);
@@ -75,7 +75,7 @@ extern unsigned long recover_probed_instruction(kprobe_opcode_t *buf,
75 * Copy an instruction and adjust the displacement if the instruction 75 * Copy an instruction and adjust the displacement if the instruction
76 * uses the %rip-relative addressing mode. 76 * uses the %rip-relative addressing mode.
77 */ 77 */
78extern int __copy_instruction(u8 *dest, u8 *src); 78extern int __copy_instruction(u8 *dest, u8 *src, struct insn *insn);
79 79
80/* Generate a relative-jump/call instruction */ 80/* Generate a relative-jump/call instruction */
81extern void synthesize_reljump(void *from, void *to); 81extern void synthesize_reljump(void *from, void *to);
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 993fa4fe4f68..19e1f2a6d7b0 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -164,42 +164,38 @@ static kprobe_opcode_t *skip_prefixes(kprobe_opcode_t *insn)
164NOKPROBE_SYMBOL(skip_prefixes); 164NOKPROBE_SYMBOL(skip_prefixes);
165 165
166/* 166/*
167 * Returns non-zero if opcode is boostable. 167 * Returns non-zero if INSN is boostable.
168 * RIP relative instructions are adjusted at copying time in 64 bits mode 168 * RIP relative instructions are adjusted at copying time in 64 bits mode
169 */ 169 */
170int can_boost(kprobe_opcode_t *opcodes, void *addr) 170int can_boost(struct insn *insn, void *addr)
171{ 171{
172 kprobe_opcode_t opcode; 172 kprobe_opcode_t opcode;
173 kprobe_opcode_t *orig_opcodes = opcodes;
174 173
175 if (search_exception_tables((unsigned long)addr)) 174 if (search_exception_tables((unsigned long)addr))
176 return 0; /* Page fault may occur on this address. */ 175 return 0; /* Page fault may occur on this address. */
177 176
178retry:
179 if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1)
180 return 0;
181 opcode = *(opcodes++);
182
183 /* 2nd-byte opcode */ 177 /* 2nd-byte opcode */
184 if (opcode == 0x0f) { 178 if (insn->opcode.nbytes == 2)
185 if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1) 179 return test_bit(insn->opcode.bytes[1],
186 return 0;
187 return test_bit(*opcodes,
188 (unsigned long *)twobyte_is_boostable); 180 (unsigned long *)twobyte_is_boostable);
189 } 181
182 if (insn->opcode.nbytes != 1)
183 return 0;
184
185 /* Can't boost Address-size override prefix */
186 if (unlikely(inat_is_address_size_prefix(insn->attr)))
187 return 0;
188
189 opcode = insn->opcode.bytes[0];
190 190
191 switch (opcode & 0xf0) { 191 switch (opcode & 0xf0) {
192#ifdef CONFIG_X86_64
193 case 0x40:
194 goto retry; /* REX prefix is boostable */
195#endif
196 case 0x60: 192 case 0x60:
197 if (0x63 < opcode && opcode < 0x67) 193 /* can't boost "bound" */
198 goto retry; /* prefixes */ 194 return (opcode != 0x62);
199 /* can't boost Address-size override and bound */
200 return (opcode != 0x62 && opcode != 0x67);
201 case 0x70: 195 case 0x70:
202 return 0; /* can't boost conditional jump */ 196 return 0; /* can't boost conditional jump */
197 case 0x90:
198 return opcode != 0x9a; /* can't boost call far */
203 case 0xc0: 199 case 0xc0:
204 /* can't boost software-interruptions */ 200 /* can't boost software-interruptions */
205 return (0xc1 < opcode && opcode < 0xcc) || opcode == 0xcf; 201 return (0xc1 < opcode && opcode < 0xcc) || opcode == 0xcf;
@@ -210,14 +206,9 @@ retry:
210 /* can boost in/out and absolute jmps */ 206 /* can boost in/out and absolute jmps */
211 return ((opcode & 0x04) || opcode == 0xea); 207 return ((opcode & 0x04) || opcode == 0xea);
212 case 0xf0: 208 case 0xf0:
213 if ((opcode & 0x0c) == 0 && opcode != 0xf1)
214 goto retry; /* lock/rep(ne) prefix */
215 /* clear and set flags are boostable */ 209 /* clear and set flags are boostable */
216 return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe)); 210 return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe));
217 default: 211 default:
218 /* segment override prefixes are boostable */
219 if (opcode == 0x26 || opcode == 0x36 || opcode == 0x3e)
220 goto retry; /* prefixes */
221 /* CS override prefix and call are not boostable */ 212 /* CS override prefix and call are not boostable */
222 return (opcode != 0x2e && opcode != 0x9a); 213 return (opcode != 0x2e && opcode != 0x9a);
223 } 214 }
@@ -264,7 +255,10 @@ __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
264 * Fortunately, we know that the original code is the ideal 5-byte 255 * Fortunately, we know that the original code is the ideal 5-byte
265 * long NOP. 256 * long NOP.
266 */ 257 */
267 memcpy(buf, (void *)addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); 258 if (probe_kernel_read(buf, (void *)addr,
259 MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
260 return 0UL;
261
268 if (faddr) 262 if (faddr)
269 memcpy(buf, ideal_nops[NOP_ATOMIC5], 5); 263 memcpy(buf, ideal_nops[NOP_ATOMIC5], 5);
270 else 264 else
@@ -276,7 +270,7 @@ __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
276 * Recover the probed instruction at addr for further analysis. 270 * Recover the probed instruction at addr for further analysis.
277 * Caller must lock kprobes by kprobe_mutex, or disable preemption 271 * Caller must lock kprobes by kprobe_mutex, or disable preemption
278 * for preventing to release referencing kprobes. 272 * for preventing to release referencing kprobes.
279 * Returns zero if the instruction can not get recovered. 273 * Returns zero if the instruction can not get recovered (or access failed).
280 */ 274 */
281unsigned long recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr) 275unsigned long recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr)
282{ 276{
@@ -348,37 +342,36 @@ static int is_IF_modifier(kprobe_opcode_t *insn)
348} 342}
349 343
350/* 344/*
351 * Copy an instruction and adjust the displacement if the instruction 345 * Copy an instruction with recovering modified instruction by kprobes
352 * uses the %rip-relative addressing mode. 346 * and adjust the displacement if the instruction uses the %rip-relative
353 * If it does, Return the address of the 32-bit displacement word. 347 * addressing mode.
354 * If not, return null. 348 * This returns the length of copied instruction, or 0 if it has an error.
355 * Only applicable to 64-bit x86.
356 */ 349 */
357int __copy_instruction(u8 *dest, u8 *src) 350int __copy_instruction(u8 *dest, u8 *src, struct insn *insn)
358{ 351{
359 struct insn insn;
360 kprobe_opcode_t buf[MAX_INSN_SIZE]; 352 kprobe_opcode_t buf[MAX_INSN_SIZE];
361 int length;
362 unsigned long recovered_insn = 353 unsigned long recovered_insn =
363 recover_probed_instruction(buf, (unsigned long)src); 354 recover_probed_instruction(buf, (unsigned long)src);
364 355
365 if (!recovered_insn) 356 if (!recovered_insn || !insn)
357 return 0;
358
359 /* This can access kernel text if given address is not recovered */
360 if (probe_kernel_read(dest, (void *)recovered_insn, MAX_INSN_SIZE))
366 return 0; 361 return 0;
367 kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE); 362
368 insn_get_length(&insn); 363 kernel_insn_init(insn, dest, MAX_INSN_SIZE);
369 length = insn.length; 364 insn_get_length(insn);
370 365
371 /* Another subsystem puts a breakpoint, failed to recover */ 366 /* Another subsystem puts a breakpoint, failed to recover */
372 if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION) 367 if (insn->opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
373 return 0; 368 return 0;
374 memcpy(dest, insn.kaddr, length);
375 369
376#ifdef CONFIG_X86_64 370#ifdef CONFIG_X86_64
377 if (insn_rip_relative(&insn)) { 371 /* Only x86_64 has RIP relative instructions */
372 if (insn_rip_relative(insn)) {
378 s64 newdisp; 373 s64 newdisp;
379 u8 *disp; 374 u8 *disp;
380 kernel_insn_init(&insn, dest, length);
381 insn_get_displacement(&insn);
382 /* 375 /*
383 * The copied instruction uses the %rip-relative addressing 376 * The copied instruction uses the %rip-relative addressing
384 * mode. Adjust the displacement for the difference between 377 * mode. Adjust the displacement for the difference between
@@ -391,36 +384,57 @@ int __copy_instruction(u8 *dest, u8 *src)
391 * extension of the original signed 32-bit displacement would 384 * extension of the original signed 32-bit displacement would
392 * have given. 385 * have given.
393 */ 386 */
394 newdisp = (u8 *) src + (s64) insn.displacement.value - (u8 *) dest; 387 newdisp = (u8 *) src + (s64) insn->displacement.value
388 - (u8 *) dest;
395 if ((s64) (s32) newdisp != newdisp) { 389 if ((s64) (s32) newdisp != newdisp) {
396 pr_err("Kprobes error: new displacement does not fit into s32 (%llx)\n", newdisp); 390 pr_err("Kprobes error: new displacement does not fit into s32 (%llx)\n", newdisp);
397 pr_err("\tSrc: %p, Dest: %p, old disp: %x\n", src, dest, insn.displacement.value); 391 pr_err("\tSrc: %p, Dest: %p, old disp: %x\n",
392 src, dest, insn->displacement.value);
398 return 0; 393 return 0;
399 } 394 }
400 disp = (u8 *) dest + insn_offset_displacement(&insn); 395 disp = (u8 *) dest + insn_offset_displacement(insn);
401 *(s32 *) disp = (s32) newdisp; 396 *(s32 *) disp = (s32) newdisp;
402 } 397 }
403#endif 398#endif
404 return length; 399 return insn->length;
400}
401
402/* Prepare reljump right after instruction to boost */
403static void prepare_boost(struct kprobe *p, struct insn *insn)
404{
405 if (can_boost(insn, p->addr) &&
406 MAX_INSN_SIZE - insn->length >= RELATIVEJUMP_SIZE) {
407 /*
408 * These instructions can be executed directly if it
409 * jumps back to correct address.
410 */
411 synthesize_reljump(p->ainsn.insn + insn->length,
412 p->addr + insn->length);
413 p->ainsn.boostable = true;
414 } else {
415 p->ainsn.boostable = false;
416 }
405} 417}
406 418
407static int arch_copy_kprobe(struct kprobe *p) 419static int arch_copy_kprobe(struct kprobe *p)
408{ 420{
409 int ret; 421 struct insn insn;
422 int len;
423
424 set_memory_rw((unsigned long)p->ainsn.insn & PAGE_MASK, 1);
410 425
411 /* Copy an instruction with recovering if other optprobe modifies it.*/ 426 /* Copy an instruction with recovering if other optprobe modifies it.*/
412 ret = __copy_instruction(p->ainsn.insn, p->addr); 427 len = __copy_instruction(p->ainsn.insn, p->addr, &insn);
413 if (!ret) 428 if (!len)
414 return -EINVAL; 429 return -EINVAL;
415 430
416 /* 431 /*
417 * __copy_instruction can modify the displacement of the instruction, 432 * __copy_instruction can modify the displacement of the instruction,
418 * but it doesn't affect boostable check. 433 * but it doesn't affect boostable check.
419 */ 434 */
420 if (can_boost(p->ainsn.insn, p->addr)) 435 prepare_boost(p, &insn);
421 p->ainsn.boostable = 0; 436
422 else 437 set_memory_ro((unsigned long)p->ainsn.insn & PAGE_MASK, 1);
423 p->ainsn.boostable = -1;
424 438
425 /* Check whether the instruction modifies Interrupt Flag or not */ 439 /* Check whether the instruction modifies Interrupt Flag or not */
426 p->ainsn.if_modifier = is_IF_modifier(p->ainsn.insn); 440 p->ainsn.if_modifier = is_IF_modifier(p->ainsn.insn);
@@ -459,7 +473,7 @@ void arch_disarm_kprobe(struct kprobe *p)
459void arch_remove_kprobe(struct kprobe *p) 473void arch_remove_kprobe(struct kprobe *p)
460{ 474{
461 if (p->ainsn.insn) { 475 if (p->ainsn.insn) {
462 free_insn_slot(p->ainsn.insn, (p->ainsn.boostable == 1)); 476 free_insn_slot(p->ainsn.insn, p->ainsn.boostable);
463 p->ainsn.insn = NULL; 477 p->ainsn.insn = NULL;
464 } 478 }
465} 479}
@@ -531,7 +545,7 @@ static void setup_singlestep(struct kprobe *p, struct pt_regs *regs,
531 return; 545 return;
532 546
533#if !defined(CONFIG_PREEMPT) 547#if !defined(CONFIG_PREEMPT)
534 if (p->ainsn.boostable == 1 && !p->post_handler) { 548 if (p->ainsn.boostable && !p->post_handler) {
535 /* Boost up -- we can execute copied instructions directly */ 549 /* Boost up -- we can execute copied instructions directly */
536 if (!reenter) 550 if (!reenter)
537 reset_current_kprobe(); 551 reset_current_kprobe();
@@ -851,7 +865,7 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs,
851 case 0xcf: 865 case 0xcf:
852 case 0xea: /* jmp absolute -- ip is correct */ 866 case 0xea: /* jmp absolute -- ip is correct */
853 /* ip is already adjusted, no more changes required */ 867 /* ip is already adjusted, no more changes required */
854 p->ainsn.boostable = 1; 868 p->ainsn.boostable = true;
855 goto no_change; 869 goto no_change;
856 case 0xe8: /* call relative - Fix return addr */ 870 case 0xe8: /* call relative - Fix return addr */
857 *tos = orig_ip + (*tos - copy_ip); 871 *tos = orig_ip + (*tos - copy_ip);
@@ -876,28 +890,13 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs,
876 * jmp near and far, absolute indirect 890 * jmp near and far, absolute indirect
877 * ip is correct. And this is boostable 891 * ip is correct. And this is boostable
878 */ 892 */
879 p->ainsn.boostable = 1; 893 p->ainsn.boostable = true;
880 goto no_change; 894 goto no_change;
881 } 895 }
882 default: 896 default:
883 break; 897 break;
884 } 898 }
885 899
886 if (p->ainsn.boostable == 0) {
887 if ((regs->ip > copy_ip) &&
888 (regs->ip - copy_ip) + 5 < MAX_INSN_SIZE) {
889 /*
890 * These instructions can be executed directly if it
891 * jumps back to correct address.
892 */
893 synthesize_reljump((void *)regs->ip,
894 (void *)orig_ip + (regs->ip - copy_ip));
895 p->ainsn.boostable = 1;
896 } else {
897 p->ainsn.boostable = -1;
898 }
899 }
900
901 regs->ip += orig_ip - copy_ip; 900 regs->ip += orig_ip - copy_ip;
902 901
903no_change: 902no_change:
diff --git a/arch/x86/kernel/kprobes/ftrace.c b/arch/x86/kernel/kprobes/ftrace.c
index 5f8f0b3cc674..041f7b6dfa0f 100644
--- a/arch/x86/kernel/kprobes/ftrace.c
+++ b/arch/x86/kernel/kprobes/ftrace.c
@@ -94,6 +94,6 @@ NOKPROBE_SYMBOL(kprobe_ftrace_handler);
94int arch_prepare_kprobe_ftrace(struct kprobe *p) 94int arch_prepare_kprobe_ftrace(struct kprobe *p)
95{ 95{
96 p->ainsn.insn = NULL; 96 p->ainsn.insn = NULL;
97 p->ainsn.boostable = -1; 97 p->ainsn.boostable = false;
98 return 0; 98 return 0;
99} 99}
diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c
index 3e7c6e5a08ff..9aadff3d0902 100644
--- a/arch/x86/kernel/kprobes/opt.c
+++ b/arch/x86/kernel/kprobes/opt.c
@@ -65,7 +65,10 @@ found:
65 * overwritten by jump destination address. In this case, original 65 * overwritten by jump destination address. In this case, original
66 * bytes must be recovered from op->optinsn.copied_insn buffer. 66 * bytes must be recovered from op->optinsn.copied_insn buffer.
67 */ 67 */
68 memcpy(buf, (void *)addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); 68 if (probe_kernel_read(buf, (void *)addr,
69 MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
70 return 0UL;
71
69 if (addr == (unsigned long)kp->addr) { 72 if (addr == (unsigned long)kp->addr) {
70 buf[0] = kp->opcode; 73 buf[0] = kp->opcode;
71 memcpy(buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE); 74 memcpy(buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
@@ -174,11 +177,12 @@ NOKPROBE_SYMBOL(optimized_callback);
174 177
175static int copy_optimized_instructions(u8 *dest, u8 *src) 178static int copy_optimized_instructions(u8 *dest, u8 *src)
176{ 179{
180 struct insn insn;
177 int len = 0, ret; 181 int len = 0, ret;
178 182
179 while (len < RELATIVEJUMP_SIZE) { 183 while (len < RELATIVEJUMP_SIZE) {
180 ret = __copy_instruction(dest + len, src + len); 184 ret = __copy_instruction(dest + len, src + len, &insn);
181 if (!ret || !can_boost(dest + len, src + len)) 185 if (!ret || !can_boost(&insn, src + len))
182 return -EINVAL; 186 return -EINVAL;
183 len += ret; 187 len += ret;
184 } 188 }
@@ -350,6 +354,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op,
350 } 354 }
351 355
352 buf = (u8 *)op->optinsn.insn; 356 buf = (u8 *)op->optinsn.insn;
357 set_memory_rw((unsigned long)buf & PAGE_MASK, 1);
353 358
354 /* Copy instructions into the out-of-line buffer */ 359 /* Copy instructions into the out-of-line buffer */
355 ret = copy_optimized_instructions(buf + TMPL_END_IDX, op->kp.addr); 360 ret = copy_optimized_instructions(buf + TMPL_END_IDX, op->kp.addr);
@@ -372,6 +377,8 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op,
372 synthesize_reljump(buf + TMPL_END_IDX + op->optinsn.size, 377 synthesize_reljump(buf + TMPL_END_IDX + op->optinsn.size,
373 (u8 *)op->kp.addr + op->optinsn.size); 378 (u8 *)op->kp.addr + op->optinsn.size);
374 379
380 set_memory_ro((unsigned long)buf & PAGE_MASK, 1);
381
375 flush_icache_range((unsigned long) buf, 382 flush_icache_range((unsigned long) buf,
376 (unsigned long) buf + TMPL_END_IDX + 383 (unsigned long) buf + TMPL_END_IDX +
377 op->optinsn.size + RELATIVEJUMP_SIZE); 384 op->optinsn.size + RELATIVEJUMP_SIZE);
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index f67591561711..0bb88428cbf2 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -37,6 +37,7 @@
37#include <asm/vm86.h> 37#include <asm/vm86.h>
38#include <asm/switch_to.h> 38#include <asm/switch_to.h>
39#include <asm/desc.h> 39#include <asm/desc.h>
40#include <asm/prctl.h>
40 41
41/* 42/*
42 * per-CPU TSS segments. Threads are completely 'soft' on Linux, 43 * per-CPU TSS segments. Threads are completely 'soft' on Linux,
@@ -124,11 +125,6 @@ void flush_thread(void)
124 fpu__clear(&tsk->thread.fpu); 125 fpu__clear(&tsk->thread.fpu);
125} 126}
126 127
127static void hard_disable_TSC(void)
128{
129 cr4_set_bits(X86_CR4_TSD);
130}
131
132void disable_TSC(void) 128void disable_TSC(void)
133{ 129{
134 preempt_disable(); 130 preempt_disable();
@@ -137,15 +133,10 @@ void disable_TSC(void)
137 * Must flip the CPU state synchronously with 133 * Must flip the CPU state synchronously with
138 * TIF_NOTSC in the current running context. 134 * TIF_NOTSC in the current running context.
139 */ 135 */
140 hard_disable_TSC(); 136 cr4_set_bits(X86_CR4_TSD);
141 preempt_enable(); 137 preempt_enable();
142} 138}
143 139
144static void hard_enable_TSC(void)
145{
146 cr4_clear_bits(X86_CR4_TSD);
147}
148
149static void enable_TSC(void) 140static void enable_TSC(void)
150{ 141{
151 preempt_disable(); 142 preempt_disable();
@@ -154,7 +145,7 @@ static void enable_TSC(void)
154 * Must flip the CPU state synchronously with 145 * Must flip the CPU state synchronously with
155 * TIF_NOTSC in the current running context. 146 * TIF_NOTSC in the current running context.
156 */ 147 */
157 hard_enable_TSC(); 148 cr4_clear_bits(X86_CR4_TSD);
158 preempt_enable(); 149 preempt_enable();
159} 150}
160 151
@@ -182,54 +173,129 @@ int set_tsc_mode(unsigned int val)
182 return 0; 173 return 0;
183} 174}
184 175
185void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, 176DEFINE_PER_CPU(u64, msr_misc_features_shadow);
186 struct tss_struct *tss)
187{
188 struct thread_struct *prev, *next;
189
190 prev = &prev_p->thread;
191 next = &next_p->thread;
192 177
193 if (test_tsk_thread_flag(prev_p, TIF_BLOCKSTEP) ^ 178static void set_cpuid_faulting(bool on)
194 test_tsk_thread_flag(next_p, TIF_BLOCKSTEP)) { 179{
195 unsigned long debugctl = get_debugctlmsr(); 180 u64 msrval;
196 181
197 debugctl &= ~DEBUGCTLMSR_BTF; 182 msrval = this_cpu_read(msr_misc_features_shadow);
198 if (test_tsk_thread_flag(next_p, TIF_BLOCKSTEP)) 183 msrval &= ~MSR_MISC_FEATURES_ENABLES_CPUID_FAULT;
199 debugctl |= DEBUGCTLMSR_BTF; 184 msrval |= (on << MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT);
185 this_cpu_write(msr_misc_features_shadow, msrval);
186 wrmsrl(MSR_MISC_FEATURES_ENABLES, msrval);
187}
200 188
201 update_debugctlmsr(debugctl); 189static void disable_cpuid(void)
190{
191 preempt_disable();
192 if (!test_and_set_thread_flag(TIF_NOCPUID)) {
193 /*
194 * Must flip the CPU state synchronously with
195 * TIF_NOCPUID in the current running context.
196 */
197 set_cpuid_faulting(true);
202 } 198 }
199 preempt_enable();
200}
203 201
204 if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ 202static void enable_cpuid(void)
205 test_tsk_thread_flag(next_p, TIF_NOTSC)) { 203{
206 /* prev and next are different */ 204 preempt_disable();
207 if (test_tsk_thread_flag(next_p, TIF_NOTSC)) 205 if (test_and_clear_thread_flag(TIF_NOCPUID)) {
208 hard_disable_TSC(); 206 /*
209 else 207 * Must flip the CPU state synchronously with
210 hard_enable_TSC(); 208 * TIF_NOCPUID in the current running context.
209 */
210 set_cpuid_faulting(false);
211 } 211 }
212 preempt_enable();
213}
214
215static int get_cpuid_mode(void)
216{
217 return !test_thread_flag(TIF_NOCPUID);
218}
219
220static int set_cpuid_mode(struct task_struct *task, unsigned long cpuid_enabled)
221{
222 if (!static_cpu_has(X86_FEATURE_CPUID_FAULT))
223 return -ENODEV;
224
225 if (cpuid_enabled)
226 enable_cpuid();
227 else
228 disable_cpuid();
229
230 return 0;
231}
232
233/*
234 * Called immediately after a successful exec.
235 */
236void arch_setup_new_exec(void)
237{
238 /* If cpuid was previously disabled for this task, re-enable it. */
239 if (test_thread_flag(TIF_NOCPUID))
240 enable_cpuid();
241}
212 242
213 if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { 243static inline void switch_to_bitmap(struct tss_struct *tss,
244 struct thread_struct *prev,
245 struct thread_struct *next,
246 unsigned long tifp, unsigned long tifn)
247{
248 if (tifn & _TIF_IO_BITMAP) {
214 /* 249 /*
215 * Copy the relevant range of the IO bitmap. 250 * Copy the relevant range of the IO bitmap.
216 * Normally this is 128 bytes or less: 251 * Normally this is 128 bytes or less:
217 */ 252 */
218 memcpy(tss->io_bitmap, next->io_bitmap_ptr, 253 memcpy(tss->io_bitmap, next->io_bitmap_ptr,
219 max(prev->io_bitmap_max, next->io_bitmap_max)); 254 max(prev->io_bitmap_max, next->io_bitmap_max));
220
221 /* 255 /*
222 * Make sure that the TSS limit is correct for the CPU 256 * Make sure that the TSS limit is correct for the CPU
223 * to notice the IO bitmap. 257 * to notice the IO bitmap.
224 */ 258 */
225 refresh_tss_limit(); 259 refresh_tss_limit();
226 } else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) { 260 } else if (tifp & _TIF_IO_BITMAP) {
227 /* 261 /*
228 * Clear any possible leftover bits: 262 * Clear any possible leftover bits:
229 */ 263 */
230 memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); 264 memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
231 } 265 }
266}
267
268void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
269 struct tss_struct *tss)
270{
271 struct thread_struct *prev, *next;
272 unsigned long tifp, tifn;
273
274 prev = &prev_p->thread;
275 next = &next_p->thread;
276
277 tifn = READ_ONCE(task_thread_info(next_p)->flags);
278 tifp = READ_ONCE(task_thread_info(prev_p)->flags);
279 switch_to_bitmap(tss, prev, next, tifp, tifn);
280
232 propagate_user_return_notify(prev_p, next_p); 281 propagate_user_return_notify(prev_p, next_p);
282
283 if ((tifp & _TIF_BLOCKSTEP || tifn & _TIF_BLOCKSTEP) &&
284 arch_has_block_step()) {
285 unsigned long debugctl, msk;
286
287 rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
288 debugctl &= ~DEBUGCTLMSR_BTF;
289 msk = tifn & _TIF_BLOCKSTEP;
290 debugctl |= (msk >> TIF_BLOCKSTEP) << DEBUGCTLMSR_BTF_SHIFT;
291 wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
292 }
293
294 if ((tifp ^ tifn) & _TIF_NOTSC)
295 cr4_toggle_bits(X86_CR4_TSD);
296
297 if ((tifp ^ tifn) & _TIF_NOCPUID)
298 set_cpuid_faulting(!!(tifn & _TIF_NOCPUID));
233} 299}
234 300
235/* 301/*
@@ -550,3 +616,16 @@ out:
550 put_task_stack(p); 616 put_task_stack(p);
551 return ret; 617 return ret;
552} 618}
619
620long do_arch_prctl_common(struct task_struct *task, int option,
621 unsigned long cpuid_enabled)
622{
623 switch (option) {
624 case ARCH_GET_CPUID:
625 return get_cpuid_mode();
626 case ARCH_SET_CPUID:
627 return set_cpuid_mode(task, cpuid_enabled);
628 }
629
630 return -EINVAL;
631}
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 4c818f8bc135..ff40e74c9181 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -37,6 +37,7 @@
37#include <linux/uaccess.h> 37#include <linux/uaccess.h>
38#include <linux/io.h> 38#include <linux/io.h>
39#include <linux/kdebug.h> 39#include <linux/kdebug.h>
40#include <linux/syscalls.h>
40 41
41#include <asm/pgtable.h> 42#include <asm/pgtable.h>
42#include <asm/ldt.h> 43#include <asm/ldt.h>
@@ -56,6 +57,7 @@
56#include <asm/switch_to.h> 57#include <asm/switch_to.h>
57#include <asm/vm86.h> 58#include <asm/vm86.h>
58#include <asm/intel_rdt.h> 59#include <asm/intel_rdt.h>
60#include <asm/proto.h>
59 61
60void __show_regs(struct pt_regs *regs, int all) 62void __show_regs(struct pt_regs *regs, int all)
61{ 63{
@@ -304,3 +306,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
304 306
305 return prev_p; 307 return prev_p;
306} 308}
309
310SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2)
311{
312 return do_arch_prctl_common(current, option, arg2);
313}
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index d6b784a5520d..ea1a6180bf39 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -37,6 +37,7 @@
37#include <linux/uaccess.h> 37#include <linux/uaccess.h>
38#include <linux/io.h> 38#include <linux/io.h>
39#include <linux/ftrace.h> 39#include <linux/ftrace.h>
40#include <linux/syscalls.h>
40 41
41#include <asm/pgtable.h> 42#include <asm/pgtable.h>
42#include <asm/processor.h> 43#include <asm/processor.h>
@@ -204,7 +205,7 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long sp,
204 (struct user_desc __user *)tls, 0); 205 (struct user_desc __user *)tls, 0);
205 else 206 else
206#endif 207#endif
207 err = do_arch_prctl(p, ARCH_SET_FS, tls); 208 err = do_arch_prctl_64(p, ARCH_SET_FS, tls);
208 if (err) 209 if (err)
209 goto out; 210 goto out;
210 } 211 }
@@ -547,70 +548,72 @@ static long prctl_map_vdso(const struct vdso_image *image, unsigned long addr)
547} 548}
548#endif 549#endif
549 550
550long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) 551long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2)
551{ 552{
552 int ret = 0; 553 int ret = 0;
553 int doit = task == current; 554 int doit = task == current;
554 int cpu; 555 int cpu;
555 556
556 switch (code) { 557 switch (option) {
557 case ARCH_SET_GS: 558 case ARCH_SET_GS:
558 if (addr >= TASK_SIZE_MAX) 559 if (arg2 >= TASK_SIZE_MAX)
559 return -EPERM; 560 return -EPERM;
560 cpu = get_cpu(); 561 cpu = get_cpu();
561 task->thread.gsindex = 0; 562 task->thread.gsindex = 0;
562 task->thread.gsbase = addr; 563 task->thread.gsbase = arg2;
563 if (doit) { 564 if (doit) {
564 load_gs_index(0); 565 load_gs_index(0);
565 ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, addr); 566 ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, arg2);
566 } 567 }
567 put_cpu(); 568 put_cpu();
568 break; 569 break;
569 case ARCH_SET_FS: 570 case ARCH_SET_FS:
570 /* Not strictly needed for fs, but do it for symmetry 571 /* Not strictly needed for fs, but do it for symmetry
571 with gs */ 572 with gs */
572 if (addr >= TASK_SIZE_MAX) 573 if (arg2 >= TASK_SIZE_MAX)
573 return -EPERM; 574 return -EPERM;
574 cpu = get_cpu(); 575 cpu = get_cpu();
575 task->thread.fsindex = 0; 576 task->thread.fsindex = 0;
576 task->thread.fsbase = addr; 577 task->thread.fsbase = arg2;
577 if (doit) { 578 if (doit) {
578 /* set the selector to 0 to not confuse __switch_to */ 579 /* set the selector to 0 to not confuse __switch_to */
579 loadsegment(fs, 0); 580 loadsegment(fs, 0);
580 ret = wrmsrl_safe(MSR_FS_BASE, addr); 581 ret = wrmsrl_safe(MSR_FS_BASE, arg2);
581 } 582 }
582 put_cpu(); 583 put_cpu();
583 break; 584 break;
584 case ARCH_GET_FS: { 585 case ARCH_GET_FS: {
585 unsigned long base; 586 unsigned long base;
587
586 if (doit) 588 if (doit)
587 rdmsrl(MSR_FS_BASE, base); 589 rdmsrl(MSR_FS_BASE, base);
588 else 590 else
589 base = task->thread.fsbase; 591 base = task->thread.fsbase;
590 ret = put_user(base, (unsigned long __user *)addr); 592 ret = put_user(base, (unsigned long __user *)arg2);
591 break; 593 break;
592 } 594 }
593 case ARCH_GET_GS: { 595 case ARCH_GET_GS: {
594 unsigned long base; 596 unsigned long base;
597
595 if (doit) 598 if (doit)
596 rdmsrl(MSR_KERNEL_GS_BASE, base); 599 rdmsrl(MSR_KERNEL_GS_BASE, base);
597 else 600 else
598 base = task->thread.gsbase; 601 base = task->thread.gsbase;
599 ret = put_user(base, (unsigned long __user *)addr); 602 ret = put_user(base, (unsigned long __user *)arg2);
600 break; 603 break;
601 } 604 }
602 605
603#ifdef CONFIG_CHECKPOINT_RESTORE 606#ifdef CONFIG_CHECKPOINT_RESTORE
604# ifdef CONFIG_X86_X32_ABI 607# ifdef CONFIG_X86_X32_ABI
605 case ARCH_MAP_VDSO_X32: 608 case ARCH_MAP_VDSO_X32:
606 return prctl_map_vdso(&vdso_image_x32, addr); 609 return prctl_map_vdso(&vdso_image_x32, arg2);
607# endif 610# endif
608# if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION 611# if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
609 case ARCH_MAP_VDSO_32: 612 case ARCH_MAP_VDSO_32:
610 return prctl_map_vdso(&vdso_image_32, addr); 613 return prctl_map_vdso(&vdso_image_32, arg2);
611# endif 614# endif
612 case ARCH_MAP_VDSO_64: 615 case ARCH_MAP_VDSO_64:
613 return prctl_map_vdso(&vdso_image_64, addr); 616 return prctl_map_vdso(&vdso_image_64, arg2);
614#endif 617#endif
615 618
616 default: 619 default:
@@ -621,10 +624,23 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
621 return ret; 624 return ret;
622} 625}
623 626
624long sys_arch_prctl(int code, unsigned long addr) 627SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2)
628{
629 long ret;
630
631 ret = do_arch_prctl_64(current, option, arg2);
632 if (ret == -EINVAL)
633 ret = do_arch_prctl_common(current, option, arg2);
634
635 return ret;
636}
637
638#ifdef CONFIG_IA32_EMULATION
639COMPAT_SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2)
625{ 640{
626 return do_arch_prctl(current, code, addr); 641 return do_arch_prctl_common(current, option, arg2);
627} 642}
643#endif
628 644
629unsigned long KSTK_ESP(struct task_struct *task) 645unsigned long KSTK_ESP(struct task_struct *task)
630{ 646{
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 2364b23ea3e5..f37d18124648 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -396,12 +396,12 @@ static int putreg(struct task_struct *child,
396 if (value >= TASK_SIZE_MAX) 396 if (value >= TASK_SIZE_MAX)
397 return -EIO; 397 return -EIO;
398 /* 398 /*
399 * When changing the segment base, use do_arch_prctl 399 * When changing the segment base, use do_arch_prctl_64
400 * to set either thread.fs or thread.fsindex and the 400 * to set either thread.fs or thread.fsindex and the
401 * corresponding GDT slot. 401 * corresponding GDT slot.
402 */ 402 */
403 if (child->thread.fsbase != value) 403 if (child->thread.fsbase != value)
404 return do_arch_prctl(child, ARCH_SET_FS, value); 404 return do_arch_prctl_64(child, ARCH_SET_FS, value);
405 return 0; 405 return 0;
406 case offsetof(struct user_regs_struct,gs_base): 406 case offsetof(struct user_regs_struct,gs_base):
407 /* 407 /*
@@ -410,7 +410,7 @@ static int putreg(struct task_struct *child,
410 if (value >= TASK_SIZE_MAX) 410 if (value >= TASK_SIZE_MAX)
411 return -EIO; 411 return -EIO;
412 if (child->thread.gsbase != value) 412 if (child->thread.gsbase != value)
413 return do_arch_prctl(child, ARCH_SET_GS, value); 413 return do_arch_prctl_64(child, ARCH_SET_GS, value);
414 return 0; 414 return 0;
415#endif 415#endif
416 } 416 }
@@ -869,7 +869,7 @@ long arch_ptrace(struct task_struct *child, long request,
869 Works just like arch_prctl, except that the arguments 869 Works just like arch_prctl, except that the arguments
870 are reversed. */ 870 are reversed. */
871 case PTRACE_ARCH_PRCTL: 871 case PTRACE_ARCH_PRCTL:
872 ret = do_arch_prctl(child, data, addr); 872 ret = do_arch_prctl_64(child, data, addr);
873 break; 873 break;
874#endif 874#endif
875 875
diff --git a/arch/x86/um/Makefile b/arch/x86/um/Makefile
index e7e7055a8658..69f0827d5f53 100644
--- a/arch/x86/um/Makefile
+++ b/arch/x86/um/Makefile
@@ -16,7 +16,7 @@ obj-y = bug.o bugs_$(BITS).o delay.o fault.o ldt.o \
16 16
17ifeq ($(CONFIG_X86_32),y) 17ifeq ($(CONFIG_X86_32),y)
18 18
19obj-y += checksum_32.o 19obj-y += checksum_32.o syscalls_32.o
20obj-$(CONFIG_ELF_CORE) += elfcore.o 20obj-$(CONFIG_ELF_CORE) += elfcore.o
21 21
22subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o 22subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o
diff --git a/arch/x86/um/asm/ptrace.h b/arch/x86/um/asm/ptrace.h
index e59eef20647b..b291ca5cf66b 100644
--- a/arch/x86/um/asm/ptrace.h
+++ b/arch/x86/um/asm/ptrace.h
@@ -78,7 +78,7 @@ static inline int ptrace_set_thread_area(struct task_struct *child, int idx,
78 return -ENOSYS; 78 return -ENOSYS;
79} 79}
80 80
81extern long arch_prctl(struct task_struct *task, int code, 81extern long arch_prctl(struct task_struct *task, int option,
82 unsigned long __user *addr); 82 unsigned long __user *addr);
83 83
84#endif 84#endif
diff --git a/arch/x86/um/os-Linux/prctl.c b/arch/x86/um/os-Linux/prctl.c
index 96eb2bd28832..8431e87ac333 100644
--- a/arch/x86/um/os-Linux/prctl.c
+++ b/arch/x86/um/os-Linux/prctl.c
@@ -6,7 +6,7 @@
6#include <sys/ptrace.h> 6#include <sys/ptrace.h>
7#include <asm/ptrace.h> 7#include <asm/ptrace.h>
8 8
9int os_arch_prctl(int pid, int code, unsigned long *addr) 9int os_arch_prctl(int pid, int option, unsigned long *arg2)
10{ 10{
11 return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) addr, code); 11 return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) arg2, option);
12} 12}
diff --git a/arch/x86/um/syscalls_32.c b/arch/x86/um/syscalls_32.c
new file mode 100644
index 000000000000..627d68836b16
--- /dev/null
+++ b/arch/x86/um/syscalls_32.c
@@ -0,0 +1,7 @@
1#include <linux/syscalls.h>
2#include <os.h>
3
4SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2)
5{
6 return -EINVAL;
7}
diff --git a/arch/x86/um/syscalls_64.c b/arch/x86/um/syscalls_64.c
index 10d907098c26..81b9fe100f7c 100644
--- a/arch/x86/um/syscalls_64.c
+++ b/arch/x86/um/syscalls_64.c
@@ -7,13 +7,15 @@
7 7
8#include <linux/sched.h> 8#include <linux/sched.h>
9#include <linux/sched/mm.h> 9#include <linux/sched/mm.h>
10#include <linux/syscalls.h>
10#include <linux/uaccess.h> 11#include <linux/uaccess.h>
11#include <asm/prctl.h> /* XXX This should get the constants from libc */ 12#include <asm/prctl.h> /* XXX This should get the constants from libc */
12#include <os.h> 13#include <os.h>
13 14
14long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) 15long arch_prctl(struct task_struct *task, int option)
16 unsigned long __user *arg2)
15{ 17{
16 unsigned long *ptr = addr, tmp; 18 unsigned long *ptr = arg2, tmp;
17 long ret; 19 long ret;
18 int pid = task->mm->context.id.u.pid; 20 int pid = task->mm->context.id.u.pid;
19 21
@@ -30,7 +32,7 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
30 * arch_prctl is run on the host, then the registers are read 32 * arch_prctl is run on the host, then the registers are read
31 * back. 33 * back.
32 */ 34 */
33 switch (code) { 35 switch (option) {
34 case ARCH_SET_FS: 36 case ARCH_SET_FS:
35 case ARCH_SET_GS: 37 case ARCH_SET_GS:
36 ret = restore_registers(pid, &current->thread.regs.regs); 38 ret = restore_registers(pid, &current->thread.regs.regs);
@@ -50,11 +52,11 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
50 ptr = &tmp; 52 ptr = &tmp;
51 } 53 }
52 54
53 ret = os_arch_prctl(pid, code, ptr); 55 ret = os_arch_prctl(pid, option, ptr);
54 if (ret) 56 if (ret)
55 return ret; 57 return ret;
56 58
57 switch (code) { 59 switch (option) {
58 case ARCH_SET_FS: 60 case ARCH_SET_FS:
59 current->thread.arch.fs = (unsigned long) ptr; 61 current->thread.arch.fs = (unsigned long) ptr;
60 ret = save_registers(pid, &current->thread.regs.regs); 62 ret = save_registers(pid, &current->thread.regs.regs);
@@ -63,19 +65,19 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
63 ret = save_registers(pid, &current->thread.regs.regs); 65 ret = save_registers(pid, &current->thread.regs.regs);
64 break; 66 break;
65 case ARCH_GET_FS: 67 case ARCH_GET_FS:
66 ret = put_user(tmp, addr); 68 ret = put_user(tmp, arg2);
67 break; 69 break;
68 case ARCH_GET_GS: 70 case ARCH_GET_GS:
69 ret = put_user(tmp, addr); 71 ret = put_user(tmp, arg2);
70 break; 72 break;
71 } 73 }
72 74
73 return ret; 75 return ret;
74} 76}
75 77
76long sys_arch_prctl(int code, unsigned long addr) 78SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2)
77{ 79{
78 return arch_prctl(current, code, (unsigned long __user *) addr); 80 return arch_prctl(current, option, (unsigned long __user *) arg2);
79} 81}
80 82
81void arch_switch_to(struct task_struct *to) 83void arch_switch_to(struct task_struct *to)
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index d7325c6534ad..979ea6ec7902 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -321,7 +321,7 @@ static int etb_set_buffer(struct coresight_device *csdev,
321 321
322static unsigned long etb_reset_buffer(struct coresight_device *csdev, 322static unsigned long etb_reset_buffer(struct coresight_device *csdev,
323 struct perf_output_handle *handle, 323 struct perf_output_handle *handle,
324 void *sink_config, bool *lost) 324 void *sink_config)
325{ 325{
326 unsigned long size = 0; 326 unsigned long size = 0;
327 struct cs_buffers *buf = sink_config; 327 struct cs_buffers *buf = sink_config;
@@ -343,7 +343,6 @@ static unsigned long etb_reset_buffer(struct coresight_device *csdev,
343 * resetting parameters here and squaring off with the ring 343 * resetting parameters here and squaring off with the ring
344 * buffer API in the tracer PMU is fine. 344 * buffer API in the tracer PMU is fine.
345 */ 345 */
346 *lost = !!local_xchg(&buf->lost, 0);
347 size = local_xchg(&buf->data_size, 0); 346 size = local_xchg(&buf->data_size, 0);
348 } 347 }
349 348
@@ -385,7 +384,7 @@ static void etb_update_buffer(struct coresight_device *csdev,
385 (unsigned long)write_ptr); 384 (unsigned long)write_ptr);
386 385
387 write_ptr &= ~(ETB_FRAME_SIZE_WORDS - 1); 386 write_ptr &= ~(ETB_FRAME_SIZE_WORDS - 1);
388 local_inc(&buf->lost); 387 perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
389 } 388 }
390 389
391 /* 390 /*
@@ -396,7 +395,7 @@ static void etb_update_buffer(struct coresight_device *csdev,
396 */ 395 */
397 status = readl_relaxed(drvdata->base + ETB_STATUS_REG); 396 status = readl_relaxed(drvdata->base + ETB_STATUS_REG);
398 if (status & ETB_STATUS_RAM_FULL) { 397 if (status & ETB_STATUS_RAM_FULL) {
399 local_inc(&buf->lost); 398 perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
400 to_read = capacity; 399 to_read = capacity;
401 read_ptr = write_ptr; 400 read_ptr = write_ptr;
402 } else { 401 } else {
@@ -429,7 +428,7 @@ static void etb_update_buffer(struct coresight_device *csdev,
429 if (read_ptr > (drvdata->buffer_depth - 1)) 428 if (read_ptr > (drvdata->buffer_depth - 1))
430 read_ptr -= drvdata->buffer_depth; 429 read_ptr -= drvdata->buffer_depth;
431 /* let the decoder know we've skipped ahead */ 430 /* let the decoder know we've skipped ahead */
432 local_inc(&buf->lost); 431 perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
433 } 432 }
434 433
435 /* finally tell HW where we want to start reading from */ 434 /* finally tell HW where we want to start reading from */
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 26cfac3e6de7..288a423c1b27 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -302,7 +302,8 @@ out:
302 return; 302 return;
303 303
304fail_end_stop: 304fail_end_stop:
305 perf_aux_output_end(handle, 0, true); 305 perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
306 perf_aux_output_end(handle, 0);
306fail: 307fail:
307 event->hw.state = PERF_HES_STOPPED; 308 event->hw.state = PERF_HES_STOPPED;
308 goto out; 309 goto out;
@@ -310,7 +311,6 @@ fail:
310 311
311static void etm_event_stop(struct perf_event *event, int mode) 312static void etm_event_stop(struct perf_event *event, int mode)
312{ 313{
313 bool lost;
314 int cpu = smp_processor_id(); 314 int cpu = smp_processor_id();
315 unsigned long size; 315 unsigned long size;
316 struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu); 316 struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu);
@@ -348,10 +348,9 @@ static void etm_event_stop(struct perf_event *event, int mode)
348 return; 348 return;
349 349
350 size = sink_ops(sink)->reset_buffer(sink, handle, 350 size = sink_ops(sink)->reset_buffer(sink, handle,
351 event_data->snk_config, 351 event_data->snk_config);
352 &lost);
353 352
354 perf_aux_output_end(handle, size, lost); 353 perf_aux_output_end(handle, size);
355 } 354 }
356 355
357 /* Disabling the path make its elements available to other sessions */ 356 /* Disabling the path make its elements available to other sessions */
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index ef9d8e93e3b2..5f662d82052c 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -76,7 +76,6 @@ enum cs_mode {
76 * @nr_pages: max number of pages granted to us 76 * @nr_pages: max number of pages granted to us
77 * @offset: offset within the current buffer 77 * @offset: offset within the current buffer
78 * @data_size: how much we collected in this run 78 * @data_size: how much we collected in this run
79 * @lost: other than zero if we had a HW buffer wrap around
80 * @snapshot: is this run in snapshot mode 79 * @snapshot: is this run in snapshot mode
81 * @data_pages: a handle the ring buffer 80 * @data_pages: a handle the ring buffer
82 */ 81 */
@@ -85,7 +84,6 @@ struct cs_buffers {
85 unsigned int nr_pages; 84 unsigned int nr_pages;
86 unsigned long offset; 85 unsigned long offset;
87 local_t data_size; 86 local_t data_size;
88 local_t lost;
89 bool snapshot; 87 bool snapshot;
90 void **data_pages; 88 void **data_pages;
91}; 89};
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index 1549436e2492..aec61a6d5c63 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -329,7 +329,7 @@ static int tmc_set_etf_buffer(struct coresight_device *csdev,
329 329
330static unsigned long tmc_reset_etf_buffer(struct coresight_device *csdev, 330static unsigned long tmc_reset_etf_buffer(struct coresight_device *csdev,
331 struct perf_output_handle *handle, 331 struct perf_output_handle *handle,
332 void *sink_config, bool *lost) 332 void *sink_config)
333{ 333{
334 long size = 0; 334 long size = 0;
335 struct cs_buffers *buf = sink_config; 335 struct cs_buffers *buf = sink_config;
@@ -350,7 +350,6 @@ static unsigned long tmc_reset_etf_buffer(struct coresight_device *csdev,
350 * resetting parameters here and squaring off with the ring 350 * resetting parameters here and squaring off with the ring
351 * buffer API in the tracer PMU is fine. 351 * buffer API in the tracer PMU is fine.
352 */ 352 */
353 *lost = !!local_xchg(&buf->lost, 0);
354 size = local_xchg(&buf->data_size, 0); 353 size = local_xchg(&buf->data_size, 0);
355 } 354 }
356 355
@@ -389,7 +388,7 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev,
389 */ 388 */
390 status = readl_relaxed(drvdata->base + TMC_STS); 389 status = readl_relaxed(drvdata->base + TMC_STS);
391 if (status & TMC_STS_FULL) { 390 if (status & TMC_STS_FULL) {
392 local_inc(&buf->lost); 391 perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
393 to_read = drvdata->size; 392 to_read = drvdata->size;
394 } else { 393 } else {
395 to_read = CIRC_CNT(write_ptr, read_ptr, drvdata->size); 394 to_read = CIRC_CNT(write_ptr, read_ptr, drvdata->size);
@@ -434,7 +433,7 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev,
434 read_ptr -= drvdata->size; 433 read_ptr -= drvdata->size;
435 /* Tell the HW */ 434 /* Tell the HW */
436 writel_relaxed(read_ptr, drvdata->base + TMC_RRP); 435 writel_relaxed(read_ptr, drvdata->base + TMC_RRP);
437 local_inc(&buf->lost); 436 perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
438 } 437 }
439 438
440 cur = buf->cur; 439 cur = buf->cur;
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index b17536d6e69b..63cacf5d6cf2 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1234,7 +1234,7 @@ static void __domain_flush_pages(struct protection_domain *domain,
1234 1234
1235 build_inv_iommu_pages(&cmd, address, size, domain->id, pde); 1235 build_inv_iommu_pages(&cmd, address, size, domain->id, pde);
1236 1236
1237 for (i = 0; i < amd_iommus_present; ++i) { 1237 for (i = 0; i < amd_iommu_get_num_iommus(); ++i) {
1238 if (!domain->dev_iommu[i]) 1238 if (!domain->dev_iommu[i])
1239 continue; 1239 continue;
1240 1240
@@ -1278,7 +1278,7 @@ static void domain_flush_complete(struct protection_domain *domain)
1278{ 1278{
1279 int i; 1279 int i;
1280 1280
1281 for (i = 0; i < amd_iommus_present; ++i) { 1281 for (i = 0; i < amd_iommu_get_num_iommus(); ++i) {
1282 if (domain && !domain->dev_iommu[i]) 1282 if (domain && !domain->dev_iommu[i])
1283 continue; 1283 continue;
1284 1284
@@ -3363,7 +3363,7 @@ static int __flush_pasid(struct protection_domain *domain, int pasid,
3363 * IOMMU TLB needs to be flushed before Device TLB to 3363 * IOMMU TLB needs to be flushed before Device TLB to
3364 * prevent device TLB refill from IOMMU TLB 3364 * prevent device TLB refill from IOMMU TLB
3365 */ 3365 */
3366 for (i = 0; i < amd_iommus_present; ++i) { 3366 for (i = 0; i < amd_iommu_get_num_iommus(); ++i) {
3367 if (domain->dev_iommu[i] == 0) 3367 if (domain->dev_iommu[i] == 0)
3368 continue; 3368 continue;
3369 3369
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 6130278c5d71..5a11328f4d98 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -167,7 +167,9 @@ LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the
167 167
168/* Array to assign indices to IOMMUs*/ 168/* Array to assign indices to IOMMUs*/
169struct amd_iommu *amd_iommus[MAX_IOMMUS]; 169struct amd_iommu *amd_iommus[MAX_IOMMUS];
170int amd_iommus_present; 170
171/* Number of IOMMUs present in the system */
172static int amd_iommus_present;
171 173
172/* IOMMUs have a non-present cache? */ 174/* IOMMUs have a non-present cache? */
173bool amd_iommu_np_cache __read_mostly; 175bool amd_iommu_np_cache __read_mostly;
@@ -254,10 +256,6 @@ static int amd_iommu_enable_interrupts(void);
254static int __init iommu_go_to_state(enum iommu_init_state state); 256static int __init iommu_go_to_state(enum iommu_init_state state);
255static void init_device_table_dma(void); 257static void init_device_table_dma(void);
256 258
257static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu,
258 u8 bank, u8 cntr, u8 fxn,
259 u64 *value, bool is_write);
260
261static inline void update_last_devid(u16 devid) 259static inline void update_last_devid(u16 devid)
262{ 260{
263 if (devid > amd_iommu_last_bdf) 261 if (devid > amd_iommu_last_bdf)
@@ -272,6 +270,11 @@ static inline unsigned long tbl_size(int entry_size)
272 return 1UL << shift; 270 return 1UL << shift;
273} 271}
274 272
273int amd_iommu_get_num_iommus(void)
274{
275 return amd_iommus_present;
276}
277
275/* Access to l1 and l2 indexed register spaces */ 278/* Access to l1 and l2 indexed register spaces */
276 279
277static u32 iommu_read_l1(struct amd_iommu *iommu, u16 l1, u8 address) 280static u32 iommu_read_l1(struct amd_iommu *iommu, u16 l1, u8 address)
@@ -1336,7 +1339,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
1336 1339
1337 /* Add IOMMU to internal data structures */ 1340 /* Add IOMMU to internal data structures */
1338 list_add_tail(&iommu->list, &amd_iommu_list); 1341 list_add_tail(&iommu->list, &amd_iommu_list);
1339 iommu->index = amd_iommus_present++; 1342 iommu->index = amd_iommus_present++;
1340 1343
1341 if (unlikely(iommu->index >= MAX_IOMMUS)) { 1344 if (unlikely(iommu->index >= MAX_IOMMUS)) {
1342 WARN(1, "AMD-Vi: System has more IOMMUs than supported by this driver\n"); 1345 WARN(1, "AMD-Vi: System has more IOMMUs than supported by this driver\n");
@@ -1477,6 +1480,8 @@ static int __init init_iommu_all(struct acpi_table_header *table)
1477 return 0; 1480 return 0;
1478} 1481}
1479 1482
1483static int iommu_pc_get_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr,
1484 u8 fxn, u64 *value, bool is_write);
1480 1485
1481static void init_iommu_perf_ctr(struct amd_iommu *iommu) 1486static void init_iommu_perf_ctr(struct amd_iommu *iommu)
1482{ 1487{
@@ -1488,8 +1493,8 @@ static void init_iommu_perf_ctr(struct amd_iommu *iommu)
1488 amd_iommu_pc_present = true; 1493 amd_iommu_pc_present = true;
1489 1494
1490 /* Check if the performance counters can be written to */ 1495 /* Check if the performance counters can be written to */
1491 if ((0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val, true)) || 1496 if ((iommu_pc_get_set_reg(iommu, 0, 0, 0, &val, true)) ||
1492 (0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val2, false)) || 1497 (iommu_pc_get_set_reg(iommu, 0, 0, 0, &val2, false)) ||
1493 (val != val2)) { 1498 (val != val2)) {
1494 pr_err("AMD-Vi: Unable to write to IOMMU perf counter.\n"); 1499 pr_err("AMD-Vi: Unable to write to IOMMU perf counter.\n");
1495 amd_iommu_pc_present = false; 1500 amd_iommu_pc_present = false;
@@ -2711,6 +2716,18 @@ bool amd_iommu_v2_supported(void)
2711} 2716}
2712EXPORT_SYMBOL(amd_iommu_v2_supported); 2717EXPORT_SYMBOL(amd_iommu_v2_supported);
2713 2718
2719struct amd_iommu *get_amd_iommu(unsigned int idx)
2720{
2721 unsigned int i = 0;
2722 struct amd_iommu *iommu;
2723
2724 for_each_iommu(iommu)
2725 if (i++ == idx)
2726 return iommu;
2727 return NULL;
2728}
2729EXPORT_SYMBOL(get_amd_iommu);
2730
2714/**************************************************************************** 2731/****************************************************************************
2715 * 2732 *
2716 * IOMMU EFR Performance Counter support functionality. This code allows 2733 * IOMMU EFR Performance Counter support functionality. This code allows
@@ -2718,17 +2735,14 @@ EXPORT_SYMBOL(amd_iommu_v2_supported);
2718 * 2735 *
2719 ****************************************************************************/ 2736 ****************************************************************************/
2720 2737
2721u8 amd_iommu_pc_get_max_banks(u16 devid) 2738u8 amd_iommu_pc_get_max_banks(unsigned int idx)
2722{ 2739{
2723 struct amd_iommu *iommu; 2740 struct amd_iommu *iommu = get_amd_iommu(idx);
2724 u8 ret = 0;
2725 2741
2726 /* locate the iommu governing the devid */
2727 iommu = amd_iommu_rlookup_table[devid];
2728 if (iommu) 2742 if (iommu)
2729 ret = iommu->max_banks; 2743 return iommu->max_banks;
2730 2744
2731 return ret; 2745 return 0;
2732} 2746}
2733EXPORT_SYMBOL(amd_iommu_pc_get_max_banks); 2747EXPORT_SYMBOL(amd_iommu_pc_get_max_banks);
2734 2748
@@ -2738,62 +2752,69 @@ bool amd_iommu_pc_supported(void)
2738} 2752}
2739EXPORT_SYMBOL(amd_iommu_pc_supported); 2753EXPORT_SYMBOL(amd_iommu_pc_supported);
2740 2754
2741u8 amd_iommu_pc_get_max_counters(u16 devid) 2755u8 amd_iommu_pc_get_max_counters(unsigned int idx)
2742{ 2756{
2743 struct amd_iommu *iommu; 2757 struct amd_iommu *iommu = get_amd_iommu(idx);
2744 u8 ret = 0;
2745 2758
2746 /* locate the iommu governing the devid */
2747 iommu = amd_iommu_rlookup_table[devid];
2748 if (iommu) 2759 if (iommu)
2749 ret = iommu->max_counters; 2760 return iommu->max_counters;
2750 2761
2751 return ret; 2762 return 0;
2752} 2763}
2753EXPORT_SYMBOL(amd_iommu_pc_get_max_counters); 2764EXPORT_SYMBOL(amd_iommu_pc_get_max_counters);
2754 2765
2755static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu, 2766static int iommu_pc_get_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr,
2756 u8 bank, u8 cntr, u8 fxn, 2767 u8 fxn, u64 *value, bool is_write)
2757 u64 *value, bool is_write)
2758{ 2768{
2759 u32 offset; 2769 u32 offset;
2760 u32 max_offset_lim; 2770 u32 max_offset_lim;
2761 2771
2772 /* Make sure the IOMMU PC resource is available */
2773 if (!amd_iommu_pc_present)
2774 return -ENODEV;
2775
2762 /* Check for valid iommu and pc register indexing */ 2776 /* Check for valid iommu and pc register indexing */
2763 if (WARN_ON((fxn > 0x28) || (fxn & 7))) 2777 if (WARN_ON(!iommu || (fxn > 0x28) || (fxn & 7)))
2764 return -ENODEV; 2778 return -ENODEV;
2765 2779
2766 offset = (u32)(((0x40|bank) << 12) | (cntr << 8) | fxn); 2780 offset = (u32)(((0x40 | bank) << 12) | (cntr << 8) | fxn);
2767 2781
2768 /* Limit the offset to the hw defined mmio region aperture */ 2782 /* Limit the offset to the hw defined mmio region aperture */
2769 max_offset_lim = (u32)(((0x40|iommu->max_banks) << 12) | 2783 max_offset_lim = (u32)(((0x40 | iommu->max_banks) << 12) |
2770 (iommu->max_counters << 8) | 0x28); 2784 (iommu->max_counters << 8) | 0x28);
2771 if ((offset < MMIO_CNTR_REG_OFFSET) || 2785 if ((offset < MMIO_CNTR_REG_OFFSET) ||
2772 (offset > max_offset_lim)) 2786 (offset > max_offset_lim))
2773 return -EINVAL; 2787 return -EINVAL;
2774 2788
2775 if (is_write) { 2789 if (is_write) {
2776 writel((u32)*value, iommu->mmio_base + offset); 2790 u64 val = *value & GENMASK_ULL(47, 0);
2777 writel((*value >> 32), iommu->mmio_base + offset + 4); 2791
2792 writel((u32)val, iommu->mmio_base + offset);
2793 writel((val >> 32), iommu->mmio_base + offset + 4);
2778 } else { 2794 } else {
2779 *value = readl(iommu->mmio_base + offset + 4); 2795 *value = readl(iommu->mmio_base + offset + 4);
2780 *value <<= 32; 2796 *value <<= 32;
2781 *value = readl(iommu->mmio_base + offset); 2797 *value |= readl(iommu->mmio_base + offset);
2798 *value &= GENMASK_ULL(47, 0);
2782 } 2799 }
2783 2800
2784 return 0; 2801 return 0;
2785} 2802}
2786EXPORT_SYMBOL(amd_iommu_pc_get_set_reg_val);
2787 2803
2788int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn, 2804int amd_iommu_pc_get_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, u8 fxn, u64 *value)
2789 u64 *value, bool is_write)
2790{ 2805{
2791 struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; 2806 if (!iommu)
2807 return -EINVAL;
2792 2808
2793 /* Make sure the IOMMU PC resource is available */ 2809 return iommu_pc_get_set_reg(iommu, bank, cntr, fxn, value, false);
2794 if (!amd_iommu_pc_present || iommu == NULL) 2810}
2795 return -ENODEV; 2811EXPORT_SYMBOL(amd_iommu_pc_get_reg);
2812
2813int amd_iommu_pc_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, u8 fxn, u64 *value)
2814{
2815 if (!iommu)
2816 return -EINVAL;
2796 2817
2797 return iommu_pc_get_set_reg_val(iommu, bank, cntr, fxn, 2818 return iommu_pc_get_set_reg(iommu, bank, cntr, fxn, value, true);
2798 value, is_write);
2799} 2819}
2820EXPORT_SYMBOL(amd_iommu_pc_set_reg);
diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h
index 7eb60c15c582..466260f8a1df 100644
--- a/drivers/iommu/amd_iommu_proto.h
+++ b/drivers/iommu/amd_iommu_proto.h
@@ -21,6 +21,7 @@
21 21
22#include "amd_iommu_types.h" 22#include "amd_iommu_types.h"
23 23
24extern int amd_iommu_get_num_iommus(void);
24extern int amd_iommu_init_dma_ops(void); 25extern int amd_iommu_init_dma_ops(void);
25extern int amd_iommu_init_passthrough(void); 26extern int amd_iommu_init_passthrough(void);
26extern irqreturn_t amd_iommu_int_thread(int irq, void *data); 27extern irqreturn_t amd_iommu_int_thread(int irq, void *data);
@@ -56,13 +57,6 @@ extern int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, int pasid,
56extern int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid); 57extern int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid);
57extern struct iommu_domain *amd_iommu_get_v2_domain(struct pci_dev *pdev); 58extern struct iommu_domain *amd_iommu_get_v2_domain(struct pci_dev *pdev);
58 59
59/* IOMMU Performance Counter functions */
60extern bool amd_iommu_pc_supported(void);
61extern u8 amd_iommu_pc_get_max_banks(u16 devid);
62extern u8 amd_iommu_pc_get_max_counters(u16 devid);
63extern int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
64 u64 *value, bool is_write);
65
66#ifdef CONFIG_IRQ_REMAP 60#ifdef CONFIG_IRQ_REMAP
67extern int amd_iommu_create_irq_domain(struct amd_iommu *iommu); 61extern int amd_iommu_create_irq_domain(struct amd_iommu *iommu);
68#else 62#else
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 003f3ceb2661..4de8f4160bb8 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -611,9 +611,6 @@ extern struct list_head amd_iommu_list;
611 */ 611 */
612extern struct amd_iommu *amd_iommus[MAX_IOMMUS]; 612extern struct amd_iommu *amd_iommus[MAX_IOMMUS];
613 613
614/* Number of IOMMUs present in the system */
615extern int amd_iommus_present;
616
617/* 614/*
618 * Declarations for the global list of all protection domains 615 * Declarations for the global list of all protection domains
619 */ 616 */
diff --git a/fs/exec.c b/fs/exec.c
index 65145a3df065..72934df68471 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1320,6 +1320,7 @@ void setup_new_exec(struct linux_binprm * bprm)
1320 else 1320 else
1321 set_dumpable(current->mm, suid_dumpable); 1321 set_dumpable(current->mm, suid_dumpable);
1322 1322
1323 arch_setup_new_exec();
1323 perf_event_exec(); 1324 perf_event_exec();
1324 __set_task_comm(current, kbasename(bprm->filename), true); 1325 __set_task_comm(current, kbasename(bprm->filename), true);
1325 1326
diff --git a/include/linux/compat.h b/include/linux/compat.h
index aef47be2a5c1..af9dbc44fd92 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -723,6 +723,8 @@ asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid,
723asmlinkage long compat_sys_fanotify_mark(int, unsigned int, __u32, __u32, 723asmlinkage long compat_sys_fanotify_mark(int, unsigned int, __u32, __u32,
724 int, const char __user *); 724 int, const char __user *);
725 725
726asmlinkage long compat_sys_arch_prctl(int option, unsigned long arg2);
727
726/* 728/*
727 * For most but not all architectures, "am I in a compat syscall?" and 729 * For most but not all architectures, "am I in a compat syscall?" and
728 * "am I a compat task?" are the same question. For architectures on which 730 * "am I a compat task?" are the same question. For architectures on which
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 2a5982c37dfb..035c16c9a505 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -201,7 +201,7 @@ struct coresight_ops_sink {
201 void *sink_config); 201 void *sink_config);
202 unsigned long (*reset_buffer)(struct coresight_device *csdev, 202 unsigned long (*reset_buffer)(struct coresight_device *csdev,
203 struct perf_output_handle *handle, 203 struct perf_output_handle *handle,
204 void *sink_config, bool *lost); 204 void *sink_config);
205 void (*update_buffer)(struct coresight_device *csdev, 205 void (*update_buffer)(struct coresight_device *csdev,
206 struct perf_output_handle *handle, 206 struct perf_output_handle *handle,
207 void *sink_config); 207 void *sink_config);
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index c328e4f7dcad..47e4da5b4fa2 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -267,6 +267,8 @@ extern int arch_init_kprobes(void);
267extern void show_registers(struct pt_regs *regs); 267extern void show_registers(struct pt_regs *regs);
268extern void kprobes_inc_nmissed_count(struct kprobe *p); 268extern void kprobes_inc_nmissed_count(struct kprobe *p);
269extern bool arch_within_kprobe_blacklist(unsigned long addr); 269extern bool arch_within_kprobe_blacklist(unsigned long addr);
270extern bool arch_function_offset_within_entry(unsigned long offset);
271extern bool function_offset_within_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset);
270 272
271extern bool within_kprobe_blacklist(unsigned long addr); 273extern bool within_kprobe_blacklist(unsigned long addr);
272 274
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 000fdb211c7d..24a635887f28 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -165,6 +165,13 @@ struct hw_perf_event {
165 struct list_head bp_list; 165 struct list_head bp_list;
166 }; 166 };
167#endif 167#endif
168 struct { /* amd_iommu */
169 u8 iommu_bank;
170 u8 iommu_cntr;
171 u16 padding;
172 u64 conf;
173 u64 conf1;
174 };
168 }; 175 };
169 /* 176 /*
170 * If the event is a per task event, this will point to the task in 177 * If the event is a per task event, this will point to the task in
@@ -801,6 +808,7 @@ struct perf_output_handle {
801 struct ring_buffer *rb; 808 struct ring_buffer *rb;
802 unsigned long wakeup; 809 unsigned long wakeup;
803 unsigned long size; 810 unsigned long size;
811 u64 aux_flags;
804 union { 812 union {
805 void *addr; 813 void *addr;
806 unsigned long head; 814 unsigned long head;
@@ -849,10 +857,11 @@ perf_cgroup_from_task(struct task_struct *task, struct perf_event_context *ctx)
849extern void *perf_aux_output_begin(struct perf_output_handle *handle, 857extern void *perf_aux_output_begin(struct perf_output_handle *handle,
850 struct perf_event *event); 858 struct perf_event *event);
851extern void perf_aux_output_end(struct perf_output_handle *handle, 859extern void perf_aux_output_end(struct perf_output_handle *handle,
852 unsigned long size, bool truncated); 860 unsigned long size);
853extern int perf_aux_output_skip(struct perf_output_handle *handle, 861extern int perf_aux_output_skip(struct perf_output_handle *handle,
854 unsigned long size); 862 unsigned long size);
855extern void *perf_get_aux(struct perf_output_handle *handle); 863extern void *perf_get_aux(struct perf_output_handle *handle);
864extern void perf_aux_output_flag(struct perf_output_handle *handle, u64 flags);
856 865
857extern int perf_pmu_register(struct pmu *pmu, const char *name, int type); 866extern int perf_pmu_register(struct pmu *pmu, const char *name, int type);
858extern void perf_pmu_unregister(struct pmu *pmu); 867extern void perf_pmu_unregister(struct pmu *pmu);
@@ -1112,6 +1121,7 @@ extern int perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks
1112 1121
1113extern void perf_event_exec(void); 1122extern void perf_event_exec(void);
1114extern void perf_event_comm(struct task_struct *tsk, bool exec); 1123extern void perf_event_comm(struct task_struct *tsk, bool exec);
1124extern void perf_event_namespaces(struct task_struct *tsk);
1115extern void perf_event_fork(struct task_struct *tsk); 1125extern void perf_event_fork(struct task_struct *tsk);
1116 1126
1117/* Callchains */ 1127/* Callchains */
@@ -1267,8 +1277,8 @@ static inline void *
1267perf_aux_output_begin(struct perf_output_handle *handle, 1277perf_aux_output_begin(struct perf_output_handle *handle,
1268 struct perf_event *event) { return NULL; } 1278 struct perf_event *event) { return NULL; }
1269static inline void 1279static inline void
1270perf_aux_output_end(struct perf_output_handle *handle, unsigned long size, 1280perf_aux_output_end(struct perf_output_handle *handle, unsigned long size)
1271 bool truncated) { } 1281 { }
1272static inline int 1282static inline int
1273perf_aux_output_skip(struct perf_output_handle *handle, 1283perf_aux_output_skip(struct perf_output_handle *handle,
1274 unsigned long size) { return -EINVAL; } 1284 unsigned long size) { return -EINVAL; }
@@ -1315,6 +1325,7 @@ static inline int perf_unregister_guest_info_callbacks
1315static inline void perf_event_mmap(struct vm_area_struct *vma) { } 1325static inline void perf_event_mmap(struct vm_area_struct *vma) { }
1316static inline void perf_event_exec(void) { } 1326static inline void perf_event_exec(void) { }
1317static inline void perf_event_comm(struct task_struct *tsk, bool exec) { } 1327static inline void perf_event_comm(struct task_struct *tsk, bool exec) { }
1328static inline void perf_event_namespaces(struct task_struct *tsk) { }
1318static inline void perf_event_fork(struct task_struct *tsk) { } 1329static inline void perf_event_fork(struct task_struct *tsk) { }
1319static inline void perf_event_init(void) { } 1330static inline void perf_event_init(void) { }
1320static inline int perf_swevent_get_recursion_context(void) { return -1; } 1331static inline int perf_swevent_get_recursion_context(void) { return -1; }
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index 58373875e8ee..55125d674338 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -101,6 +101,10 @@ static inline void check_object_size(const void *ptr, unsigned long n,
101{ } 101{ }
102#endif /* CONFIG_HARDENED_USERCOPY */ 102#endif /* CONFIG_HARDENED_USERCOPY */
103 103
104#ifndef arch_setup_new_exec
105static inline void arch_setup_new_exec(void) { }
106#endif
107
104#endif /* __KERNEL__ */ 108#endif /* __KERNEL__ */
105 109
106#endif /* _LINUX_THREAD_INFO_H */ 110#endif /* _LINUX_THREAD_INFO_H */
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index c66a485a24ac..d09a9cd021b1 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -344,7 +344,8 @@ struct perf_event_attr {
344 use_clockid : 1, /* use @clockid for time fields */ 344 use_clockid : 1, /* use @clockid for time fields */
345 context_switch : 1, /* context switch data */ 345 context_switch : 1, /* context switch data */
346 write_backward : 1, /* Write ring buffer from end to beginning */ 346 write_backward : 1, /* Write ring buffer from end to beginning */
347 __reserved_1 : 36; 347 namespaces : 1, /* include namespaces data */
348 __reserved_1 : 35;
348 349
349 union { 350 union {
350 __u32 wakeup_events; /* wakeup every n events */ 351 __u32 wakeup_events; /* wakeup every n events */
@@ -610,6 +611,23 @@ struct perf_event_header {
610 __u16 size; 611 __u16 size;
611}; 612};
612 613
614struct perf_ns_link_info {
615 __u64 dev;
616 __u64 ino;
617};
618
619enum {
620 NET_NS_INDEX = 0,
621 UTS_NS_INDEX = 1,
622 IPC_NS_INDEX = 2,
623 PID_NS_INDEX = 3,
624 USER_NS_INDEX = 4,
625 MNT_NS_INDEX = 5,
626 CGROUP_NS_INDEX = 6,
627
628 NR_NAMESPACES, /* number of available namespaces */
629};
630
613enum perf_event_type { 631enum perf_event_type {
614 632
615 /* 633 /*
@@ -862,6 +880,18 @@ enum perf_event_type {
862 */ 880 */
863 PERF_RECORD_SWITCH_CPU_WIDE = 15, 881 PERF_RECORD_SWITCH_CPU_WIDE = 15,
864 882
883 /*
884 * struct {
885 * struct perf_event_header header;
886 * u32 pid;
887 * u32 tid;
888 * u64 nr_namespaces;
889 * { u64 dev, inode; } [nr_namespaces];
890 * struct sample_id sample_id;
891 * };
892 */
893 PERF_RECORD_NAMESPACES = 16,
894
865 PERF_RECORD_MAX, /* non-ABI */ 895 PERF_RECORD_MAX, /* non-ABI */
866}; 896};
867 897
@@ -885,6 +915,7 @@ enum perf_callchain_context {
885 */ 915 */
886#define PERF_AUX_FLAG_TRUNCATED 0x01 /* record was truncated to fit */ 916#define PERF_AUX_FLAG_TRUNCATED 0x01 /* record was truncated to fit */
887#define PERF_AUX_FLAG_OVERWRITE 0x02 /* snapshot from overwrite mode */ 917#define PERF_AUX_FLAG_OVERWRITE 0x02 /* snapshot from overwrite mode */
918#define PERF_AUX_FLAG_PARTIAL 0x04 /* record contains gaps */
888 919
889#define PERF_FLAG_FD_NO_GROUP (1UL << 0) 920#define PERF_FLAG_FD_NO_GROUP (1UL << 0)
890#define PERF_FLAG_FD_OUTPUT (1UL << 1) 921#define PERF_FLAG_FD_OUTPUT (1UL << 1)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index ff01cba86f43..6e75a5c9412d 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -48,6 +48,8 @@
48#include <linux/parser.h> 48#include <linux/parser.h>
49#include <linux/sched/clock.h> 49#include <linux/sched/clock.h>
50#include <linux/sched/mm.h> 50#include <linux/sched/mm.h>
51#include <linux/proc_ns.h>
52#include <linux/mount.h>
51 53
52#include "internal.h" 54#include "internal.h"
53 55
@@ -379,6 +381,7 @@ static DEFINE_PER_CPU(struct pmu_event_list, pmu_sb_events);
379 381
380static atomic_t nr_mmap_events __read_mostly; 382static atomic_t nr_mmap_events __read_mostly;
381static atomic_t nr_comm_events __read_mostly; 383static atomic_t nr_comm_events __read_mostly;
384static atomic_t nr_namespaces_events __read_mostly;
382static atomic_t nr_task_events __read_mostly; 385static atomic_t nr_task_events __read_mostly;
383static atomic_t nr_freq_events __read_mostly; 386static atomic_t nr_freq_events __read_mostly;
384static atomic_t nr_switch_events __read_mostly; 387static atomic_t nr_switch_events __read_mostly;
@@ -3991,6 +3994,8 @@ static void unaccount_event(struct perf_event *event)
3991 atomic_dec(&nr_mmap_events); 3994 atomic_dec(&nr_mmap_events);
3992 if (event->attr.comm) 3995 if (event->attr.comm)
3993 atomic_dec(&nr_comm_events); 3996 atomic_dec(&nr_comm_events);
3997 if (event->attr.namespaces)
3998 atomic_dec(&nr_namespaces_events);
3994 if (event->attr.task) 3999 if (event->attr.task)
3995 atomic_dec(&nr_task_events); 4000 atomic_dec(&nr_task_events);
3996 if (event->attr.freq) 4001 if (event->attr.freq)
@@ -6491,6 +6496,7 @@ static void perf_event_task(struct task_struct *task,
6491void perf_event_fork(struct task_struct *task) 6496void perf_event_fork(struct task_struct *task)
6492{ 6497{
6493 perf_event_task(task, NULL, 1); 6498 perf_event_task(task, NULL, 1);
6499 perf_event_namespaces(task);
6494} 6500}
6495 6501
6496/* 6502/*
@@ -6593,6 +6599,132 @@ void perf_event_comm(struct task_struct *task, bool exec)
6593} 6599}
6594 6600
6595/* 6601/*
6602 * namespaces tracking
6603 */
6604
6605struct perf_namespaces_event {
6606 struct task_struct *task;
6607
6608 struct {
6609 struct perf_event_header header;
6610
6611 u32 pid;
6612 u32 tid;
6613 u64 nr_namespaces;
6614 struct perf_ns_link_info link_info[NR_NAMESPACES];
6615 } event_id;
6616};
6617
6618static int perf_event_namespaces_match(struct perf_event *event)
6619{
6620 return event->attr.namespaces;
6621}
6622
6623static void perf_event_namespaces_output(struct perf_event *event,
6624 void *data)
6625{
6626 struct perf_namespaces_event *namespaces_event = data;
6627 struct perf_output_handle handle;
6628 struct perf_sample_data sample;
6629 int ret;
6630
6631 if (!perf_event_namespaces_match(event))
6632 return;
6633
6634 perf_event_header__init_id(&namespaces_event->event_id.header,
6635 &sample, event);
6636 ret = perf_output_begin(&handle, event,
6637 namespaces_event->event_id.header.size);
6638 if (ret)
6639 return;
6640
6641 namespaces_event->event_id.pid = perf_event_pid(event,
6642 namespaces_event->task);
6643 namespaces_event->event_id.tid = perf_event_tid(event,
6644 namespaces_event->task);
6645
6646 perf_output_put(&handle, namespaces_event->event_id);
6647
6648 perf_event__output_id_sample(event, &handle, &sample);
6649
6650 perf_output_end(&handle);
6651}
6652
6653static void perf_fill_ns_link_info(struct perf_ns_link_info *ns_link_info,
6654 struct task_struct *task,
6655 const struct proc_ns_operations *ns_ops)
6656{
6657 struct path ns_path;
6658 struct inode *ns_inode;
6659 void *error;
6660
6661 error = ns_get_path(&ns_path, task, ns_ops);
6662 if (!error) {
6663 ns_inode = ns_path.dentry->d_inode;
6664 ns_link_info->dev = new_encode_dev(ns_inode->i_sb->s_dev);
6665 ns_link_info->ino = ns_inode->i_ino;
6666 }
6667}
6668
6669void perf_event_namespaces(struct task_struct *task)
6670{
6671 struct perf_namespaces_event namespaces_event;
6672 struct perf_ns_link_info *ns_link_info;
6673
6674 if (!atomic_read(&nr_namespaces_events))
6675 return;
6676
6677 namespaces_event = (struct perf_namespaces_event){
6678 .task = task,
6679 .event_id = {
6680 .header = {
6681 .type = PERF_RECORD_NAMESPACES,
6682 .misc = 0,
6683 .size = sizeof(namespaces_event.event_id),
6684 },
6685 /* .pid */
6686 /* .tid */
6687 .nr_namespaces = NR_NAMESPACES,
6688 /* .link_info[NR_NAMESPACES] */
6689 },
6690 };
6691
6692 ns_link_info = namespaces_event.event_id.link_info;
6693
6694 perf_fill_ns_link_info(&ns_link_info[MNT_NS_INDEX],
6695 task, &mntns_operations);
6696
6697#ifdef CONFIG_USER_NS
6698 perf_fill_ns_link_info(&ns_link_info[USER_NS_INDEX],
6699 task, &userns_operations);
6700#endif
6701#ifdef CONFIG_NET_NS
6702 perf_fill_ns_link_info(&ns_link_info[NET_NS_INDEX],
6703 task, &netns_operations);
6704#endif
6705#ifdef CONFIG_UTS_NS
6706 perf_fill_ns_link_info(&ns_link_info[UTS_NS_INDEX],
6707 task, &utsns_operations);
6708#endif
6709#ifdef CONFIG_IPC_NS
6710 perf_fill_ns_link_info(&ns_link_info[IPC_NS_INDEX],
6711 task, &ipcns_operations);
6712#endif
6713#ifdef CONFIG_PID_NS
6714 perf_fill_ns_link_info(&ns_link_info[PID_NS_INDEX],
6715 task, &pidns_operations);
6716#endif
6717#ifdef CONFIG_CGROUPS
6718 perf_fill_ns_link_info(&ns_link_info[CGROUP_NS_INDEX],
6719 task, &cgroupns_operations);
6720#endif
6721
6722 perf_iterate_sb(perf_event_namespaces_output,
6723 &namespaces_event,
6724 NULL);
6725}
6726
6727/*
6596 * mmap tracking 6728 * mmap tracking
6597 */ 6729 */
6598 6730
@@ -9146,6 +9278,8 @@ static void account_event(struct perf_event *event)
9146 atomic_inc(&nr_mmap_events); 9278 atomic_inc(&nr_mmap_events);
9147 if (event->attr.comm) 9279 if (event->attr.comm)
9148 atomic_inc(&nr_comm_events); 9280 atomic_inc(&nr_comm_events);
9281 if (event->attr.namespaces)
9282 atomic_inc(&nr_namespaces_events);
9149 if (event->attr.task) 9283 if (event->attr.task)
9150 atomic_inc(&nr_task_events); 9284 atomic_inc(&nr_task_events);
9151 if (event->attr.freq) 9285 if (event->attr.freq)
@@ -9691,6 +9825,11 @@ SYSCALL_DEFINE5(perf_event_open,
9691 return -EACCES; 9825 return -EACCES;
9692 } 9826 }
9693 9827
9828 if (attr.namespaces) {
9829 if (!capable(CAP_SYS_ADMIN))
9830 return -EACCES;
9831 }
9832
9694 if (attr.freq) { 9833 if (attr.freq) {
9695 if (attr.sample_freq > sysctl_perf_event_sample_rate) 9834 if (attr.sample_freq > sysctl_perf_event_sample_rate)
9696 return -EINVAL; 9835 return -EINVAL;
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 257fa460b846..2831480c63a2 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -297,6 +297,19 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)
297 rb->paused = 1; 297 rb->paused = 1;
298} 298}
299 299
300void perf_aux_output_flag(struct perf_output_handle *handle, u64 flags)
301{
302 /*
303 * OVERWRITE is determined by perf_aux_output_end() and can't
304 * be passed in directly.
305 */
306 if (WARN_ON_ONCE(flags & PERF_AUX_FLAG_OVERWRITE))
307 return;
308
309 handle->aux_flags |= flags;
310}
311EXPORT_SYMBOL_GPL(perf_aux_output_flag);
312
300/* 313/*
301 * This is called before hardware starts writing to the AUX area to 314 * This is called before hardware starts writing to the AUX area to
302 * obtain an output handle and make sure there's room in the buffer. 315 * obtain an output handle and make sure there's room in the buffer.
@@ -360,6 +373,7 @@ void *perf_aux_output_begin(struct perf_output_handle *handle,
360 handle->event = event; 373 handle->event = event;
361 handle->head = aux_head; 374 handle->head = aux_head;
362 handle->size = 0; 375 handle->size = 0;
376 handle->aux_flags = 0;
363 377
364 /* 378 /*
365 * In overwrite mode, AUX data stores do not depend on aux_tail, 379 * In overwrite mode, AUX data stores do not depend on aux_tail,
@@ -408,34 +422,32 @@ err:
408 * of the AUX buffer management code is that after pmu::stop(), the AUX 422 * of the AUX buffer management code is that after pmu::stop(), the AUX
409 * transaction must be stopped and therefore drop the AUX reference count. 423 * transaction must be stopped and therefore drop the AUX reference count.
410 */ 424 */
411void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size, 425void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size)
412 bool truncated)
413{ 426{
427 bool wakeup = !!(handle->aux_flags & PERF_AUX_FLAG_TRUNCATED);
414 struct ring_buffer *rb = handle->rb; 428 struct ring_buffer *rb = handle->rb;
415 bool wakeup = truncated;
416 unsigned long aux_head; 429 unsigned long aux_head;
417 u64 flags = 0;
418
419 if (truncated)
420 flags |= PERF_AUX_FLAG_TRUNCATED;
421 430
422 /* in overwrite mode, driver provides aux_head via handle */ 431 /* in overwrite mode, driver provides aux_head via handle */
423 if (rb->aux_overwrite) { 432 if (rb->aux_overwrite) {
424 flags |= PERF_AUX_FLAG_OVERWRITE; 433 handle->aux_flags |= PERF_AUX_FLAG_OVERWRITE;
425 434
426 aux_head = handle->head; 435 aux_head = handle->head;
427 local_set(&rb->aux_head, aux_head); 436 local_set(&rb->aux_head, aux_head);
428 } else { 437 } else {
438 handle->aux_flags &= ~PERF_AUX_FLAG_OVERWRITE;
439
429 aux_head = local_read(&rb->aux_head); 440 aux_head = local_read(&rb->aux_head);
430 local_add(size, &rb->aux_head); 441 local_add(size, &rb->aux_head);
431 } 442 }
432 443
433 if (size || flags) { 444 if (size || handle->aux_flags) {
434 /* 445 /*
435 * Only send RECORD_AUX if we have something useful to communicate 446 * Only send RECORD_AUX if we have something useful to communicate
436 */ 447 */
437 448
438 perf_event_aux_event(handle->event, aux_head, size, flags); 449 perf_event_aux_event(handle->event, aux_head, size,
450 handle->aux_flags);
439 } 451 }
440 452
441 aux_head = rb->user_page->aux_head = local_read(&rb->aux_head); 453 aux_head = rb->user_page->aux_head = local_read(&rb->aux_head);
@@ -446,7 +458,7 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size,
446 } 458 }
447 459
448 if (wakeup) { 460 if (wakeup) {
449 if (truncated) 461 if (handle->aux_flags & PERF_AUX_FLAG_TRUNCATED)
450 handle->event->pending_disable = 1; 462 handle->event->pending_disable = 1;
451 perf_output_wakeup(handle); 463 perf_output_wakeup(handle);
452 } 464 }
diff --git a/kernel/fork.c b/kernel/fork.c
index 6c463c80e93d..afa2947286cd 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -2352,6 +2352,8 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
2352 } 2352 }
2353 } 2353 }
2354 2354
2355 perf_event_namespaces(current);
2356
2355bad_unshare_cleanup_cred: 2357bad_unshare_cleanup_cred:
2356 if (new_cred) 2358 if (new_cred)
2357 put_cred(new_cred); 2359 put_cred(new_cred);
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 699c5bc51a92..d733479a10ee 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1391,21 +1391,19 @@ bool within_kprobe_blacklist(unsigned long addr)
1391 * This returns encoded errors if it fails to look up symbol or invalid 1391 * This returns encoded errors if it fails to look up symbol or invalid
1392 * combination of parameters. 1392 * combination of parameters.
1393 */ 1393 */
1394static kprobe_opcode_t *kprobe_addr(struct kprobe *p) 1394static kprobe_opcode_t *_kprobe_addr(kprobe_opcode_t *addr,
1395 const char *symbol_name, unsigned int offset)
1395{ 1396{
1396 kprobe_opcode_t *addr = p->addr; 1397 if ((symbol_name && addr) || (!symbol_name && !addr))
1397
1398 if ((p->symbol_name && p->addr) ||
1399 (!p->symbol_name && !p->addr))
1400 goto invalid; 1398 goto invalid;
1401 1399
1402 if (p->symbol_name) { 1400 if (symbol_name) {
1403 kprobe_lookup_name(p->symbol_name, addr); 1401 kprobe_lookup_name(symbol_name, addr);
1404 if (!addr) 1402 if (!addr)
1405 return ERR_PTR(-ENOENT); 1403 return ERR_PTR(-ENOENT);
1406 } 1404 }
1407 1405
1408 addr = (kprobe_opcode_t *)(((char *)addr) + p->offset); 1406 addr = (kprobe_opcode_t *)(((char *)addr) + offset);
1409 if (addr) 1407 if (addr)
1410 return addr; 1408 return addr;
1411 1409
@@ -1413,6 +1411,11 @@ invalid:
1413 return ERR_PTR(-EINVAL); 1411 return ERR_PTR(-EINVAL);
1414} 1412}
1415 1413
1414static kprobe_opcode_t *kprobe_addr(struct kprobe *p)
1415{
1416 return _kprobe_addr(p->addr, p->symbol_name, p->offset);
1417}
1418
1416/* Check passed kprobe is valid and return kprobe in kprobe_table. */ 1419/* Check passed kprobe is valid and return kprobe in kprobe_table. */
1417static struct kprobe *__get_valid_kprobe(struct kprobe *p) 1420static struct kprobe *__get_valid_kprobe(struct kprobe *p)
1418{ 1421{
@@ -1740,11 +1743,12 @@ void unregister_kprobes(struct kprobe **kps, int num)
1740} 1743}
1741EXPORT_SYMBOL_GPL(unregister_kprobes); 1744EXPORT_SYMBOL_GPL(unregister_kprobes);
1742 1745
1743int __weak __kprobes kprobe_exceptions_notify(struct notifier_block *self, 1746int __weak kprobe_exceptions_notify(struct notifier_block *self,
1744 unsigned long val, void *data) 1747 unsigned long val, void *data)
1745{ 1748{
1746 return NOTIFY_DONE; 1749 return NOTIFY_DONE;
1747} 1750}
1751NOKPROBE_SYMBOL(kprobe_exceptions_notify);
1748 1752
1749static struct notifier_block kprobe_exceptions_nb = { 1753static struct notifier_block kprobe_exceptions_nb = {
1750 .notifier_call = kprobe_exceptions_notify, 1754 .notifier_call = kprobe_exceptions_notify,
@@ -1875,6 +1879,25 @@ static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
1875} 1879}
1876NOKPROBE_SYMBOL(pre_handler_kretprobe); 1880NOKPROBE_SYMBOL(pre_handler_kretprobe);
1877 1881
1882bool __weak arch_function_offset_within_entry(unsigned long offset)
1883{
1884 return !offset;
1885}
1886
1887bool function_offset_within_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset)
1888{
1889 kprobe_opcode_t *kp_addr = _kprobe_addr(addr, sym, offset);
1890
1891 if (IS_ERR(kp_addr))
1892 return false;
1893
1894 if (!kallsyms_lookup_size_offset((unsigned long)kp_addr, NULL, &offset) ||
1895 !arch_function_offset_within_entry(offset))
1896 return false;
1897
1898 return true;
1899}
1900
1878int register_kretprobe(struct kretprobe *rp) 1901int register_kretprobe(struct kretprobe *rp)
1879{ 1902{
1880 int ret = 0; 1903 int ret = 0;
@@ -1882,6 +1905,9 @@ int register_kretprobe(struct kretprobe *rp)
1882 int i; 1905 int i;
1883 void *addr; 1906 void *addr;
1884 1907
1908 if (!function_offset_within_entry(rp->kp.addr, rp->kp.symbol_name, rp->kp.offset))
1909 return -EINVAL;
1910
1885 if (kretprobe_blacklist_size) { 1911 if (kretprobe_blacklist_size) {
1886 addr = kprobe_addr(&rp->kp); 1912 addr = kprobe_addr(&rp->kp);
1887 if (IS_ERR(addr)) 1913 if (IS_ERR(addr))
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index 782102e59eed..f6c5d330059a 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -26,6 +26,7 @@
26#include <linux/file.h> 26#include <linux/file.h>
27#include <linux/syscalls.h> 27#include <linux/syscalls.h>
28#include <linux/cgroup.h> 28#include <linux/cgroup.h>
29#include <linux/perf_event.h>
29 30
30static struct kmem_cache *nsproxy_cachep; 31static struct kmem_cache *nsproxy_cachep;
31 32
@@ -262,6 +263,8 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype)
262 goto out; 263 goto out;
263 } 264 }
264 switch_task_namespaces(tsk, new_nsproxy); 265 switch_task_namespaces(tsk, new_nsproxy);
266
267 perf_event_namespaces(tsk);
265out: 268out:
266 fput(file); 269 fput(file);
267 return err; 270 return err;
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index d4a06e714645..9619b5768e4b 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -455,7 +455,7 @@ config UPROBE_EVENTS
455 select UPROBES 455 select UPROBES
456 select PROBE_EVENTS 456 select PROBE_EVENTS
457 select TRACING 457 select TRACING
458 default n 458 default y
459 help 459 help
460 This allows the user to add tracing events on top of userspace 460 This allows the user to add tracing events on top of userspace
461 dynamic events (similar to tracepoints) on the fly via the trace 461 dynamic events (similar to tracepoints) on the fly via the trace
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 0ad75e9698f6..b253d59b9c51 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4355,6 +4355,7 @@ static const char readme_msg[] =
4355 "\t -:[<group>/]<event>\n" 4355 "\t -:[<group>/]<event>\n"
4356#ifdef CONFIG_KPROBE_EVENTS 4356#ifdef CONFIG_KPROBE_EVENTS
4357 "\t place: [<module>:]<symbol>[+<offset>]|<memaddr>\n" 4357 "\t place: [<module>:]<symbol>[+<offset>]|<memaddr>\n"
4358 "place (kretprobe): [<module>:]<symbol>[+<offset>]|<memaddr>\n"
4358#endif 4359#endif
4359#ifdef CONFIG_UPROBE_EVENTS 4360#ifdef CONFIG_UPROBE_EVENTS
4360 "\t place: <path>:<offset>\n" 4361 "\t place: <path>:<offset>\n"
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 5f688cc724f0..013f4e7146d4 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -681,10 +681,6 @@ static int create_trace_kprobe(int argc, char **argv)
681 return -EINVAL; 681 return -EINVAL;
682 } 682 }
683 if (isdigit(argv[1][0])) { 683 if (isdigit(argv[1][0])) {
684 if (is_return) {
685 pr_info("Return probe point must be a symbol.\n");
686 return -EINVAL;
687 }
688 /* an address specified */ 684 /* an address specified */
689 ret = kstrtoul(&argv[1][0], 0, (unsigned long *)&addr); 685 ret = kstrtoul(&argv[1][0], 0, (unsigned long *)&addr);
690 if (ret) { 686 if (ret) {
@@ -700,8 +696,9 @@ static int create_trace_kprobe(int argc, char **argv)
700 pr_info("Failed to parse symbol.\n"); 696 pr_info("Failed to parse symbol.\n");
701 return ret; 697 return ret;
702 } 698 }
703 if (offset && is_return) { 699 if (offset && is_return &&
704 pr_info("Return probe must be used without offset.\n"); 700 !function_offset_within_entry(NULL, symbol, offset)) {
701 pr_info("Given offset is not valid for return probe.\n");
705 return -EINVAL; 702 return -EINVAL;
706 } 703 }
707 } 704 }
diff --git a/tools/arch/arm/include/uapi/asm/kvm.h b/tools/arch/arm/include/uapi/asm/kvm.h
index af05f8e0903e..6ebd3e6a1fd1 100644
--- a/tools/arch/arm/include/uapi/asm/kvm.h
+++ b/tools/arch/arm/include/uapi/asm/kvm.h
@@ -181,10 +181,23 @@ struct kvm_arch_memory_slot {
181#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2 181#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2
182#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32 182#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
183#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT) 183#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
184#define KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT 32
185#define KVM_DEV_ARM_VGIC_V3_MPIDR_MASK \
186 (0xffffffffULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
184#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0 187#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
185#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT) 188#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
189#define KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff)
186#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3 190#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
187#define KVM_DEV_ARM_VGIC_GRP_CTRL 4 191#define KVM_DEV_ARM_VGIC_GRP_CTRL 4
192#define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
193#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
194#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
195#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
196#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
197 (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
198#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
199#define VGIC_LEVEL_INFO_LINE_LEVEL 0
200
188#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 201#define KVM_DEV_ARM_VGIC_CTRL_INIT 0
189 202
190/* KVM_IRQ_LINE irq field index values */ 203/* KVM_IRQ_LINE irq field index values */
diff --git a/tools/arch/arm64/include/uapi/asm/kvm.h b/tools/arch/arm64/include/uapi/asm/kvm.h
index 3051f86a9b5f..c2860358ae3e 100644
--- a/tools/arch/arm64/include/uapi/asm/kvm.h
+++ b/tools/arch/arm64/include/uapi/asm/kvm.h
@@ -201,10 +201,23 @@ struct kvm_arch_memory_slot {
201#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2 201#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2
202#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32 202#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
203#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT) 203#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
204#define KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT 32
205#define KVM_DEV_ARM_VGIC_V3_MPIDR_MASK \
206 (0xffffffffULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
204#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0 207#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
205#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT) 208#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
209#define KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff)
206#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3 210#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
207#define KVM_DEV_ARM_VGIC_GRP_CTRL 4 211#define KVM_DEV_ARM_VGIC_GRP_CTRL 4
212#define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
213#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
214#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
215#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
216#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
217 (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
218#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
219#define VGIC_LEVEL_INFO_LINE_LEVEL 0
220
208#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 221#define KVM_DEV_ARM_VGIC_CTRL_INIT 0
209 222
210/* Device Control API on vcpu fd */ 223/* Device Control API on vcpu fd */
diff --git a/tools/arch/powerpc/include/uapi/asm/kvm.h b/tools/arch/powerpc/include/uapi/asm/kvm.h
index 3603b6f51b11..4edbe4bb0e8b 100644
--- a/tools/arch/powerpc/include/uapi/asm/kvm.h
+++ b/tools/arch/powerpc/include/uapi/asm/kvm.h
@@ -413,6 +413,26 @@ struct kvm_get_htab_header {
413 __u16 n_invalid; 413 __u16 n_invalid;
414}; 414};
415 415
416/* For KVM_PPC_CONFIGURE_V3_MMU */
417struct kvm_ppc_mmuv3_cfg {
418 __u64 flags;
419 __u64 process_table; /* second doubleword of partition table entry */
420};
421
422/* Flag values for KVM_PPC_CONFIGURE_V3_MMU */
423#define KVM_PPC_MMUV3_RADIX 1 /* 1 = radix mode, 0 = HPT */
424#define KVM_PPC_MMUV3_GTSE 2 /* global translation shootdown enb. */
425
426/* For KVM_PPC_GET_RMMU_INFO */
427struct kvm_ppc_rmmu_info {
428 struct kvm_ppc_radix_geom {
429 __u8 page_shift;
430 __u8 level_bits[4];
431 __u8 pad[3];
432 } geometries[8];
433 __u32 ap_encodings[8];
434};
435
416/* Per-vcpu XICS interrupt controller state */ 436/* Per-vcpu XICS interrupt controller state */
417#define KVM_REG_PPC_ICP_STATE (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8c) 437#define KVM_REG_PPC_ICP_STATE (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8c)
418 438
@@ -613,5 +633,7 @@ struct kvm_get_htab_header {
613#define KVM_XICS_LEVEL_SENSITIVE (1ULL << 40) 633#define KVM_XICS_LEVEL_SENSITIVE (1ULL << 40)
614#define KVM_XICS_MASKED (1ULL << 41) 634#define KVM_XICS_MASKED (1ULL << 41)
615#define KVM_XICS_PENDING (1ULL << 42) 635#define KVM_XICS_PENDING (1ULL << 42)
636#define KVM_XICS_PRESENTED (1ULL << 43)
637#define KVM_XICS_QUEUED (1ULL << 44)
616 638
617#endif /* __LINUX_KVM_POWERPC_H */ 639#endif /* __LINUX_KVM_POWERPC_H */
diff --git a/tools/arch/x86/include/asm/atomic.h b/tools/arch/x86/include/asm/atomic.h
index 059e33e94260..328eeceec709 100644
--- a/tools/arch/x86/include/asm/atomic.h
+++ b/tools/arch/x86/include/asm/atomic.h
@@ -7,6 +7,8 @@
7 7
8#define LOCK_PREFIX "\n\tlock; " 8#define LOCK_PREFIX "\n\tlock; "
9 9
10#include <asm/cmpxchg.h>
11
10/* 12/*
11 * Atomic operations that C can't guarantee us. Useful for 13 * Atomic operations that C can't guarantee us. Useful for
12 * resource counting etc.. 14 * resource counting etc..
@@ -62,4 +64,9 @@ static inline int atomic_dec_and_test(atomic_t *v)
62 GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", "e"); 64 GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", "e");
63} 65}
64 66
67static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new)
68{
69 return cmpxchg(&v->counter, old, new);
70}
71
65#endif /* _TOOLS_LINUX_ASM_X86_ATOMIC_H */ 72#endif /* _TOOLS_LINUX_ASM_X86_ATOMIC_H */
diff --git a/tools/arch/x86/include/asm/cmpxchg.h b/tools/arch/x86/include/asm/cmpxchg.h
new file mode 100644
index 000000000000..f5253260f3cc
--- /dev/null
+++ b/tools/arch/x86/include/asm/cmpxchg.h
@@ -0,0 +1,89 @@
1#ifndef TOOLS_ASM_X86_CMPXCHG_H
2#define TOOLS_ASM_X86_CMPXCHG_H
3
4#include <linux/compiler.h>
5
6/*
7 * Non-existant functions to indicate usage errors at link time
8 * (or compile-time if the compiler implements __compiletime_error().
9 */
10extern void __cmpxchg_wrong_size(void)
11 __compiletime_error("Bad argument size for cmpxchg");
12
13/*
14 * Constants for operation sizes. On 32-bit, the 64-bit size it set to
15 * -1 because sizeof will never return -1, thereby making those switch
16 * case statements guaranteeed dead code which the compiler will
17 * eliminate, and allowing the "missing symbol in the default case" to
18 * indicate a usage error.
19 */
20#define __X86_CASE_B 1
21#define __X86_CASE_W 2
22#define __X86_CASE_L 4
23#ifdef __x86_64__
24#define __X86_CASE_Q 8
25#else
26#define __X86_CASE_Q -1 /* sizeof will never return -1 */
27#endif
28
29/*
30 * Atomic compare and exchange. Compare OLD with MEM, if identical,
31 * store NEW in MEM. Return the initial value in MEM. Success is
32 * indicated by comparing RETURN with OLD.
33 */
34#define __raw_cmpxchg(ptr, old, new, size, lock) \
35({ \
36 __typeof__(*(ptr)) __ret; \
37 __typeof__(*(ptr)) __old = (old); \
38 __typeof__(*(ptr)) __new = (new); \
39 switch (size) { \
40 case __X86_CASE_B: \
41 { \
42 volatile u8 *__ptr = (volatile u8 *)(ptr); \
43 asm volatile(lock "cmpxchgb %2,%1" \
44 : "=a" (__ret), "+m" (*__ptr) \
45 : "q" (__new), "0" (__old) \
46 : "memory"); \
47 break; \
48 } \
49 case __X86_CASE_W: \
50 { \
51 volatile u16 *__ptr = (volatile u16 *)(ptr); \
52 asm volatile(lock "cmpxchgw %2,%1" \
53 : "=a" (__ret), "+m" (*__ptr) \
54 : "r" (__new), "0" (__old) \
55 : "memory"); \
56 break; \
57 } \
58 case __X86_CASE_L: \
59 { \
60 volatile u32 *__ptr = (volatile u32 *)(ptr); \
61 asm volatile(lock "cmpxchgl %2,%1" \
62 : "=a" (__ret), "+m" (*__ptr) \
63 : "r" (__new), "0" (__old) \
64 : "memory"); \
65 break; \
66 } \
67 case __X86_CASE_Q: \
68 { \
69 volatile u64 *__ptr = (volatile u64 *)(ptr); \
70 asm volatile(lock "cmpxchgq %2,%1" \
71 : "=a" (__ret), "+m" (*__ptr) \
72 : "r" (__new), "0" (__old) \
73 : "memory"); \
74 break; \
75 } \
76 default: \
77 __cmpxchg_wrong_size(); \
78 } \
79 __ret; \
80})
81
82#define __cmpxchg(ptr, old, new, size) \
83 __raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
84
85#define cmpxchg(ptr, old, new) \
86 __cmpxchg(ptr, old, new, sizeof(*(ptr)))
87
88
89#endif /* TOOLS_ASM_X86_CMPXCHG_H */
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
index 293149a1c6a1..0fe00446f9ca 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -100,7 +100,7 @@
100#define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* cpu topology enum extensions */ 100#define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* cpu topology enum extensions */
101#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */ 101#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */
102#define X86_FEATURE_NONSTOP_TSC ( 3*32+24) /* TSC does not stop in C states */ 102#define X86_FEATURE_NONSTOP_TSC ( 3*32+24) /* TSC does not stop in C states */
103/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */ 103#define X86_FEATURE_CPUID ( 3*32+25) /* CPU has CPUID instruction itself */
104#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* has extended APICID (8 bits) */ 104#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* has extended APICID (8 bits) */
105#define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */ 105#define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */
106#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */ 106#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */
@@ -186,7 +186,8 @@
186 * 186 *
187 * Reuse free bits when adding new feature flags! 187 * Reuse free bits when adding new feature flags!
188 */ 188 */
189 189#define X86_FEATURE_RING3MWAIT ( 7*32+ 0) /* Ring 3 MONITOR/MWAIT */
190#define X86_FEATURE_CPUID_FAULT ( 7*32+ 1) /* Intel CPUID faulting */
190#define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */ 191#define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */
191#define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */ 192#define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */
192#define X86_FEATURE_CAT_L3 ( 7*32+ 4) /* Cache Allocation Technology L3 */ 193#define X86_FEATURE_CAT_L3 ( 7*32+ 4) /* Cache Allocation Technology L3 */
@@ -289,7 +290,8 @@
289#define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */ 290#define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */
290#define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */ 291#define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */
291#define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */ 292#define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */
292#define X86_FEATURE_RDPID (16*32+ 22) /* RDPID instruction */ 293#define X86_FEATURE_LA57 (16*32+16) /* 5-level page tables */
294#define X86_FEATURE_RDPID (16*32+22) /* RDPID instruction */
293 295
294/* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */ 296/* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */
295#define X86_FEATURE_OVERFLOW_RECOV (17*32+0) /* MCA overflow recovery support */ 297#define X86_FEATURE_OVERFLOW_RECOV (17*32+0) /* MCA overflow recovery support */
@@ -321,5 +323,4 @@
321#define X86_BUG_SWAPGS_FENCE X86_BUG(11) /* SWAPGS without input dep on GS */ 323#define X86_BUG_SWAPGS_FENCE X86_BUG(11) /* SWAPGS without input dep on GS */
322#define X86_BUG_MONITOR X86_BUG(12) /* IPI required to wake up remote CPU */ 324#define X86_BUG_MONITOR X86_BUG(12) /* IPI required to wake up remote CPU */
323#define X86_BUG_AMD_E400 X86_BUG(13) /* CPU is among the affected by Erratum 400 */ 325#define X86_BUG_AMD_E400 X86_BUG(13) /* CPU is among the affected by Erratum 400 */
324
325#endif /* _ASM_X86_CPUFEATURES_H */ 326#endif /* _ASM_X86_CPUFEATURES_H */
diff --git a/tools/arch/x86/lib/memcpy_64.S b/tools/arch/x86/lib/memcpy_64.S
index 49e6ebac7e73..98dcc112b363 100644
--- a/tools/arch/x86/lib/memcpy_64.S
+++ b/tools/arch/x86/lib/memcpy_64.S
@@ -286,7 +286,7 @@ ENDPROC(memcpy_mcsafe_unrolled)
286 _ASM_EXTABLE_FAULT(.L_copy_leading_bytes, .L_memcpy_mcsafe_fail) 286 _ASM_EXTABLE_FAULT(.L_copy_leading_bytes, .L_memcpy_mcsafe_fail)
287 _ASM_EXTABLE_FAULT(.L_cache_w0, .L_memcpy_mcsafe_fail) 287 _ASM_EXTABLE_FAULT(.L_cache_w0, .L_memcpy_mcsafe_fail)
288 _ASM_EXTABLE_FAULT(.L_cache_w1, .L_memcpy_mcsafe_fail) 288 _ASM_EXTABLE_FAULT(.L_cache_w1, .L_memcpy_mcsafe_fail)
289 _ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail) 289 _ASM_EXTABLE_FAULT(.L_cache_w2, .L_memcpy_mcsafe_fail)
290 _ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail) 290 _ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail)
291 _ASM_EXTABLE_FAULT(.L_cache_w4, .L_memcpy_mcsafe_fail) 291 _ASM_EXTABLE_FAULT(.L_cache_w4, .L_memcpy_mcsafe_fail)
292 _ASM_EXTABLE_FAULT(.L_cache_w5, .L_memcpy_mcsafe_fail) 292 _ASM_EXTABLE_FAULT(.L_cache_w5, .L_memcpy_mcsafe_fail)
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index e3fb5ecbdcb6..523911f316ce 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -63,6 +63,7 @@ FEATURE_TESTS_BASIC := \
63 lzma \ 63 lzma \
64 get_cpuid \ 64 get_cpuid \
65 bpf \ 65 bpf \
66 sched_getcpu \
66 sdt 67 sdt
67 68
68# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list 69# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index b564a2eea039..e35e4e5ad192 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -48,21 +48,22 @@ FILES= \
48 test-get_cpuid.bin \ 48 test-get_cpuid.bin \
49 test-sdt.bin \ 49 test-sdt.bin \
50 test-cxx.bin \ 50 test-cxx.bin \
51 test-jvmti.bin 51 test-jvmti.bin \
52 test-sched_getcpu.bin
52 53
53FILES := $(addprefix $(OUTPUT),$(FILES)) 54FILES := $(addprefix $(OUTPUT),$(FILES))
54 55
55CC := $(CROSS_COMPILE)gcc -MD 56CC ?= $(CROSS_COMPILE)gcc
56CXX := $(CROSS_COMPILE)g++ -MD 57CXX ?= $(CROSS_COMPILE)g++
57PKG_CONFIG := $(CROSS_COMPILE)pkg-config 58PKG_CONFIG ?= $(CROSS_COMPILE)pkg-config
58LLVM_CONFIG ?= llvm-config 59LLVM_CONFIG ?= llvm-config
59 60
60all: $(FILES) 61all: $(FILES)
61 62
62__BUILD = $(CC) $(CFLAGS) -Wall -Werror -o $@ $(patsubst %.bin,%.c,$(@F)) $(LDFLAGS) 63__BUILD = $(CC) $(CFLAGS) -MD -Wall -Werror -o $@ $(patsubst %.bin,%.c,$(@F)) $(LDFLAGS)
63 BUILD = $(__BUILD) > $(@:.bin=.make.output) 2>&1 64 BUILD = $(__BUILD) > $(@:.bin=.make.output) 2>&1
64 65
65__BUILDXX = $(CXX) $(CXXFLAGS) -Wall -Werror -o $@ $(patsubst %.bin,%.cpp,$(@F)) $(LDFLAGS) 66__BUILDXX = $(CXX) $(CXXFLAGS) -MD -Wall -Werror -o $@ $(patsubst %.bin,%.cpp,$(@F)) $(LDFLAGS)
66 BUILDXX = $(__BUILDXX) > $(@:.bin=.make.output) 2>&1 67 BUILDXX = $(__BUILDXX) > $(@:.bin=.make.output) 2>&1
67 68
68############################### 69###############################
@@ -91,6 +92,9 @@ $(OUTPUT)test-libelf.bin:
91$(OUTPUT)test-glibc.bin: 92$(OUTPUT)test-glibc.bin:
92 $(BUILD) 93 $(BUILD)
93 94
95$(OUTPUT)test-sched_getcpu.bin:
96 $(BUILD)
97
94DWARFLIBS := -ldw 98DWARFLIBS := -ldw
95ifeq ($(findstring -static,${LDFLAGS}),-static) 99ifeq ($(findstring -static,${LDFLAGS}),-static)
96DWARFLIBS += -lelf -lebl -lz -llzma -lbz2 100DWARFLIBS += -lelf -lebl -lz -llzma -lbz2
@@ -171,7 +175,7 @@ $(OUTPUT)test-libperl.bin:
171 $(BUILD) $(FLAGS_PERL_EMBED) 175 $(BUILD) $(FLAGS_PERL_EMBED)
172 176
173$(OUTPUT)test-libpython.bin: 177$(OUTPUT)test-libpython.bin:
174 $(BUILD) 178 $(BUILD) $(FLAGS_PYTHON_EMBED)
175 179
176$(OUTPUT)test-libpython-version.bin: 180$(OUTPUT)test-libpython-version.bin:
177 $(BUILD) 181 $(BUILD)
diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c
index 699e43627397..cc6c7c01f4ca 100644
--- a/tools/build/feature/test-all.c
+++ b/tools/build/feature/test-all.c
@@ -117,6 +117,10 @@
117# include "test-pthread-attr-setaffinity-np.c" 117# include "test-pthread-attr-setaffinity-np.c"
118#undef main 118#undef main
119 119
120#define main main_test_sched_getcpu
121# include "test-sched_getcpu.c"
122#undef main
123
120# if 0 124# if 0
121/* 125/*
122 * Disable libbabeltrace check for test-all, because the requested 126 * Disable libbabeltrace check for test-all, because the requested
@@ -182,6 +186,7 @@ int main(int argc, char *argv[])
182 main_test_get_cpuid(); 186 main_test_get_cpuid();
183 main_test_bpf(); 187 main_test_bpf();
184 main_test_libcrypto(); 188 main_test_libcrypto();
189 main_test_sched_getcpu();
185 main_test_sdt(); 190 main_test_sdt();
186 191
187 return 0; 192 return 0;
diff --git a/tools/build/feature/test-sched_getcpu.c b/tools/build/feature/test-sched_getcpu.c
new file mode 100644
index 000000000000..c4a148dd7104
--- /dev/null
+++ b/tools/build/feature/test-sched_getcpu.c
@@ -0,0 +1,7 @@
1#define _GNU_SOURCE
2#include <sched.h>
3
4int main(void)
5{
6 return sched_getcpu();
7}
diff --git a/tools/include/asm-generic/atomic-gcc.h b/tools/include/asm-generic/atomic-gcc.h
index 2ba78c9f5701..5e9738f97bf3 100644
--- a/tools/include/asm-generic/atomic-gcc.h
+++ b/tools/include/asm-generic/atomic-gcc.h
@@ -60,4 +60,12 @@ static inline int atomic_dec_and_test(atomic_t *v)
60 return __sync_sub_and_fetch(&v->counter, 1) == 0; 60 return __sync_sub_and_fetch(&v->counter, 1) == 0;
61} 61}
62 62
63#define cmpxchg(ptr, oldval, newval) \
64 __sync_val_compare_and_swap(ptr, oldval, newval)
65
66static inline int atomic_cmpxchg(atomic_t *v, int oldval, int newval)
67{
68 return cmpxchg(&(v)->counter, oldval, newval);
69}
70
63#endif /* __TOOLS_ASM_GENERIC_ATOMIC_H */ 71#endif /* __TOOLS_ASM_GENERIC_ATOMIC_H */
diff --git a/tools/include/linux/atomic.h b/tools/include/linux/atomic.h
index 4e3d3d18ebab..9f21fc2b092b 100644
--- a/tools/include/linux/atomic.h
+++ b/tools/include/linux/atomic.h
@@ -3,4 +3,10 @@
3 3
4#include <asm/atomic.h> 4#include <asm/atomic.h>
5 5
6/* atomic_cmpxchg_relaxed */
7#ifndef atomic_cmpxchg_relaxed
8#define atomic_cmpxchg_relaxed atomic_cmpxchg
9#define atomic_cmpxchg_release atomic_cmpxchg
10#endif /* atomic_cmpxchg_relaxed */
11
6#endif /* __TOOLS_LINUX_ATOMIC_H */ 12#endif /* __TOOLS_LINUX_ATOMIC_H */
diff --git a/tools/include/linux/bug.h b/tools/include/linux/bug.h
new file mode 100644
index 000000000000..8e4a4f49135d
--- /dev/null
+++ b/tools/include/linux/bug.h
@@ -0,0 +1,10 @@
1#ifndef _TOOLS_PERF_LINUX_BUG_H
2#define _TOOLS_PERF_LINUX_BUG_H
3
4/* Force a compilation error if condition is true, but also produce a
5 result (of value 0 and type size_t), so the expression can be used
6 e.g. in a structure initializer (or where-ever else comma expressions
7 aren't permitted). */
8#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
9
10#endif /* _TOOLS_PERF_LINUX_BUG_H */
diff --git a/tools/include/linux/compiler-gcc.h b/tools/include/linux/compiler-gcc.h
index 48af2f10a42d..825d44f89a29 100644
--- a/tools/include/linux/compiler-gcc.h
+++ b/tools/include/linux/compiler-gcc.h
@@ -12,3 +12,10 @@
12#if GCC_VERSION >= 70000 && !defined(__CHECKER__) 12#if GCC_VERSION >= 70000 && !defined(__CHECKER__)
13# define __fallthrough __attribute__ ((fallthrough)) 13# define __fallthrough __attribute__ ((fallthrough))
14#endif 14#endif
15
16#if GCC_VERSION >= 40300
17# define __compiletime_error(message) __attribute__((error(message)))
18#endif /* GCC_VERSION >= 40300 */
19
20/* &a[0] degrades to a pointer: a different type from an array */
21#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 8de163b17c0d..23299d7e7160 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -5,6 +5,10 @@
5#include <linux/compiler-gcc.h> 5#include <linux/compiler-gcc.h>
6#endif 6#endif
7 7
8#ifndef __compiletime_error
9# define __compiletime_error(message)
10#endif
11
8/* Optimization barrier */ 12/* Optimization barrier */
9/* The "volatile" is due to gcc bugs */ 13/* The "volatile" is due to gcc bugs */
10#define barrier() __asm__ __volatile__("": : :"memory") 14#define barrier() __asm__ __volatile__("": : :"memory")
@@ -13,6 +17,11 @@
13# define __always_inline inline __attribute__((always_inline)) 17# define __always_inline inline __attribute__((always_inline))
14#endif 18#endif
15 19
20/* Are two types/vars the same type (ignoring qualifiers)? */
21#ifndef __same_type
22# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
23#endif
24
16#ifdef __ANDROID__ 25#ifdef __ANDROID__
17/* 26/*
18 * FIXME: Big hammer to get rid of tons of: 27 * FIXME: Big hammer to get rid of tons of:
diff --git a/tools/include/linux/hashtable.h b/tools/include/linux/hashtable.h
index c65cc0aa2659..251eabf2a05e 100644
--- a/tools/include/linux/hashtable.h
+++ b/tools/include/linux/hashtable.h
@@ -13,10 +13,6 @@
13#include <linux/hash.h> 13#include <linux/hash.h>
14#include <linux/log2.h> 14#include <linux/log2.h>
15 15
16#ifndef ARRAY_SIZE
17#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
18#endif
19
20#define DEFINE_HASHTABLE(name, bits) \ 16#define DEFINE_HASHTABLE(name, bits) \
21 struct hlist_head name[1 << (bits)] = \ 17 struct hlist_head name[1 << (bits)] = \
22 { [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT } 18 { [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 28607db02bd3..73ccc48126bb 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -4,6 +4,11 @@
4#include <stdarg.h> 4#include <stdarg.h>
5#include <stddef.h> 5#include <stddef.h>
6#include <assert.h> 6#include <assert.h>
7#include <linux/compiler.h>
8
9#ifndef UINT_MAX
10#define UINT_MAX (~0U)
11#endif
7 12
8#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) 13#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
9 14
@@ -72,6 +77,8 @@
72int vscnprintf(char *buf, size_t size, const char *fmt, va_list args); 77int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
73int scnprintf(char * buf, size_t size, const char * fmt, ...); 78int scnprintf(char * buf, size_t size, const char * fmt, ...);
74 79
80#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
81
75/* 82/*
76 * This looks more complex than it should be. But we need to 83 * This looks more complex than it should be. But we need to
77 * get the type for the ~ right in round_down (it needs to be 84 * get the type for the ~ right in round_down (it needs to be
diff --git a/tools/include/linux/log2.h b/tools/include/linux/log2.h
index d5677d39c1e4..0325cefc2220 100644
--- a/tools/include/linux/log2.h
+++ b/tools/include/linux/log2.h
@@ -12,6 +12,9 @@
12#ifndef _TOOLS_LINUX_LOG2_H 12#ifndef _TOOLS_LINUX_LOG2_H
13#define _TOOLS_LINUX_LOG2_H 13#define _TOOLS_LINUX_LOG2_H
14 14
15#include <linux/bitops.h>
16#include <linux/types.h>
17
15/* 18/*
16 * non-constant log of base 2 calculators 19 * non-constant log of base 2 calculators
17 * - the arch may override these in asm/bitops.h if they can be implemented 20 * - the arch may override these in asm/bitops.h if they can be implemented
diff --git a/tools/include/linux/refcount.h b/tools/include/linux/refcount.h
new file mode 100644
index 000000000000..a0177c1f55b1
--- /dev/null
+++ b/tools/include/linux/refcount.h
@@ -0,0 +1,151 @@
1#ifndef _TOOLS_LINUX_REFCOUNT_H
2#define _TOOLS_LINUX_REFCOUNT_H
3
4/*
5 * Variant of atomic_t specialized for reference counts.
6 *
7 * The interface matches the atomic_t interface (to aid in porting) but only
8 * provides the few functions one should use for reference counting.
9 *
10 * It differs in that the counter saturates at UINT_MAX and will not move once
11 * there. This avoids wrapping the counter and causing 'spurious'
12 * use-after-free issues.
13 *
14 * Memory ordering rules are slightly relaxed wrt regular atomic_t functions
15 * and provide only what is strictly required for refcounts.
16 *
17 * The increments are fully relaxed; these will not provide ordering. The
18 * rationale is that whatever is used to obtain the object we're increasing the
19 * reference count on will provide the ordering. For locked data structures,
20 * its the lock acquire, for RCU/lockless data structures its the dependent
21 * load.
22 *
23 * Do note that inc_not_zero() provides a control dependency which will order
24 * future stores against the inc, this ensures we'll never modify the object
25 * if we did not in fact acquire a reference.
26 *
27 * The decrements will provide release order, such that all the prior loads and
28 * stores will be issued before, it also provides a control dependency, which
29 * will order us against the subsequent free().
30 *
31 * The control dependency is against the load of the cmpxchg (ll/sc) that
32 * succeeded. This means the stores aren't fully ordered, but this is fine
33 * because the 1->0 transition indicates no concurrency.
34 *
35 * Note that the allocator is responsible for ordering things between free()
36 * and alloc().
37 *
38 */
39
40#include <linux/atomic.h>
41#include <linux/kernel.h>
42
43#ifdef NDEBUG
44#define REFCOUNT_WARN(cond, str) (void)(cond)
45#define __refcount_check
46#else
47#define REFCOUNT_WARN(cond, str) BUG_ON(cond)
48#define __refcount_check __must_check
49#endif
50
51typedef struct refcount_struct {
52 atomic_t refs;
53} refcount_t;
54
55#define REFCOUNT_INIT(n) { .refs = ATOMIC_INIT(n), }
56
57static inline void refcount_set(refcount_t *r, unsigned int n)
58{
59 atomic_set(&r->refs, n);
60}
61
62static inline unsigned int refcount_read(const refcount_t *r)
63{
64 return atomic_read(&r->refs);
65}
66
67/*
68 * Similar to atomic_inc_not_zero(), will saturate at UINT_MAX and WARN.
69 *
70 * Provides no memory ordering, it is assumed the caller has guaranteed the
71 * object memory to be stable (RCU, etc.). It does provide a control dependency
72 * and thereby orders future stores. See the comment on top.
73 */
74static inline __refcount_check
75bool refcount_inc_not_zero(refcount_t *r)
76{
77 unsigned int old, new, val = atomic_read(&r->refs);
78
79 for (;;) {
80 new = val + 1;
81
82 if (!val)
83 return false;
84
85 if (unlikely(!new))
86 return true;
87
88 old = atomic_cmpxchg_relaxed(&r->refs, val, new);
89 if (old == val)
90 break;
91
92 val = old;
93 }
94
95 REFCOUNT_WARN(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n");
96
97 return true;
98}
99
100/*
101 * Similar to atomic_inc(), will saturate at UINT_MAX and WARN.
102 *
103 * Provides no memory ordering, it is assumed the caller already has a
104 * reference on the object, will WARN when this is not so.
105 */
106static inline void refcount_inc(refcount_t *r)
107{
108 REFCOUNT_WARN(!refcount_inc_not_zero(r), "refcount_t: increment on 0; use-after-free.\n");
109}
110
111/*
112 * Similar to atomic_dec_and_test(), it will WARN on underflow and fail to
113 * decrement when saturated at UINT_MAX.
114 *
115 * Provides release memory ordering, such that prior loads and stores are done
116 * before, and provides a control dependency such that free() must come after.
117 * See the comment on top.
118 */
119static inline __refcount_check
120bool refcount_sub_and_test(unsigned int i, refcount_t *r)
121{
122 unsigned int old, new, val = atomic_read(&r->refs);
123
124 for (;;) {
125 if (unlikely(val == UINT_MAX))
126 return false;
127
128 new = val - i;
129 if (new > val) {
130 REFCOUNT_WARN(new > val, "refcount_t: underflow; use-after-free.\n");
131 return false;
132 }
133
134 old = atomic_cmpxchg_release(&r->refs, val, new);
135 if (old == val)
136 break;
137
138 val = old;
139 }
140
141 return !new;
142}
143
144static inline __refcount_check
145bool refcount_dec_and_test(refcount_t *r)
146{
147 return refcount_sub_and_test(1, r);
148}
149
150
151#endif /* _ATOMIC_LINUX_REFCOUNT_H */
diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h
index f436d2420a18..d62b56cf8c12 100644
--- a/tools/include/linux/string.h
+++ b/tools/include/linux/string.h
@@ -18,4 +18,6 @@ extern size_t strlcpy(char *dest, const char *src, size_t size);
18 18
19char *str_error_r(int errnum, char *buf, size_t buflen); 19char *str_error_r(int errnum, char *buf, size_t buflen);
20 20
21int prefixcmp(const char *str, const char *prefix);
22
21#endif /* _LINUX_STRING_H_ */ 23#endif /* _LINUX_STRING_H_ */
diff --git a/tools/include/linux/types.h b/tools/include/linux/types.h
index c24b3e3ae296..77a28a26a670 100644
--- a/tools/include/linux/types.h
+++ b/tools/include/linux/types.h
@@ -7,6 +7,7 @@
7 7
8#define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */ 8#define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */
9#include <asm/types.h> 9#include <asm/types.h>
10#include <asm/posix_types.h>
10 11
11struct page; 12struct page;
12struct kmem_cache; 13struct kmem_cache;
diff --git a/tools/include/uapi/linux/fcntl.h b/tools/include/uapi/linux/fcntl.h
new file mode 100644
index 000000000000..813afd6eee71
--- /dev/null
+++ b/tools/include/uapi/linux/fcntl.h
@@ -0,0 +1,72 @@
1#ifndef _UAPI_LINUX_FCNTL_H
2#define _UAPI_LINUX_FCNTL_H
3
4#include <asm/fcntl.h>
5
6#define F_SETLEASE (F_LINUX_SPECIFIC_BASE + 0)
7#define F_GETLEASE (F_LINUX_SPECIFIC_BASE + 1)
8
9/*
10 * Cancel a blocking posix lock; internal use only until we expose an
11 * asynchronous lock api to userspace:
12 */
13#define F_CANCELLK (F_LINUX_SPECIFIC_BASE + 5)
14
15/* Create a file descriptor with FD_CLOEXEC set. */
16#define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
17
18/*
19 * Request nofications on a directory.
20 * See below for events that may be notified.
21 */
22#define F_NOTIFY (F_LINUX_SPECIFIC_BASE+2)
23
24/*
25 * Set and get of pipe page size array
26 */
27#define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
28#define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8)
29
30/*
31 * Set/Get seals
32 */
33#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
34#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
35
36/*
37 * Types of seals
38 */
39#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
40#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
41#define F_SEAL_GROW 0x0004 /* prevent file from growing */
42#define F_SEAL_WRITE 0x0008 /* prevent writes */
43/* (1U << 31) is reserved for signed error codes */
44
45/*
46 * Types of directory notifications that may be requested.
47 */
48#define DN_ACCESS 0x00000001 /* File accessed */
49#define DN_MODIFY 0x00000002 /* File modified */
50#define DN_CREATE 0x00000004 /* File created */
51#define DN_DELETE 0x00000008 /* File removed */
52#define DN_RENAME 0x00000010 /* File renamed */
53#define DN_ATTRIB 0x00000020 /* File changed attibutes */
54#define DN_MULTISHOT 0x80000000 /* Don't remove notifier */
55
56#define AT_FDCWD -100 /* Special value used to indicate
57 openat should use the current
58 working directory. */
59#define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links. */
60#define AT_REMOVEDIR 0x200 /* Remove directory instead of
61 unlinking file. */
62#define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */
63#define AT_NO_AUTOMOUNT 0x800 /* Suppress terminal automount traversal */
64#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */
65
66#define AT_STATX_SYNC_TYPE 0x6000 /* Type of synchronisation required from statx() */
67#define AT_STATX_SYNC_AS_STAT 0x0000 /* - Do whatever stat() does */
68#define AT_STATX_FORCE_SYNC 0x2000 /* - Force the attributes to be sync'd with the server */
69#define AT_STATX_DONT_SYNC 0x4000 /* - Don't sync attributes with the server */
70
71
72#endif /* _UAPI_LINUX_FCNTL_H */
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index c66a485a24ac..d09a9cd021b1 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -344,7 +344,8 @@ struct perf_event_attr {
344 use_clockid : 1, /* use @clockid for time fields */ 344 use_clockid : 1, /* use @clockid for time fields */
345 context_switch : 1, /* context switch data */ 345 context_switch : 1, /* context switch data */
346 write_backward : 1, /* Write ring buffer from end to beginning */ 346 write_backward : 1, /* Write ring buffer from end to beginning */
347 __reserved_1 : 36; 347 namespaces : 1, /* include namespaces data */
348 __reserved_1 : 35;
348 349
349 union { 350 union {
350 __u32 wakeup_events; /* wakeup every n events */ 351 __u32 wakeup_events; /* wakeup every n events */
@@ -610,6 +611,23 @@ struct perf_event_header {
610 __u16 size; 611 __u16 size;
611}; 612};
612 613
614struct perf_ns_link_info {
615 __u64 dev;
616 __u64 ino;
617};
618
619enum {
620 NET_NS_INDEX = 0,
621 UTS_NS_INDEX = 1,
622 IPC_NS_INDEX = 2,
623 PID_NS_INDEX = 3,
624 USER_NS_INDEX = 4,
625 MNT_NS_INDEX = 5,
626 CGROUP_NS_INDEX = 6,
627
628 NR_NAMESPACES, /* number of available namespaces */
629};
630
613enum perf_event_type { 631enum perf_event_type {
614 632
615 /* 633 /*
@@ -862,6 +880,18 @@ enum perf_event_type {
862 */ 880 */
863 PERF_RECORD_SWITCH_CPU_WIDE = 15, 881 PERF_RECORD_SWITCH_CPU_WIDE = 15,
864 882
883 /*
884 * struct {
885 * struct perf_event_header header;
886 * u32 pid;
887 * u32 tid;
888 * u64 nr_namespaces;
889 * { u64 dev, inode; } [nr_namespaces];
890 * struct sample_id sample_id;
891 * };
892 */
893 PERF_RECORD_NAMESPACES = 16,
894
865 PERF_RECORD_MAX, /* non-ABI */ 895 PERF_RECORD_MAX, /* non-ABI */
866}; 896};
867 897
@@ -885,6 +915,7 @@ enum perf_callchain_context {
885 */ 915 */
886#define PERF_AUX_FLAG_TRUNCATED 0x01 /* record was truncated to fit */ 916#define PERF_AUX_FLAG_TRUNCATED 0x01 /* record was truncated to fit */
887#define PERF_AUX_FLAG_OVERWRITE 0x02 /* snapshot from overwrite mode */ 917#define PERF_AUX_FLAG_OVERWRITE 0x02 /* snapshot from overwrite mode */
918#define PERF_AUX_FLAG_PARTIAL 0x04 /* record contains gaps */
888 919
889#define PERF_FLAG_FD_NO_GROUP (1UL << 0) 920#define PERF_FLAG_FD_NO_GROUP (1UL << 0)
890#define PERF_FLAG_FD_OUTPUT (1UL << 1) 921#define PERF_FLAG_FD_OUTPUT (1UL << 1)
diff --git a/tools/include/uapi/linux/stat.h b/tools/include/uapi/linux/stat.h
new file mode 100644
index 000000000000..d538897b8e08
--- /dev/null
+++ b/tools/include/uapi/linux/stat.h
@@ -0,0 +1,177 @@
1#ifndef _UAPI_LINUX_STAT_H
2#define _UAPI_LINUX_STAT_H
3
4#include <linux/types.h>
5
6#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
7
8#define S_IFMT 00170000
9#define S_IFSOCK 0140000
10#define S_IFLNK 0120000
11#define S_IFREG 0100000
12#define S_IFBLK 0060000
13#define S_IFDIR 0040000
14#define S_IFCHR 0020000
15#define S_IFIFO 0010000
16#define S_ISUID 0004000
17#define S_ISGID 0002000
18#define S_ISVTX 0001000
19
20#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
21#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
22#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
23#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
24#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
25#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
26#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
27
28#define S_IRWXU 00700
29#define S_IRUSR 00400
30#define S_IWUSR 00200
31#define S_IXUSR 00100
32
33#define S_IRWXG 00070
34#define S_IRGRP 00040
35#define S_IWGRP 00020
36#define S_IXGRP 00010
37
38#define S_IRWXO 00007
39#define S_IROTH 00004
40#define S_IWOTH 00002
41#define S_IXOTH 00001
42
43#endif
44
45/*
46 * Timestamp structure for the timestamps in struct statx.
47 *
48 * tv_sec holds the number of seconds before (negative) or after (positive)
49 * 00:00:00 1st January 1970 UTC.
50 *
51 * tv_nsec holds a number of nanoseconds before (0..-999,999,999 if tv_sec is
52 * negative) or after (0..999,999,999 if tv_sec is positive) the tv_sec time.
53 *
54 * Note that if both tv_sec and tv_nsec are non-zero, then the two values must
55 * either be both positive or both negative.
56 *
57 * __reserved is held in case we need a yet finer resolution.
58 */
59struct statx_timestamp {
60 __s64 tv_sec;
61 __s32 tv_nsec;
62 __s32 __reserved;
63};
64
65/*
66 * Structures for the extended file attribute retrieval system call
67 * (statx()).
68 *
69 * The caller passes a mask of what they're specifically interested in as a
70 * parameter to statx(). What statx() actually got will be indicated in
71 * st_mask upon return.
72 *
73 * For each bit in the mask argument:
74 *
75 * - if the datum is not supported:
76 *
77 * - the bit will be cleared, and
78 *
79 * - the datum will be set to an appropriate fabricated value if one is
80 * available (eg. CIFS can take a default uid and gid), otherwise
81 *
82 * - the field will be cleared;
83 *
84 * - otherwise, if explicitly requested:
85 *
86 * - the datum will be synchronised to the server if AT_STATX_FORCE_SYNC is
87 * set or if the datum is considered out of date, and
88 *
89 * - the field will be filled in and the bit will be set;
90 *
91 * - otherwise, if not requested, but available in approximate form without any
92 * effort, it will be filled in anyway, and the bit will be set upon return
93 * (it might not be up to date, however, and no attempt will be made to
94 * synchronise the internal state first);
95 *
96 * - otherwise the field and the bit will be cleared before returning.
97 *
98 * Items in STATX_BASIC_STATS may be marked unavailable on return, but they
99 * will have values installed for compatibility purposes so that stat() and
100 * co. can be emulated in userspace.
101 */
102struct statx {
103 /* 0x00 */
104 __u32 stx_mask; /* What results were written [uncond] */
105 __u32 stx_blksize; /* Preferred general I/O size [uncond] */
106 __u64 stx_attributes; /* Flags conveying information about the file [uncond] */
107 /* 0x10 */
108 __u32 stx_nlink; /* Number of hard links */
109 __u32 stx_uid; /* User ID of owner */
110 __u32 stx_gid; /* Group ID of owner */
111 __u16 stx_mode; /* File mode */
112 __u16 __spare0[1];
113 /* 0x20 */
114 __u64 stx_ino; /* Inode number */
115 __u64 stx_size; /* File size */
116 __u64 stx_blocks; /* Number of 512-byte blocks allocated */
117 __u64 stx_attributes_mask; /* Mask to show what's supported in stx_attributes */
118 /* 0x40 */
119 struct statx_timestamp stx_atime; /* Last access time */
120 struct statx_timestamp stx_btime; /* File creation time */
121 struct statx_timestamp stx_ctime; /* Last attribute change time */
122 struct statx_timestamp stx_mtime; /* Last data modification time */
123 /* 0x80 */
124 __u32 stx_rdev_major; /* Device ID of special file [if bdev/cdev] */
125 __u32 stx_rdev_minor;
126 __u32 stx_dev_major; /* ID of device containing file [uncond] */
127 __u32 stx_dev_minor;
128 /* 0x90 */
129 __u64 __spare2[14]; /* Spare space for future expansion */
130 /* 0x100 */
131};
132
133/*
134 * Flags to be stx_mask
135 *
136 * Query request/result mask for statx() and struct statx::stx_mask.
137 *
138 * These bits should be set in the mask argument of statx() to request
139 * particular items when calling statx().
140 */
141#define STATX_TYPE 0x00000001U /* Want/got stx_mode & S_IFMT */
142#define STATX_MODE 0x00000002U /* Want/got stx_mode & ~S_IFMT */
143#define STATX_NLINK 0x00000004U /* Want/got stx_nlink */
144#define STATX_UID 0x00000008U /* Want/got stx_uid */
145#define STATX_GID 0x00000010U /* Want/got stx_gid */
146#define STATX_ATIME 0x00000020U /* Want/got stx_atime */
147#define STATX_MTIME 0x00000040U /* Want/got stx_mtime */
148#define STATX_CTIME 0x00000080U /* Want/got stx_ctime */
149#define STATX_INO 0x00000100U /* Want/got stx_ino */
150#define STATX_SIZE 0x00000200U /* Want/got stx_size */
151#define STATX_BLOCKS 0x00000400U /* Want/got stx_blocks */
152#define STATX_BASIC_STATS 0x000007ffU /* The stuff in the normal stat struct */
153#define STATX_BTIME 0x00000800U /* Want/got stx_btime */
154#define STATX_ALL 0x00000fffU /* All currently supported flags */
155#define STATX__RESERVED 0x80000000U /* Reserved for future struct statx expansion */
156
157/*
158 * Attributes to be found in stx_attributes and masked in stx_attributes_mask.
159 *
160 * These give information about the features or the state of a file that might
161 * be of use to ordinary userspace programs such as GUIs or ls rather than
162 * specialised tools.
163 *
164 * Note that the flags marked [I] correspond to generic FS_IOC_FLAGS
165 * semantically. Where possible, the numerical value is picked to correspond
166 * also.
167 */
168#define STATX_ATTR_COMPRESSED 0x00000004 /* [I] File is compressed by the fs */
169#define STATX_ATTR_IMMUTABLE 0x00000010 /* [I] File is marked immutable */
170#define STATX_ATTR_APPEND 0x00000020 /* [I] File is append-only */
171#define STATX_ATTR_NODUMP 0x00000040 /* [I] File is not to be dumped */
172#define STATX_ATTR_ENCRYPTED 0x00000800 /* [I] File requires key to decrypt in fs */
173
174#define STATX_ATTR_AUTOMOUNT 0x00001000 /* Dir: Automount trigger */
175
176
177#endif /* _UAPI_LINUX_STAT_H */
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c
index 4b6bfc43cccf..809c7721cd24 100644
--- a/tools/lib/api/fs/fs.c
+++ b/tools/lib/api/fs/fs.c
@@ -439,6 +439,35 @@ int sysfs__read_str(const char *entry, char **buf, size_t *sizep)
439 return filename__read_str(path, buf, sizep); 439 return filename__read_str(path, buf, sizep);
440} 440}
441 441
442int sysfs__read_bool(const char *entry, bool *value)
443{
444 char *buf;
445 size_t size;
446 int ret;
447
448 ret = sysfs__read_str(entry, &buf, &size);
449 if (ret < 0)
450 return ret;
451
452 switch (buf[0]) {
453 case '1':
454 case 'y':
455 case 'Y':
456 *value = true;
457 break;
458 case '0':
459 case 'n':
460 case 'N':
461 *value = false;
462 break;
463 default:
464 ret = -1;
465 }
466
467 free(buf);
468
469 return ret;
470}
442int sysctl__read_int(const char *sysctl, int *value) 471int sysctl__read_int(const char *sysctl, int *value)
443{ 472{
444 char path[PATH_MAX]; 473 char path[PATH_MAX];
diff --git a/tools/lib/api/fs/fs.h b/tools/lib/api/fs/fs.h
index 6b332dc74498..956c21127d1e 100644
--- a/tools/lib/api/fs/fs.h
+++ b/tools/lib/api/fs/fs.h
@@ -37,4 +37,5 @@ int sysctl__read_int(const char *sysctl, int *value);
37int sysfs__read_int(const char *entry, int *value); 37int sysfs__read_int(const char *entry, int *value);
38int sysfs__read_ull(const char *entry, unsigned long long *value); 38int sysfs__read_ull(const char *entry, unsigned long long *value);
39int sysfs__read_str(const char *entry, char **buf, size_t *sizep); 39int sysfs__read_str(const char *entry, char **buf, size_t *sizep);
40int sysfs__read_bool(const char *entry, bool *value);
40#endif /* __API_FS__ */ 41#endif /* __API_FS__ */
diff --git a/tools/lib/string.c b/tools/lib/string.c
index bd239bc1d557..8e678af1c6ee 100644
--- a/tools/lib/string.c
+++ b/tools/lib/string.c
@@ -87,3 +87,12 @@ size_t __weak strlcpy(char *dest, const char *src, size_t size)
87 } 87 }
88 return ret; 88 return ret;
89} 89}
90
91int prefixcmp(const char *str, const char *prefix)
92{
93 for (; ; str++, prefix++)
94 if (!*prefix)
95 return 0;
96 else if (*str != *prefix)
97 return (unsigned char)*prefix - (unsigned char)*str;
98}
diff --git a/tools/lib/subcmd/help.c b/tools/lib/subcmd/help.c
index e228c3cb3716..ba970a73d053 100644
--- a/tools/lib/subcmd/help.c
+++ b/tools/lib/subcmd/help.c
@@ -1,6 +1,7 @@
1#include <stdio.h> 1#include <stdio.h>
2#include <stdlib.h> 2#include <stdlib.h>
3#include <string.h> 3#include <string.h>
4#include <linux/string.h>
4#include <termios.h> 5#include <termios.h>
5#include <sys/ioctl.h> 6#include <sys/ioctl.h>
6#include <sys/types.h> 7#include <sys/types.h>
diff --git a/tools/lib/subcmd/help.h b/tools/lib/subcmd/help.h
index e145a020780c..9bd4223dc722 100644
--- a/tools/lib/subcmd/help.h
+++ b/tools/lib/subcmd/help.h
@@ -2,6 +2,7 @@
2#define __SUBCMD_HELP_H 2#define __SUBCMD_HELP_H
3 3
4#include <sys/types.h> 4#include <sys/types.h>
5#include <stdio.h>
5 6
6struct cmdnames { 7struct cmdnames {
7 size_t alloc; 8 size_t alloc;
diff --git a/tools/lib/subcmd/parse-options.c b/tools/lib/subcmd/parse-options.c
index 6bc24025d054..359bfa77f39c 100644
--- a/tools/lib/subcmd/parse-options.c
+++ b/tools/lib/subcmd/parse-options.c
@@ -1,4 +1,5 @@
1#include <linux/compiler.h> 1#include <linux/compiler.h>
2#include <linux/string.h>
2#include <linux/types.h> 3#include <linux/types.h>
3#include <stdio.h> 4#include <stdio.h>
4#include <stdlib.h> 5#include <stdlib.h>
diff --git a/tools/lib/subcmd/subcmd-util.h b/tools/lib/subcmd/subcmd-util.h
index fc2e45d8aaf1..8fa5f036eff0 100644
--- a/tools/lib/subcmd/subcmd-util.h
+++ b/tools/lib/subcmd/subcmd-util.h
@@ -79,13 +79,4 @@ static inline void astrcat(char **out, const char *add)
79 free(tmp); 79 free(tmp);
80} 80}
81 81
82static inline int prefixcmp(const char *str, const char *prefix)
83{
84 for (; ; str++, prefix++)
85 if (!*prefix)
86 return 0;
87 else if (*str != *prefix)
88 return (unsigned char)*prefix - (unsigned char)*str;
89}
90
91#endif /* __SUBCMD_UTIL_H */ 82#endif /* __SUBCMD_UTIL_H */
diff --git a/tools/lib/symbol/kallsyms.c b/tools/lib/symbol/kallsyms.c
index 5e431077fcd6..d270ac00613d 100644
--- a/tools/lib/symbol/kallsyms.c
+++ b/tools/lib/symbol/kallsyms.c
@@ -1,3 +1,4 @@
1#include <ctype.h>
1#include "symbol/kallsyms.h" 2#include "symbol/kallsyms.h"
2#include <stdio.h> 3#include <stdio.h>
3#include <stdlib.h> 4#include <stdlib.h>
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index 066086dd59a8..282a60368b14 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -36,8 +36,7 @@
36#include "warn.h" 36#include "warn.h"
37 37
38#include <linux/hashtable.h> 38#include <linux/hashtable.h>
39 39#include <linux/kernel.h>
40#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
41 40
42#define STATE_FP_SAVED 0x1 41#define STATE_FP_SAVED 0x1
43#define STATE_FP_SETUP 0x2 42#define STATE_FP_SETUP 0x2
diff --git a/tools/objtool/objtool.c b/tools/objtool/objtool.c
index 46c326db4f46..ecc5b1b5d15d 100644
--- a/tools/objtool/objtool.c
+++ b/tools/objtool/objtool.c
@@ -31,11 +31,10 @@
31#include <stdlib.h> 31#include <stdlib.h>
32#include <subcmd/exec-cmd.h> 32#include <subcmd/exec-cmd.h>
33#include <subcmd/pager.h> 33#include <subcmd/pager.h>
34#include <linux/kernel.h>
34 35
35#include "builtin.h" 36#include "builtin.h"
36 37
37#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
38
39struct cmd_struct { 38struct cmd_struct {
40 const char *name; 39 const char *name;
41 int (*fn)(int, const char **); 40 int (*fn)(int, const char **);
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 3db3db9278be..643cc4ba6872 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -31,3 +31,5 @@ config.mak.autogen
31.config-detected 31.config-detected
32util/intel-pt-decoder/inat-tables.c 32util/intel-pt-decoder/inat-tables.c
33arch/*/include/generated/ 33arch/*/include/generated/
34pmu-events/pmu-events.c
35pmu-events/jevents
diff --git a/tools/perf/Build b/tools/perf/Build
index 9b79f8d7db50..bd8eeb60533c 100644
--- a/tools/perf/Build
+++ b/tools/perf/Build
@@ -50,5 +50,6 @@ libperf-y += util/
50libperf-y += arch/ 50libperf-y += arch/
51libperf-y += ui/ 51libperf-y += ui/
52libperf-y += scripts/ 52libperf-y += scripts/
53libperf-y += trace/beauty/
53 54
54gtk-y += ui/gtk/ 55gtk-y += ui/gtk/
diff --git a/tools/perf/Documentation/perf-ftrace.txt b/tools/perf/Documentation/perf-ftrace.txt
index 2d96de6132a9..6e6a8b22c859 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -30,6 +30,24 @@ OPTIONS
30--verbose=:: 30--verbose=::
31 Verbosity level. 31 Verbosity level.
32 32
33-p::
34--pid=::
35 Trace on existing process id (comma separated list).
36
37-a::
38--all-cpus::
39 Force system-wide collection. Scripts run without a <command>
40 normally use -a by default, while scripts run with a <command>
41 normally don't - this option allows the latter to be run in
42 system-wide mode.
43
44-C::
45--cpu=::
46 Only trace for the list of CPUs provided. Multiple CPUs can
47 be provided as a comma separated list with no space like: 0,1.
48 Ranges of CPUs are specified with -: 0-2.
49 Default is to trace on all online CPUs.
50
33 51
34SEE ALSO 52SEE ALSO
35-------- 53--------
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 41857cce5e86..f709de54707b 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -8,7 +8,7 @@ perf-list - List all symbolic event types
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf list' [--no-desc] [--long-desc] [hw|sw|cache|tracepoint|pmu|event_glob] 11'perf list' [--no-desc] [--long-desc] [hw|sw|cache|tracepoint|pmu|sdt|event_glob]
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
@@ -24,6 +24,10 @@ Don't print descriptions.
24--long-desc:: 24--long-desc::
25Print longer event descriptions. 25Print longer event descriptions.
26 26
27--details::
28Print how named events are resolved internally into perf events, and also
29any extra expressions computed by perf stat.
30
27 31
28[[EVENT_MODIFIERS]] 32[[EVENT_MODIFIERS]]
29EVENT MODIFIERS 33EVENT MODIFIERS
@@ -240,6 +244,8 @@ To limit the list use:
240 244
241. 'pmu' to print the kernel supplied PMU events. 245. 'pmu' to print the kernel supplied PMU events.
242 246
247. 'sdt' to list all Statically Defined Tracepoint events.
248
243. If none of the above is matched, it will apply the supplied glob to all 249. If none of the above is matched, it will apply the supplied glob to all
244 events, printing the ones that match. 250 events, printing the ones that match.
245 251
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index b16003ec14a7..ea3789d05e5e 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -347,6 +347,9 @@ Enable weightened sampling. An additional weight is recorded per sample and can
347displayed with the weight and local_weight sort keys. This currently works for TSX 347displayed with the weight and local_weight sort keys. This currently works for TSX
348abort events and some memory events in precise mode on modern Intel CPUs. 348abort events and some memory events in precise mode on modern Intel CPUs.
349 349
350--namespaces::
351Record events of type PERF_RECORD_NAMESPACES.
352
350--transaction:: 353--transaction::
351Record transaction flags for transaction related events. 354Record transaction flags for transaction related events.
352 355
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index c04cc0647c16..37a175914157 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -72,7 +72,8 @@ OPTIONS
72--sort=:: 72--sort=::
73 Sort histogram entries by given key(s) - multiple keys can be specified 73 Sort histogram entries by given key(s) - multiple keys can be specified
74 in CSV format. Following sort keys are available: 74 in CSV format. Following sort keys are available:
75 pid, comm, dso, symbol, parent, cpu, socket, srcline, weight, local_weight. 75 pid, comm, dso, symbol, parent, cpu, socket, srcline, weight,
76 local_weight, cgroup_id.
76 77
77 Each key has following meaning: 78 Each key has following meaning:
78 79
@@ -80,6 +81,7 @@ OPTIONS
80 - pid: command and tid of the task 81 - pid: command and tid of the task
81 - dso: name of library or module executed at the time of sample 82 - dso: name of library or module executed at the time of sample
82 - symbol: name of function executed at the time of sample 83 - symbol: name of function executed at the time of sample
84 - symbol_size: size of function executed at the time of sample
83 - parent: name of function matched to the parent regex filter. Unmatched 85 - parent: name of function matched to the parent regex filter. Unmatched
84 entries are displayed as "[other]". 86 entries are displayed as "[other]".
85 - cpu: cpu number the task ran at the time of sample 87 - cpu: cpu number the task ran at the time of sample
@@ -91,6 +93,7 @@ OPTIONS
91 - weight: Event specific weight, e.g. memory latency or transaction 93 - weight: Event specific weight, e.g. memory latency or transaction
92 abort cost. This is the global weight. 94 abort cost. This is the global weight.
93 - local_weight: Local weight version of the weight above. 95 - local_weight: Local weight version of the weight above.
96 - cgroup_id: ID derived from cgroup namespace device and inode numbers.
94 - transaction: Transaction abort flags. 97 - transaction: Transaction abort flags.
95 - overhead: Overhead percentage of sample 98 - overhead: Overhead percentage of sample
96 - overhead_sys: Overhead percentage of sample running in system mode 99 - overhead_sys: Overhead percentage of sample running in system mode
@@ -172,6 +175,9 @@ OPTIONS
172 By default, every sort keys not specified in -F will be appended 175 By default, every sort keys not specified in -F will be appended
173 automatically. 176 automatically.
174 177
178 If the keys starts with a prefix '+', then it will append the specified
179 field(s) to the default field order. For example: perf report -F +period,sample.
180
175-p:: 181-p::
176--parent=<regex>:: 182--parent=<regex>::
177 A regex filter to identify parent. The parent is a caller of this 183 A regex filter to identify parent. The parent is a caller of this
@@ -229,6 +235,7 @@ OPTIONS
229 sort_key can be: 235 sort_key can be:
230 - function: compare on functions (default) 236 - function: compare on functions (default)
231 - address: compare on individual code addresses 237 - address: compare on individual code addresses
238 - srcline: compare on source filename and line number
232 239
233 branch can be: 240 branch can be:
234 - branch: include last branch information in callgraph when available. 241 - branch: include last branch information in callgraph when available.
@@ -424,6 +431,10 @@ include::itrace.txt[]
424--hierarchy:: 431--hierarchy::
425 Enable hierarchical output. 432 Enable hierarchical output.
426 433
434--inline::
435 If a callgraph address belongs to an inlined function, the inline stack
436 will be printed. Each entry is function name or file/line.
437
427include::callchain-overhead-calculation.txt[] 438include::callchain-overhead-calculation.txt[]
428 439
429SEE ALSO 440SEE ALSO
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index d33deddb0146..a092a2499e8f 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -132,6 +132,10 @@ OPTIONS for 'perf sched timehist'
132--migrations:: 132--migrations::
133 Show migration events. 133 Show migration events.
134 134
135-n::
136--next::
137 Show next task.
138
135-I:: 139-I::
136--idle-hist:: 140--idle-hist::
137 Show idle-related events only. 141 Show idle-related events only.
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 4ed5f239ba7d..cb0eda3925e6 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -116,7 +116,7 @@ OPTIONS
116--fields:: 116--fields::
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
119 srcline, period, iregs, brstack, brstacksym, flags, bpf-output, 119 srcline, period, iregs, brstack, brstacksym, flags, bpf-output, brstackinsn,
120 callindent, insn, insnlen. Field list can be prepended with the type, trace, sw or hw, 120 callindent, insn, insnlen. Field list can be prepended with the type, trace, sw or hw,
121 to indicate to which event type the field list applies. 121 to indicate to which event type the field list applies.
122 e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace 122 e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace
@@ -189,15 +189,20 @@ OPTIONS
189 i.e., -F "" is not allowed. 189 i.e., -F "" is not allowed.
190 190
191 The brstack output includes branch related information with raw addresses using the 191 The brstack output includes branch related information with raw addresses using the
192 /v/v/v/v/ syntax in the following order: 192 /v/v/v/v/cycles syntax in the following order:
193 FROM: branch source instruction 193 FROM: branch source instruction
194 TO : branch target instruction 194 TO : branch target instruction
195 M/P/-: M=branch target mispredicted or branch direction was mispredicted, P=target predicted or direction predicted, -=not supported 195 M/P/-: M=branch target mispredicted or branch direction was mispredicted, P=target predicted or direction predicted, -=not supported
196 X/- : X=branch inside a transactional region, -=not in transaction region or not supported 196 X/- : X=branch inside a transactional region, -=not in transaction region or not supported
197 A/- : A=TSX abort entry, -=not aborted region or not supported 197 A/- : A=TSX abort entry, -=not aborted region or not supported
198 cycles
198 199
199 The brstacksym is identical to brstack, except that the FROM and TO addresses are printed in a symbolic form if possible. 200 The brstacksym is identical to brstack, except that the FROM and TO addresses are printed in a symbolic form if possible.
200 201
202 When brstackinsn is specified the full assembler sequences of branch sequences for each sample
203 is printed. This is the full execution path leading to the sample. This is only supported when the
204 sample was recorded with perf record -b or -j any.
205
201-k:: 206-k::
202--vmlinux=<file>:: 207--vmlinux=<file>::
203 vmlinux pathname 208 vmlinux pathname
@@ -248,6 +253,9 @@ OPTIONS
248--show-mmap-events 253--show-mmap-events
249 Display mmap related events (e.g. MMAP, MMAP2). 254 Display mmap related events (e.g. MMAP, MMAP2).
250 255
256--show-namespace-events
257 Display namespace events i.e. events of type PERF_RECORD_NAMESPACES.
258
251--show-switch-events 259--show-switch-events
252 Display context switch events i.e. events of type PERF_RECORD_SWITCH or 260 Display context switch events i.e. events of type PERF_RECORD_SWITCH or
253 PERF_RECORD_SWITCH_CPU_WIDE. 261 PERF_RECORD_SWITCH_CPU_WIDE.
@@ -299,6 +307,10 @@ include::itrace.txt[]
299 stop time is not given (i.e, time string is 'x.y,') then analysis goes 307 stop time is not given (i.e, time string is 'x.y,') then analysis goes
300 to end of file. 308 to end of file.
301 309
310--max-blocks::
311 Set the maximum number of program blocks to print with brstackasm for
312 each sample.
313
302SEE ALSO 314SEE ALSO
303-------- 315--------
304linkperf:perf-record[1], linkperf:perf-script-perl[1], 316linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index aecf2a87e7d6..bd0e4417f2be 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -94,8 +94,7 @@ to activate system-wide monitoring. Default is to count on all CPUs.
94 94
95-A:: 95-A::
96--no-aggr:: 96--no-aggr::
97Do not aggregate counts across all monitored CPUs in system-wide mode (-a). 97Do not aggregate counts across all monitored CPUs.
98This option is only valid in system-wide mode.
99 98
100-n:: 99-n::
101--null:: 100--null::
@@ -237,6 +236,9 @@ To interpret the results it is usually needed to know on which
237CPUs the workload runs on. If needed the CPUs can be forced using 236CPUs the workload runs on. If needed the CPUs can be forced using
238taskset. 237taskset.
239 238
239--no-merge::
240Do not merge results from same PMUs.
241
240EXAMPLES 242EXAMPLES
241-------- 243--------
242 244
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index afd728672b6f..c1e3288a2dfb 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -123,7 +123,8 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
123 major or all pagefaults. Default value is maj. 123 major or all pagefaults. Default value is maj.
124 124
125--syscalls:: 125--syscalls::
126 Trace system calls. This options is enabled by default. 126 Trace system calls. This options is enabled by default, disable with
127 --no-syscalls.
127 128
128--call-graph [mode,type,min[,limit],order[,key][,branch]]:: 129--call-graph [mode,type,min[,limit],order[,key][,branch]]::
129 Setup and enable call-graph (stack chain/backtrace) recording. 130 Setup and enable call-graph (stack chain/backtrace) recording.
diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
index b664b18d3991..fa2a9132f0a9 100644
--- a/tools/perf/Documentation/perf.data-file-format.txt
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -11,8 +11,8 @@ All fields are in native-endian of the machine that generated the perf.data.
11 11
12When perf is writing to a pipe it uses a special version of the file 12When perf is writing to a pipe it uses a special version of the file
13format that does not rely on seeking to adjust data offsets. This 13format that does not rely on seeking to adjust data offsets. This
14format is not described here. The pipe version can be converted to 14format is described in "Pipe-mode data" section. The pipe data version can be
15normal perf.data with perf inject. 15augmented with additional events using perf inject.
16 16
17The file starts with a perf_header: 17The file starts with a perf_header:
18 18
@@ -411,6 +411,21 @@ An array bound by the perf_file_section size.
411 411
412ids points to a array of uint64_t defining the ids for event attr attr. 412ids points to a array of uint64_t defining the ids for event attr attr.
413 413
414Pipe-mode data
415
416Pipe-mode avoid seeks in the file by removing the perf_file_section and flags
417from the struct perf_header. The trimmed header is:
418
419struct perf_pipe_file_header {
420 u64 magic;
421 u64 size;
422};
423
424The information about attrs, data, and event_types is instead in the
425synthesized events PERF_RECORD_ATTR, PERF_RECORD_HEADER_TRACING_DATA and
426PERF_RECORD_HEADER_EVENT_TYPE that are generated by perf record in pipe-mode.
427
428
414References: 429References:
415 430
416include/uapi/linux/perf_event.h 431include/uapi/linux/perf_event.h
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 8672f835ae4e..a29da46d180f 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -12,6 +12,7 @@ tools/arch/sparc/include/asm/barrier_32.h
12tools/arch/sparc/include/asm/barrier_64.h 12tools/arch/sparc/include/asm/barrier_64.h
13tools/arch/tile/include/asm/barrier.h 13tools/arch/tile/include/asm/barrier.h
14tools/arch/x86/include/asm/barrier.h 14tools/arch/x86/include/asm/barrier.h
15tools/arch/x86/include/asm/cmpxchg.h
15tools/arch/x86/include/asm/cpufeatures.h 16tools/arch/x86/include/asm/cpufeatures.h
16tools/arch/x86/include/asm/disabled-features.h 17tools/arch/x86/include/asm/disabled-features.h
17tools/arch/x86/include/asm/required-features.h 18tools/arch/x86/include/asm/required-features.h
@@ -63,6 +64,7 @@ tools/include/linux/bitops.h
63tools/include/linux/compiler.h 64tools/include/linux/compiler.h
64tools/include/linux/compiler-gcc.h 65tools/include/linux/compiler-gcc.h
65tools/include/linux/coresight-pmu.h 66tools/include/linux/coresight-pmu.h
67tools/include/linux/bug.h
66tools/include/linux/filter.h 68tools/include/linux/filter.h
67tools/include/linux/hash.h 69tools/include/linux/hash.h
68tools/include/linux/kernel.h 70tools/include/linux/kernel.h
@@ -72,12 +74,15 @@ tools/include/uapi/asm-generic/mman-common.h
72tools/include/uapi/asm-generic/mman.h 74tools/include/uapi/asm-generic/mman.h
73tools/include/uapi/linux/bpf.h 75tools/include/uapi/linux/bpf.h
74tools/include/uapi/linux/bpf_common.h 76tools/include/uapi/linux/bpf_common.h
77tools/include/uapi/linux/fcntl.h
75tools/include/uapi/linux/hw_breakpoint.h 78tools/include/uapi/linux/hw_breakpoint.h
76tools/include/uapi/linux/mman.h 79tools/include/uapi/linux/mman.h
77tools/include/uapi/linux/perf_event.h 80tools/include/uapi/linux/perf_event.h
81tools/include/uapi/linux/stat.h
78tools/include/linux/poison.h 82tools/include/linux/poison.h
79tools/include/linux/rbtree.h 83tools/include/linux/rbtree.h
80tools/include/linux/rbtree_augmented.h 84tools/include/linux/rbtree_augmented.h
85tools/include/linux/refcount.h
81tools/include/linux/string.h 86tools/include/linux/string.h
82tools/include/linux/stringify.h 87tools/include/linux/stringify.h
83tools/include/linux/types.h 88tools/include/linux/types.h
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 27c9fbca7bd9..8354d04b392f 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -170,13 +170,20 @@ PYTHON2_CONFIG := \
170override PYTHON_CONFIG := \ 170override PYTHON_CONFIG := \
171 $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON2_CONFIG)) 171 $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON2_CONFIG))
172 172
173PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG)) 173grep-libs = $(filter -l%,$(1))
174strip-libs = $(filter-out -l%,$(1))
174 175
175PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null) 176PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
176PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
177 177
178ifeq ($(CC), clang) 178ifdef PYTHON_CONFIG
179 PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS)) 179 PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
180 PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
181 PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil
182 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
183 ifeq ($(CC), clang)
184 PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS))
185 endif
186 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
180endif 187endif
181 188
182FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS) 189FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS)
@@ -267,6 +274,7 @@ ifdef NO_LIBELF
267 NO_LIBUNWIND := 1 274 NO_LIBUNWIND := 1
268 NO_LIBDW_DWARF_UNWIND := 1 275 NO_LIBDW_DWARF_UNWIND := 1
269 NO_LIBBPF := 1 276 NO_LIBBPF := 1
277 NO_JVMTI := 1
270else 278else
271 ifeq ($(feature-libelf), 0) 279 ifeq ($(feature-libelf), 0)
272 ifeq ($(feature-glibc), 1) 280 ifeq ($(feature-glibc), 1)
@@ -276,7 +284,7 @@ else
276 LIBC_SUPPORT := 1 284 LIBC_SUPPORT := 1
277 endif 285 endif
278 ifeq ($(LIBC_SUPPORT),1) 286 ifeq ($(LIBC_SUPPORT),1)
279 msg := $(warning No libelf found, disables 'probe' tool and BPF support in 'perf record', please install libelf-dev, libelf-devel or elfutils-libelf-devel); 287 msg := $(warning No libelf found. Disables 'probe' tool, jvmti and BPF support in 'perf record'. Please install libelf-dev, libelf-devel or elfutils-libelf-devel);
280 288
281 NO_LIBELF := 1 289 NO_LIBELF := 1
282 NO_DWARF := 1 290 NO_DWARF := 1
@@ -284,6 +292,7 @@ else
284 NO_LIBUNWIND := 1 292 NO_LIBUNWIND := 1
285 NO_LIBDW_DWARF_UNWIND := 1 293 NO_LIBDW_DWARF_UNWIND := 1
286 NO_LIBBPF := 1 294 NO_LIBBPF := 1
295 NO_JVMTI := 1
287 else 296 else
288 ifneq ($(filter s% -static%,$(LDFLAGS),),) 297 ifneq ($(filter s% -static%,$(LDFLAGS),),)
289 msg := $(error No static glibc found, please install glibc-static); 298 msg := $(error No static glibc found, please install glibc-static);
@@ -317,6 +326,10 @@ ifdef NO_DWARF
317 NO_LIBDW_DWARF_UNWIND := 1 326 NO_LIBDW_DWARF_UNWIND := 1
318endif 327endif
319 328
329ifeq ($(feature-sched_getcpu), 1)
330 CFLAGS += -DHAVE_SCHED_GETCPU_SUPPORT
331endif
332
320ifndef NO_LIBELF 333ifndef NO_LIBELF
321 CFLAGS += -DHAVE_LIBELF_SUPPORT 334 CFLAGS += -DHAVE_LIBELF_SUPPORT
322 EXTLIBS += -lelf 335 EXTLIBS += -lelf
@@ -550,8 +563,6 @@ ifndef NO_GTK2
550 endif 563 endif
551endif 564endif
552 565
553grep-libs = $(filter -l%,$(1))
554strip-libs = $(filter-out -l%,$(1))
555 566
556ifdef NO_LIBPERL 567ifdef NO_LIBPERL
557 CFLAGS += -DNO_LIBPERL 568 CFLAGS += -DNO_LIBPERL
@@ -599,21 +610,9 @@ else
599 $(call disable-python,No 'python-config' tool was found: disables Python support - please install python-devel/python-dev) 610 $(call disable-python,No 'python-config' tool was found: disables Python support - please install python-devel/python-dev)
600 else 611 else
601 612
602 PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
603
604 PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
605 PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
606 PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil
607 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
608 ifeq ($(CC), clang)
609 PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS))
610 endif
611 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
612
613 ifneq ($(feature-libpython), 1) 613 ifneq ($(feature-libpython), 1)
614 $(call disable-python,No 'Python.h' (for Python 2.x support) was found: disables Python support - please install python-devel/python-dev) 614 $(call disable-python,No 'Python.h' (for Python 2.x support) was found: disables Python support - please install python-devel/python-dev)
615 else 615 else
616
617 ifneq ($(feature-libpython-version), 1) 616 ifneq ($(feature-libpython-version), 1)
618 $(warning Python 3 is not yet supported; please set) 617 $(warning Python 3 is not yet supported; please set)
619 $(warning PYTHON and/or PYTHON_CONFIG appropriately.) 618 $(warning PYTHON and/or PYTHON_CONFIG appropriately.)
diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c
index dfea6b635525..29361d9b635a 100644
--- a/tools/perf/arch/arm/util/cs-etm.c
+++ b/tools/perf/arch/arm/util/cs-etm.c
@@ -33,6 +33,7 @@
33#include "../../util/cs-etm.h" 33#include "../../util/cs-etm.h"
34 34
35#include <stdlib.h> 35#include <stdlib.h>
36#include <sys/stat.h>
36 37
37#define ENABLE_SINK_MAX 128 38#define ENABLE_SINK_MAX 128
38#define CS_BUS_DEVICE_PATH "/bus/coresight/devices/" 39#define CS_BUS_DEVICE_PATH "/bus/coresight/devices/"
diff --git a/tools/perf/arch/arm/util/dwarf-regs.c b/tools/perf/arch/arm/util/dwarf-regs.c
index 33ec5b339da8..8bb176a37990 100644
--- a/tools/perf/arch/arm/util/dwarf-regs.c
+++ b/tools/perf/arch/arm/util/dwarf-regs.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include <stddef.h> 11#include <stddef.h>
12#include <linux/stringify.h>
12#include <dwarf-regs.h> 13#include <dwarf-regs.h>
13 14
14struct pt_regs_dwarfnum { 15struct pt_regs_dwarfnum {
@@ -16,10 +17,9 @@ struct pt_regs_dwarfnum {
16 unsigned int dwarfnum; 17 unsigned int dwarfnum;
17}; 18};
18 19
19#define STR(s) #s
20#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num} 20#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num}
21#define GPR_DWARFNUM_NAME(num) \ 21#define GPR_DWARFNUM_NAME(num) \
22 {.name = STR(%r##num), .dwarfnum = num} 22 {.name = __stringify(%r##num), .dwarfnum = num}
23#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0} 23#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0}
24 24
25/* 25/*
diff --git a/tools/perf/arch/arm/util/unwind-libdw.c b/tools/perf/arch/arm/util/unwind-libdw.c
index b4176c60117a..bacfa00fca39 100644
--- a/tools/perf/arch/arm/util/unwind-libdw.c
+++ b/tools/perf/arch/arm/util/unwind-libdw.c
@@ -1,6 +1,7 @@
1#include <elfutils/libdwfl.h> 1#include <elfutils/libdwfl.h>
2#include "../../util/unwind-libdw.h" 2#include "../../util/unwind-libdw.h"
3#include "../../util/perf_regs.h" 3#include "../../util/perf_regs.h"
4#include "../../util/event.h"
4 5
5bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg) 6bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
6{ 7{
diff --git a/tools/perf/arch/arm64/util/dwarf-regs.c b/tools/perf/arch/arm64/util/dwarf-regs.c
index 068b6189157b..cd764a9fd098 100644
--- a/tools/perf/arch/arm64/util/dwarf-regs.c
+++ b/tools/perf/arch/arm64/util/dwarf-regs.c
@@ -8,9 +8,12 @@
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 */ 9 */
10 10
11#include <errno.h>
11#include <stddef.h> 12#include <stddef.h>
13#include <string.h>
12#include <dwarf-regs.h> 14#include <dwarf-regs.h>
13#include <linux/ptrace.h> /* for struct user_pt_regs */ 15#include <linux/ptrace.h> /* for struct user_pt_regs */
16#include <linux/stringify.h>
14#include "util.h" 17#include "util.h"
15 18
16struct pt_regs_dwarfnum { 19struct pt_regs_dwarfnum {
@@ -20,7 +23,7 @@ struct pt_regs_dwarfnum {
20 23
21#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num} 24#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num}
22#define GPR_DWARFNUM_NAME(num) \ 25#define GPR_DWARFNUM_NAME(num) \
23 {.name = STR(%x##num), .dwarfnum = num} 26 {.name = __stringify(%x##num), .dwarfnum = num}
24#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0} 27#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0}
25#define DWARFNUM2OFFSET(index) \ 28#define DWARFNUM2OFFSET(index) \
26 (index * sizeof((struct user_pt_regs *)0)->regs[0]) 29 (index * sizeof((struct user_pt_regs *)0)->regs[0])
diff --git a/tools/perf/arch/arm64/util/unwind-libunwind.c b/tools/perf/arch/arm64/util/unwind-libunwind.c
index c116b713f7f7..b415dfdbccca 100644
--- a/tools/perf/arch/arm64/util/unwind-libunwind.c
+++ b/tools/perf/arch/arm64/util/unwind-libunwind.c
@@ -1,6 +1,6 @@
1#include <errno.h>
1 2
2#ifndef REMOTE_UNWIND_LIBUNWIND 3#ifndef REMOTE_UNWIND_LIBUNWIND
3#include <errno.h>
4#include <libunwind.h> 4#include <libunwind.h>
5#include "perf_regs.h" 5#include "perf_regs.h"
6#include "../../util/unwind.h" 6#include "../../util/unwind.h"
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index 886dd2aaff0d..837067f48a4c 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -4,6 +4,8 @@
4#include "../util/util.h" 4#include "../util/util.h"
5#include "../util/debug.h" 5#include "../util/debug.h"
6 6
7#include "sane_ctype.h"
8
7const char *const arm_triplets[] = { 9const char *const arm_triplets[] = {
8 "arm-eabi-", 10 "arm-eabi-",
9 "arm-linux-androideabi-", 11 "arm-linux-androideabi-",
diff --git a/tools/perf/arch/powerpc/util/dwarf-regs.c b/tools/perf/arch/powerpc/util/dwarf-regs.c
index 41bdf9530d82..98ac87052a74 100644
--- a/tools/perf/arch/powerpc/util/dwarf-regs.c
+++ b/tools/perf/arch/powerpc/util/dwarf-regs.c
@@ -15,6 +15,7 @@
15#include <dwarf-regs.h> 15#include <dwarf-regs.h>
16#include <linux/ptrace.h> 16#include <linux/ptrace.h>
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/stringify.h>
18#include "util.h" 19#include "util.h"
19 20
20struct pt_regs_dwarfnum { 21struct pt_regs_dwarfnum {
@@ -24,10 +25,10 @@ struct pt_regs_dwarfnum {
24}; 25};
25 26
26#define REG_DWARFNUM_NAME(r, num) \ 27#define REG_DWARFNUM_NAME(r, num) \
27 {.name = STR(%)STR(r), .dwarfnum = num, \ 28 {.name = __stringify(%)__stringify(r), .dwarfnum = num, \
28 .ptregs_offset = offsetof(struct pt_regs, r)} 29 .ptregs_offset = offsetof(struct pt_regs, r)}
29#define GPR_DWARFNUM_NAME(num) \ 30#define GPR_DWARFNUM_NAME(num) \
30 {.name = STR(%gpr##num), .dwarfnum = num, \ 31 {.name = __stringify(%gpr##num), .dwarfnum = num, \
31 .ptregs_offset = offsetof(struct pt_regs, gpr[num])} 32 .ptregs_offset = offsetof(struct pt_regs, gpr[num])}
32#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0, .ptregs_offset = 0} 33#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0, .ptregs_offset = 0}
33 34
diff --git a/tools/perf/arch/powerpc/util/kvm-stat.c b/tools/perf/arch/powerpc/util/kvm-stat.c
index 74eee30398f8..249723f0e6a9 100644
--- a/tools/perf/arch/powerpc/util/kvm-stat.c
+++ b/tools/perf/arch/powerpc/util/kvm-stat.c
@@ -1,3 +1,4 @@
1#include <errno.h>
1#include "util/kvm-stat.h" 2#include "util/kvm-stat.h"
2#include "util/parse-events.h" 3#include "util/parse-events.h"
3#include "util/debug.h" 4#include "util/debug.h"
diff --git a/tools/perf/arch/powerpc/util/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c
index a3c3e1ce6807..f860dc411f69 100644
--- a/tools/perf/arch/powerpc/util/perf_regs.c
+++ b/tools/perf/arch/powerpc/util/perf_regs.c
@@ -1,5 +1,11 @@
1#include <errno.h>
2#include <string.h>
3#include <regex.h>
4
1#include "../../perf.h" 5#include "../../perf.h"
6#include "../../util/util.h"
2#include "../../util/perf_regs.h" 7#include "../../util/perf_regs.h"
8#include "../../util/debug.h"
3 9
4const struct sample_reg sample_reg_masks[] = { 10const struct sample_reg sample_reg_masks[] = {
5 SMPL_REG(r0, PERF_REG_POWERPC_R0), 11 SMPL_REG(r0, PERF_REG_POWERPC_R0),
@@ -47,3 +53,109 @@ const struct sample_reg sample_reg_masks[] = {
47 SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR), 53 SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
48 SMPL_REG_END 54 SMPL_REG_END
49}; 55};
56
57/* REG or %rREG */
58#define SDT_OP_REGEX1 "^(%r)?([1-2]?[0-9]|3[0-1])$"
59
60/* -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) */
61#define SDT_OP_REGEX2 "^(\\-)?([0-9]+)\\((%r)?([1-2]?[0-9]|3[0-1])\\)$"
62
63static regex_t sdt_op_regex1, sdt_op_regex2;
64
65static int sdt_init_op_regex(void)
66{
67 static int initialized;
68 int ret = 0;
69
70 if (initialized)
71 return 0;
72
73 ret = regcomp(&sdt_op_regex1, SDT_OP_REGEX1, REG_EXTENDED);
74 if (ret)
75 goto error;
76
77 ret = regcomp(&sdt_op_regex2, SDT_OP_REGEX2, REG_EXTENDED);
78 if (ret)
79 goto free_regex1;
80
81 initialized = 1;
82 return 0;
83
84free_regex1:
85 regfree(&sdt_op_regex1);
86error:
87 pr_debug4("Regex compilation error.\n");
88 return ret;
89}
90
91/*
92 * Parse OP and convert it into uprobe format, which is, +/-NUM(%gprREG).
93 * Possible variants of OP are:
94 * Format Example
95 * -------------------------
96 * NUM(REG) 48(18)
97 * -NUM(REG) -48(18)
98 * NUM(%rREG) 48(%r18)
99 * -NUM(%rREG) -48(%r18)
100 * REG 18
101 * %rREG %r18
102 * iNUM i0
103 * i-NUM i-1
104 *
105 * SDT marker arguments on Powerpc uses %rREG form with -mregnames flag
106 * and REG form with -mno-regnames. Here REG is general purpose register,
107 * which is in 0 to 31 range.
108 */
109int arch_sdt_arg_parse_op(char *old_op, char **new_op)
110{
111 int ret, new_len;
112 regmatch_t rm[5];
113 char prefix;
114
115 /* Constant argument. Uprobe does not support it */
116 if (old_op[0] == 'i') {
117 pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
118 return SDT_ARG_SKIP;
119 }
120
121 ret = sdt_init_op_regex();
122 if (ret < 0)
123 return ret;
124
125 if (!regexec(&sdt_op_regex1, old_op, 3, rm, 0)) {
126 /* REG or %rREG --> %gprREG */
127
128 new_len = 5; /* % g p r NULL */
129 new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
130
131 *new_op = zalloc(new_len);
132 if (!*new_op)
133 return -ENOMEM;
134
135 scnprintf(*new_op, new_len, "%%gpr%.*s",
136 (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so);
137 } else if (!regexec(&sdt_op_regex2, old_op, 5, rm, 0)) {
138 /*
139 * -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) -->
140 * +/-NUM(%gprREG)
141 */
142 prefix = (rm[1].rm_so == -1) ? '+' : '-';
143
144 new_len = 8; /* +/- ( % g p r ) NULL */
145 new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
146 new_len += (int)(rm[4].rm_eo - rm[4].rm_so);
147
148 *new_op = zalloc(new_len);
149 if (!*new_op)
150 return -ENOMEM;
151
152 scnprintf(*new_op, new_len, "%c%.*s(%%gpr%.*s)", prefix,
153 (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so,
154 (int)(rm[4].rm_eo - rm[4].rm_so), old_op + rm[4].rm_so);
155 } else {
156 pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
157 return SDT_ARG_SKIP;
158 }
159
160 return SDT_ARG_VALID;
161}
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
index 1030a6e504bb..bf9a2594572c 100644
--- a/tools/perf/arch/powerpc/util/sym-handling.c
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -10,6 +10,7 @@
10#include "symbol.h" 10#include "symbol.h"
11#include "map.h" 11#include "map.h"
12#include "probe-event.h" 12#include "probe-event.h"
13#include "probe-file.h"
13 14
14#ifdef HAVE_LIBELF_SUPPORT 15#ifdef HAVE_LIBELF_SUPPORT
15bool elf__needs_adjust_symbols(GElf_Ehdr ehdr) 16bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
@@ -51,6 +52,18 @@ int arch__compare_symbol_names(const char *namea, const char *nameb)
51 52
52 return strcmp(namea, nameb); 53 return strcmp(namea, nameb);
53} 54}
55
56int arch__compare_symbol_names_n(const char *namea, const char *nameb,
57 unsigned int n)
58{
59 /* Skip over initial dot */
60 if (*namea == '.')
61 namea++;
62 if (*nameb == '.')
63 nameb++;
64
65 return strncmp(namea, nameb, n);
66}
54#endif 67#endif
55 68
56#if defined(_CALL_ELF) && _CALL_ELF == 2 69#if defined(_CALL_ELF) && _CALL_ELF == 2
@@ -79,13 +92,18 @@ void arch__fix_tev_from_maps(struct perf_probe_event *pev,
79 * However, if the user specifies an offset, we fall back to using the 92 * However, if the user specifies an offset, we fall back to using the
80 * GEP since all userspace applications (objdump/readelf) show function 93 * GEP since all userspace applications (objdump/readelf) show function
81 * disassembly with offsets from the GEP. 94 * disassembly with offsets from the GEP.
82 *
83 * In addition, we shouldn't specify an offset for kretprobes.
84 */ 95 */
85 if (pev->point.offset || (!pev->uprobes && pev->point.retprobe) || 96 if (pev->point.offset || !map || !sym)
86 !map || !sym)
87 return; 97 return;
88 98
99 /* For kretprobes, add an offset only if the kernel supports it */
100 if (!pev->uprobes && pev->point.retprobe) {
101#ifdef HAVE_LIBELF_SUPPORT
102 if (!kretprobe_offset_is_supported())
103#endif
104 return;
105 }
106
89 lep_offset = PPC64_LOCAL_ENTRY_OFFSET(sym->arch_sym); 107 lep_offset = PPC64_LOCAL_ENTRY_OFFSET(sym->arch_sym);
90 108
91 if (map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) 109 if (map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS)
diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c
new file mode 100644
index 000000000000..745b4b1b8b21
--- /dev/null
+++ b/tools/perf/arch/s390/annotate/instructions.c
@@ -0,0 +1,30 @@
1static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *name)
2{
3 struct ins_ops *ops = NULL;
4
5 /* catch all kind of jumps */
6 if (strchr(name, 'j') ||
7 !strncmp(name, "bct", 3) ||
8 !strncmp(name, "br", 2))
9 ops = &jump_ops;
10 /* override call/returns */
11 if (!strcmp(name, "bras") ||
12 !strcmp(name, "brasl") ||
13 !strcmp(name, "basr"))
14 ops = &call_ops;
15 if (!strcmp(name, "br"))
16 ops = &ret_ops;
17
18 arch__associate_ins_ops(arch, name, ops);
19 return ops;
20}
21
22static int s390__annotate_init(struct arch *arch)
23{
24 if (!arch->initialized) {
25 arch->initialized = true;
26 arch->associate_instruction_ops = s390__associate_ins_ops;
27 }
28
29 return 0;
30}
diff --git a/tools/perf/arch/s390/util/kvm-stat.c b/tools/perf/arch/s390/util/kvm-stat.c
index ed57df2e6d68..d233e2eb9592 100644
--- a/tools/perf/arch/s390/util/kvm-stat.c
+++ b/tools/perf/arch/s390/util/kvm-stat.c
@@ -9,6 +9,7 @@
9 * as published by the Free Software Foundation. 9 * as published by the Free Software Foundation.
10 */ 10 */
11 11
12#include <errno.h>
12#include "../../util/kvm-stat.h" 13#include "../../util/kvm-stat.h"
13#include <asm/sie.h> 14#include <asm/sie.h>
14 15
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
index e93ef0b38db8..5aef183e2f85 100644
--- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
@@ -338,6 +338,7 @@
338329 common pkey_mprotect sys_pkey_mprotect 338329 common pkey_mprotect sys_pkey_mprotect
339330 common pkey_alloc sys_pkey_alloc 339330 common pkey_alloc sys_pkey_alloc
340331 common pkey_free sys_pkey_free 340331 common pkey_free sys_pkey_free
341332 common statx sys_statx
341 342
342# 343#
343# x32-specific system call numbers start at 512 to avoid cache impact 344# x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/tools/perf/arch/x86/tests/intel-cqm.c b/tools/perf/arch/x86/tests/intel-cqm.c
index 7f064eb37158..f9713a71d77e 100644
--- a/tools/perf/arch/x86/tests/intel-cqm.c
+++ b/tools/perf/arch/x86/tests/intel-cqm.c
@@ -6,7 +6,10 @@
6#include "evsel.h" 6#include "evsel.h"
7#include "arch-tests.h" 7#include "arch-tests.h"
8 8
9#include <signal.h>
9#include <sys/mman.h> 10#include <sys/mman.h>
11#include <sys/wait.h>
12#include <errno.h>
10#include <string.h> 13#include <string.h>
11 14
12static pid_t spawn(void) 15static pid_t spawn(void)
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 5c76cc83186a..e3ae9cff2b67 100644
--- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -1,3 +1,5 @@
1#include <errno.h>
2#include <inttypes.h>
1#include <stdio.h> 3#include <stdio.h>
2#include <unistd.h> 4#include <unistd.h>
3#include <linux/types.h> 5#include <linux/types.h>
diff --git a/tools/perf/arch/x86/util/auxtrace.c b/tools/perf/arch/x86/util/auxtrace.c
index cc1d865e31f1..6aa3f2a38321 100644
--- a/tools/perf/arch/x86/util/auxtrace.c
+++ b/tools/perf/arch/x86/util/auxtrace.c
@@ -13,6 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16#include <errno.h>
16#include <stdbool.h> 17#include <stdbool.h>
17 18
18#include "../../util/header.h" 19#include "../../util/header.h"
diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c
index 5132775a044f..af2bce7a2cd6 100644
--- a/tools/perf/arch/x86/util/intel-bts.c
+++ b/tools/perf/arch/x86/util/intel-bts.c
@@ -13,6 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16#include <errno.h>
16#include <linux/kernel.h> 17#include <linux/kernel.h>
17#include <linux/types.h> 18#include <linux/types.h>
18#include <linux/bitops.h> 19#include <linux/bitops.h>
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index 90fa2286edcf..f630de0206a1 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -13,6 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16#include <errno.h>
16#include <stdbool.h> 17#include <stdbool.h>
17#include <linux/kernel.h> 18#include <linux/kernel.h>
18#include <linux/types.h> 19#include <linux/types.h>
diff --git a/tools/perf/arch/x86/util/kvm-stat.c b/tools/perf/arch/x86/util/kvm-stat.c
index b63d4be655a2..bf817beca0a8 100644
--- a/tools/perf/arch/x86/util/kvm-stat.c
+++ b/tools/perf/arch/x86/util/kvm-stat.c
@@ -1,3 +1,4 @@
1#include <errno.h>
1#include "../../util/kvm-stat.h" 2#include "../../util/kvm-stat.h"
2#include <asm/svm.h> 3#include <asm/svm.h>
3#include <asm/vmx.h> 4#include <asm/vmx.h>
diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
index c5db14f36cc7..f95edebfb716 100644
--- a/tools/perf/arch/x86/util/perf_regs.c
+++ b/tools/perf/arch/x86/util/perf_regs.c
@@ -1,5 +1,11 @@
1#include <errno.h>
2#include <string.h>
3#include <regex.h>
4
1#include "../../perf.h" 5#include "../../perf.h"
6#include "../../util/util.h"
2#include "../../util/perf_regs.h" 7#include "../../util/perf_regs.h"
8#include "../../util/debug.h"
3 9
4const struct sample_reg sample_reg_masks[] = { 10const struct sample_reg sample_reg_masks[] = {
5 SMPL_REG(AX, PERF_REG_X86_AX), 11 SMPL_REG(AX, PERF_REG_X86_AX),
@@ -26,3 +32,224 @@ const struct sample_reg sample_reg_masks[] = {
26#endif 32#endif
27 SMPL_REG_END 33 SMPL_REG_END
28}; 34};
35
36struct sdt_name_reg {
37 const char *sdt_name;
38 const char *uprobe_name;
39};
40#define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
41#define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
42
43static const struct sdt_name_reg sdt_reg_tbl[] = {
44 SDT_NAME_REG(eax, ax),
45 SDT_NAME_REG(rax, ax),
46 SDT_NAME_REG(al, ax),
47 SDT_NAME_REG(ah, ax),
48 SDT_NAME_REG(ebx, bx),
49 SDT_NAME_REG(rbx, bx),
50 SDT_NAME_REG(bl, bx),
51 SDT_NAME_REG(bh, bx),
52 SDT_NAME_REG(ecx, cx),
53 SDT_NAME_REG(rcx, cx),
54 SDT_NAME_REG(cl, cx),
55 SDT_NAME_REG(ch, cx),
56 SDT_NAME_REG(edx, dx),
57 SDT_NAME_REG(rdx, dx),
58 SDT_NAME_REG(dl, dx),
59 SDT_NAME_REG(dh, dx),
60 SDT_NAME_REG(esi, si),
61 SDT_NAME_REG(rsi, si),
62 SDT_NAME_REG(sil, si),
63 SDT_NAME_REG(edi, di),
64 SDT_NAME_REG(rdi, di),
65 SDT_NAME_REG(dil, di),
66 SDT_NAME_REG(ebp, bp),
67 SDT_NAME_REG(rbp, bp),
68 SDT_NAME_REG(bpl, bp),
69 SDT_NAME_REG(rsp, sp),
70 SDT_NAME_REG(esp, sp),
71 SDT_NAME_REG(spl, sp),
72
73 /* rNN registers */
74 SDT_NAME_REG(r8b, r8),
75 SDT_NAME_REG(r8w, r8),
76 SDT_NAME_REG(r8d, r8),
77 SDT_NAME_REG(r9b, r9),
78 SDT_NAME_REG(r9w, r9),
79 SDT_NAME_REG(r9d, r9),
80 SDT_NAME_REG(r10b, r10),
81 SDT_NAME_REG(r10w, r10),
82 SDT_NAME_REG(r10d, r10),
83 SDT_NAME_REG(r11b, r11),
84 SDT_NAME_REG(r11w, r11),
85 SDT_NAME_REG(r11d, r11),
86 SDT_NAME_REG(r12b, r12),
87 SDT_NAME_REG(r12w, r12),
88 SDT_NAME_REG(r12d, r12),
89 SDT_NAME_REG(r13b, r13),
90 SDT_NAME_REG(r13w, r13),
91 SDT_NAME_REG(r13d, r13),
92 SDT_NAME_REG(r14b, r14),
93 SDT_NAME_REG(r14w, r14),
94 SDT_NAME_REG(r14d, r14),
95 SDT_NAME_REG(r15b, r15),
96 SDT_NAME_REG(r15w, r15),
97 SDT_NAME_REG(r15d, r15),
98 SDT_NAME_REG_END,
99};
100
101/*
102 * Perf only supports OP which is in +/-NUM(REG) form.
103 * Here plus-minus sign, NUM and parenthesis are optional,
104 * only REG is mandatory.
105 *
106 * SDT events also supports indirect addressing mode with a
107 * symbol as offset, scaled mode and constants in OP. But
108 * perf does not support them yet. Below are few examples.
109 *
110 * OP with scaled mode:
111 * (%rax,%rsi,8)
112 * 10(%ras,%rsi,8)
113 *
114 * OP with indirect addressing mode:
115 * check_action(%rip)
116 * mp_+52(%rip)
117 * 44+mp_(%rip)
118 *
119 * OP with constant values:
120 * $0
121 * $123
122 * $-1
123 */
124#define SDT_OP_REGEX "^([+\\-]?)([0-9]*)(\\(?)(%[a-z][a-z0-9]+)(\\)?)$"
125
126static regex_t sdt_op_regex;
127
128static int sdt_init_op_regex(void)
129{
130 static int initialized;
131 int ret = 0;
132
133 if (initialized)
134 return 0;
135
136 ret = regcomp(&sdt_op_regex, SDT_OP_REGEX, REG_EXTENDED);
137 if (ret < 0) {
138 pr_debug4("Regex compilation error.\n");
139 return ret;
140 }
141
142 initialized = 1;
143 return 0;
144}
145
146/*
147 * Max x86 register name length is 5(ex: %r15d). So, 6th char
148 * should always contain NULL. This helps to find register name
149 * length using strlen, insted of maintaing one more variable.
150 */
151#define SDT_REG_NAME_SIZE 6
152
153/*
154 * The uprobe parser does not support all gas register names;
155 * so, we have to replace them (ex. for x86_64: %rax -> %ax).
156 * Note: If register does not require renaming, just copy
157 * paste as it is, but don't leave it empty.
158 */
159static void sdt_rename_register(char *sdt_reg, int sdt_len, char *uprobe_reg)
160{
161 int i = 0;
162
163 for (i = 0; sdt_reg_tbl[i].sdt_name != NULL; i++) {
164 if (!strncmp(sdt_reg_tbl[i].sdt_name, sdt_reg, sdt_len)) {
165 strcpy(uprobe_reg, sdt_reg_tbl[i].uprobe_name);
166 return;
167 }
168 }
169
170 strncpy(uprobe_reg, sdt_reg, sdt_len);
171}
172
173int arch_sdt_arg_parse_op(char *old_op, char **new_op)
174{
175 char new_reg[SDT_REG_NAME_SIZE] = {0};
176 int new_len = 0, ret;
177 /*
178 * rm[0]: +/-NUM(REG)
179 * rm[1]: +/-
180 * rm[2]: NUM
181 * rm[3]: (
182 * rm[4]: REG
183 * rm[5]: )
184 */
185 regmatch_t rm[6];
186 /*
187 * Max prefix length is 2 as it may contains sign(+/-)
188 * and displacement 0 (Both sign and displacement 0 are
189 * optional so it may be empty). Use one more character
190 * to hold last NULL so that strlen can be used to find
191 * prefix length, instead of maintaing one more variable.
192 */
193 char prefix[3] = {0};
194
195 ret = sdt_init_op_regex();
196 if (ret < 0)
197 return ret;
198
199 /*
200 * If unsupported OR does not match with regex OR
201 * register name too long, skip it.
202 */
203 if (strchr(old_op, ',') || strchr(old_op, '$') ||
204 regexec(&sdt_op_regex, old_op, 6, rm, 0) ||
205 rm[4].rm_eo - rm[4].rm_so > SDT_REG_NAME_SIZE) {
206 pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
207 return SDT_ARG_SKIP;
208 }
209
210 /*
211 * Prepare prefix.
212 * If SDT OP has parenthesis but does not provide
213 * displacement, add 0 for displacement.
214 * SDT Uprobe Prefix
215 * -----------------------------
216 * +24(%rdi) +24(%di) +
217 * 24(%rdi) +24(%di) +
218 * %rdi %di
219 * (%rdi) +0(%di) +0
220 * -80(%rbx) -80(%bx) -
221 */
222 if (rm[3].rm_so != rm[3].rm_eo) {
223 if (rm[1].rm_so != rm[1].rm_eo)
224 prefix[0] = *(old_op + rm[1].rm_so);
225 else if (rm[2].rm_so != rm[2].rm_eo)
226 prefix[0] = '+';
227 else
228 strncpy(prefix, "+0", 2);
229 }
230
231 /* Rename register */
232 sdt_rename_register(old_op + rm[4].rm_so, rm[4].rm_eo - rm[4].rm_so,
233 new_reg);
234
235 /* Prepare final OP which should be valid for uprobe_events */
236 new_len = strlen(prefix) +
237 (rm[2].rm_eo - rm[2].rm_so) +
238 (rm[3].rm_eo - rm[3].rm_so) +
239 strlen(new_reg) +
240 (rm[5].rm_eo - rm[5].rm_so) +
241 1; /* NULL */
242
243 *new_op = zalloc(new_len);
244 if (!*new_op)
245 return -ENOMEM;
246
247 scnprintf(*new_op, new_len, "%.*s%.*s%.*s%.*s%.*s",
248 strlen(prefix), prefix,
249 (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so,
250 (int)(rm[3].rm_eo - rm[3].rm_so), old_op + rm[3].rm_so,
251 strlen(new_reg), new_reg,
252 (int)(rm[5].rm_eo - rm[5].rm_so), old_op + rm[5].rm_so);
253
254 return SDT_ARG_VALID;
255}
diff --git a/tools/perf/arch/x86/util/unwind-libdw.c b/tools/perf/arch/x86/util/unwind-libdw.c
index c4b72176ca83..38dc9bb2a7c9 100644
--- a/tools/perf/arch/x86/util/unwind-libdw.c
+++ b/tools/perf/arch/x86/util/unwind-libdw.c
@@ -1,6 +1,7 @@
1#include <elfutils/libdwfl.h> 1#include <elfutils/libdwfl.h>
2#include "../../util/unwind-libdw.h" 2#include "../../util/unwind-libdw.h"
3#include "../../util/perf_regs.h" 3#include "../../util/perf_regs.h"
4#include "../../util/event.h"
4 5
5bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg) 6bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
6{ 7{
diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h
index 579a592990dd..842ab2781cdc 100644
--- a/tools/perf/bench/bench.h
+++ b/tools/perf/bench/bench.h
@@ -25,17 +25,17 @@
25# endif 25# endif
26#endif 26#endif
27 27
28int bench_numa(int argc, const char **argv, const char *prefix); 28int bench_numa(int argc, const char **argv);
29int bench_sched_messaging(int argc, const char **argv, const char *prefix); 29int bench_sched_messaging(int argc, const char **argv);
30int bench_sched_pipe(int argc, const char **argv, const char *prefix); 30int bench_sched_pipe(int argc, const char **argv);
31int bench_mem_memcpy(int argc, const char **argv, const char *prefix); 31int bench_mem_memcpy(int argc, const char **argv);
32int bench_mem_memset(int argc, const char **argv, const char *prefix); 32int bench_mem_memset(int argc, const char **argv);
33int bench_futex_hash(int argc, const char **argv, const char *prefix); 33int bench_futex_hash(int argc, const char **argv);
34int bench_futex_wake(int argc, const char **argv, const char *prefix); 34int bench_futex_wake(int argc, const char **argv);
35int bench_futex_wake_parallel(int argc, const char **argv, const char *prefix); 35int bench_futex_wake_parallel(int argc, const char **argv);
36int bench_futex_requeue(int argc, const char **argv, const char *prefix); 36int bench_futex_requeue(int argc, const char **argv);
37/* pi futexes */ 37/* pi futexes */
38int bench_futex_lock_pi(int argc, const char **argv, const char *prefix); 38int bench_futex_lock_pi(int argc, const char **argv);
39 39
40#define BENCH_FORMAT_DEFAULT_STR "default" 40#define BENCH_FORMAT_DEFAULT_STR "default"
41#define BENCH_FORMAT_DEFAULT 0 41#define BENCH_FORMAT_DEFAULT 0
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index da04b8c5568a..fe16b310097f 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11/* For the CLR_() macros */ 11/* For the CLR_() macros */
12#include <string.h>
12#include <pthread.h> 13#include <pthread.h>
13 14
14#include <errno.h> 15#include <errno.h>
@@ -113,8 +114,7 @@ static void print_summary(void)
113 (int) runtime.tv_sec); 114 (int) runtime.tv_sec);
114} 115}
115 116
116int bench_futex_hash(int argc, const char **argv, 117int bench_futex_hash(int argc, const char **argv)
117 const char *prefix __maybe_unused)
118{ 118{
119 int ret = 0; 119 int ret = 0;
120 cpu_set_t cpu; 120 cpu_set_t cpu;
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index 91877777ec6e..73a1c44ea63c 100644
--- a/tools/perf/bench/futex-lock-pi.c
+++ b/tools/perf/bench/futex-lock-pi.c
@@ -3,6 +3,7 @@
3 */ 3 */
4 4
5/* For the CLR_() macros */ 5/* For the CLR_() macros */
6#include <string.h>
6#include <pthread.h> 7#include <pthread.h>
7 8
8#include <signal.h> 9#include <signal.h>
@@ -139,8 +140,7 @@ static void create_threads(struct worker *w, pthread_attr_t thread_attr)
139 } 140 }
140} 141}
141 142
142int bench_futex_lock_pi(int argc, const char **argv, 143int bench_futex_lock_pi(int argc, const char **argv)
143 const char *prefix __maybe_unused)
144{ 144{
145 int ret = 0; 145 int ret = 0;
146 unsigned int i; 146 unsigned int i;
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index 2b9705a8734c..41786cbea24c 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11/* For the CLR_() macros */ 11/* For the CLR_() macros */
12#include <string.h>
12#include <pthread.h> 13#include <pthread.h>
13 14
14#include <signal.h> 15#include <signal.h>
@@ -108,8 +109,7 @@ static void toggle_done(int sig __maybe_unused,
108 done = true; 109 done = true;
109} 110}
110 111
111int bench_futex_requeue(int argc, const char **argv, 112int bench_futex_requeue(int argc, const char **argv)
112 const char *prefix __maybe_unused)
113{ 113{
114 int ret = 0; 114 int ret = 0;
115 unsigned int i, j; 115 unsigned int i, j;
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index 2c8fa67ad537..4ab12c8e016a 100644
--- a/tools/perf/bench/futex-wake-parallel.c
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -8,6 +8,7 @@
8 */ 8 */
9 9
10/* For the CLR_() macros */ 10/* For the CLR_() macros */
11#include <string.h>
11#include <pthread.h> 12#include <pthread.h>
12 13
13#include <signal.h> 14#include <signal.h>
@@ -196,8 +197,7 @@ static void toggle_done(int sig __maybe_unused,
196 done = true; 197 done = true;
197} 198}
198 199
199int bench_futex_wake_parallel(int argc, const char **argv, 200int bench_futex_wake_parallel(int argc, const char **argv)
200 const char *prefix __maybe_unused)
201{ 201{
202 int ret = 0; 202 int ret = 0;
203 unsigned int i, j; 203 unsigned int i, j;
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index e246b1b8388a..2fa49222ef8d 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11/* For the CLR_() macros */ 11/* For the CLR_() macros */
12#include <string.h>
12#include <pthread.h> 13#include <pthread.h>
13 14
14#include <signal.h> 15#include <signal.h>
@@ -114,8 +115,7 @@ static void toggle_done(int sig __maybe_unused,
114 done = true; 115 done = true;
115} 116}
116 117
117int bench_futex_wake(int argc, const char **argv, 118int bench_futex_wake(int argc, const char **argv)
118 const char *prefix __maybe_unused)
119{ 119{
120 int ret = 0; 120 int ret = 0;
121 unsigned int i, j; 121 unsigned int i, j;
diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
index b2e06d1190d0..e44fd3239530 100644
--- a/tools/perf/bench/futex.h
+++ b/tools/perf/bench/futex.h
@@ -88,13 +88,11 @@ futex_cmp_requeue(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, int nr_wak
88 88
89#ifndef HAVE_PTHREAD_ATTR_SETAFFINITY_NP 89#ifndef HAVE_PTHREAD_ATTR_SETAFFINITY_NP
90#include <pthread.h> 90#include <pthread.h>
91static inline int pthread_attr_setaffinity_np(pthread_attr_t *attr, 91#include <linux/compiler.h>
92 size_t cpusetsize, 92static inline int pthread_attr_setaffinity_np(pthread_attr_t *attr __maybe_unused,
93 cpu_set_t *cpuset) 93 size_t cpusetsize __maybe_unused,
94 cpu_set_t *cpuset __maybe_unused)
94{ 95{
95 attr = attr;
96 cpusetsize = cpusetsize;
97 cpuset = cpuset;
98 return 0; 96 return 0;
99} 97}
100#endif 98#endif
diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c
index 52504a83b5a1..fbd732b54047 100644
--- a/tools/perf/bench/mem-functions.c
+++ b/tools/perf/bench/mem-functions.c
@@ -12,6 +12,7 @@
12#include <subcmd/parse-options.h> 12#include <subcmd/parse-options.h>
13#include "../util/header.h" 13#include "../util/header.h"
14#include "../util/cloexec.h" 14#include "../util/cloexec.h"
15#include "../util/string2.h"
15#include "bench.h" 16#include "bench.h"
16#include "mem-memcpy-arch.h" 17#include "mem-memcpy-arch.h"
17#include "mem-memset-arch.h" 18#include "mem-memset-arch.h"
@@ -284,7 +285,7 @@ static const char * const bench_mem_memcpy_usage[] = {
284 NULL 285 NULL
285}; 286};
286 287
287int bench_mem_memcpy(int argc, const char **argv, const char *prefix __maybe_unused) 288int bench_mem_memcpy(int argc, const char **argv)
288{ 289{
289 struct bench_mem_info info = { 290 struct bench_mem_info info = {
290 .functions = memcpy_functions, 291 .functions = memcpy_functions,
@@ -358,7 +359,7 @@ static const struct function memset_functions[] = {
358 { .name = NULL, } 359 { .name = NULL, }
359}; 360};
360 361
361int bench_mem_memset(int argc, const char **argv, const char *prefix __maybe_unused) 362int bench_mem_memset(int argc, const char **argv)
362{ 363{
363 struct bench_mem_info info = { 364 struct bench_mem_info info = {
364 .functions = memset_functions, 365 .functions = memset_functions,
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 3083fc36282b..27de0c8c5c19 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -4,6 +4,7 @@
4 * numa: Simulate NUMA-sensitive workload and measure their NUMA performance 4 * numa: Simulate NUMA-sensitive workload and measure their NUMA performance
5 */ 5 */
6 6
7#include <inttypes.h>
7/* For the CLR_() macros */ 8/* For the CLR_() macros */
8#include <pthread.h> 9#include <pthread.h>
9 10
@@ -30,6 +31,7 @@
30#include <sys/wait.h> 31#include <sys/wait.h>
31#include <sys/prctl.h> 32#include <sys/prctl.h>
32#include <sys/types.h> 33#include <sys/types.h>
34#include <linux/kernel.h>
33#include <linux/time64.h> 35#include <linux/time64.h>
34 36
35#include <numa.h> 37#include <numa.h>
@@ -187,7 +189,8 @@ static const struct option options[] = {
187 OPT_INCR ('d', "show_details" , &p0.show_details, "Show details"), 189 OPT_INCR ('d', "show_details" , &p0.show_details, "Show details"),
188 OPT_INCR ('a', "all" , &p0.run_all, "Run all tests in the suite"), 190 OPT_INCR ('a', "all" , &p0.run_all, "Run all tests in the suite"),
189 OPT_INTEGER('H', "thp" , &p0.thp, "MADV_NOHUGEPAGE < 0 < MADV_HUGEPAGE"), 191 OPT_INTEGER('H', "thp" , &p0.thp, "MADV_NOHUGEPAGE < 0 < MADV_HUGEPAGE"),
190 OPT_BOOLEAN('c', "show_convergence", &p0.show_convergence, "show convergence details"), 192 OPT_BOOLEAN('c', "show_convergence", &p0.show_convergence, "show convergence details, "
193 "convergence is reached when each process (all its threads) is running on a single NUMA node."),
191 OPT_BOOLEAN('m', "measure_convergence", &p0.measure_convergence, "measure convergence latency"), 194 OPT_BOOLEAN('m', "measure_convergence", &p0.measure_convergence, "measure convergence latency"),
192 OPT_BOOLEAN('q', "quiet" , &p0.show_quiet, "quiet mode"), 195 OPT_BOOLEAN('q', "quiet" , &p0.show_quiet, "quiet mode"),
193 OPT_BOOLEAN('S', "serialize-startup", &p0.serialize_startup,"serialize thread startup"), 196 OPT_BOOLEAN('S', "serialize-startup", &p0.serialize_startup,"serialize thread startup"),
@@ -1766,7 +1769,7 @@ static int bench_all(void)
1766 return 0; 1769 return 0;
1767} 1770}
1768 1771
1769int bench_numa(int argc, const char **argv, const char *prefix __maybe_unused) 1772int bench_numa(int argc, const char **argv)
1770{ 1773{
1771 init_params(&p0, "main,", argc, argv); 1774 init_params(&p0, "main,", argc, argv);
1772 argc = parse_options(argc, argv, options, bench_numa_usage, 0); 1775 argc = parse_options(argc, argv, options, bench_numa_usage, 0);
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
index 6a111e775210..4f961e74535b 100644
--- a/tools/perf/bench/sched-messaging.c
+++ b/tools/perf/bench/sched-messaging.c
@@ -260,8 +260,7 @@ static const char * const bench_sched_message_usage[] = {
260 NULL 260 NULL
261}; 261};
262 262
263int bench_sched_messaging(int argc, const char **argv, 263int bench_sched_messaging(int argc, const char **argv)
264 const char *prefix __maybe_unused)
265{ 264{
266 unsigned int i, total_children; 265 unsigned int i, total_children;
267 struct timeval start, stop, diff; 266 struct timeval start, stop, diff;
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index 2243f0150d76..a152737370c5 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -76,7 +76,7 @@ static void *worker_thread(void *__tdata)
76 return NULL; 76 return NULL;
77} 77}
78 78
79int bench_sched_pipe(int argc, const char **argv, const char *prefix __maybe_unused) 79int bench_sched_pipe(int argc, const char **argv)
80{ 80{
81 struct thread_data threads[2], *td; 81 struct thread_data threads[2], *td;
82 int pipe_1[2], pipe_2[2]; 82 int pipe_1[2], pipe_2[2];
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 4f52d85f5ebc..7a5dc7e5c577 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -33,6 +33,7 @@
33#include "util/block-range.h" 33#include "util/block-range.h"
34 34
35#include <dlfcn.h> 35#include <dlfcn.h>
36#include <errno.h>
36#include <linux/bitmap.h> 37#include <linux/bitmap.h>
37 38
38struct perf_annotate { 39struct perf_annotate {
@@ -383,7 +384,7 @@ static const char * const annotate_usage[] = {
383 NULL 384 NULL
384}; 385};
385 386
386int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) 387int cmd_annotate(int argc, const char **argv)
387{ 388{
388 struct perf_annotate annotate = { 389 struct perf_annotate annotate = {
389 .tool = { 390 .tool = {
@@ -393,6 +394,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
393 .comm = perf_event__process_comm, 394 .comm = perf_event__process_comm,
394 .exit = perf_event__process_exit, 395 .exit = perf_event__process_exit,
395 .fork = perf_event__process_fork, 396 .fork = perf_event__process_fork,
397 .namespaces = perf_event__process_namespaces,
398 .attr = perf_event__process_attr,
399 .build_id = perf_event__process_build_id,
396 .ordered_events = true, 400 .ordered_events = true,
397 .ordering_requires_timestamps = true, 401 .ordering_requires_timestamps = true,
398 }, 402 },
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index a1cddc6bbf0f..445e62881254 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -25,7 +25,7 @@
25#include <string.h> 25#include <string.h>
26#include <sys/prctl.h> 26#include <sys/prctl.h>
27 27
28typedef int (*bench_fn_t)(int argc, const char **argv, const char *prefix); 28typedef int (*bench_fn_t)(int argc, const char **argv);
29 29
30struct bench { 30struct bench {
31 const char *name; 31 const char *name;
@@ -155,7 +155,7 @@ static int bench_str2int(const char *str)
155 * to something meaningful: 155 * to something meaningful:
156 */ 156 */
157static int run_bench(const char *coll_name, const char *bench_name, bench_fn_t fn, 157static int run_bench(const char *coll_name, const char *bench_name, bench_fn_t fn,
158 int argc, const char **argv, const char *prefix) 158 int argc, const char **argv)
159{ 159{
160 int size; 160 int size;
161 char *name; 161 char *name;
@@ -171,7 +171,7 @@ static int run_bench(const char *coll_name, const char *bench_name, bench_fn_t f
171 prctl(PR_SET_NAME, name); 171 prctl(PR_SET_NAME, name);
172 argv[0] = name; 172 argv[0] = name;
173 173
174 ret = fn(argc, argv, prefix); 174 ret = fn(argc, argv);
175 175
176 free(name); 176 free(name);
177 177
@@ -198,7 +198,7 @@ static void run_collection(struct collection *coll)
198 fflush(stdout); 198 fflush(stdout);
199 199
200 argv[1] = bench->name; 200 argv[1] = bench->name;
201 run_bench(coll->name, bench->name, bench->fn, 1, argv, NULL); 201 run_bench(coll->name, bench->name, bench->fn, 1, argv);
202 printf("\n"); 202 printf("\n");
203 } 203 }
204} 204}
@@ -211,7 +211,7 @@ static void run_all_collections(void)
211 run_collection(coll); 211 run_collection(coll);
212} 212}
213 213
214int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused) 214int cmd_bench(int argc, const char **argv)
215{ 215{
216 struct collection *coll; 216 struct collection *coll;
217 int ret = 0; 217 int ret = 0;
@@ -270,7 +270,7 @@ int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
270 if (bench_format == BENCH_FORMAT_DEFAULT) 270 if (bench_format == BENCH_FORMAT_DEFAULT)
271 printf("# Running '%s/%s' benchmark:\n", coll->name, bench->name); 271 printf("# Running '%s/%s' benchmark:\n", coll->name, bench->name);
272 fflush(stdout); 272 fflush(stdout);
273 ret = run_bench(coll->name, bench->name, bench->fn, argc-1, argv+1, prefix); 273 ret = run_bench(coll->name, bench->name, bench->fn, argc-1, argv+1);
274 goto end; 274 goto end;
275 } 275 }
276 276
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 30e2b2cb2421..9eba7f1add1f 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -10,6 +10,7 @@
10#include <sys/time.h> 10#include <sys/time.h>
11#include <time.h> 11#include <time.h>
12#include <dirent.h> 12#include <dirent.h>
13#include <errno.h>
13#include <unistd.h> 14#include <unistd.h>
14#include "builtin.h" 15#include "builtin.h"
15#include "perf.h" 16#include "perf.h"
@@ -21,6 +22,7 @@
21#include "util/build-id.h" 22#include "util/build-id.h"
22#include "util/session.h" 23#include "util/session.h"
23#include "util/symbol.h" 24#include "util/symbol.h"
25#include "util/time-utils.h"
24 26
25static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid) 27static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid)
26{ 28{
@@ -47,19 +49,22 @@ static bool same_kallsyms_reloc(const char *from_dir, char *to_dir)
47 char to[PATH_MAX]; 49 char to[PATH_MAX];
48 const char *name; 50 const char *name;
49 u64 addr1 = 0, addr2 = 0; 51 u64 addr1 = 0, addr2 = 0;
50 int i; 52 int i, err = -1;
51 53
52 scnprintf(from, sizeof(from), "%s/kallsyms", from_dir); 54 scnprintf(from, sizeof(from), "%s/kallsyms", from_dir);
53 scnprintf(to, sizeof(to), "%s/kallsyms", to_dir); 55 scnprintf(to, sizeof(to), "%s/kallsyms", to_dir);
54 56
55 for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) { 57 for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
56 addr1 = kallsyms__get_function_start(from, name); 58 err = kallsyms__get_function_start(from, name, &addr1);
57 if (addr1) 59 if (!err)
58 break; 60 break;
59 } 61 }
60 62
61 if (name) 63 if (err)
62 addr2 = kallsyms__get_function_start(to, name); 64 return false;
65
66 if (kallsyms__get_function_start(to, name, &addr2))
67 return false;
63 68
64 return addr1 == addr2; 69 return addr1 == addr2;
65} 70}
@@ -276,8 +281,7 @@ static int build_id_cache__update_file(const char *filename)
276 return err; 281 return err;
277} 282}
278 283
279int cmd_buildid_cache(int argc, const char **argv, 284int cmd_buildid_cache(int argc, const char **argv)
280 const char *prefix __maybe_unused)
281{ 285{
282 struct strlist *list; 286 struct strlist *list;
283 struct str_node *pos; 287 struct str_node *pos;
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 5e914ee79eb3..fdaca16e0c74 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -16,6 +16,7 @@
16#include "util/session.h" 16#include "util/session.h"
17#include "util/symbol.h" 17#include "util/symbol.h"
18#include "util/data.h" 18#include "util/data.h"
19#include <errno.h>
19 20
20static int sysfs__fprintf_build_id(FILE *fp) 21static int sysfs__fprintf_build_id(FILE *fp)
21{ 22{
@@ -87,8 +88,7 @@ out:
87 return 0; 88 return 0;
88} 89}
89 90
90int cmd_buildid_list(int argc, const char **argv, 91int cmd_buildid_list(int argc, const char **argv)
91 const char *prefix __maybe_unused)
92{ 92{
93 bool show_kernel = false; 93 bool show_kernel = false;
94 bool with_hits = false; 94 bool with_hits = false;
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index e2b21723bbf8..620a467ee304 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -9,10 +9,13 @@
9 * Dick Fowles <fowles@inreach.com> 9 * Dick Fowles <fowles@inreach.com>
10 * Joe Mario <jmario@redhat.com> 10 * Joe Mario <jmario@redhat.com>
11 */ 11 */
12#include <errno.h>
13#include <inttypes.h>
12#include <linux/compiler.h> 14#include <linux/compiler.h>
13#include <linux/kernel.h> 15#include <linux/kernel.h>
14#include <linux/stringify.h> 16#include <linux/stringify.h>
15#include <asm/bug.h> 17#include <asm/bug.h>
18#include <sys/param.h>
16#include "util.h" 19#include "util.h"
17#include "debug.h" 20#include "debug.h"
18#include "builtin.h" 21#include "builtin.h"
@@ -24,11 +27,13 @@
24#include "tool.h" 27#include "tool.h"
25#include "data.h" 28#include "data.h"
26#include "sort.h" 29#include "sort.h"
30#include "event.h"
27#include "evlist.h" 31#include "evlist.h"
28#include "evsel.h" 32#include "evsel.h"
29#include <asm/bug.h> 33#include <asm/bug.h>
30#include "ui/browsers/hists.h" 34#include "ui/browsers/hists.h"
31#include "evlist.h" 35#include "evlist.h"
36#include "thread.h"
32 37
33struct c2c_hists { 38struct c2c_hists {
34 struct hists hists; 39 struct hists hists;
@@ -2334,7 +2339,7 @@ out:
2334 2339
2335static void perf_c2c_display(struct perf_session *session) 2340static void perf_c2c_display(struct perf_session *session)
2336{ 2341{
2337 if (c2c.use_stdio) 2342 if (use_browser == 0)
2338 perf_c2c__hists_fprintf(stdout, session); 2343 perf_c2c__hists_fprintf(stdout, session);
2339 else 2344 else
2340 perf_c2c__hists_browse(&c2c.hists.hists); 2345 perf_c2c__hists_browse(&c2c.hists.hists);
@@ -2536,7 +2541,7 @@ static int perf_c2c__report(int argc, const char **argv)
2536 OPT_BOOLEAN(0, "stdio", &c2c.use_stdio, "Use the stdio interface"), 2541 OPT_BOOLEAN(0, "stdio", &c2c.use_stdio, "Use the stdio interface"),
2537#endif 2542#endif
2538 OPT_BOOLEAN(0, "stats", &c2c.stats_only, 2543 OPT_BOOLEAN(0, "stats", &c2c.stats_only,
2539 "Use the stdio interface"), 2544 "Display only statistic tables (implies --stdio)"),
2540 OPT_BOOLEAN(0, "full-symbols", &c2c.symbol_full, 2545 OPT_BOOLEAN(0, "full-symbols", &c2c.symbol_full,
2541 "Display full length of symbols"), 2546 "Display full length of symbols"),
2542 OPT_BOOLEAN(0, "no-source", &no_source, 2547 OPT_BOOLEAN(0, "no-source", &no_source,
@@ -2755,12 +2760,12 @@ static int perf_c2c__record(int argc, const char **argv)
2755 pr_debug("\n"); 2760 pr_debug("\n");
2756 } 2761 }
2757 2762
2758 ret = cmd_record(i, rec_argv, NULL); 2763 ret = cmd_record(i, rec_argv);
2759 free(rec_argv); 2764 free(rec_argv);
2760 return ret; 2765 return ret;
2761} 2766}
2762 2767
2763int cmd_c2c(int argc, const char **argv, const char *prefix __maybe_unused) 2768int cmd_c2c(int argc, const char **argv)
2764{ 2769{
2765 argc = parse_options(argc, argv, c2c_options, c2c_usage, 2770 argc = parse_options(argc, argv, c2c_options, c2c_usage,
2766 PARSE_OPT_STOP_AT_NON_OPTION); 2771 PARSE_OPT_STOP_AT_NON_OPTION);
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index 8c0d93b7c2f0..80668fa7556e 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -154,11 +154,12 @@ static int parse_config_arg(char *arg, char **var, char **value)
154 return 0; 154 return 0;
155} 155}
156 156
157int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) 157int cmd_config(int argc, const char **argv)
158{ 158{
159 int i, ret = 0; 159 int i, ret = 0;
160 struct perf_config_set *set; 160 struct perf_config_set *set;
161 char *user_config = mkpath("%s/.perfconfig", getenv("HOME")); 161 char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
162 const char *config_filename;
162 163
163 argc = parse_options(argc, argv, config_options, config_usage, 164 argc = parse_options(argc, argv, config_options, config_usage,
164 PARSE_OPT_STOP_AT_NON_OPTION); 165 PARSE_OPT_STOP_AT_NON_OPTION);
@@ -175,6 +176,11 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
175 else if (use_user_config) 176 else if (use_user_config)
176 config_exclusive_filename = user_config; 177 config_exclusive_filename = user_config;
177 178
179 if (!config_exclusive_filename)
180 config_filename = user_config;
181 else
182 config_filename = config_exclusive_filename;
183
178 /* 184 /*
179 * At only 'config' sub-command, individually use the config set 185 * At only 'config' sub-command, individually use the config set
180 * because of reinitializing with options config file location. 186 * because of reinitializing with options config file location.
@@ -192,13 +198,9 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
192 parse_options_usage(config_usage, config_options, "l", 1); 198 parse_options_usage(config_usage, config_options, "l", 1);
193 } else { 199 } else {
194 ret = show_config(set); 200 ret = show_config(set);
195 if (ret < 0) { 201 if (ret < 0)
196 const char * config_filename = config_exclusive_filename;
197 if (!config_exclusive_filename)
198 config_filename = user_config;
199 pr_err("Nothing configured, " 202 pr_err("Nothing configured, "
200 "please check your %s \n", config_filename); 203 "please check your %s \n", config_filename);
201 }
202 } 204 }
203 break; 205 break;
204 default: 206 default:
@@ -221,13 +223,8 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
221 223
222 if (value == NULL) 224 if (value == NULL)
223 ret = show_spec_config(set, var); 225 ret = show_spec_config(set, var);
224 else { 226 else
225 const char *config_filename = config_exclusive_filename;
226
227 if (!config_exclusive_filename)
228 config_filename = user_config;
229 ret = set_config(set, config_filename, var, value); 227 ret = set_config(set, config_filename, var, value);
230 }
231 free(arg); 228 free(arg);
232 } 229 }
233 } else 230 } else
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c
index 7ad6e17ac6b3..0adb5f82335a 100644
--- a/tools/perf/builtin-data.c
+++ b/tools/perf/builtin-data.c
@@ -6,7 +6,7 @@
6#include "data-convert.h" 6#include "data-convert.h"
7#include "data-convert-bt.h" 7#include "data-convert-bt.h"
8 8
9typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix); 9typedef int (*data_cmd_fn_t)(int argc, const char **argv);
10 10
11struct data_cmd { 11struct data_cmd {
12 const char *name; 12 const char *name;
@@ -50,8 +50,7 @@ static const char * const data_convert_usage[] = {
50 NULL 50 NULL
51}; 51};
52 52
53static int cmd_data_convert(int argc, const char **argv, 53static int cmd_data_convert(int argc, const char **argv)
54 const char *prefix __maybe_unused)
55{ 54{
56 const char *to_ctf = NULL; 55 const char *to_ctf = NULL;
57 struct perf_data_convert_opts opts = { 56 struct perf_data_convert_opts opts = {
@@ -98,7 +97,7 @@ static struct data_cmd data_cmds[] = {
98 { .name = NULL, }, 97 { .name = NULL, },
99}; 98};
100 99
101int cmd_data(int argc, const char **argv, const char *prefix) 100int cmd_data(int argc, const char **argv)
102{ 101{
103 struct data_cmd *cmd; 102 struct data_cmd *cmd;
104 const char *cmdstr; 103 const char *cmdstr;
@@ -118,7 +117,7 @@ int cmd_data(int argc, const char **argv, const char *prefix)
118 if (strcmp(cmd->name, cmdstr)) 117 if (strcmp(cmd->name, cmdstr))
119 continue; 118 continue;
120 119
121 return cmd->fn(argc, argv, prefix); 120 return cmd->fn(argc, argv);
122 } 121 }
123 122
124 pr_err("Unknown command: %s\n", cmdstr); 123 pr_err("Unknown command: %s\n", cmdstr);
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 1b96a3122228..eec5df80f5a3 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -19,6 +19,8 @@
19#include "util/data.h" 19#include "util/data.h"
20#include "util/config.h" 20#include "util/config.h"
21 21
22#include <errno.h>
23#include <inttypes.h>
22#include <stdlib.h> 24#include <stdlib.h>
23#include <math.h> 25#include <math.h>
24 26
@@ -364,6 +366,7 @@ static struct perf_tool tool = {
364 .exit = perf_event__process_exit, 366 .exit = perf_event__process_exit,
365 .fork = perf_event__process_fork, 367 .fork = perf_event__process_fork,
366 .lost = perf_event__process_lost, 368 .lost = perf_event__process_lost,
369 .namespaces = perf_event__process_namespaces,
367 .ordered_events = true, 370 .ordered_events = true,
368 .ordering_requires_timestamps = true, 371 .ordering_requires_timestamps = true,
369}; 372};
@@ -1320,7 +1323,7 @@ static int diff__config(const char *var, const char *value,
1320 return 0; 1323 return 0;
1321} 1324}
1322 1325
1323int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) 1326int cmd_diff(int argc, const char **argv)
1324{ 1327{
1325 int ret = hists__init(); 1328 int ret = hists__init();
1326 1329
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index e09c4287fe87..6d210e40d611 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -46,7 +46,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
46 return 0; 46 return 0;
47} 47}
48 48
49int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused) 49int cmd_evlist(int argc, const char **argv)
50{ 50{
51 struct perf_attr_details details = { .verbose = false, }; 51 struct perf_attr_details details = { .verbose = false, };
52 const struct option options[] = { 52 const struct option options[] = {
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index c3e643666c72..9e0b35cd0eea 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -9,13 +9,18 @@
9#include "builtin.h" 9#include "builtin.h"
10#include "perf.h" 10#include "perf.h"
11 11
12#include <errno.h>
12#include <unistd.h> 13#include <unistd.h>
13#include <signal.h> 14#include <signal.h>
15#include <fcntl.h>
16#include <poll.h>
14 17
15#include "debug.h" 18#include "debug.h"
16#include <subcmd/parse-options.h> 19#include <subcmd/parse-options.h>
20#include <api/fs/tracing_path.h>
17#include "evlist.h" 21#include "evlist.h"
18#include "target.h" 22#include "target.h"
23#include "cpumap.h"
19#include "thread_map.h" 24#include "thread_map.h"
20#include "util/config.h" 25#include "util/config.h"
21 26
@@ -50,11 +55,12 @@ static void ftrace__workload_exec_failed_signal(int signo __maybe_unused,
50 done = true; 55 done = true;
51} 56}
52 57
53static int write_tracing_file(const char *name, const char *val) 58static int __write_tracing_file(const char *name, const char *val, bool append)
54{ 59{
55 char *file; 60 char *file;
56 int fd, ret = -1; 61 int fd, ret = -1;
57 ssize_t size = strlen(val); 62 ssize_t size = strlen(val);
63 int flags = O_WRONLY;
58 64
59 file = get_tracing_file(name); 65 file = get_tracing_file(name);
60 if (!file) { 66 if (!file) {
@@ -62,7 +68,12 @@ static int write_tracing_file(const char *name, const char *val)
62 return -1; 68 return -1;
63 } 69 }
64 70
65 fd = open(file, O_WRONLY); 71 if (append)
72 flags |= O_APPEND;
73 else
74 flags |= O_TRUNC;
75
76 fd = open(file, flags);
66 if (fd < 0) { 77 if (fd < 0) {
67 pr_debug("cannot open tracing file: %s\n", name); 78 pr_debug("cannot open tracing file: %s\n", name);
68 goto out; 79 goto out;
@@ -79,6 +90,18 @@ out:
79 return ret; 90 return ret;
80} 91}
81 92
93static int write_tracing_file(const char *name, const char *val)
94{
95 return __write_tracing_file(name, val, false);
96}
97
98static int append_tracing_file(const char *name, const char *val)
99{
100 return __write_tracing_file(name, val, true);
101}
102
103static int reset_tracing_cpu(void);
104
82static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused) 105static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
83{ 106{
84 if (write_tracing_file("tracing_on", "0") < 0) 107 if (write_tracing_file("tracing_on", "0") < 0)
@@ -90,14 +113,78 @@ static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
90 if (write_tracing_file("set_ftrace_pid", " ") < 0) 113 if (write_tracing_file("set_ftrace_pid", " ") < 0)
91 return -1; 114 return -1;
92 115
116 if (reset_tracing_cpu() < 0)
117 return -1;
118
119 return 0;
120}
121
122static int set_tracing_pid(struct perf_ftrace *ftrace)
123{
124 int i;
125 char buf[16];
126
127 if (target__has_cpu(&ftrace->target))
128 return 0;
129
130 for (i = 0; i < thread_map__nr(ftrace->evlist->threads); i++) {
131 scnprintf(buf, sizeof(buf), "%d",
132 ftrace->evlist->threads->map[i]);
133 if (append_tracing_file("set_ftrace_pid", buf) < 0)
134 return -1;
135 }
93 return 0; 136 return 0;
94} 137}
95 138
139static int set_tracing_cpumask(struct cpu_map *cpumap)
140{
141 char *cpumask;
142 size_t mask_size;
143 int ret;
144 int last_cpu;
145
146 last_cpu = cpu_map__cpu(cpumap, cpumap->nr - 1);
147 mask_size = (last_cpu + 3) / 4 + 1;
148 mask_size += last_cpu / 32; /* ',' is needed for every 32th cpus */
149
150 cpumask = malloc(mask_size);
151 if (cpumask == NULL) {
152 pr_debug("failed to allocate cpu mask\n");
153 return -1;
154 }
155
156 cpu_map__snprint_mask(cpumap, cpumask, mask_size);
157
158 ret = write_tracing_file("tracing_cpumask", cpumask);
159
160 free(cpumask);
161 return ret;
162}
163
164static int set_tracing_cpu(struct perf_ftrace *ftrace)
165{
166 struct cpu_map *cpumap = ftrace->evlist->cpus;
167
168 if (!target__has_cpu(&ftrace->target))
169 return 0;
170
171 return set_tracing_cpumask(cpumap);
172}
173
174static int reset_tracing_cpu(void)
175{
176 struct cpu_map *cpumap = cpu_map__new(NULL);
177 int ret;
178
179 ret = set_tracing_cpumask(cpumap);
180 cpu_map__put(cpumap);
181 return ret;
182}
183
96static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv) 184static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
97{ 185{
98 char *trace_file; 186 char *trace_file;
99 int trace_fd; 187 int trace_fd;
100 char *trace_pid;
101 char buf[4096]; 188 char buf[4096];
102 struct pollfd pollfd = { 189 struct pollfd pollfd = {
103 .events = POLLIN, 190 .events = POLLIN,
@@ -108,42 +195,43 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
108 return -1; 195 return -1;
109 } 196 }
110 197
111 if (argc < 1)
112 return -1;
113
114 signal(SIGINT, sig_handler); 198 signal(SIGINT, sig_handler);
115 signal(SIGUSR1, sig_handler); 199 signal(SIGUSR1, sig_handler);
116 signal(SIGCHLD, sig_handler); 200 signal(SIGCHLD, sig_handler);
201 signal(SIGPIPE, sig_handler);
117 202
118 reset_tracing_files(ftrace); 203 if (reset_tracing_files(ftrace) < 0)
204 goto out;
119 205
120 /* reset ftrace buffer */ 206 /* reset ftrace buffer */
121 if (write_tracing_file("trace", "0") < 0) 207 if (write_tracing_file("trace", "0") < 0)
122 goto out; 208 goto out;
123 209
124 if (perf_evlist__prepare_workload(ftrace->evlist, &ftrace->target, 210 if (argc && perf_evlist__prepare_workload(ftrace->evlist,
125 argv, false, ftrace__workload_exec_failed_signal) < 0) 211 &ftrace->target, argv, false,
212 ftrace__workload_exec_failed_signal) < 0) {
126 goto out; 213 goto out;
214 }
127 215
128 if (write_tracing_file("current_tracer", ftrace->tracer) < 0) { 216 if (set_tracing_pid(ftrace) < 0) {
129 pr_err("failed to set current_tracer to %s\n", ftrace->tracer); 217 pr_err("failed to set ftrace pid\n");
130 goto out; 218 goto out_reset;
131 } 219 }
132 220
133 if (asprintf(&trace_pid, "%d", thread_map__pid(ftrace->evlist->threads, 0)) < 0) { 221 if (set_tracing_cpu(ftrace) < 0) {
134 pr_err("failed to allocate pid string\n"); 222 pr_err("failed to set tracing cpumask\n");
135 goto out; 223 goto out_reset;
136 } 224 }
137 225
138 if (write_tracing_file("set_ftrace_pid", trace_pid) < 0) { 226 if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
139 pr_err("failed to set pid: %s\n", trace_pid); 227 pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
140 goto out_free_pid; 228 goto out_reset;
141 } 229 }
142 230
143 trace_file = get_tracing_file("trace_pipe"); 231 trace_file = get_tracing_file("trace_pipe");
144 if (!trace_file) { 232 if (!trace_file) {
145 pr_err("failed to open trace_pipe\n"); 233 pr_err("failed to open trace_pipe\n");
146 goto out_free_pid; 234 goto out_reset;
147 } 235 }
148 236
149 trace_fd = open(trace_file, O_RDONLY); 237 trace_fd = open(trace_file, O_RDONLY);
@@ -152,7 +240,7 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
152 240
153 if (trace_fd < 0) { 241 if (trace_fd < 0) {
154 pr_err("failed to open trace_pipe\n"); 242 pr_err("failed to open trace_pipe\n");
155 goto out_free_pid; 243 goto out_reset;
156 } 244 }
157 245
158 fcntl(trace_fd, F_SETFL, O_NONBLOCK); 246 fcntl(trace_fd, F_SETFL, O_NONBLOCK);
@@ -163,6 +251,8 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
163 goto out_close_fd; 251 goto out_close_fd;
164 } 252 }
165 253
254 setup_pager();
255
166 perf_evlist__start_workload(ftrace->evlist); 256 perf_evlist__start_workload(ftrace->evlist);
167 257
168 while (!done) { 258 while (!done) {
@@ -191,11 +281,9 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
191 281
192out_close_fd: 282out_close_fd:
193 close(trace_fd); 283 close(trace_fd);
194out_free_pid: 284out_reset:
195 free(trace_pid);
196out:
197 reset_tracing_files(ftrace); 285 reset_tracing_files(ftrace);
198 286out:
199 return done ? 0 : -1; 287 return done ? 0 : -1;
200} 288}
201 289
@@ -219,7 +307,7 @@ static int perf_ftrace_config(const char *var, const char *value, void *cb)
219 return -1; 307 return -1;
220} 308}
221 309
222int cmd_ftrace(int argc, const char **argv, const char *prefix __maybe_unused) 310int cmd_ftrace(int argc, const char **argv)
223{ 311{
224 int ret; 312 int ret;
225 struct perf_ftrace ftrace = { 313 struct perf_ftrace ftrace = {
@@ -227,15 +315,21 @@ int cmd_ftrace(int argc, const char **argv, const char *prefix __maybe_unused)
227 .target = { .uid = UINT_MAX, }, 315 .target = { .uid = UINT_MAX, },
228 }; 316 };
229 const char * const ftrace_usage[] = { 317 const char * const ftrace_usage[] = {
230 "perf ftrace [<options>] <command>", 318 "perf ftrace [<options>] [<command>]",
231 "perf ftrace [<options>] -- <command> [<options>]", 319 "perf ftrace [<options>] -- <command> [<options>]",
232 NULL 320 NULL
233 }; 321 };
234 const struct option ftrace_options[] = { 322 const struct option ftrace_options[] = {
235 OPT_STRING('t', "tracer", &ftrace.tracer, "tracer", 323 OPT_STRING('t', "tracer", &ftrace.tracer, "tracer",
236 "tracer to use: function_graph(default) or function"), 324 "tracer to use: function_graph(default) or function"),
325 OPT_STRING('p', "pid", &ftrace.target.pid, "pid",
326 "trace on existing process id"),
237 OPT_INCR('v', "verbose", &verbose, 327 OPT_INCR('v', "verbose", &verbose,
238 "be more verbose"), 328 "be more verbose"),
329 OPT_BOOLEAN('a', "all-cpus", &ftrace.target.system_wide,
330 "system-wide collection from all CPUs"),
331 OPT_STRING('C', "cpu", &ftrace.target.cpu_list, "cpu",
332 "list of cpus to monitor"),
239 OPT_END() 333 OPT_END()
240 }; 334 };
241 335
@@ -245,9 +339,18 @@ int cmd_ftrace(int argc, const char **argv, const char *prefix __maybe_unused)
245 339
246 argc = parse_options(argc, argv, ftrace_options, ftrace_usage, 340 argc = parse_options(argc, argv, ftrace_options, ftrace_usage,
247 PARSE_OPT_STOP_AT_NON_OPTION); 341 PARSE_OPT_STOP_AT_NON_OPTION);
248 if (!argc) 342 if (!argc && target__none(&ftrace.target))
249 usage_with_options(ftrace_usage, ftrace_options); 343 usage_with_options(ftrace_usage, ftrace_options);
250 344
345 ret = target__validate(&ftrace.target);
346 if (ret) {
347 char errbuf[512];
348
349 target__strerror(&ftrace.target, ret, errbuf, 512);
350 pr_err("%s\n", errbuf);
351 return -EINVAL;
352 }
353
251 ftrace.evlist = perf_evlist__new(); 354 ftrace.evlist = perf_evlist__new();
252 if (ftrace.evlist == NULL) 355 if (ftrace.evlist == NULL)
253 return -ENOMEM; 356 return -ENOMEM;
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index aed0d844e8c2..492f8e14ab09 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -12,16 +12,22 @@
12#include <subcmd/run-command.h> 12#include <subcmd/run-command.h>
13#include <subcmd/help.h> 13#include <subcmd/help.h>
14#include "util/debug.h" 14#include "util/debug.h"
15#include <linux/kernel.h>
16#include <errno.h>
17#include <stdio.h>
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <unistd.h>
15 21
16static struct man_viewer_list { 22static struct man_viewer_list {
17 struct man_viewer_list *next; 23 struct man_viewer_list *next;
18 char name[FLEX_ARRAY]; 24 char name[0];
19} *man_viewer_list; 25} *man_viewer_list;
20 26
21static struct man_viewer_info_list { 27static struct man_viewer_info_list {
22 struct man_viewer_info_list *next; 28 struct man_viewer_info_list *next;
23 const char *info; 29 const char *info;
24 char name[FLEX_ARRAY]; 30 char name[0];
25} *man_viewer_info_list; 31} *man_viewer_info_list;
26 32
27enum help_format { 33enum help_format {
@@ -301,12 +307,6 @@ void list_common_cmds_help(void)
301 } 307 }
302} 308}
303 309
304static int is_perf_command(const char *s)
305{
306 return is_in_cmdlist(&main_cmds, s) ||
307 is_in_cmdlist(&other_cmds, s);
308}
309
310static const char *cmd_to_page(const char *perf_cmd) 310static const char *cmd_to_page(const char *perf_cmd)
311{ 311{
312 char *s; 312 char *s;
@@ -418,7 +418,7 @@ static int show_html_page(const char *perf_cmd)
418 return 0; 418 return 0;
419} 419}
420 420
421int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused) 421int cmd_help(int argc, const char **argv)
422{ 422{
423 bool show_all = false; 423 bool show_all = false;
424 enum help_format help_format = HELP_FORMAT_MAN; 424 enum help_format help_format = HELP_FORMAT_MAN;
@@ -446,7 +446,6 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
446 "perf help [--all] [--man|--web|--info] [command]", 446 "perf help [--all] [--man|--web|--info] [command]",
447 NULL 447 NULL
448 }; 448 };
449 const char *alias;
450 int rc; 449 int rc;
451 450
452 load_command_list("perf-", &main_cmds, &other_cmds); 451 load_command_list("perf-", &main_cmds, &other_cmds);
@@ -472,12 +471,6 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
472 return 0; 471 return 0;
473 } 472 }
474 473
475 alias = alias_lookup(argv[0]);
476 if (alias && !is_perf_command(argv[0])) {
477 printf("`perf %s' is aliased to `%s'\n", argv[0], alias);
478 return 0;
479 }
480
481 switch (help_format) { 474 switch (help_format) {
482 case HELP_FORMAT_MAN: 475 case HELP_FORMAT_MAN:
483 rc = show_man_page(argv[0]); 476 rc = show_man_page(argv[0]);
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index b9bc7e39833a..ea8db38eedd1 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -18,10 +18,13 @@
18#include "util/data.h" 18#include "util/data.h"
19#include "util/auxtrace.h" 19#include "util/auxtrace.h"
20#include "util/jit.h" 20#include "util/jit.h"
21#include "util/thread.h"
21 22
22#include <subcmd/parse-options.h> 23#include <subcmd/parse-options.h>
23 24
24#include <linux/list.h> 25#include <linux/list.h>
26#include <errno.h>
27#include <signal.h>
25 28
26struct perf_inject { 29struct perf_inject {
27 struct perf_tool tool; 30 struct perf_tool tool;
@@ -333,6 +336,18 @@ static int perf_event__repipe_comm(struct perf_tool *tool,
333 return err; 336 return err;
334} 337}
335 338
339static int perf_event__repipe_namespaces(struct perf_tool *tool,
340 union perf_event *event,
341 struct perf_sample *sample,
342 struct machine *machine)
343{
344 int err = perf_event__process_namespaces(tool, event, sample, machine);
345
346 perf_event__repipe(tool, event, sample, machine);
347
348 return err;
349}
350
336static int perf_event__repipe_exit(struct perf_tool *tool, 351static int perf_event__repipe_exit(struct perf_tool *tool,
337 union perf_event *event, 352 union perf_event *event,
338 struct perf_sample *sample, 353 struct perf_sample *sample,
@@ -660,6 +675,7 @@ static int __cmd_inject(struct perf_inject *inject)
660 session->itrace_synth_opts = &inject->itrace_synth_opts; 675 session->itrace_synth_opts = &inject->itrace_synth_opts;
661 inject->itrace_synth_opts.inject = true; 676 inject->itrace_synth_opts.inject = true;
662 inject->tool.comm = perf_event__repipe_comm; 677 inject->tool.comm = perf_event__repipe_comm;
678 inject->tool.namespaces = perf_event__repipe_namespaces;
663 inject->tool.exit = perf_event__repipe_exit; 679 inject->tool.exit = perf_event__repipe_exit;
664 inject->tool.id_index = perf_event__repipe_id_index; 680 inject->tool.id_index = perf_event__repipe_id_index;
665 inject->tool.auxtrace_info = perf_event__process_auxtrace_info; 681 inject->tool.auxtrace_info = perf_event__process_auxtrace_info;
@@ -681,6 +697,8 @@ static int __cmd_inject(struct perf_inject *inject)
681 lseek(fd, output_data_offset, SEEK_SET); 697 lseek(fd, output_data_offset, SEEK_SET);
682 698
683 ret = perf_session__process_events(session); 699 ret = perf_session__process_events(session);
700 if (ret)
701 return ret;
684 702
685 if (!file_out->is_pipe) { 703 if (!file_out->is_pipe) {
686 if (inject->build_ids) 704 if (inject->build_ids)
@@ -725,7 +743,7 @@ static int __cmd_inject(struct perf_inject *inject)
725 return ret; 743 return ret;
726} 744}
727 745
728int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) 746int cmd_inject(int argc, const char **argv)
729{ 747{
730 struct perf_inject inject = { 748 struct perf_inject inject = {
731 .tool = { 749 .tool = {
diff --git a/tools/perf/builtin-kallsyms.c b/tools/perf/builtin-kallsyms.c
index 224bfc454b4a..bcfb363112d3 100644
--- a/tools/perf/builtin-kallsyms.c
+++ b/tools/perf/builtin-kallsyms.c
@@ -7,6 +7,7 @@
7 * 7 *
8 * Released under the GPL v2. (and only v2, not any later version) 8 * Released under the GPL v2. (and only v2, not any later version)
9 */ 9 */
10#include <inttypes.h>
10#include "builtin.h" 11#include "builtin.h"
11#include <linux/compiler.h> 12#include <linux/compiler.h>
12#include <subcmd/parse-options.h> 13#include <subcmd/parse-options.h>
@@ -43,7 +44,7 @@ static int __cmd_kallsyms(int argc, const char **argv)
43 return 0; 44 return 0;
44} 45}
45 46
46int cmd_kallsyms(int argc, const char **argv, const char *prefix __maybe_unused) 47int cmd_kallsyms(int argc, const char **argv)
47{ 48{
48 const struct option options[] = { 49 const struct option options[] = {
49 OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"), 50 OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"),
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 6da8d083e4e5..9409c9464667 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -20,11 +20,16 @@
20 20
21#include "util/debug.h" 21#include "util/debug.h"
22 22
23#include <linux/kernel.h>
23#include <linux/rbtree.h> 24#include <linux/rbtree.h>
24#include <linux/string.h> 25#include <linux/string.h>
26#include <errno.h>
27#include <inttypes.h>
25#include <locale.h> 28#include <locale.h>
26#include <regex.h> 29#include <regex.h>
27 30
31#include "sane_ctype.h"
32
28static int kmem_slab; 33static int kmem_slab;
29static int kmem_page; 34static int kmem_page;
30 35
@@ -964,6 +969,7 @@ static struct perf_tool perf_kmem = {
964 .comm = perf_event__process_comm, 969 .comm = perf_event__process_comm,
965 .mmap = perf_event__process_mmap, 970 .mmap = perf_event__process_mmap,
966 .mmap2 = perf_event__process_mmap2, 971 .mmap2 = perf_event__process_mmap2,
972 .namespaces = perf_event__process_namespaces,
967 .ordered_events = true, 973 .ordered_events = true,
968}; 974};
969 975
@@ -1865,7 +1871,7 @@ static int __cmd_record(int argc, const char **argv)
1865 for (j = 1; j < (unsigned int)argc; j++, i++) 1871 for (j = 1; j < (unsigned int)argc; j++, i++)
1866 rec_argv[i] = argv[j]; 1872 rec_argv[i] = argv[j];
1867 1873
1868 return cmd_record(i, rec_argv, NULL); 1874 return cmd_record(i, rec_argv);
1869} 1875}
1870 1876
1871static int kmem_config(const char *var, const char *value, void *cb __maybe_unused) 1877static int kmem_config(const char *var, const char *value, void *cb __maybe_unused)
@@ -1884,7 +1890,7 @@ static int kmem_config(const char *var, const char *value, void *cb __maybe_unus
1884 return 0; 1890 return 0;
1885} 1891}
1886 1892
1887int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) 1893int cmd_kmem(int argc, const char **argv)
1888{ 1894{
1889 const char * const default_slab_sort = "frag,hit,bytes"; 1895 const char * const default_slab_sort = "frag,hit,bytes";
1890 const char * const default_page_sort = "bytes,hit"; 1896 const char * const default_page_sort = "bytes,hit";
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 08fa88f62a24..f309c3773522 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -3,6 +3,7 @@
3 3
4#include "util/evsel.h" 4#include "util/evsel.h"
5#include "util/evlist.h" 5#include "util/evlist.h"
6#include "util/term.h"
6#include "util/util.h" 7#include "util/util.h"
7#include "util/cache.h" 8#include "util/cache.h"
8#include "util/symbol.h" 9#include "util/symbol.h"
@@ -23,13 +24,33 @@
23#ifdef HAVE_TIMERFD_SUPPORT 24#ifdef HAVE_TIMERFD_SUPPORT
24#include <sys/timerfd.h> 25#include <sys/timerfd.h>
25#endif 26#endif
27#include <sys/time.h>
26 28
29#include <linux/kernel.h>
27#include <linux/time64.h> 30#include <linux/time64.h>
31#include <errno.h>
32#include <inttypes.h>
33#include <poll.h>
28#include <termios.h> 34#include <termios.h>
29#include <semaphore.h> 35#include <semaphore.h>
36#include <signal.h>
30#include <pthread.h> 37#include <pthread.h>
31#include <math.h> 38#include <math.h>
32 39
40static const char *get_filename_for_perf_kvm(void)
41{
42 const char *filename;
43
44 if (perf_host && !perf_guest)
45 filename = strdup("perf.data.host");
46 else if (!perf_host && perf_guest)
47 filename = strdup("perf.data.guest");
48 else
49 filename = strdup("perf.data.kvm");
50
51 return filename;
52}
53
33#ifdef HAVE_KVM_STAT_SUPPORT 54#ifdef HAVE_KVM_STAT_SUPPORT
34#include "util/kvm-stat.h" 55#include "util/kvm-stat.h"
35 56
@@ -1044,6 +1065,7 @@ static int read_events(struct perf_kvm_stat *kvm)
1044 struct perf_tool eops = { 1065 struct perf_tool eops = {
1045 .sample = process_sample_event, 1066 .sample = process_sample_event,
1046 .comm = perf_event__process_comm, 1067 .comm = perf_event__process_comm,
1068 .namespaces = perf_event__process_namespaces,
1047 .ordered_events = true, 1069 .ordered_events = true,
1048 }; 1070 };
1049 struct perf_data_file file = { 1071 struct perf_data_file file = {
@@ -1208,7 +1230,7 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
1208 set_option_flag(record_options, 0, "transaction", PARSE_OPT_DISABLED); 1230 set_option_flag(record_options, 0, "transaction", PARSE_OPT_DISABLED);
1209 1231
1210 record_usage = kvm_stat_record_usage; 1232 record_usage = kvm_stat_record_usage;
1211 return cmd_record(i, rec_argv, NULL); 1233 return cmd_record(i, rec_argv);
1212} 1234}
1213 1235
1214static int 1236static int
@@ -1348,6 +1370,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1348 kvm->tool.exit = perf_event__process_exit; 1370 kvm->tool.exit = perf_event__process_exit;
1349 kvm->tool.fork = perf_event__process_fork; 1371 kvm->tool.fork = perf_event__process_fork;
1350 kvm->tool.lost = process_lost_event; 1372 kvm->tool.lost = process_lost_event;
1373 kvm->tool.namespaces = perf_event__process_namespaces;
1351 kvm->tool.ordered_events = true; 1374 kvm->tool.ordered_events = true;
1352 perf_tool__fill_defaults(&kvm->tool); 1375 perf_tool__fill_defaults(&kvm->tool);
1353 1376
@@ -1475,7 +1498,7 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
1475#endif 1498#endif
1476 1499
1477perf_stat: 1500perf_stat:
1478 return cmd_stat(argc, argv, NULL); 1501 return cmd_stat(argc, argv);
1479} 1502}
1480#endif /* HAVE_KVM_STAT_SUPPORT */ 1503#endif /* HAVE_KVM_STAT_SUPPORT */
1481 1504
@@ -1494,7 +1517,7 @@ static int __cmd_record(const char *file_name, int argc, const char **argv)
1494 1517
1495 BUG_ON(i != rec_argc); 1518 BUG_ON(i != rec_argc);
1496 1519
1497 return cmd_record(i, rec_argv, NULL); 1520 return cmd_record(i, rec_argv);
1498} 1521}
1499 1522
1500static int __cmd_report(const char *file_name, int argc, const char **argv) 1523static int __cmd_report(const char *file_name, int argc, const char **argv)
@@ -1512,7 +1535,7 @@ static int __cmd_report(const char *file_name, int argc, const char **argv)
1512 1535
1513 BUG_ON(i != rec_argc); 1536 BUG_ON(i != rec_argc);
1514 1537
1515 return cmd_report(i, rec_argv, NULL); 1538 return cmd_report(i, rec_argv);
1516} 1539}
1517 1540
1518static int 1541static int
@@ -1531,10 +1554,10 @@ __cmd_buildid_list(const char *file_name, int argc, const char **argv)
1531 1554
1532 BUG_ON(i != rec_argc); 1555 BUG_ON(i != rec_argc);
1533 1556
1534 return cmd_buildid_list(i, rec_argv, NULL); 1557 return cmd_buildid_list(i, rec_argv);
1535} 1558}
1536 1559
1537int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) 1560int cmd_kvm(int argc, const char **argv)
1538{ 1561{
1539 const char *file_name = NULL; 1562 const char *file_name = NULL;
1540 const struct option kvm_options[] = { 1563 const struct option kvm_options[] = {
@@ -1589,9 +1612,9 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
1589 else if (!strncmp(argv[0], "rep", 3)) 1612 else if (!strncmp(argv[0], "rep", 3))
1590 return __cmd_report(file_name, argc, argv); 1613 return __cmd_report(file_name, argc, argv);
1591 else if (!strncmp(argv[0], "diff", 4)) 1614 else if (!strncmp(argv[0], "diff", 4))
1592 return cmd_diff(argc, argv, NULL); 1615 return cmd_diff(argc, argv);
1593 else if (!strncmp(argv[0], "top", 3)) 1616 else if (!strncmp(argv[0], "top", 3))
1594 return cmd_top(argc, argv, NULL); 1617 return cmd_top(argc, argv);
1595 else if (!strncmp(argv[0], "buildid-list", 12)) 1618 else if (!strncmp(argv[0], "buildid-list", 12))
1596 return __cmd_buildid_list(file_name, argc, argv); 1619 return __cmd_buildid_list(file_name, argc, argv);
1597#ifdef HAVE_KVM_STAT_SUPPORT 1620#ifdef HAVE_KVM_STAT_SUPPORT
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 3b9d98b5feef..4bf2cb4d25aa 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -18,8 +18,9 @@
18#include <subcmd/parse-options.h> 18#include <subcmd/parse-options.h>
19 19
20static bool desc_flag = true; 20static bool desc_flag = true;
21static bool details_flag;
21 22
22int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) 23int cmd_list(int argc, const char **argv)
23{ 24{
24 int i; 25 int i;
25 bool raw_dump = false; 26 bool raw_dump = false;
@@ -30,6 +31,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
30 "Print extra event descriptions. --no-desc to not print."), 31 "Print extra event descriptions. --no-desc to not print."),
31 OPT_BOOLEAN('v', "long-desc", &long_desc_flag, 32 OPT_BOOLEAN('v', "long-desc", &long_desc_flag,
32 "Print longer event descriptions."), 33 "Print longer event descriptions."),
34 OPT_BOOLEAN(0, "details", &details_flag,
35 "Print information on the perf event names and expressions used internally by events."),
33 OPT_INCR(0, "debug", &verbose, 36 OPT_INCR(0, "debug", &verbose,
34 "Enable debugging output"), 37 "Enable debugging output"),
35 OPT_END() 38 OPT_END()
@@ -50,7 +53,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
50 printf("\nList of pre-defined events (to be used in -e):\n\n"); 53 printf("\nList of pre-defined events (to be used in -e):\n\n");
51 54
52 if (argc == 0) { 55 if (argc == 0) {
53 print_events(NULL, raw_dump, !desc_flag, long_desc_flag); 56 print_events(NULL, raw_dump, !desc_flag, long_desc_flag,
57 details_flag);
54 return 0; 58 return 0;
55 } 59 }
56 60
@@ -72,7 +76,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
72 print_hwcache_events(NULL, raw_dump); 76 print_hwcache_events(NULL, raw_dump);
73 else if (strcmp(argv[i], "pmu") == 0) 77 else if (strcmp(argv[i], "pmu") == 0)
74 print_pmu_events(NULL, raw_dump, !desc_flag, 78 print_pmu_events(NULL, raw_dump, !desc_flag,
75 long_desc_flag); 79 long_desc_flag, details_flag);
76 else if (strcmp(argv[i], "sdt") == 0) 80 else if (strcmp(argv[i], "sdt") == 0)
77 print_sdt_events(NULL, NULL, raw_dump); 81 print_sdt_events(NULL, NULL, raw_dump);
78 else if ((sep = strchr(argv[i], ':')) != NULL) { 82 else if ((sep = strchr(argv[i], ':')) != NULL) {
@@ -80,7 +84,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
80 84
81 if (sep == NULL) { 85 if (sep == NULL) {
82 print_events(argv[i], raw_dump, !desc_flag, 86 print_events(argv[i], raw_dump, !desc_flag,
83 long_desc_flag); 87 long_desc_flag,
88 details_flag);
84 continue; 89 continue;
85 } 90 }
86 sep_idx = sep - argv[i]; 91 sep_idx = sep - argv[i];
@@ -103,7 +108,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
103 event_symbols_sw, PERF_COUNT_SW_MAX, raw_dump); 108 event_symbols_sw, PERF_COUNT_SW_MAX, raw_dump);
104 print_hwcache_events(s, raw_dump); 109 print_hwcache_events(s, raw_dump);
105 print_pmu_events(s, raw_dump, !desc_flag, 110 print_pmu_events(s, raw_dump, !desc_flag,
106 long_desc_flag); 111 long_desc_flag,
112 details_flag);
107 print_tracepoint_events(NULL, s, raw_dump); 113 print_tracepoint_events(NULL, s, raw_dump);
108 print_sdt_events(NULL, s, raw_dump); 114 print_sdt_events(NULL, s, raw_dump);
109 free(s); 115 free(s);
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index ce3bfb48b26f..ff98652484a7 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -1,3 +1,5 @@
1#include <errno.h>
2#include <inttypes.h>
1#include "builtin.h" 3#include "builtin.h"
2#include "perf.h" 4#include "perf.h"
3 5
@@ -26,6 +28,7 @@
26 28
27#include <linux/list.h> 29#include <linux/list.h>
28#include <linux/hash.h> 30#include <linux/hash.h>
31#include <linux/kernel.h>
29 32
30static struct perf_session *session; 33static struct perf_session *session;
31 34
@@ -858,6 +861,7 @@ static int __cmd_report(bool display_info)
858 struct perf_tool eops = { 861 struct perf_tool eops = {
859 .sample = process_sample_event, 862 .sample = process_sample_event,
860 .comm = perf_event__process_comm, 863 .comm = perf_event__process_comm,
864 .namespaces = perf_event__process_namespaces,
861 .ordered_events = true, 865 .ordered_events = true,
862 }; 866 };
863 struct perf_data_file file = { 867 struct perf_data_file file = {
@@ -940,34 +944,36 @@ static int __cmd_record(int argc, const char **argv)
940 944
941 BUG_ON(i != rec_argc); 945 BUG_ON(i != rec_argc);
942 946
943 ret = cmd_record(i, rec_argv, NULL); 947 ret = cmd_record(i, rec_argv);
944 free(rec_argv); 948 free(rec_argv);
945 return ret; 949 return ret;
946} 950}
947 951
948int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) 952int cmd_lock(int argc, const char **argv)
949{ 953{
950 const struct option info_options[] = {
951 OPT_BOOLEAN('t', "threads", &info_threads,
952 "dump thread list in perf.data"),
953 OPT_BOOLEAN('m', "map", &info_map,
954 "map of lock instances (address:name table)"),
955 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
956 OPT_END()
957 };
958 const struct option lock_options[] = { 954 const struct option lock_options[] = {
959 OPT_STRING('i', "input", &input_name, "file", "input file name"), 955 OPT_STRING('i', "input", &input_name, "file", "input file name"),
960 OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), 956 OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"),
961 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), 957 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"),
958 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
962 OPT_END() 959 OPT_END()
963 }; 960 };
961
962 const struct option info_options[] = {
963 OPT_BOOLEAN('t', "threads", &info_threads,
964 "dump thread list in perf.data"),
965 OPT_BOOLEAN('m', "map", &info_map,
966 "map of lock instances (address:name table)"),
967 OPT_PARENT(lock_options)
968 };
969
964 const struct option report_options[] = { 970 const struct option report_options[] = {
965 OPT_STRING('k', "key", &sort_key, "acquired", 971 OPT_STRING('k', "key", &sort_key, "acquired",
966 "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"), 972 "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
967 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
968 /* TODO: type */ 973 /* TODO: type */
969 OPT_END() 974 OPT_PARENT(lock_options)
970 }; 975 };
976
971 const char * const info_usage[] = { 977 const char * const info_usage[] = {
972 "perf lock info [<options>]", 978 "perf lock info [<options>]",
973 NULL 979 NULL
@@ -1006,7 +1012,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
1006 rc = __cmd_report(false); 1012 rc = __cmd_report(false);
1007 } else if (!strcmp(argv[0], "script")) { 1013 } else if (!strcmp(argv[0], "script")) {
1008 /* Aliased to 'perf script' */ 1014 /* Aliased to 'perf script' */
1009 return cmd_script(argc, argv, prefix); 1015 return cmd_script(argc, argv);
1010 } else if (!strcmp(argv[0], "info")) { 1016 } else if (!strcmp(argv[0], "info")) {
1011 if (argc) { 1017 if (argc) {
1012 argc = parse_options(argc, argv, 1018 argc = parse_options(argc, argv,
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 6114e07ca613..e001c0290793 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -1,3 +1,7 @@
1#include <inttypes.h>
2#include <sys/types.h>
3#include <sys/stat.h>
4#include <unistd.h>
1#include "builtin.h" 5#include "builtin.h"
2#include "perf.h" 6#include "perf.h"
3 7
@@ -8,6 +12,7 @@
8#include "util/data.h" 12#include "util/data.h"
9#include "util/mem-events.h" 13#include "util/mem-events.h"
10#include "util/debug.h" 14#include "util/debug.h"
15#include "util/symbol.h"
11 16
12#define MEM_OPERATION_LOAD 0x1 17#define MEM_OPERATION_LOAD 0x1
13#define MEM_OPERATION_STORE 0x2 18#define MEM_OPERATION_STORE 0x2
@@ -129,7 +134,7 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
129 pr_debug("\n"); 134 pr_debug("\n");
130 } 135 }
131 136
132 ret = cmd_record(i, rec_argv, NULL); 137 ret = cmd_record(i, rec_argv);
133 free(rec_argv); 138 free(rec_argv);
134 return ret; 139 return ret;
135} 140}
@@ -256,7 +261,7 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem)
256 for (j = 1; j < argc; j++, i++) 261 for (j = 1; j < argc; j++, i++)
257 rep_argv[i] = argv[j]; 262 rep_argv[i] = argv[j];
258 263
259 ret = cmd_report(i, rep_argv, NULL); 264 ret = cmd_report(i, rep_argv);
260 free(rep_argv); 265 free(rep_argv);
261 return ret; 266 return ret;
262} 267}
@@ -330,7 +335,7 @@ error:
330 return ret; 335 return ret;
331} 336}
332 337
333int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) 338int cmd_mem(int argc, const char **argv)
334{ 339{
335 struct stat st; 340 struct stat st;
336 struct perf_mem mem = { 341 struct perf_mem mem = {
@@ -342,6 +347,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
342 .lost = perf_event__process_lost, 347 .lost = perf_event__process_lost,
343 .fork = perf_event__process_fork, 348 .fork = perf_event__process_fork,
344 .build_id = perf_event__process_build_id, 349 .build_id = perf_event__process_build_id,
350 .namespaces = perf_event__process_namespaces,
345 .ordered_events = true, 351 .ordered_events = true,
346 }, 352 },
347 .input_name = "perf.data", 353 .input_name = "perf.data",
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 1fcebc31a508..d7360c2bda13 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -442,9 +442,9 @@ static int perf_del_probe_events(struct strfilter *filter)
442 } 442 }
443 443
444 if (ret == -ENOENT && ret2 == -ENOENT) 444 if (ret == -ENOENT && ret2 == -ENOENT)
445 pr_debug("\"%s\" does not hit any event.\n", str); 445 pr_warning("\"%s\" does not hit any event.\n", str);
446 /* Note that this is silently ignored */ 446 else
447 ret = 0; 447 ret = 0;
448 448
449error: 449error:
450 if (kfd >= 0) 450 if (kfd >= 0)
@@ -468,7 +468,7 @@ out:
468 468
469 469
470static int 470static int
471__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) 471__cmd_probe(int argc, const char **argv)
472{ 472{
473 const char * const probe_usage[] = { 473 const char * const probe_usage[] = {
474 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]", 474 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
@@ -687,13 +687,13 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
687 return 0; 687 return 0;
688} 688}
689 689
690int cmd_probe(int argc, const char **argv, const char *prefix) 690int cmd_probe(int argc, const char **argv)
691{ 691{
692 int ret; 692 int ret;
693 693
694 ret = init_params(); 694 ret = init_params();
695 if (!ret) { 695 if (!ret) {
696 ret = __cmd_probe(argc, argv, prefix); 696 ret = __cmd_probe(argc, argv);
697 cleanup_params(); 697 cleanup_params();
698 } 698 }
699 699
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index bc84a375295d..ee7d0a82ccd0 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -38,11 +38,18 @@
38#include "util/bpf-loader.h" 38#include "util/bpf-loader.h"
39#include "util/trigger.h" 39#include "util/trigger.h"
40#include "util/perf-hooks.h" 40#include "util/perf-hooks.h"
41#include "util/time-utils.h"
42#include "util/units.h"
41#include "asm/bug.h" 43#include "asm/bug.h"
42 44
45#include <errno.h>
46#include <inttypes.h>
47#include <poll.h>
43#include <unistd.h> 48#include <unistd.h>
44#include <sched.h> 49#include <sched.h>
50#include <signal.h>
45#include <sys/mman.h> 51#include <sys/mman.h>
52#include <sys/wait.h>
46#include <asm/bug.h> 53#include <asm/bug.h>
47#include <linux/time64.h> 54#include <linux/time64.h>
48 55
@@ -876,6 +883,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
876 signal(SIGTERM, sig_handler); 883 signal(SIGTERM, sig_handler);
877 signal(SIGSEGV, sigsegv_handler); 884 signal(SIGSEGV, sigsegv_handler);
878 885
886 if (rec->opts.record_namespaces)
887 tool->namespace_events = true;
888
879 if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) { 889 if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) {
880 signal(SIGUSR2, snapshot_sig_handler); 890 signal(SIGUSR2, snapshot_sig_handler);
881 if (rec->opts.auxtrace_snapshot_mode) 891 if (rec->opts.auxtrace_snapshot_mode)
@@ -983,6 +993,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
983 */ 993 */
984 if (forks) { 994 if (forks) {
985 union perf_event *event; 995 union perf_event *event;
996 pid_t tgid;
986 997
987 event = malloc(sizeof(event->comm) + machine->id_hdr_size); 998 event = malloc(sizeof(event->comm) + machine->id_hdr_size);
988 if (event == NULL) { 999 if (event == NULL) {
@@ -996,10 +1007,30 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
996 * cannot see a correct process name for those events. 1007 * cannot see a correct process name for those events.
997 * Synthesize COMM event to prevent it. 1008 * Synthesize COMM event to prevent it.
998 */ 1009 */
999 perf_event__synthesize_comm(tool, event, 1010 tgid = perf_event__synthesize_comm(tool, event,
1000 rec->evlist->workload.pid, 1011 rec->evlist->workload.pid,
1001 process_synthesized_event, 1012 process_synthesized_event,
1002 machine); 1013 machine);
1014 free(event);
1015
1016 if (tgid == -1)
1017 goto out_child;
1018
1019 event = malloc(sizeof(event->namespaces) +
1020 (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
1021 machine->id_hdr_size);
1022 if (event == NULL) {
1023 err = -ENOMEM;
1024 goto out_child;
1025 }
1026
1027 /*
1028 * Synthesize NAMESPACES event for the command specified.
1029 */
1030 perf_event__synthesize_namespaces(tool, event,
1031 rec->evlist->workload.pid,
1032 tgid, process_synthesized_event,
1033 machine);
1003 free(event); 1034 free(event);
1004 1035
1005 perf_evlist__start_workload(rec->evlist); 1036 perf_evlist__start_workload(rec->evlist);
@@ -1497,6 +1528,7 @@ static struct record record = {
1497 .fork = perf_event__process_fork, 1528 .fork = perf_event__process_fork,
1498 .exit = perf_event__process_exit, 1529 .exit = perf_event__process_exit,
1499 .comm = perf_event__process_comm, 1530 .comm = perf_event__process_comm,
1531 .namespaces = perf_event__process_namespaces,
1500 .mmap = perf_event__process_mmap, 1532 .mmap = perf_event__process_mmap,
1501 .mmap2 = perf_event__process_mmap2, 1533 .mmap2 = perf_event__process_mmap2,
1502 .ordered_events = true, 1534 .ordered_events = true,
@@ -1611,6 +1643,8 @@ static struct option __record_options[] = {
1611 "opts", "AUX area tracing Snapshot Mode", ""), 1643 "opts", "AUX area tracing Snapshot Mode", ""),
1612 OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout, 1644 OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout,
1613 "per thread proc mmap processing timeout in ms"), 1645 "per thread proc mmap processing timeout in ms"),
1646 OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces,
1647 "Record namespaces events"),
1614 OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1648 OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
1615 "Record context switch events"), 1649 "Record context switch events"),
1616 OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 1650 OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
@@ -1640,7 +1674,7 @@ static struct option __record_options[] = {
1640 1674
1641struct option *record_options = __record_options; 1675struct option *record_options = __record_options;
1642 1676
1643int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 1677int cmd_record(int argc, const char **argv)
1644{ 1678{
1645 int err; 1679 int err;
1646 struct record *rec = &record; 1680 struct record *rec = &record;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 0a88670e56f3..22478ff2b706 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -16,7 +16,6 @@
16#include <linux/rbtree.h> 16#include <linux/rbtree.h>
17#include "util/symbol.h" 17#include "util/symbol.h"
18#include "util/callchain.h" 18#include "util/callchain.h"
19#include "util/strlist.h"
20#include "util/values.h" 19#include "util/values.h"
21 20
22#include "perf.h" 21#include "perf.h"
@@ -38,10 +37,18 @@
38#include "arch/common.h" 37#include "arch/common.h"
39#include "util/time-utils.h" 38#include "util/time-utils.h"
40#include "util/auxtrace.h" 39#include "util/auxtrace.h"
40#include "util/units.h"
41 41
42#include <dlfcn.h> 42#include <dlfcn.h>
43#include <errno.h>
44#include <inttypes.h>
45#include <regex.h>
46#include <signal.h>
43#include <linux/bitmap.h> 47#include <linux/bitmap.h>
44#include <linux/stringify.h> 48#include <linux/stringify.h>
49#include <sys/types.h>
50#include <sys/stat.h>
51#include <unistd.h>
45 52
46struct report { 53struct report {
47 struct perf_tool tool; 54 struct perf_tool tool;
@@ -394,8 +401,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
394 fprintf(stdout, "\n\n"); 401 fprintf(stdout, "\n\n");
395 } 402 }
396 403
397 if (sort_order == NULL && 404 if (!quiet)
398 parent_pattern == default_parent_pattern)
399 fprintf(stdout, "#\n# (%s)\n#\n", help); 405 fprintf(stdout, "#\n# (%s)\n#\n", help);
400 406
401 if (rep->show_threads) { 407 if (rep->show_threads) {
@@ -682,7 +688,7 @@ const char report_callchain_help[] = "Display call graph (stack chain/backtrace)
682 CALLCHAIN_REPORT_HELP 688 CALLCHAIN_REPORT_HELP
683 "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT; 689 "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT;
684 690
685int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) 691int cmd_report(int argc, const char **argv)
686{ 692{
687 struct perf_session *session; 693 struct perf_session *session;
688 struct itrace_synth_opts itrace_synth_opts = { .set = 0, }; 694 struct itrace_synth_opts itrace_synth_opts = { .set = 0, };
@@ -701,6 +707,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
701 .mmap = perf_event__process_mmap, 707 .mmap = perf_event__process_mmap,
702 .mmap2 = perf_event__process_mmap2, 708 .mmap2 = perf_event__process_mmap2,
703 .comm = perf_event__process_comm, 709 .comm = perf_event__process_comm,
710 .namespaces = perf_event__process_namespaces,
704 .exit = perf_event__process_exit, 711 .exit = perf_event__process_exit,
705 .fork = perf_event__process_fork, 712 .fork = perf_event__process_fork,
706 .lost = perf_event__process_lost, 713 .lost = perf_event__process_lost,
@@ -845,6 +852,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
845 stdio__config_color, "always"), 852 stdio__config_color, "always"),
846 OPT_STRING(0, "time", &report.time_str, "str", 853 OPT_STRING(0, "time", &report.time_str, "str",
847 "Time span of interest (start,stop)"), 854 "Time span of interest (start,stop)"),
855 OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
856 "Show inline function"),
848 OPT_END() 857 OPT_END()
849 }; 858 };
850 struct perf_data_file file = { 859 struct perf_data_file file = {
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index b94cf0de715a..39996c53995a 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -22,16 +22,21 @@
22 22
23#include "util/debug.h" 23#include "util/debug.h"
24 24
25#include <linux/kernel.h>
25#include <linux/log2.h> 26#include <linux/log2.h>
26#include <sys/prctl.h> 27#include <sys/prctl.h>
27#include <sys/resource.h> 28#include <sys/resource.h>
29#include <inttypes.h>
28 30
31#include <errno.h>
29#include <semaphore.h> 32#include <semaphore.h>
30#include <pthread.h> 33#include <pthread.h>
31#include <math.h> 34#include <math.h>
32#include <api/fs/fs.h> 35#include <api/fs/fs.h>
33#include <linux/time64.h> 36#include <linux/time64.h>
34 37
38#include "sane_ctype.h"
39
35#define PR_SET_NAME 15 /* Set process name */ 40#define PR_SET_NAME 15 /* Set process name */
36#define MAX_CPUS 4096 41#define MAX_CPUS 4096
37#define COMM_LEN 20 42#define COMM_LEN 20
@@ -221,6 +226,7 @@ struct perf_sched {
221 unsigned int max_stack; 226 unsigned int max_stack;
222 bool show_cpu_visual; 227 bool show_cpu_visual;
223 bool show_wakeups; 228 bool show_wakeups;
229 bool show_next;
224 bool show_migrations; 230 bool show_migrations;
225 bool show_state; 231 bool show_state;
226 u64 skipped_samples; 232 u64 skipped_samples;
@@ -1897,14 +1903,18 @@ static char task_state_char(struct thread *thread, int state)
1897} 1903}
1898 1904
1899static void timehist_print_sample(struct perf_sched *sched, 1905static void timehist_print_sample(struct perf_sched *sched,
1906 struct perf_evsel *evsel,
1900 struct perf_sample *sample, 1907 struct perf_sample *sample,
1901 struct addr_location *al, 1908 struct addr_location *al,
1902 struct thread *thread, 1909 struct thread *thread,
1903 u64 t, int state) 1910 u64 t, int state)
1904{ 1911{
1905 struct thread_runtime *tr = thread__priv(thread); 1912 struct thread_runtime *tr = thread__priv(thread);
1913 const char *next_comm = perf_evsel__strval(evsel, sample, "next_comm");
1914 const u32 next_pid = perf_evsel__intval(evsel, sample, "next_pid");
1906 u32 max_cpus = sched->max_cpu + 1; 1915 u32 max_cpus = sched->max_cpu + 1;
1907 char tstr[64]; 1916 char tstr[64];
1917 char nstr[30];
1908 u64 wait_time; 1918 u64 wait_time;
1909 1919
1910 timestamp__scnprintf_usec(t, tstr, sizeof(tstr)); 1920 timestamp__scnprintf_usec(t, tstr, sizeof(tstr));
@@ -1937,7 +1947,12 @@ static void timehist_print_sample(struct perf_sched *sched,
1937 if (sched->show_state) 1947 if (sched->show_state)
1938 printf(" %5c ", task_state_char(thread, state)); 1948 printf(" %5c ", task_state_char(thread, state));
1939 1949
1940 if (sched->show_wakeups) 1950 if (sched->show_next) {
1951 snprintf(nstr, sizeof(nstr), "next: %s[%d]", next_comm, next_pid);
1952 printf(" %-*s", comm_width, nstr);
1953 }
1954
1955 if (sched->show_wakeups && !sched->show_next)
1941 printf(" %-*s", comm_width, ""); 1956 printf(" %-*s", comm_width, "");
1942 1957
1943 if (thread->tid == 0) 1958 if (thread->tid == 0)
@@ -2531,7 +2546,7 @@ static int timehist_sched_change_event(struct perf_tool *tool,
2531 } 2546 }
2532 2547
2533 if (!sched->summary_only) 2548 if (!sched->summary_only)
2534 timehist_print_sample(sched, sample, &al, thread, t, state); 2549 timehist_print_sample(sched, evsel, sample, &al, thread, t, state);
2535 2550
2536out: 2551out:
2537 if (sched->hist_time.start == 0 && t >= ptime->start) 2552 if (sched->hist_time.start == 0 && t >= ptime->start)
@@ -3262,16 +3277,17 @@ static int __cmd_record(int argc, const char **argv)
3262 3277
3263 BUG_ON(i != rec_argc); 3278 BUG_ON(i != rec_argc);
3264 3279
3265 return cmd_record(i, rec_argv, NULL); 3280 return cmd_record(i, rec_argv);
3266} 3281}
3267 3282
3268int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) 3283int cmd_sched(int argc, const char **argv)
3269{ 3284{
3270 const char default_sort_order[] = "avg, max, switch, runtime"; 3285 const char default_sort_order[] = "avg, max, switch, runtime";
3271 struct perf_sched sched = { 3286 struct perf_sched sched = {
3272 .tool = { 3287 .tool = {
3273 .sample = perf_sched__process_tracepoint_sample, 3288 .sample = perf_sched__process_tracepoint_sample,
3274 .comm = perf_event__process_comm, 3289 .comm = perf_event__process_comm,
3290 .namespaces = perf_event__process_namespaces,
3275 .lost = perf_event__process_lost, 3291 .lost = perf_event__process_lost,
3276 .fork = perf_sched__process_fork_event, 3292 .fork = perf_sched__process_fork_event,
3277 .ordered_events = true, 3293 .ordered_events = true,
@@ -3340,6 +3356,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
3340 OPT_BOOLEAN('S', "with-summary", &sched.summary, 3356 OPT_BOOLEAN('S', "with-summary", &sched.summary,
3341 "Show all syscalls and summary with statistics"), 3357 "Show all syscalls and summary with statistics"),
3342 OPT_BOOLEAN('w', "wakeups", &sched.show_wakeups, "Show wakeup events"), 3358 OPT_BOOLEAN('w', "wakeups", &sched.show_wakeups, "Show wakeup events"),
3359 OPT_BOOLEAN('n', "next", &sched.show_next, "Show next task"),
3343 OPT_BOOLEAN('M', "migrations", &sched.show_migrations, "Show migration events"), 3360 OPT_BOOLEAN('M', "migrations", &sched.show_migrations, "Show migration events"),
3344 OPT_BOOLEAN('V', "cpu-visual", &sched.show_cpu_visual, "Add CPU visual"), 3361 OPT_BOOLEAN('V', "cpu-visual", &sched.show_cpu_visual, "Add CPU visual"),
3345 OPT_BOOLEAN('I', "idle-hist", &sched.idle_hist, "Show idle events only"), 3362 OPT_BOOLEAN('I', "idle-hist", &sched.idle_hist, "Show idle events only"),
@@ -3400,7 +3417,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
3400 * Aliased to 'perf script' for now: 3417 * Aliased to 'perf script' for now:
3401 */ 3418 */
3402 if (!strcmp(argv[0], "script")) 3419 if (!strcmp(argv[0], "script"))
3403 return cmd_script(argc, argv, prefix); 3420 return cmd_script(argc, argv);
3404 3421
3405 if (!strncmp(argv[0], "rec", 3)) { 3422 if (!strncmp(argv[0], "rec", 3)) {
3406 return __cmd_record(argc, argv); 3423 return __cmd_record(argc, argv);
@@ -3437,10 +3454,14 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
3437 if (argc) 3454 if (argc)
3438 usage_with_options(timehist_usage, timehist_options); 3455 usage_with_options(timehist_usage, timehist_options);
3439 } 3456 }
3440 if (sched.show_wakeups && sched.summary_only) { 3457 if ((sched.show_wakeups || sched.show_next) &&
3441 pr_err(" Error: -s and -w are mutually exclusive.\n"); 3458 sched.summary_only) {
3459 pr_err(" Error: -s and -[n|w] are mutually exclusive.\n");
3442 parse_options_usage(timehist_usage, timehist_options, "s", true); 3460 parse_options_usage(timehist_usage, timehist_options, "s", true);
3443 parse_options_usage(NULL, timehist_options, "w", true); 3461 if (sched.show_wakeups)
3462 parse_options_usage(NULL, timehist_options, "w", true);
3463 if (sched.show_next)
3464 parse_options_usage(NULL, timehist_options, "n", true);
3444 return -EINVAL; 3465 return -EINVAL;
3445 } 3466 }
3446 3467
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index c0783b4f7b6c..d05aec491cff 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -21,13 +21,27 @@
21#include "util/cpumap.h" 21#include "util/cpumap.h"
22#include "util/thread_map.h" 22#include "util/thread_map.h"
23#include "util/stat.h" 23#include "util/stat.h"
24#include "util/string2.h"
24#include "util/thread-stack.h" 25#include "util/thread-stack.h"
25#include "util/time-utils.h" 26#include "util/time-utils.h"
27#include "print_binary.h"
26#include <linux/bitmap.h> 28#include <linux/bitmap.h>
29#include <linux/kernel.h>
27#include <linux/stringify.h> 30#include <linux/stringify.h>
28#include <linux/time64.h> 31#include <linux/time64.h>
29#include "asm/bug.h" 32#include "asm/bug.h"
30#include "util/mem-events.h" 33#include "util/mem-events.h"
34#include "util/dump-insn.h"
35#include <dirent.h>
36#include <errno.h>
37#include <inttypes.h>
38#include <signal.h>
39#include <sys/param.h>
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <unistd.h>
43
44#include "sane_ctype.h"
31 45
32static char const *script_name; 46static char const *script_name;
33static char const *generate_script_lang; 47static char const *generate_script_lang;
@@ -42,6 +56,7 @@ static bool nanosecs;
42static const char *cpu_list; 56static const char *cpu_list;
43static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 57static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
44static struct perf_stat_config stat_config; 58static struct perf_stat_config stat_config;
59static int max_blocks;
45 60
46unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH; 61unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;
47 62
@@ -69,6 +84,7 @@ enum perf_output_field {
69 PERF_OUTPUT_CALLINDENT = 1U << 20, 84 PERF_OUTPUT_CALLINDENT = 1U << 20,
70 PERF_OUTPUT_INSN = 1U << 21, 85 PERF_OUTPUT_INSN = 1U << 21,
71 PERF_OUTPUT_INSNLEN = 1U << 22, 86 PERF_OUTPUT_INSNLEN = 1U << 22,
87 PERF_OUTPUT_BRSTACKINSN = 1U << 23,
72}; 88};
73 89
74struct output_option { 90struct output_option {
@@ -98,6 +114,7 @@ struct output_option {
98 {.str = "callindent", .field = PERF_OUTPUT_CALLINDENT}, 114 {.str = "callindent", .field = PERF_OUTPUT_CALLINDENT},
99 {.str = "insn", .field = PERF_OUTPUT_INSN}, 115 {.str = "insn", .field = PERF_OUTPUT_INSN},
100 {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN}, 116 {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN},
117 {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN},
101}; 118};
102 119
103/* default set to maintain compatibility with current format */ 120/* default set to maintain compatibility with current format */
@@ -292,7 +309,13 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
292 "selected. Hence, no address to lookup the source line number.\n"); 309 "selected. Hence, no address to lookup the source line number.\n");
293 return -EINVAL; 310 return -EINVAL;
294 } 311 }
295 312 if (PRINT_FIELD(BRSTACKINSN) &&
313 !(perf_evlist__combined_branch_type(session->evlist) &
314 PERF_SAMPLE_BRANCH_ANY)) {
315 pr_err("Display of branch stack assembler requested, but non all-branch filter set\n"
316 "Hint: run 'perf record -b ...'\n");
317 return -EINVAL;
318 }
296 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && 319 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
297 perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID", 320 perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID",
298 PERF_OUTPUT_TID|PERF_OUTPUT_PID)) 321 PERF_OUTPUT_TID|PERF_OUTPUT_PID))
@@ -546,6 +569,233 @@ static void print_sample_brstacksym(struct perf_sample *sample,
546 } 569 }
547} 570}
548 571
572#define MAXBB 16384UL
573
574static int grab_bb(u8 *buffer, u64 start, u64 end,
575 struct machine *machine, struct thread *thread,
576 bool *is64bit, u8 *cpumode, bool last)
577{
578 long offset, len;
579 struct addr_location al;
580 bool kernel;
581
582 if (!start || !end)
583 return 0;
584
585 kernel = machine__kernel_ip(machine, start);
586 if (kernel)
587 *cpumode = PERF_RECORD_MISC_KERNEL;
588 else
589 *cpumode = PERF_RECORD_MISC_USER;
590
591 /*
592 * Block overlaps between kernel and user.
593 * This can happen due to ring filtering
594 * On Intel CPUs the entry into the kernel is filtered,
595 * but the exit is not. Let the caller patch it up.
596 */
597 if (kernel != machine__kernel_ip(machine, end)) {
598 printf("\tblock %" PRIx64 "-%" PRIx64 " transfers between kernel and user\n",
599 start, end);
600 return -ENXIO;
601 }
602
603 memset(&al, 0, sizeof(al));
604 if (end - start > MAXBB - MAXINSN) {
605 if (last)
606 printf("\tbrstack does not reach to final jump (%" PRIx64 "-%" PRIx64 ")\n", start, end);
607 else
608 printf("\tblock %" PRIx64 "-%" PRIx64 " (%" PRIu64 ") too long to dump\n", start, end, end - start);
609 return 0;
610 }
611
612 thread__find_addr_map(thread, *cpumode, MAP__FUNCTION, start, &al);
613 if (!al.map || !al.map->dso) {
614 printf("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);
615 return 0;
616 }
617 if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR) {
618 printf("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);
619 return 0;
620 }
621
622 /* Load maps to ensure dso->is_64_bit has been updated */
623 map__load(al.map);
624
625 offset = al.map->map_ip(al.map, start);
626 len = dso__data_read_offset(al.map->dso, machine, offset, (u8 *)buffer,
627 end - start + MAXINSN);
628
629 *is64bit = al.map->dso->is_64_bit;
630 if (len <= 0)
631 printf("\tcannot fetch code for block at %" PRIx64 "-%" PRIx64 "\n",
632 start, end);
633 return len;
634}
635
636static void print_jump(uint64_t ip, struct branch_entry *en,
637 struct perf_insn *x, u8 *inbuf, int len,
638 int insn)
639{
640 printf("\t%016" PRIx64 "\t%-30s\t#%s%s%s%s",
641 ip,
642 dump_insn(x, ip, inbuf, len, NULL),
643 en->flags.predicted ? " PRED" : "",
644 en->flags.mispred ? " MISPRED" : "",
645 en->flags.in_tx ? " INTX" : "",
646 en->flags.abort ? " ABORT" : "");
647 if (en->flags.cycles) {
648 printf(" %d cycles", en->flags.cycles);
649 if (insn)
650 printf(" %.2f IPC", (float)insn / en->flags.cycles);
651 }
652 putchar('\n');
653}
654
655static void print_ip_sym(struct thread *thread, u8 cpumode, int cpu,
656 uint64_t addr, struct symbol **lastsym,
657 struct perf_event_attr *attr)
658{
659 struct addr_location al;
660 int off;
661
662 memset(&al, 0, sizeof(al));
663
664 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al);
665 if (!al.map)
666 thread__find_addr_map(thread, cpumode, MAP__VARIABLE,
667 addr, &al);
668 if ((*lastsym) && al.addr >= (*lastsym)->start && al.addr < (*lastsym)->end)
669 return;
670
671 al.cpu = cpu;
672 al.sym = NULL;
673 if (al.map)
674 al.sym = map__find_symbol(al.map, al.addr);
675
676 if (!al.sym)
677 return;
678
679 if (al.addr < al.sym->end)
680 off = al.addr - al.sym->start;
681 else
682 off = al.addr - al.map->start - al.sym->start;
683 printf("\t%s", al.sym->name);
684 if (off)
685 printf("%+d", off);
686 putchar(':');
687 if (PRINT_FIELD(SRCLINE))
688 map__fprintf_srcline(al.map, al.addr, "\t", stdout);
689 putchar('\n');
690 *lastsym = al.sym;
691}
692
693static void print_sample_brstackinsn(struct perf_sample *sample,
694 struct thread *thread,
695 struct perf_event_attr *attr,
696 struct machine *machine)
697{
698 struct branch_stack *br = sample->branch_stack;
699 u64 start, end;
700 int i, insn, len, nr, ilen;
701 struct perf_insn x;
702 u8 buffer[MAXBB];
703 unsigned off;
704 struct symbol *lastsym = NULL;
705
706 if (!(br && br->nr))
707 return;
708 nr = br->nr;
709 if (max_blocks && nr > max_blocks + 1)
710 nr = max_blocks + 1;
711
712 x.thread = thread;
713 x.cpu = sample->cpu;
714
715 putchar('\n');
716
717 /* Handle first from jump, of which we don't know the entry. */
718 len = grab_bb(buffer, br->entries[nr-1].from,
719 br->entries[nr-1].from,
720 machine, thread, &x.is64bit, &x.cpumode, false);
721 if (len > 0) {
722 print_ip_sym(thread, x.cpumode, x.cpu,
723 br->entries[nr - 1].from, &lastsym, attr);
724 print_jump(br->entries[nr - 1].from, &br->entries[nr - 1],
725 &x, buffer, len, 0);
726 }
727
728 /* Print all blocks */
729 for (i = nr - 2; i >= 0; i--) {
730 if (br->entries[i].from || br->entries[i].to)
731 pr_debug("%d: %" PRIx64 "-%" PRIx64 "\n", i,
732 br->entries[i].from,
733 br->entries[i].to);
734 start = br->entries[i + 1].to;
735 end = br->entries[i].from;
736
737 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false);
738 /* Patch up missing kernel transfers due to ring filters */
739 if (len == -ENXIO && i > 0) {
740 end = br->entries[--i].from;
741 pr_debug("\tpatching up to %" PRIx64 "-%" PRIx64 "\n", start, end);
742 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false);
743 }
744 if (len <= 0)
745 continue;
746
747 insn = 0;
748 for (off = 0;; off += ilen) {
749 uint64_t ip = start + off;
750
751 print_ip_sym(thread, x.cpumode, x.cpu, ip, &lastsym, attr);
752 if (ip == end) {
753 print_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn);
754 break;
755 } else {
756 printf("\t%016" PRIx64 "\t%s\n", ip,
757 dump_insn(&x, ip, buffer + off, len - off, &ilen));
758 if (ilen == 0)
759 break;
760 insn++;
761 }
762 }
763 }
764
765 /*
766 * Hit the branch? In this case we are already done, and the target
767 * has not been executed yet.
768 */
769 if (br->entries[0].from == sample->ip)
770 return;
771 if (br->entries[0].flags.abort)
772 return;
773
774 /*
775 * Print final block upto sample
776 */
777 start = br->entries[0].to;
778 end = sample->ip;
779 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true);
780 print_ip_sym(thread, x.cpumode, x.cpu, start, &lastsym, attr);
781 if (len <= 0) {
782 /* Print at least last IP if basic block did not work */
783 len = grab_bb(buffer, sample->ip, sample->ip,
784 machine, thread, &x.is64bit, &x.cpumode, false);
785 if (len <= 0)
786 return;
787
788 printf("\t%016" PRIx64 "\t%s\n", sample->ip,
789 dump_insn(&x, sample->ip, buffer, len, NULL));
790 return;
791 }
792 for (off = 0; off <= end - start; off += ilen) {
793 printf("\t%016" PRIx64 "\t%s\n", start + off,
794 dump_insn(&x, start + off, buffer + off, len - off, &ilen));
795 if (ilen == 0)
796 break;
797 }
798}
549 799
550static void print_sample_addr(struct perf_sample *sample, 800static void print_sample_addr(struct perf_sample *sample,
551 struct thread *thread, 801 struct thread *thread,
@@ -632,7 +882,9 @@ static void print_sample_callindent(struct perf_sample *sample,
632} 882}
633 883
634static void print_insn(struct perf_sample *sample, 884static void print_insn(struct perf_sample *sample,
635 struct perf_event_attr *attr) 885 struct perf_event_attr *attr,
886 struct thread *thread,
887 struct machine *machine)
636{ 888{
637 if (PRINT_FIELD(INSNLEN)) 889 if (PRINT_FIELD(INSNLEN))
638 printf(" ilen: %d", sample->insn_len); 890 printf(" ilen: %d", sample->insn_len);
@@ -643,12 +895,15 @@ static void print_insn(struct perf_sample *sample,
643 for (i = 0; i < sample->insn_len; i++) 895 for (i = 0; i < sample->insn_len; i++)
644 printf(" %02x", (unsigned char)sample->insn[i]); 896 printf(" %02x", (unsigned char)sample->insn[i]);
645 } 897 }
898 if (PRINT_FIELD(BRSTACKINSN))
899 print_sample_brstackinsn(sample, thread, attr, machine);
646} 900}
647 901
648static void print_sample_bts(struct perf_sample *sample, 902static void print_sample_bts(struct perf_sample *sample,
649 struct perf_evsel *evsel, 903 struct perf_evsel *evsel,
650 struct thread *thread, 904 struct thread *thread,
651 struct addr_location *al) 905 struct addr_location *al,
906 struct machine *machine)
652{ 907{
653 struct perf_event_attr *attr = &evsel->attr; 908 struct perf_event_attr *attr = &evsel->attr;
654 bool print_srcline_last = false; 909 bool print_srcline_last = false;
@@ -689,7 +944,7 @@ static void print_sample_bts(struct perf_sample *sample,
689 if (print_srcline_last) 944 if (print_srcline_last)
690 map__fprintf_srcline(al->map, al->addr, "\n ", stdout); 945 map__fprintf_srcline(al->map, al->addr, "\n ", stdout);
691 946
692 print_insn(sample, attr); 947 print_insn(sample, attr, thread, machine);
693 948
694 printf("\n"); 949 printf("\n");
695} 950}
@@ -830,6 +1085,7 @@ struct perf_script {
830 bool show_task_events; 1085 bool show_task_events;
831 bool show_mmap_events; 1086 bool show_mmap_events;
832 bool show_switch_events; 1087 bool show_switch_events;
1088 bool show_namespace_events;
833 bool allocated; 1089 bool allocated;
834 struct cpu_map *cpus; 1090 struct cpu_map *cpus;
835 struct thread_map *threads; 1091 struct thread_map *threads;
@@ -871,7 +1127,8 @@ static size_t data_src__printf(u64 data_src)
871 1127
872static void process_event(struct perf_script *script, 1128static void process_event(struct perf_script *script,
873 struct perf_sample *sample, struct perf_evsel *evsel, 1129 struct perf_sample *sample, struct perf_evsel *evsel,
874 struct addr_location *al) 1130 struct addr_location *al,
1131 struct machine *machine)
875{ 1132{
876 struct thread *thread = al->thread; 1133 struct thread *thread = al->thread;
877 struct perf_event_attr *attr = &evsel->attr; 1134 struct perf_event_attr *attr = &evsel->attr;
@@ -898,7 +1155,7 @@ static void process_event(struct perf_script *script,
898 print_sample_flags(sample->flags); 1155 print_sample_flags(sample->flags);
899 1156
900 if (is_bts_event(attr)) { 1157 if (is_bts_event(attr)) {
901 print_sample_bts(sample, evsel, thread, al); 1158 print_sample_bts(sample, evsel, thread, al, machine);
902 return; 1159 return;
903 } 1160 }
904 1161
@@ -936,7 +1193,7 @@ static void process_event(struct perf_script *script,
936 1193
937 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT)) 1194 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
938 print_sample_bpf_output(sample); 1195 print_sample_bpf_output(sample);
939 print_insn(sample, attr); 1196 print_insn(sample, attr, thread, machine);
940 printf("\n"); 1197 printf("\n");
941} 1198}
942 1199
@@ -1046,7 +1303,7 @@ static int process_sample_event(struct perf_tool *tool,
1046 if (scripting_ops) 1303 if (scripting_ops)
1047 scripting_ops->process_event(event, sample, evsel, &al); 1304 scripting_ops->process_event(event, sample, evsel, &al);
1048 else 1305 else
1049 process_event(scr, sample, evsel, &al); 1306 process_event(scr, sample, evsel, &al, machine);
1050 1307
1051out_put: 1308out_put:
1052 addr_location__put(&al); 1309 addr_location__put(&al);
@@ -1118,6 +1375,41 @@ out:
1118 return ret; 1375 return ret;
1119} 1376}
1120 1377
1378static int process_namespaces_event(struct perf_tool *tool,
1379 union perf_event *event,
1380 struct perf_sample *sample,
1381 struct machine *machine)
1382{
1383 struct thread *thread;
1384 struct perf_script *script = container_of(tool, struct perf_script, tool);
1385 struct perf_session *session = script->session;
1386 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
1387 int ret = -1;
1388
1389 thread = machine__findnew_thread(machine, event->namespaces.pid,
1390 event->namespaces.tid);
1391 if (thread == NULL) {
1392 pr_debug("problem processing NAMESPACES event, skipping it.\n");
1393 return -1;
1394 }
1395
1396 if (perf_event__process_namespaces(tool, event, sample, machine) < 0)
1397 goto out;
1398
1399 if (!evsel->attr.sample_id_all) {
1400 sample->cpu = 0;
1401 sample->time = 0;
1402 sample->tid = event->namespaces.tid;
1403 sample->pid = event->namespaces.pid;
1404 }
1405 print_sample_start(sample, thread, evsel);
1406 perf_event__fprintf(event, stdout);
1407 ret = 0;
1408out:
1409 thread__put(thread);
1410 return ret;
1411}
1412
1121static int process_fork_event(struct perf_tool *tool, 1413static int process_fork_event(struct perf_tool *tool,
1122 union perf_event *event, 1414 union perf_event *event,
1123 struct perf_sample *sample, 1415 struct perf_sample *sample,
@@ -1293,6 +1585,8 @@ static int __cmd_script(struct perf_script *script)
1293 } 1585 }
1294 if (script->show_switch_events) 1586 if (script->show_switch_events)
1295 script->tool.context_switch = process_switch_event; 1587 script->tool.context_switch = process_switch_event;
1588 if (script->show_namespace_events)
1589 script->tool.namespaces = process_namespaces_event;
1296 1590
1297 ret = perf_session__process_events(script->session); 1591 ret = perf_session__process_events(script->session);
1298 1592
@@ -1427,7 +1721,7 @@ static int parse_scriptname(const struct option *opt __maybe_unused,
1427static int parse_output_fields(const struct option *opt __maybe_unused, 1721static int parse_output_fields(const struct option *opt __maybe_unused,
1428 const char *arg, int unset __maybe_unused) 1722 const char *arg, int unset __maybe_unused)
1429{ 1723{
1430 char *tok; 1724 char *tok, *strtok_saveptr = NULL;
1431 int i, imax = ARRAY_SIZE(all_output_options); 1725 int i, imax = ARRAY_SIZE(all_output_options);
1432 int j; 1726 int j;
1433 int rc = 0; 1727 int rc = 0;
@@ -1488,7 +1782,7 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
1488 } 1782 }
1489 } 1783 }
1490 1784
1491 for (tok = strtok(tok, ","); tok; tok = strtok(NULL, ",")) { 1785 for (tok = strtok_r(tok, ",", &strtok_saveptr); tok; tok = strtok_r(NULL, ",", &strtok_saveptr)) {
1492 for (i = 0; i < imax; ++i) { 1786 for (i = 0; i < imax; ++i) {
1493 if (strcmp(tok, all_output_options[i].str) == 0) 1787 if (strcmp(tok, all_output_options[i].str) == 0)
1494 break; 1788 break;
@@ -2078,7 +2372,7 @@ int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
2078 return set_maps(script); 2372 return set_maps(script);
2079} 2373}
2080 2374
2081int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) 2375int cmd_script(int argc, const char **argv)
2082{ 2376{
2083 bool show_full_info = false; 2377 bool show_full_info = false;
2084 bool header = false; 2378 bool header = false;
@@ -2097,6 +2391,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2097 .mmap = perf_event__process_mmap, 2391 .mmap = perf_event__process_mmap,
2098 .mmap2 = perf_event__process_mmap2, 2392 .mmap2 = perf_event__process_mmap2,
2099 .comm = perf_event__process_comm, 2393 .comm = perf_event__process_comm,
2394 .namespaces = perf_event__process_namespaces,
2100 .exit = perf_event__process_exit, 2395 .exit = perf_event__process_exit,
2101 .fork = perf_event__process_fork, 2396 .fork = perf_event__process_fork,
2102 .attr = process_attr, 2397 .attr = process_attr,
@@ -2152,7 +2447,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2152 "Valid types: hw,sw,trace,raw. " 2447 "Valid types: hw,sw,trace,raw. "
2153 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 2448 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
2154 "addr,symoff,period,iregs,brstack,brstacksym,flags," 2449 "addr,symoff,period,iregs,brstack,brstacksym,flags,"
2155 "bpf-output,callindent,insn,insnlen", parse_output_fields), 2450 "bpf-output,callindent,insn,insnlen,brstackinsn",
2451 parse_output_fields),
2156 OPT_BOOLEAN('a', "all-cpus", &system_wide, 2452 OPT_BOOLEAN('a', "all-cpus", &system_wide,
2157 "system-wide collection from all CPUs"), 2453 "system-wide collection from all CPUs"),
2158 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 2454 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
@@ -2180,7 +2476,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2180 "Show the mmap events"), 2476 "Show the mmap events"),
2181 OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events, 2477 OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events,
2182 "Show context switch events (if recorded)"), 2478 "Show context switch events (if recorded)"),
2479 OPT_BOOLEAN('\0', "show-namespace-events", &script.show_namespace_events,
2480 "Show namespace events (if recorded)"),
2183 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"), 2481 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
2482 OPT_INTEGER(0, "max-blocks", &max_blocks,
2483 "Maximum number of code blocks to dump with brstackinsn"),
2184 OPT_BOOLEAN(0, "ns", &nanosecs, 2484 OPT_BOOLEAN(0, "ns", &nanosecs,
2185 "Use 9 decimal places when displaying time"), 2485 "Use 9 decimal places when displaying time"),
2186 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", 2486 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
@@ -2217,7 +2517,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2217 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { 2517 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
2218 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX); 2518 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
2219 if (!rec_script_path) 2519 if (!rec_script_path)
2220 return cmd_record(argc, argv, NULL); 2520 return cmd_record(argc, argv);
2221 } 2521 }
2222 2522
2223 if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) { 2523 if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) {
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 13b54999ad79..a935b5023732 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -64,14 +64,24 @@
64#include "util/session.h" 64#include "util/session.h"
65#include "util/tool.h" 65#include "util/tool.h"
66#include "util/group.h" 66#include "util/group.h"
67#include "util/string2.h"
67#include "asm/bug.h" 68#include "asm/bug.h"
68 69
69#include <linux/time64.h> 70#include <linux/time64.h>
70#include <api/fs/fs.h> 71#include <api/fs/fs.h>
72#include <errno.h>
73#include <signal.h>
71#include <stdlib.h> 74#include <stdlib.h>
72#include <sys/prctl.h> 75#include <sys/prctl.h>
76#include <inttypes.h>
73#include <locale.h> 77#include <locale.h>
74#include <math.h> 78#include <math.h>
79#include <sys/types.h>
80#include <sys/stat.h>
81#include <sys/wait.h>
82#include <unistd.h>
83
84#include "sane_ctype.h"
75 85
76#define DEFAULT_SEPARATOR " " 86#define DEFAULT_SEPARATOR " "
77#define CNTR_NOT_SUPPORTED "<not supported>" 87#define CNTR_NOT_SUPPORTED "<not supported>"
@@ -140,12 +150,14 @@ static unsigned int unit_width = 4; /* strlen("unit") */
140static bool forever = false; 150static bool forever = false;
141static bool metric_only = false; 151static bool metric_only = false;
142static bool force_metric_only = false; 152static bool force_metric_only = false;
153static bool no_merge = false;
143static struct timespec ref_time; 154static struct timespec ref_time;
144static struct cpu_map *aggr_map; 155static struct cpu_map *aggr_map;
145static aggr_get_id_t aggr_get_id; 156static aggr_get_id_t aggr_get_id;
146static bool append_file; 157static bool append_file;
147static const char *output_name; 158static const char *output_name;
148static int output_fd; 159static int output_fd;
160static int print_free_counters_hint;
149 161
150struct perf_stat { 162struct perf_stat {
151 bool record; 163 bool record;
@@ -310,8 +322,12 @@ static int read_counter(struct perf_evsel *counter)
310 struct perf_counts_values *count; 322 struct perf_counts_values *count;
311 323
312 count = perf_counts(counter->counts, cpu, thread); 324 count = perf_counts(counter->counts, cpu, thread);
313 if (perf_evsel__read(counter, cpu, thread, count)) 325 if (perf_evsel__read(counter, cpu, thread, count)) {
326 counter->counts->scaled = -1;
327 perf_counts(counter->counts, cpu, thread)->ena = 0;
328 perf_counts(counter->counts, cpu, thread)->run = 0;
314 return -1; 329 return -1;
330 }
315 331
316 if (STAT_RECORD) { 332 if (STAT_RECORD) {
317 if (perf_evsel__write_stat_event(counter, cpu, thread, count)) { 333 if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
@@ -336,12 +352,14 @@ static int read_counter(struct perf_evsel *counter)
336static void read_counters(void) 352static void read_counters(void)
337{ 353{
338 struct perf_evsel *counter; 354 struct perf_evsel *counter;
355 int ret;
339 356
340 evlist__for_each_entry(evsel_list, counter) { 357 evlist__for_each_entry(evsel_list, counter) {
341 if (read_counter(counter)) 358 ret = read_counter(counter);
359 if (ret)
342 pr_debug("failed to read counter %s\n", counter->name); 360 pr_debug("failed to read counter %s\n", counter->name);
343 361
344 if (perf_stat_process_counter(&stat_config, counter)) 362 if (ret == 0 && perf_stat_process_counter(&stat_config, counter))
345 pr_warning("failed to process counter %s\n", counter->name); 363 pr_warning("failed to process counter %s\n", counter->name);
346 } 364 }
347} 365}
@@ -873,10 +891,7 @@ static void print_metric_csv(void *ctx,
873 return; 891 return;
874 } 892 }
875 snprintf(buf, sizeof(buf), fmt, val); 893 snprintf(buf, sizeof(buf), fmt, val);
876 vals = buf; 894 ends = vals = ltrim(buf);
877 while (isspace(*vals))
878 vals++;
879 ends = vals;
880 while (isdigit(*ends) || *ends == '.') 895 while (isdigit(*ends) || *ends == '.')
881 ends++; 896 ends++;
882 *ends = 0; 897 *ends = 0;
@@ -948,10 +963,7 @@ static void print_metric_only_csv(void *ctx, const char *color __maybe_unused,
948 return; 963 return;
949 unit = fixunit(tbuf, os->evsel, unit); 964 unit = fixunit(tbuf, os->evsel, unit);
950 snprintf(buf, sizeof buf, fmt, val); 965 snprintf(buf, sizeof buf, fmt, val);
951 vals = buf; 966 ends = vals = ltrim(buf);
952 while (isspace(*vals))
953 vals++;
954 ends = vals;
955 while (isdigit(*ends) || *ends == '.') 967 while (isdigit(*ends) || *ends == '.')
956 ends++; 968 ends++;
957 *ends = 0; 969 *ends = 0;
@@ -1109,6 +1121,9 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval,
1109 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 1121 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
1110 csv_sep); 1122 csv_sep);
1111 1123
1124 if (counter->supported)
1125 print_free_counters_hint = 1;
1126
1112 fprintf(stat_config.output, "%-*s%s", 1127 fprintf(stat_config.output, "%-*s%s",
1113 csv_output ? 0 : unit_width, 1128 csv_output ? 0 : unit_width,
1114 counter->unit, csv_sep); 1129 counter->unit, csv_sep);
@@ -1140,6 +1155,7 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval,
1140 out.print_metric = pm; 1155 out.print_metric = pm;
1141 out.new_line = nl; 1156 out.new_line = nl;
1142 out.ctx = &os; 1157 out.ctx = &os;
1158 out.force_header = false;
1143 1159
1144 if (csv_output && !metric_only) { 1160 if (csv_output && !metric_only) {
1145 print_noise(counter, noise); 1161 print_noise(counter, noise);
@@ -1178,11 +1194,81 @@ static void aggr_update_shadow(void)
1178 } 1194 }
1179} 1195}
1180 1196
1197static void collect_all_aliases(struct perf_evsel *counter,
1198 void (*cb)(struct perf_evsel *counter, void *data,
1199 bool first),
1200 void *data)
1201{
1202 struct perf_evsel *alias;
1203
1204 alias = list_prepare_entry(counter, &(evsel_list->entries), node);
1205 list_for_each_entry_continue (alias, &evsel_list->entries, node) {
1206 if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) ||
1207 alias->scale != counter->scale ||
1208 alias->cgrp != counter->cgrp ||
1209 strcmp(alias->unit, counter->unit) ||
1210 nsec_counter(alias) != nsec_counter(counter))
1211 break;
1212 alias->merged_stat = true;
1213 cb(alias, data, false);
1214 }
1215}
1216
1217static bool collect_data(struct perf_evsel *counter,
1218 void (*cb)(struct perf_evsel *counter, void *data,
1219 bool first),
1220 void *data)
1221{
1222 if (counter->merged_stat)
1223 return false;
1224 cb(counter, data, true);
1225 if (!no_merge)
1226 collect_all_aliases(counter, cb, data);
1227 return true;
1228}
1229
1230struct aggr_data {
1231 u64 ena, run, val;
1232 int id;
1233 int nr;
1234 int cpu;
1235};
1236
1237static void aggr_cb(struct perf_evsel *counter, void *data, bool first)
1238{
1239 struct aggr_data *ad = data;
1240 int cpu, s2;
1241
1242 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
1243 struct perf_counts_values *counts;
1244
1245 s2 = aggr_get_id(perf_evsel__cpus(counter), cpu);
1246 if (s2 != ad->id)
1247 continue;
1248 if (first)
1249 ad->nr++;
1250 counts = perf_counts(counter->counts, cpu, 0);
1251 /*
1252 * When any result is bad, make them all to give
1253 * consistent output in interval mode.
1254 */
1255 if (counts->ena == 0 || counts->run == 0 ||
1256 counter->counts->scaled == -1) {
1257 ad->ena = 0;
1258 ad->run = 0;
1259 break;
1260 }
1261 ad->val += counts->val;
1262 ad->ena += counts->ena;
1263 ad->run += counts->run;
1264 }
1265}
1266
1181static void print_aggr(char *prefix) 1267static void print_aggr(char *prefix)
1182{ 1268{
1183 FILE *output = stat_config.output; 1269 FILE *output = stat_config.output;
1184 struct perf_evsel *counter; 1270 struct perf_evsel *counter;
1185 int cpu, s, s2, id, nr; 1271 int s, id, nr;
1186 double uval; 1272 double uval;
1187 u64 ena, run, val; 1273 u64 ena, run, val;
1188 bool first; 1274 bool first;
@@ -1197,23 +1283,21 @@ static void print_aggr(char *prefix)
1197 * Without each counter has its own line. 1283 * Without each counter has its own line.
1198 */ 1284 */
1199 for (s = 0; s < aggr_map->nr; s++) { 1285 for (s = 0; s < aggr_map->nr; s++) {
1286 struct aggr_data ad;
1200 if (prefix && metric_only) 1287 if (prefix && metric_only)
1201 fprintf(output, "%s", prefix); 1288 fprintf(output, "%s", prefix);
1202 1289
1203 id = aggr_map->map[s]; 1290 ad.id = id = aggr_map->map[s];
1204 first = true; 1291 first = true;
1205 evlist__for_each_entry(evsel_list, counter) { 1292 evlist__for_each_entry(evsel_list, counter) {
1206 val = ena = run = 0; 1293 ad.val = ad.ena = ad.run = 0;
1207 nr = 0; 1294 ad.nr = 0;
1208 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { 1295 if (!collect_data(counter, aggr_cb, &ad))
1209 s2 = aggr_get_id(perf_evsel__cpus(counter), cpu); 1296 continue;
1210 if (s2 != id) 1297 nr = ad.nr;
1211 continue; 1298 ena = ad.ena;
1212 val += perf_counts(counter->counts, cpu, 0)->val; 1299 run = ad.run;
1213 ena += perf_counts(counter->counts, cpu, 0)->ena; 1300 val = ad.val;
1214 run += perf_counts(counter->counts, cpu, 0)->run;
1215 nr++;
1216 }
1217 if (first && metric_only) { 1301 if (first && metric_only) {
1218 first = false; 1302 first = false;
1219 aggr_printout(counter, id, nr); 1303 aggr_printout(counter, id, nr);
@@ -1257,6 +1341,21 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
1257 } 1341 }
1258} 1342}
1259 1343
1344struct caggr_data {
1345 double avg, avg_enabled, avg_running;
1346};
1347
1348static void counter_aggr_cb(struct perf_evsel *counter, void *data,
1349 bool first __maybe_unused)
1350{
1351 struct caggr_data *cd = data;
1352 struct perf_stat_evsel *ps = counter->priv;
1353
1354 cd->avg += avg_stats(&ps->res_stats[0]);
1355 cd->avg_enabled += avg_stats(&ps->res_stats[1]);
1356 cd->avg_running += avg_stats(&ps->res_stats[2]);
1357}
1358
1260/* 1359/*
1261 * Print out the results of a single counter: 1360 * Print out the results of a single counter:
1262 * aggregated counts in system-wide mode 1361 * aggregated counts in system-wide mode
@@ -1264,23 +1363,31 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
1264static void print_counter_aggr(struct perf_evsel *counter, char *prefix) 1363static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
1265{ 1364{
1266 FILE *output = stat_config.output; 1365 FILE *output = stat_config.output;
1267 struct perf_stat_evsel *ps = counter->priv;
1268 double avg = avg_stats(&ps->res_stats[0]);
1269 double uval; 1366 double uval;
1270 double avg_enabled, avg_running; 1367 struct caggr_data cd = { .avg = 0.0 };
1271 1368
1272 avg_enabled = avg_stats(&ps->res_stats[1]); 1369 if (!collect_data(counter, counter_aggr_cb, &cd))
1273 avg_running = avg_stats(&ps->res_stats[2]); 1370 return;
1274 1371
1275 if (prefix && !metric_only) 1372 if (prefix && !metric_only)
1276 fprintf(output, "%s", prefix); 1373 fprintf(output, "%s", prefix);
1277 1374
1278 uval = avg * counter->scale; 1375 uval = cd.avg * counter->scale;
1279 printout(-1, 0, counter, uval, prefix, avg_running, avg_enabled, avg); 1376 printout(-1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled, cd.avg);
1280 if (!metric_only) 1377 if (!metric_only)
1281 fprintf(output, "\n"); 1378 fprintf(output, "\n");
1282} 1379}
1283 1380
1381static void counter_cb(struct perf_evsel *counter, void *data,
1382 bool first __maybe_unused)
1383{
1384 struct aggr_data *ad = data;
1385
1386 ad->val += perf_counts(counter->counts, ad->cpu, 0)->val;
1387 ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena;
1388 ad->run += perf_counts(counter->counts, ad->cpu, 0)->run;
1389}
1390
1284/* 1391/*
1285 * Print out the results of a single counter: 1392 * Print out the results of a single counter:
1286 * does not use aggregated count in system-wide 1393 * does not use aggregated count in system-wide
@@ -1293,9 +1400,13 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
1293 int cpu; 1400 int cpu;
1294 1401
1295 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { 1402 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
1296 val = perf_counts(counter->counts, cpu, 0)->val; 1403 struct aggr_data ad = { .cpu = cpu };
1297 ena = perf_counts(counter->counts, cpu, 0)->ena; 1404
1298 run = perf_counts(counter->counts, cpu, 0)->run; 1405 if (!collect_data(counter, counter_cb, &ad))
1406 return;
1407 val = ad.val;
1408 ena = ad.ena;
1409 run = ad.run;
1299 1410
1300 if (prefix) 1411 if (prefix)
1301 fprintf(output, "%s", prefix); 1412 fprintf(output, "%s", prefix);
@@ -1380,6 +1491,7 @@ static void print_metric_headers(const char *prefix, bool no_indent)
1380 out.ctx = &os; 1491 out.ctx = &os;
1381 out.print_metric = print_metric_header; 1492 out.print_metric = print_metric_header;
1382 out.new_line = new_line_metric; 1493 out.new_line = new_line_metric;
1494 out.force_header = true;
1383 os.evsel = counter; 1495 os.evsel = counter;
1384 perf_stat__print_shadow_stats(counter, 0, 1496 perf_stat__print_shadow_stats(counter, 0,
1385 0, 1497 0,
@@ -1477,6 +1589,13 @@ static void print_footer(void)
1477 avg_stats(&walltime_nsecs_stats)); 1589 avg_stats(&walltime_nsecs_stats));
1478 } 1590 }
1479 fprintf(output, "\n\n"); 1591 fprintf(output, "\n\n");
1592
1593 if (print_free_counters_hint)
1594 fprintf(output,
1595"Some events weren't counted. Try disabling the NMI watchdog:\n"
1596" echo 0 > /proc/sys/kernel/nmi_watchdog\n"
1597" perf stat ...\n"
1598" echo 1 > /proc/sys/kernel/nmi_watchdog\n");
1480} 1599}
1481 1600
1482static void print_counters(struct timespec *ts, int argc, const char **argv) 1601static void print_counters(struct timespec *ts, int argc, const char **argv)
@@ -1633,6 +1752,7 @@ static const struct option stat_options[] = {
1633 "list of cpus to monitor in system-wide"), 1752 "list of cpus to monitor in system-wide"),
1634 OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode, 1753 OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
1635 "disable CPU count aggregation", AGGR_NONE), 1754 "disable CPU count aggregation", AGGR_NONE),
1755 OPT_BOOLEAN(0, "no-merge", &no_merge, "Do not merge identical named events"),
1636 OPT_STRING('x', "field-separator", &csv_sep, "separator", 1756 OPT_STRING('x', "field-separator", &csv_sep, "separator",
1637 "print counts with custom separator"), 1757 "print counts with custom separator"),
1638 OPT_CALLBACK('G', "cgroup", &evsel_list, "name", 1758 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
@@ -2339,7 +2459,36 @@ static int __cmd_report(int argc, const char **argv)
2339 return 0; 2459 return 0;
2340} 2460}
2341 2461
2342int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) 2462static void setup_system_wide(int forks)
2463{
2464 /*
2465 * Make system wide (-a) the default target if
2466 * no target was specified and one of following
2467 * conditions is met:
2468 *
2469 * - there's no workload specified
2470 * - there is workload specified but all requested
2471 * events are system wide events
2472 */
2473 if (!target__none(&target))
2474 return;
2475
2476 if (!forks)
2477 target.system_wide = true;
2478 else {
2479 struct perf_evsel *counter;
2480
2481 evlist__for_each_entry(evsel_list, counter) {
2482 if (!counter->system_wide)
2483 return;
2484 }
2485
2486 if (evsel_list->nr_entries)
2487 target.system_wide = true;
2488 }
2489}
2490
2491int cmd_stat(int argc, const char **argv)
2343{ 2492{
2344 const char * const stat_usage[] = { 2493 const char * const stat_usage[] = {
2345 "perf stat [<options>] [<command>]", 2494 "perf stat [<options>] [<command>]",
@@ -2361,6 +2510,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
2361 argc = parse_options_subcommand(argc, argv, stat_options, stat_subcommands, 2510 argc = parse_options_subcommand(argc, argv, stat_options, stat_subcommands,
2362 (const char **) stat_usage, 2511 (const char **) stat_usage,
2363 PARSE_OPT_STOP_AT_NON_OPTION); 2512 PARSE_OPT_STOP_AT_NON_OPTION);
2513 perf_stat__collect_metric_expr(evsel_list);
2364 perf_stat__init_shadow_stats(); 2514 perf_stat__init_shadow_stats();
2365 2515
2366 if (csv_sep) { 2516 if (csv_sep) {
@@ -2445,9 +2595,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
2445 } else if (big_num_opt == 0) /* User passed --no-big-num */ 2595 } else if (big_num_opt == 0) /* User passed --no-big-num */
2446 big_num = false; 2596 big_num = false;
2447 2597
2448 /* Make system wide (-a) the default target. */ 2598 setup_system_wide(argc);
2449 if (!argc && target__none(&target))
2450 target.system_wide = true;
2451 2599
2452 if (run_count < 0) { 2600 if (run_count < 0) {
2453 pr_err("Run count must be a positive number\n"); 2601 pr_err("Run count must be a positive number\n");
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index e7eaa298d34a..4e2e61695986 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -12,6 +12,8 @@
12 * of the License. 12 * of the License.
13 */ 13 */
14 14
15#include <errno.h>
16#include <inttypes.h>
15#include <traceevent/event-parse.h> 17#include <traceevent/event-parse.h>
16 18
17#include "builtin.h" 19#include "builtin.h"
@@ -23,11 +25,12 @@
23#include "util/cache.h" 25#include "util/cache.h"
24#include "util/evlist.h" 26#include "util/evlist.h"
25#include "util/evsel.h" 27#include "util/evsel.h"
28#include <linux/kernel.h>
26#include <linux/rbtree.h> 29#include <linux/rbtree.h>
27#include <linux/time64.h> 30#include <linux/time64.h>
28#include "util/symbol.h" 31#include "util/symbol.h"
32#include "util/thread.h"
29#include "util/callchain.h" 33#include "util/callchain.h"
30#include "util/strlist.h"
31 34
32#include "perf.h" 35#include "perf.h"
33#include "util/header.h" 36#include "util/header.h"
@@ -1773,7 +1776,7 @@ static int timechart__io_record(int argc, const char **argv)
1773 for (i = 0; i < (unsigned int)argc; i++) 1776 for (i = 0; i < (unsigned int)argc; i++)
1774 *p++ = argv[i]; 1777 *p++ = argv[i];
1775 1778
1776 return cmd_record(rec_argc, rec_argv, NULL); 1779 return cmd_record(rec_argc, rec_argv);
1777} 1780}
1778 1781
1779 1782
@@ -1864,7 +1867,7 @@ static int timechart__record(struct timechart *tchart, int argc, const char **ar
1864 for (j = 0; j < (unsigned int)argc; j++) 1867 for (j = 0; j < (unsigned int)argc; j++)
1865 *p++ = argv[j]; 1868 *p++ = argv[j];
1866 1869
1867 return cmd_record(rec_argc, rec_argv, NULL); 1870 return cmd_record(rec_argc, rec_argv);
1868} 1871}
1869 1872
1870static int 1873static int
@@ -1917,8 +1920,7 @@ parse_time(const struct option *opt, const char *arg, int __maybe_unused unset)
1917 return 0; 1920 return 0;
1918} 1921}
1919 1922
1920int cmd_timechart(int argc, const char **argv, 1923int cmd_timechart(int argc, const char **argv)
1921 const char *prefix __maybe_unused)
1922{ 1924{
1923 struct timechart tchart = { 1925 struct timechart tchart = {
1924 .tool = { 1926 .tool = {
@@ -1933,6 +1935,11 @@ int cmd_timechart(int argc, const char **argv,
1933 .merge_dist = 1000, 1935 .merge_dist = 1000,
1934 }; 1936 };
1935 const char *output_name = "output.svg"; 1937 const char *output_name = "output.svg";
1938 const struct option timechart_common_options[] = {
1939 OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"),
1940 OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only, "output processes data only"),
1941 OPT_END()
1942 };
1936 const struct option timechart_options[] = { 1943 const struct option timechart_options[] = {
1937 OPT_STRING('i', "input", &input_name, "file", "input file name"), 1944 OPT_STRING('i', "input", &input_name, "file", "input file name"),
1938 OPT_STRING('o', "output", &output_name, "file", "output file name"), 1945 OPT_STRING('o', "output", &output_name, "file", "output file name"),
@@ -1940,9 +1947,6 @@ int cmd_timechart(int argc, const char **argv,
1940 OPT_CALLBACK(0, "highlight", NULL, "duration or task name", 1947 OPT_CALLBACK(0, "highlight", NULL, "duration or task name",
1941 "highlight tasks. Pass duration in ns or process name.", 1948 "highlight tasks. Pass duration in ns or process name.",
1942 parse_highlight), 1949 parse_highlight),
1943 OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"),
1944 OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only,
1945 "output processes data only"),
1946 OPT_CALLBACK('p', "process", NULL, "process", 1950 OPT_CALLBACK('p', "process", NULL, "process",
1947 "process selector. Pass a pid or process name.", 1951 "process selector. Pass a pid or process name.",
1948 parse_process), 1952 parse_process),
@@ -1962,22 +1966,18 @@ int cmd_timechart(int argc, const char **argv,
1962 "merge events that are merge-dist us apart", 1966 "merge events that are merge-dist us apart",
1963 parse_time), 1967 parse_time),
1964 OPT_BOOLEAN('f', "force", &tchart.force, "don't complain, do it"), 1968 OPT_BOOLEAN('f', "force", &tchart.force, "don't complain, do it"),
1965 OPT_END() 1969 OPT_PARENT(timechart_common_options),
1966 }; 1970 };
1967 const char * const timechart_subcommands[] = { "record", NULL }; 1971 const char * const timechart_subcommands[] = { "record", NULL };
1968 const char *timechart_usage[] = { 1972 const char *timechart_usage[] = {
1969 "perf timechart [<options>] {record}", 1973 "perf timechart [<options>] {record}",
1970 NULL 1974 NULL
1971 }; 1975 };
1972
1973 const struct option timechart_record_options[] = { 1976 const struct option timechart_record_options[] = {
1974 OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"),
1975 OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only,
1976 "output processes data only"),
1977 OPT_BOOLEAN('I', "io-only", &tchart.io_only, 1977 OPT_BOOLEAN('I', "io-only", &tchart.io_only,
1978 "record only IO data"), 1978 "record only IO data"),
1979 OPT_BOOLEAN('g', "callchain", &tchart.with_backtrace, "record callchain"), 1979 OPT_BOOLEAN('g', "callchain", &tchart.with_backtrace, "record callchain"),
1980 OPT_END() 1980 OPT_PARENT(timechart_common_options),
1981 }; 1981 };
1982 const char * const timechart_record_usage[] = { 1982 const char * const timechart_record_usage[] = {
1983 "perf timechart record [<options>]", 1983 "perf timechart record [<options>]",
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index ab9077915763..10b6362ca0bf 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -27,19 +27,20 @@
27#include "util/drv_configs.h" 27#include "util/drv_configs.h"
28#include "util/evlist.h" 28#include "util/evlist.h"
29#include "util/evsel.h" 29#include "util/evsel.h"
30#include "util/event.h"
30#include "util/machine.h" 31#include "util/machine.h"
31#include "util/session.h" 32#include "util/session.h"
32#include "util/symbol.h" 33#include "util/symbol.h"
33#include "util/thread.h" 34#include "util/thread.h"
34#include "util/thread_map.h" 35#include "util/thread_map.h"
35#include "util/top.h" 36#include "util/top.h"
36#include "util/util.h"
37#include <linux/rbtree.h> 37#include <linux/rbtree.h>
38#include <subcmd/parse-options.h> 38#include <subcmd/parse-options.h>
39#include "util/parse-events.h" 39#include "util/parse-events.h"
40#include "util/cpumap.h" 40#include "util/cpumap.h"
41#include "util/xyarray.h" 41#include "util/xyarray.h"
42#include "util/sort.h" 42#include "util/sort.h"
43#include "util/term.h"
43#include "util/intlist.h" 44#include "util/intlist.h"
44#include "util/parse-branch-options.h" 45#include "util/parse-branch-options.h"
45#include "arch/common.h" 46#include "arch/common.h"
@@ -58,6 +59,7 @@
58#include <errno.h> 59#include <errno.h>
59#include <time.h> 60#include <time.h>
60#include <sched.h> 61#include <sched.h>
62#include <signal.h>
61 63
62#include <sys/syscall.h> 64#include <sys/syscall.h>
63#include <sys/ioctl.h> 65#include <sys/ioctl.h>
@@ -72,6 +74,8 @@
72#include <linux/time64.h> 74#include <linux/time64.h>
73#include <linux/types.h> 75#include <linux/types.h>
74 76
77#include "sane_ctype.h"
78
75static volatile int done; 79static volatile int done;
76 80
77#define HEADER_LINE_NR 5 81#define HEADER_LINE_NR 5
@@ -1075,7 +1079,7 @@ parse_percent_limit(const struct option *opt, const char *arg,
1075const char top_callchain_help[] = CALLCHAIN_RECORD_HELP CALLCHAIN_REPORT_HELP 1079const char top_callchain_help[] = CALLCHAIN_RECORD_HELP CALLCHAIN_REPORT_HELP
1076 "\n\t\t\t\tDefault: fp,graph,0.5,caller,function"; 1080 "\n\t\t\t\tDefault: fp,graph,0.5,caller,function";
1077 1081
1078int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) 1082int cmd_top(int argc, const char **argv)
1079{ 1083{
1080 char errbuf[BUFSIZ]; 1084 char errbuf[BUFSIZ];
1081 struct perf_top top = { 1085 struct perf_top top = {
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 256f1fac6f7e..d014350adc52 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -21,9 +21,11 @@
21#include "builtin.h" 21#include "builtin.h"
22#include "util/color.h" 22#include "util/color.h"
23#include "util/debug.h" 23#include "util/debug.h"
24#include "util/event.h"
24#include "util/evlist.h" 25#include "util/evlist.h"
25#include <subcmd/exec-cmd.h> 26#include <subcmd/exec-cmd.h>
26#include "util/machine.h" 27#include "util/machine.h"
28#include "util/path.h"
27#include "util/session.h" 29#include "util/session.h"
28#include "util/thread.h" 30#include "util/thread.h"
29#include <subcmd/parse-options.h> 31#include <subcmd/parse-options.h>
@@ -31,23 +33,33 @@
31#include "util/intlist.h" 33#include "util/intlist.h"
32#include "util/thread_map.h" 34#include "util/thread_map.h"
33#include "util/stat.h" 35#include "util/stat.h"
36#include "trace/beauty/beauty.h"
34#include "trace-event.h" 37#include "trace-event.h"
35#include "util/parse-events.h" 38#include "util/parse-events.h"
36#include "util/bpf-loader.h" 39#include "util/bpf-loader.h"
37#include "callchain.h" 40#include "callchain.h"
41#include "print_binary.h"
42#include "string2.h"
38#include "syscalltbl.h" 43#include "syscalltbl.h"
39#include "rb_resort.h" 44#include "rb_resort.h"
40 45
46#include <errno.h>
47#include <inttypes.h>
41#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */ 48#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
49#include <poll.h>
50#include <signal.h>
42#include <stdlib.h> 51#include <stdlib.h>
43#include <string.h> 52#include <string.h>
44#include <linux/err.h> 53#include <linux/err.h>
45#include <linux/filter.h> 54#include <linux/filter.h>
46#include <linux/audit.h> 55#include <linux/audit.h>
56#include <linux/kernel.h>
47#include <linux/random.h> 57#include <linux/random.h>
48#include <linux/stringify.h> 58#include <linux/stringify.h>
49#include <linux/time64.h> 59#include <linux/time64.h>
50 60
61#include "sane_ctype.h"
62
51#ifndef O_CLOEXEC 63#ifndef O_CLOEXEC
52# define O_CLOEXEC 02000000 64# define O_CLOEXEC 02000000
53#endif 65#endif
@@ -267,15 +279,6 @@ out_delete:
267 ({ struct syscall_tp *fields = evsel->priv; \ 279 ({ struct syscall_tp *fields = evsel->priv; \
268 fields->name.pointer(&fields->name, sample); }) 280 fields->name.pointer(&fields->name, sample); })
269 281
270struct syscall_arg {
271 unsigned long val;
272 struct thread *thread;
273 struct trace *trace;
274 void *parm;
275 u8 idx;
276 u8 mask;
277};
278
279struct strarray { 282struct strarray {
280 int offset; 283 int offset;
281 int nr_entries; 284 int nr_entries;
@@ -771,6 +774,10 @@ static struct syscall_fmt {
771 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, 774 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
772 { .name = "stat", .errmsg = true, .alias = "newstat", }, 775 { .name = "stat", .errmsg = true, .alias = "newstat", },
773 { .name = "statfs", .errmsg = true, }, 776 { .name = "statfs", .errmsg = true, },
777 { .name = "statx", .errmsg = true,
778 .arg_scnprintf = { [0] = SCA_FDAT, /* flags */
779 [2] = SCA_STATX_FLAGS, /* flags */
780 [3] = SCA_STATX_MASK, /* mask */ }, },
774 { .name = "swapoff", .errmsg = true, 781 { .name = "swapoff", .errmsg = true,
775 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, 782 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
776 { .name = "swapon", .errmsg = true, 783 { .name = "swapon", .errmsg = true,
@@ -821,12 +828,21 @@ struct syscall {
821 void **arg_parm; 828 void **arg_parm;
822}; 829};
823 830
824static size_t fprintf_duration(unsigned long t, FILE *fp) 831/*
832 * We need to have this 'calculated' boolean because in some cases we really
833 * don't know what is the duration of a syscall, for instance, when we start
834 * a session and some threads are waiting for a syscall to finish, say 'poll',
835 * in which case all we can do is to print "( ? ) for duration and for the
836 * start timestamp.
837 */
838static size_t fprintf_duration(unsigned long t, bool calculated, FILE *fp)
825{ 839{
826 double duration = (double)t / NSEC_PER_MSEC; 840 double duration = (double)t / NSEC_PER_MSEC;
827 size_t printed = fprintf(fp, "("); 841 size_t printed = fprintf(fp, "(");
828 842
829 if (duration >= 1.0) 843 if (!calculated)
844 printed += fprintf(fp, " ? ");
845 else if (duration >= 1.0)
830 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration); 846 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
831 else if (duration >= 0.01) 847 else if (duration >= 0.01)
832 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration); 848 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
@@ -1028,13 +1044,27 @@ static bool trace__filter_duration(struct trace *trace, double t)
1028 return t < (trace->duration_filter * NSEC_PER_MSEC); 1044 return t < (trace->duration_filter * NSEC_PER_MSEC);
1029} 1045}
1030 1046
1031static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp) 1047static size_t __trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1032{ 1048{
1033 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC; 1049 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
1034 1050
1035 return fprintf(fp, "%10.3f ", ts); 1051 return fprintf(fp, "%10.3f ", ts);
1036} 1052}
1037 1053
1054/*
1055 * We're handling tstamp=0 as an undefined tstamp, i.e. like when we are
1056 * using ttrace->entry_time for a thread that receives a sys_exit without
1057 * first having received a sys_enter ("poll" issued before tracing session
1058 * starts, lost sys_enter exit due to ring buffer overflow).
1059 */
1060static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1061{
1062 if (tstamp > 0)
1063 return __trace__fprintf_tstamp(trace, tstamp, fp);
1064
1065 return fprintf(fp, " ? ");
1066}
1067
1038static bool done = false; 1068static bool done = false;
1039static bool interrupted = false; 1069static bool interrupted = false;
1040 1070
@@ -1045,10 +1075,10 @@ static void sig_handler(int sig)
1045} 1075}
1046 1076
1047static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread, 1077static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
1048 u64 duration, u64 tstamp, FILE *fp) 1078 u64 duration, bool duration_calculated, u64 tstamp, FILE *fp)
1049{ 1079{
1050 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp); 1080 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
1051 printed += fprintf_duration(duration, fp); 1081 printed += fprintf_duration(duration, duration_calculated, fp);
1052 1082
1053 if (trace->multiple_threads) { 1083 if (trace->multiple_threads) {
1054 if (trace->show_comm) 1084 if (trace->show_comm)
@@ -1450,7 +1480,7 @@ static int trace__printf_interrupted_entry(struct trace *trace, struct perf_samp
1450 1480
1451 duration = sample->time - ttrace->entry_time; 1481 duration = sample->time - ttrace->entry_time;
1452 1482
1453 printed = trace__fprintf_entry_head(trace, trace->current, duration, ttrace->entry_time, trace->output); 1483 printed = trace__fprintf_entry_head(trace, trace->current, duration, true, ttrace->entry_time, trace->output);
1454 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str); 1484 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1455 ttrace->entry_pending = false; 1485 ttrace->entry_pending = false;
1456 1486
@@ -1497,7 +1527,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1497 1527
1498 if (sc->is_exit) { 1528 if (sc->is_exit) {
1499 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) { 1529 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
1500 trace__fprintf_entry_head(trace, thread, 1, ttrace->entry_time, trace->output); 1530 trace__fprintf_entry_head(trace, thread, 0, false, ttrace->entry_time, trace->output);
1501 fprintf(trace->output, "%-70s)\n", ttrace->entry_str); 1531 fprintf(trace->output, "%-70s)\n", ttrace->entry_str);
1502 } 1532 }
1503 } else { 1533 } else {
@@ -1545,6 +1575,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1545{ 1575{
1546 long ret; 1576 long ret;
1547 u64 duration = 0; 1577 u64 duration = 0;
1578 bool duration_calculated = false;
1548 struct thread *thread; 1579 struct thread *thread;
1549 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0; 1580 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0;
1550 struct syscall *sc = trace__syscall_info(trace, evsel, id); 1581 struct syscall *sc = trace__syscall_info(trace, evsel, id);
@@ -1573,6 +1604,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1573 duration = sample->time - ttrace->entry_time; 1604 duration = sample->time - ttrace->entry_time;
1574 if (trace__filter_duration(trace, duration)) 1605 if (trace__filter_duration(trace, duration))
1575 goto out; 1606 goto out;
1607 duration_calculated = true;
1576 } else if (trace->duration_filter) 1608 } else if (trace->duration_filter)
1577 goto out; 1609 goto out;
1578 1610
@@ -1588,7 +1620,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1588 if (trace->summary_only) 1620 if (trace->summary_only)
1589 goto out; 1621 goto out;
1590 1622
1591 trace__fprintf_entry_head(trace, thread, duration, ttrace->entry_time, trace->output); 1623 trace__fprintf_entry_head(trace, thread, duration, duration_calculated, ttrace->entry_time, trace->output);
1592 1624
1593 if (ttrace->entry_pending) { 1625 if (ttrace->entry_pending) {
1594 fprintf(trace->output, "%-70s", ttrace->entry_str); 1626 fprintf(trace->output, "%-70s", ttrace->entry_str);
@@ -1653,15 +1685,17 @@ static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
1653 1685
1654 ttrace = thread__priv(thread); 1686 ttrace = thread__priv(thread);
1655 if (!ttrace) 1687 if (!ttrace)
1656 goto out; 1688 goto out_put;
1657 1689
1658 filename_len = strlen(filename); 1690 filename_len = strlen(filename);
1691 if (filename_len == 0)
1692 goto out_put;
1659 1693
1660 if (ttrace->filename.namelen < filename_len) { 1694 if (ttrace->filename.namelen < filename_len) {
1661 char *f = realloc(ttrace->filename.name, filename_len + 1); 1695 char *f = realloc(ttrace->filename.name, filename_len + 1);
1662 1696
1663 if (f == NULL) 1697 if (f == NULL)
1664 goto out; 1698 goto out_put;
1665 1699
1666 ttrace->filename.namelen = filename_len; 1700 ttrace->filename.namelen = filename_len;
1667 ttrace->filename.name = f; 1701 ttrace->filename.name = f;
@@ -1671,12 +1705,12 @@ static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
1671 ttrace->filename.pending_open = true; 1705 ttrace->filename.pending_open = true;
1672 1706
1673 if (!ttrace->filename.ptr) 1707 if (!ttrace->filename.ptr)
1674 goto out; 1708 goto out_put;
1675 1709
1676 entry_str_len = strlen(ttrace->entry_str); 1710 entry_str_len = strlen(ttrace->entry_str);
1677 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */ 1711 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
1678 if (remaining_space <= 0) 1712 if (remaining_space <= 0)
1679 goto out; 1713 goto out_put;
1680 1714
1681 if (filename_len > (size_t)remaining_space) { 1715 if (filename_len > (size_t)remaining_space) {
1682 filename += filename_len - remaining_space; 1716 filename += filename_len - remaining_space;
@@ -1690,6 +1724,8 @@ static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
1690 1724
1691 ttrace->filename.ptr = 0; 1725 ttrace->filename.ptr = 0;
1692 ttrace->filename.entry_str_pos = 0; 1726 ttrace->filename.entry_str_pos = 0;
1727out_put:
1728 thread__put(thread);
1693out: 1729out:
1694 return 0; 1730 return 0;
1695} 1731}
@@ -1710,6 +1746,7 @@ static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evs
1710 1746
1711 ttrace->runtime_ms += runtime_ms; 1747 ttrace->runtime_ms += runtime_ms;
1712 trace->runtime_ms += runtime_ms; 1748 trace->runtime_ms += runtime_ms;
1749out_put:
1713 thread__put(thread); 1750 thread__put(thread);
1714 return 0; 1751 return 0;
1715 1752
@@ -1720,8 +1757,7 @@ out_dump:
1720 (pid_t)perf_evsel__intval(evsel, sample, "pid"), 1757 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
1721 runtime, 1758 runtime,
1722 perf_evsel__intval(evsel, sample, "vruntime")); 1759 perf_evsel__intval(evsel, sample, "vruntime"));
1723 thread__put(thread); 1760 goto out_put;
1724 return 0;
1725} 1761}
1726 1762
1727static void bpf_output__printer(enum binary_printer_ops op, 1763static void bpf_output__printer(enum binary_printer_ops op,
@@ -1851,7 +1887,7 @@ static int trace__pgfault(struct trace *trace,
1851 thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION, 1887 thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION,
1852 sample->ip, &al); 1888 sample->ip, &al);
1853 1889
1854 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output); 1890 trace__fprintf_entry_head(trace, thread, 0, true, sample->time, trace->output);
1855 1891
1856 fprintf(trace->output, "%sfault [", 1892 fprintf(trace->output, "%sfault [",
1857 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ? 1893 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
@@ -1920,7 +1956,7 @@ static int trace__process_sample(struct perf_tool *tool,
1920 1956
1921 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); 1957 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1922 if (thread && thread__is_filtered(thread)) 1958 if (thread && thread__is_filtered(thread))
1923 return 0; 1959 goto out;
1924 1960
1925 trace__set_base_time(trace, evsel, sample); 1961 trace__set_base_time(trace, evsel, sample);
1926 1962
@@ -1928,7 +1964,8 @@ static int trace__process_sample(struct perf_tool *tool,
1928 ++trace->nr_events; 1964 ++trace->nr_events;
1929 handler(trace, evsel, event, sample); 1965 handler(trace, evsel, event, sample);
1930 } 1966 }
1931 1967out:
1968 thread__put(thread);
1932 return err; 1969 return err;
1933} 1970}
1934 1971
@@ -1988,7 +2025,7 @@ static int trace__record(struct trace *trace, int argc, const char **argv)
1988 for (i = 0; i < (unsigned int)argc; i++) 2025 for (i = 0; i < (unsigned int)argc; i++)
1989 rec_argv[j++] = argv[i]; 2026 rec_argv[j++] = argv[i];
1990 2027
1991 return cmd_record(j, rec_argv, NULL); 2028 return cmd_record(j, rec_argv);
1992} 2029}
1993 2030
1994static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp); 2031static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
@@ -2415,8 +2452,9 @@ static int trace__replay(struct trace *trace)
2415 trace->tool.exit = perf_event__process_exit; 2452 trace->tool.exit = perf_event__process_exit;
2416 trace->tool.fork = perf_event__process_fork; 2453 trace->tool.fork = perf_event__process_fork;
2417 trace->tool.attr = perf_event__process_attr; 2454 trace->tool.attr = perf_event__process_attr;
2418 trace->tool.tracing_data = perf_event__process_tracing_data; 2455 trace->tool.tracing_data = perf_event__process_tracing_data;
2419 trace->tool.build_id = perf_event__process_build_id; 2456 trace->tool.build_id = perf_event__process_build_id;
2457 trace->tool.namespaces = perf_event__process_namespaces;
2420 2458
2421 trace->tool.ordered_events = true; 2459 trace->tool.ordered_events = true;
2422 trace->tool.ordering_requires_timestamps = true; 2460 trace->tool.ordering_requires_timestamps = true;
@@ -2785,7 +2823,7 @@ out:
2785 return err; 2823 return err;
2786} 2824}
2787 2825
2788int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) 2826int cmd_trace(int argc, const char **argv)
2789{ 2827{
2790 const char *trace_usage[] = { 2828 const char *trace_usage[] = {
2791 "perf trace [<options>] [<command>]", 2829 "perf trace [<options>] [<command>]",
diff --git a/tools/perf/builtin-version.c b/tools/perf/builtin-version.c
index 9b10cda6b6dc..d25149456a2f 100644
--- a/tools/perf/builtin-version.c
+++ b/tools/perf/builtin-version.c
@@ -1,9 +1,9 @@
1#include "util/util.h"
2#include "builtin.h" 1#include "builtin.h"
3#include "perf.h" 2#include "perf.h"
3#include <linux/compiler.h>
4#include <stdio.h>
4 5
5int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused, 6int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused)
6 const char *prefix __maybe_unused)
7{ 7{
8 printf("perf version %s\n", perf_version_string); 8 printf("perf version %s\n", perf_version_string);
9 return 0; 9 return 0;
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 036e1e35b1a8..d4d19fe3d050 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -2,46 +2,42 @@
2#define BUILTIN_H 2#define BUILTIN_H
3 3
4#include "util/util.h" 4#include "util/util.h"
5#include "util/strbuf.h"
6 5
7extern const char perf_usage_string[]; 6extern const char perf_usage_string[];
8extern const char perf_more_info_string[]; 7extern const char perf_more_info_string[];
9 8
10void list_common_cmds_help(void); 9void list_common_cmds_help(void);
11const char *help_unknown_cmd(const char *cmd); 10const char *help_unknown_cmd(const char *cmd);
12void prune_packed_objects(int);
13int read_line_with_nul(char *buf, int size, FILE *file);
14int check_pager_config(const char *cmd);
15 11
16int cmd_annotate(int argc, const char **argv, const char *prefix); 12int cmd_annotate(int argc, const char **argv);
17int cmd_bench(int argc, const char **argv, const char *prefix); 13int cmd_bench(int argc, const char **argv);
18int cmd_buildid_cache(int argc, const char **argv, const char *prefix); 14int cmd_buildid_cache(int argc, const char **argv);
19int cmd_buildid_list(int argc, const char **argv, const char *prefix); 15int cmd_buildid_list(int argc, const char **argv);
20int cmd_config(int argc, const char **argv, const char *prefix); 16int cmd_config(int argc, const char **argv);
21int cmd_c2c(int argc, const char **argv, const char *prefix); 17int cmd_c2c(int argc, const char **argv);
22int cmd_diff(int argc, const char **argv, const char *prefix); 18int cmd_diff(int argc, const char **argv);
23int cmd_evlist(int argc, const char **argv, const char *prefix); 19int cmd_evlist(int argc, const char **argv);
24int cmd_help(int argc, const char **argv, const char *prefix); 20int cmd_help(int argc, const char **argv);
25int cmd_sched(int argc, const char **argv, const char *prefix); 21int cmd_sched(int argc, const char **argv);
26int cmd_kallsyms(int argc, const char **argv, const char *prefix); 22int cmd_kallsyms(int argc, const char **argv);
27int cmd_list(int argc, const char **argv, const char *prefix); 23int cmd_list(int argc, const char **argv);
28int cmd_record(int argc, const char **argv, const char *prefix); 24int cmd_record(int argc, const char **argv);
29int cmd_report(int argc, const char **argv, const char *prefix); 25int cmd_report(int argc, const char **argv);
30int cmd_stat(int argc, const char **argv, const char *prefix); 26int cmd_stat(int argc, const char **argv);
31int cmd_timechart(int argc, const char **argv, const char *prefix); 27int cmd_timechart(int argc, const char **argv);
32int cmd_top(int argc, const char **argv, const char *prefix); 28int cmd_top(int argc, const char **argv);
33int cmd_script(int argc, const char **argv, const char *prefix); 29int cmd_script(int argc, const char **argv);
34int cmd_version(int argc, const char **argv, const char *prefix); 30int cmd_version(int argc, const char **argv);
35int cmd_probe(int argc, const char **argv, const char *prefix); 31int cmd_probe(int argc, const char **argv);
36int cmd_kmem(int argc, const char **argv, const char *prefix); 32int cmd_kmem(int argc, const char **argv);
37int cmd_lock(int argc, const char **argv, const char *prefix); 33int cmd_lock(int argc, const char **argv);
38int cmd_kvm(int argc, const char **argv, const char *prefix); 34int cmd_kvm(int argc, const char **argv);
39int cmd_test(int argc, const char **argv, const char *prefix); 35int cmd_test(int argc, const char **argv);
40int cmd_trace(int argc, const char **argv, const char *prefix); 36int cmd_trace(int argc, const char **argv);
41int cmd_inject(int argc, const char **argv, const char *prefix); 37int cmd_inject(int argc, const char **argv);
42int cmd_mem(int argc, const char **argv, const char *prefix); 38int cmd_mem(int argc, const char **argv);
43int cmd_data(int argc, const char **argv, const char *prefix); 39int cmd_data(int argc, const char **argv);
44int cmd_ftrace(int argc, const char **argv, const char *prefix); 40int cmd_ftrace(int argc, const char **argv);
45 41
46int find_scripts(char **scripts_array, char **scripts_path_array); 42int find_scripts(char **scripts_array, char **scripts_path_array);
47#endif 43#endif
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index c747bfd7f14d..83fe2202382e 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -1,7 +1,9 @@
1#!/bin/sh 1#!/bin/sh
2 2
3HEADERS=' 3HEADERS='
4include/uapi/linux/fcntl.h
4include/uapi/linux/perf_event.h 5include/uapi/linux/perf_event.h
6include/uapi/linux/stat.h
5include/linux/hash.h 7include/linux/hash.h
6include/uapi/linux/hw_breakpoint.h 8include/uapi/linux/hw_breakpoint.h
7arch/x86/include/asm/disabled-features.h 9arch/x86/include/asm/disabled-features.h
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index ac3efd396a72..2d0caf20ff3a 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -9,6 +9,7 @@ perf-buildid-cache mainporcelain common
9perf-buildid-list mainporcelain common 9perf-buildid-list mainporcelain common
10perf-data mainporcelain common 10perf-data mainporcelain common
11perf-diff mainporcelain common 11perf-diff mainporcelain common
12perf-c2c mainporcelain common
12perf-config mainporcelain common 13perf-config mainporcelain common
13perf-evlist mainporcelain common 14perf-evlist mainporcelain common
14perf-ftrace mainporcelain common 15perf-ftrace mainporcelain common
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 6d5479e03e0d..628a5e412cb1 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -17,11 +17,18 @@
17#include <subcmd/parse-options.h> 17#include <subcmd/parse-options.h>
18#include "util/bpf-loader.h" 18#include "util/bpf-loader.h"
19#include "util/debug.h" 19#include "util/debug.h"
20#include "util/event.h"
20#include <api/fs/fs.h> 21#include <api/fs/fs.h>
21#include <api/fs/tracing_path.h> 22#include <api/fs/tracing_path.h>
23#include <errno.h>
22#include <pthread.h> 24#include <pthread.h>
25#include <signal.h>
23#include <stdlib.h> 26#include <stdlib.h>
24#include <time.h> 27#include <time.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
31#include <linux/kernel.h>
25 32
26const char perf_usage_string[] = 33const char perf_usage_string[] =
27 "perf [--version] [--help] [OPTIONS] COMMAND [ARGS]"; 34 "perf [--version] [--help] [OPTIONS] COMMAND [ARGS]";
@@ -34,7 +41,7 @@ const char *input_name;
34 41
35struct cmd_struct { 42struct cmd_struct {
36 const char *cmd; 43 const char *cmd;
37 int (*fn)(int, const char **, const char *); 44 int (*fn)(int, const char **);
38 int option; 45 int option;
39}; 46};
40 47
@@ -88,7 +95,7 @@ static int pager_command_config(const char *var, const char *value, void *data)
88} 95}
89 96
90/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */ 97/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
91int check_pager_config(const char *cmd) 98static int check_pager_config(const char *cmd)
92{ 99{
93 int err; 100 int err;
94 struct pager_config c; 101 struct pager_config c;
@@ -267,71 +274,6 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
267 return handled; 274 return handled;
268} 275}
269 276
270static int handle_alias(int *argcp, const char ***argv)
271{
272 int envchanged = 0, ret = 0, saved_errno = errno;
273 int count, option_count;
274 const char **new_argv;
275 const char *alias_command;
276 char *alias_string;
277
278 alias_command = (*argv)[0];
279 alias_string = alias_lookup(alias_command);
280 if (alias_string) {
281 if (alias_string[0] == '!') {
282 if (*argcp > 1) {
283 struct strbuf buf;
284
285 if (strbuf_init(&buf, PATH_MAX) < 0 ||
286 strbuf_addstr(&buf, alias_string) < 0 ||
287 sq_quote_argv(&buf, (*argv) + 1,
288 PATH_MAX) < 0)
289 die("Failed to allocate memory.");
290 free(alias_string);
291 alias_string = buf.buf;
292 }
293 ret = system(alias_string + 1);
294 if (ret >= 0 && WIFEXITED(ret) &&
295 WEXITSTATUS(ret) != 127)
296 exit(WEXITSTATUS(ret));
297 die("Failed to run '%s' when expanding alias '%s'",
298 alias_string + 1, alias_command);
299 }
300 count = split_cmdline(alias_string, &new_argv);
301 if (count < 0)
302 die("Bad alias.%s string", alias_command);
303 option_count = handle_options(&new_argv, &count, &envchanged);
304 if (envchanged)
305 die("alias '%s' changes environment variables\n"
306 "You can use '!perf' in the alias to do this.",
307 alias_command);
308 memmove(new_argv - option_count, new_argv,
309 count * sizeof(char *));
310 new_argv -= option_count;
311
312 if (count < 1)
313 die("empty alias for %s", alias_command);
314
315 if (!strcmp(alias_command, new_argv[0]))
316 die("recursive alias: %s", alias_command);
317
318 new_argv = realloc(new_argv, sizeof(char *) *
319 (count + *argcp + 1));
320 /* insert after command name */
321 memcpy(new_argv + count, *argv + 1, sizeof(char *) * *argcp);
322 new_argv[count + *argcp] = NULL;
323
324 *argv = new_argv;
325 *argcp += count - 1;
326
327 ret = 1;
328 }
329
330 errno = saved_errno;
331
332 return ret;
333}
334
335#define RUN_SETUP (1<<0) 277#define RUN_SETUP (1<<0)
336#define USE_PAGER (1<<1) 278#define USE_PAGER (1<<1)
337 279
@@ -339,13 +281,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
339{ 281{
340 int status; 282 int status;
341 struct stat st; 283 struct stat st;
342 const char *prefix;
343 char sbuf[STRERR_BUFSIZE]; 284 char sbuf[STRERR_BUFSIZE];
344 285
345 prefix = NULL;
346 if (p->option & RUN_SETUP)
347 prefix = NULL; /* setup_perf_directory(); */
348
349 if (use_browser == -1) 286 if (use_browser == -1)
350 use_browser = check_browser_config(p->cmd); 287 use_browser = check_browser_config(p->cmd);
351 288
@@ -356,7 +293,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
356 commit_pager_choice(); 293 commit_pager_choice();
357 294
358 perf_env__set_cmdline(&perf_env, argc, argv); 295 perf_env__set_cmdline(&perf_env, argc, argv);
359 status = p->fn(argc, argv, prefix); 296 status = p->fn(argc, argv);
360 perf_config__exit(); 297 perf_config__exit();
361 exit_browser(status); 298 exit_browser(status);
362 perf_env__exit(&perf_env); 299 perf_env__exit(&perf_env);
@@ -397,16 +334,6 @@ static void handle_internal_command(int argc, const char **argv)
397{ 334{
398 const char *cmd = argv[0]; 335 const char *cmd = argv[0];
399 unsigned int i; 336 unsigned int i;
400 static const char ext[] = STRIP_EXTENSION;
401
402 if (sizeof(ext) > 1) {
403 i = strlen(argv[0]) - strlen(ext);
404 if (i > 0 && !strcmp(argv[0] + i, ext)) {
405 char *argv0 = strdup(argv[0]);
406 argv[0] = cmd = argv0;
407 argv0[i] = '\0';
408 }
409 }
410 337
411 /* Turn "perf cmd --help" into "perf help cmd" */ 338 /* Turn "perf cmd --help" into "perf help cmd" */
412 if (argc > 1 && !strcmp(argv[1], "--help")) { 339 if (argc > 1 && !strcmp(argv[1], "--help")) {
@@ -448,7 +375,8 @@ static void execv_dashed_external(const char **argv)
448 if (status != -ERR_RUN_COMMAND_EXEC) { 375 if (status != -ERR_RUN_COMMAND_EXEC) {
449 if (IS_RUN_COMMAND_ERR(status)) { 376 if (IS_RUN_COMMAND_ERR(status)) {
450do_die: 377do_die:
451 die("unable to run '%s'", argv[0]); 378 pr_err("FATAL: unable to run '%s'", argv[0]);
379 status = -128;
452 } 380 }
453 exit(-status); 381 exit(-status);
454 } 382 }
@@ -460,25 +388,12 @@ do_die:
460 388
461static int run_argv(int *argcp, const char ***argv) 389static int run_argv(int *argcp, const char ***argv)
462{ 390{
463 int done_alias = 0; 391 /* See if it's an internal command */
392 handle_internal_command(*argcp, *argv);
464 393
465 while (1) { 394 /* .. then try the external ones */
466 /* See if it's an internal command */ 395 execv_dashed_external(*argv);
467 handle_internal_command(*argcp, *argv); 396 return 0;
468
469 /* .. then try the external ones */
470 execv_dashed_external(*argv);
471
472 /* It could be an alias -- this works around the insanity
473 * of overriding "perf log" with "perf show" by having
474 * alias.log = show
475 */
476 if (done_alias || !handle_alias(argcp, argv))
477 break;
478 done_alias = 1;
479 }
480
481 return done_alias;
482} 397}
483 398
484static void pthread__block_sigwinch(void) 399static void pthread__block_sigwinch(void)
@@ -566,7 +481,7 @@ int main(int argc, const char **argv)
566#ifdef HAVE_LIBAUDIT_SUPPORT 481#ifdef HAVE_LIBAUDIT_SUPPORT
567 setup_path(); 482 setup_path();
568 argv[0] = "trace"; 483 argv[0] = "trace";
569 return cmd_trace(argc, argv, NULL); 484 return cmd_trace(argc, argv);
570#else 485#else
571 fprintf(stderr, 486 fprintf(stderr,
572 "trace command not available: missing audit-libs devel package at build time.\n"); 487 "trace command not available: missing audit-libs devel package at build time.\n");
@@ -611,17 +526,12 @@ int main(int argc, const char **argv)
611 526
612 while (1) { 527 while (1) {
613 static int done_help; 528 static int done_help;
614 int was_alias = run_argv(&argc, &argv); 529
530 run_argv(&argc, &argv);
615 531
616 if (errno != ENOENT) 532 if (errno != ENOENT)
617 break; 533 break;
618 534
619 if (was_alias) {
620 fprintf(stderr, "Expansion of alias '%s' failed; "
621 "'%s' is not a perf-command\n",
622 cmd, argv[0]);
623 goto out;
624 }
625 if (!done_help) { 535 if (!done_help) {
626 cmd = argv[0] = help_unknown_cmd(cmd); 536 cmd = argv[0] = help_unknown_cmd(cmd);
627 done_help = 1; 537 done_help = 1;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 1c27d947c2fe..806c216a1078 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -50,6 +50,7 @@ struct record_opts {
50 bool running_time; 50 bool running_time;
51 bool full_auxtrace; 51 bool full_auxtrace;
52 bool auxtrace_snapshot_mode; 52 bool auxtrace_snapshot_mode;
53 bool record_namespaces;
53 bool record_switch_events; 54 bool record_switch_events;
54 bool all_kernel; 55 bool all_kernel;
55 bool all_user; 56 bool all_user;
diff --git a/tools/perf/pmu-events/arch/x86/broadwell/uncore.json b/tools/perf/pmu-events/arch/x86/broadwell/uncore.json
new file mode 100644
index 000000000000..28e1e159a3cb
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/broadwell/uncore.json
@@ -0,0 +1,278 @@
1[
2 {
3 "Unit": "CBO",
4 "EventCode": "0x22",
5 "UMask": "0x41",
6 "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_XCORE",
7 "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which misses in some processor core.",
8 "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which misses in some processor core.",
9 "Counter": "0,1",
10 "CounterMask": "0",
11 "Invert": "0",
12 "EdgeDetect": "0"
13 },
14 {
15 "Unit": "CBO",
16 "EventCode": "0x22",
17 "UMask": "0x81",
18 "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_EVICTION",
19 "BriefDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.",
20 "PublicDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.",
21 "Counter": "0,1",
22 "CounterMask": "0",
23 "Invert": "0",
24 "EdgeDetect": "0"
25 },
26 {
27 "Unit": "CBO",
28 "EventCode": "0x22",
29 "UMask": "0x44",
30 "EventName": "UNC_CBO_XSNP_RESPONSE.HIT_XCORE",
31 "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a non-modified line in some processor core.",
32 "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a non-modified line in some processor core.",
33 "Counter": "0,1",
34 "CounterMask": "0",
35 "Invert": "0",
36 "EdgeDetect": "0"
37 },
38 {
39 "Unit": "CBO",
40 "EventCode": "0x22",
41 "UMask": "0x48",
42 "EventName": "UNC_CBO_XSNP_RESPONSE.HITM_XCORE",
43 "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a modified line in some processor core.",
44 "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a modified line in some processor core.",
45 "Counter": "0,1",
46 "CounterMask": "0",
47 "Invert": "0",
48 "EdgeDetect": "0"
49 },
50 {
51 "Unit": "CBO",
52 "EventCode": "0x34",
53 "UMask": "0x11",
54 "EventName": "UNC_CBO_CACHE_LOOKUP.READ_M",
55 "BriefDescription": "L3 Lookup read request that access cache and found line in M-state",
56 "PublicDescription": "L3 Lookup read request that access cache and found line in M-state.",
57 "Counter": "0,1",
58 "CounterMask": "0",
59 "Invert": "0",
60 "EdgeDetect": "0"
61 },
62 {
63 "Unit": "CBO",
64 "EventCode": "0x34",
65 "UMask": "0x21",
66 "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_M",
67 "BriefDescription": "L3 Lookup write request that access cache and found line in M-state",
68 "PublicDescription": "L3 Lookup write request that access cache and found line in M-state.",
69 "Counter": "0,1",
70 "CounterMask": "0",
71 "Invert": "0",
72 "EdgeDetect": "0"
73 },
74 {
75 "Unit": "CBO",
76 "EventCode": "0x34",
77 "UMask": "0x81",
78 "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_M",
79 "BriefDescription": "L3 Lookup any request that access cache and found line in M-state",
80 "PublicDescription": "L3 Lookup any request that access cache and found line in M-state.",
81 "Counter": "0,1",
82 "CounterMask": "0",
83 "Invert": "0",
84 "EdgeDetect": "0"
85 },
86 {
87 "Unit": "CBO",
88 "EventCode": "0x34",
89 "UMask": "0x18",
90 "EventName": "UNC_CBO_CACHE_LOOKUP.READ_I",
91 "BriefDescription": "L3 Lookup read request that access cache and found line in I-state",
92 "PublicDescription": "L3 Lookup read request that access cache and found line in I-state.",
93 "Counter": "0,1",
94 "CounterMask": "0",
95 "Invert": "0",
96 "EdgeDetect": "0"
97 },
98 {
99 "Unit": "CBO",
100 "EventCode": "0x34",
101 "UMask": "0x88",
102 "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_I",
103 "BriefDescription": "L3 Lookup any request that access cache and found line in I-state",
104 "PublicDescription": "L3 Lookup any request that access cache and found line in I-state.",
105 "Counter": "0,1",
106 "CounterMask": "0",
107 "Invert": "0",
108 "EdgeDetect": "0"
109 },
110 {
111 "Unit": "CBO",
112 "EventCode": "0x34",
113 "UMask": "0x1f",
114 "EventName": "UNC_CBO_CACHE_LOOKUP.READ_MESI",
115 "BriefDescription": "L3 Lookup read request that access cache and found line in any MESI-state",
116 "PublicDescription": "L3 Lookup read request that access cache and found line in any MESI-state.",
117 "Counter": "0,1",
118 "CounterMask": "0",
119 "Invert": "0",
120 "EdgeDetect": "0"
121 },
122 {
123 "Unit": "CBO",
124 "EventCode": "0x34",
125 "UMask": "0x2f",
126 "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_MESI",
127 "BriefDescription": "L3 Lookup write request that access cache and found line in MESI-state",
128 "PublicDescription": "L3 Lookup write request that access cache and found line in MESI-state.",
129 "Counter": "0,1",
130 "CounterMask": "0",
131 "Invert": "0",
132 "EdgeDetect": "0"
133 },
134 {
135 "Unit": "CBO",
136 "EventCode": "0x34",
137 "UMask": "0x8f",
138 "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_MESI",
139 "BriefDescription": "L3 Lookup any request that access cache and found line in MESI-state",
140 "PublicDescription": "L3 Lookup any request that access cache and found line in MESI-state.",
141 "Counter": "0,1",
142 "CounterMask": "0",
143 "Invert": "0",
144 "EdgeDetect": "0"
145 },
146 {
147 "Unit": "CBO",
148 "EventCode": "0x34",
149 "UMask": "0x86",
150 "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_ES",
151 "BriefDescription": "L3 Lookup any request that access cache and found line in E or S-state",
152 "PublicDescription": "L3 Lookup any request that access cache and found line in E or S-state.",
153 "Counter": "0,1",
154 "CounterMask": "0",
155 "Invert": "0",
156 "EdgeDetect": "0"
157 },
158 {
159 "Unit": "CBO",
160 "EventCode": "0x34",
161 "UMask": "0x16",
162 "EventName": "UNC_CBO_CACHE_LOOKUP.READ_ES",
163 "BriefDescription": "L3 Lookup read request that access cache and found line in E or S-state",
164 "PublicDescription": "L3 Lookup read request that access cache and found line in E or S-state.",
165 "Counter": "0,1",
166 "CounterMask": "0",
167 "Invert": "0",
168 "EdgeDetect": "0"
169 },
170 {
171 "Unit": "CBO",
172 "EventCode": "0x34",
173 "UMask": "0x26",
174 "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_ES",
175 "BriefDescription": "L3 Lookup write request that access cache and found line in E or S-state",
176 "PublicDescription": "L3 Lookup write request that access cache and found line in E or S-state.",
177 "Counter": "0,1",
178 "CounterMask": "0",
179 "Invert": "0",
180 "EdgeDetect": "0"
181 },
182 {
183 "Unit": "iMPH-U",
184 "EventCode": "0x80",
185 "UMask": "0x01",
186 "EventName": "UNC_ARB_TRK_OCCUPANCY.ALL",
187 "BriefDescription": "Each cycle count number of all Core outgoing valid entries. Such entry is defined as valid from it's allocation till first of IDI0 or DRS0 messages is sent out. Accounts for Coherent and non-coherent traffic.",
188 "PublicDescription": "Each cycle count number of all Core outgoing valid entries. Such entry is defined as valid from it's allocation till first of IDI0 or DRS0 messages is sent out. Accounts for Coherent and non-coherent traffic.",
189 "Counter": "0,",
190 "CounterMask": "0",
191 "Invert": "0",
192 "EdgeDetect": "0"
193 },
194 {
195 "Unit": "iMPH-U",
196 "EventCode": "0x80",
197 "UMask": "0x02",
198 "EventName": "UNC_ARB_TRK_OCCUPANCY.DRD_DIRECT",
199 "BriefDescription": "Each cycle count number of 'valid' coherent Data Read entries that are in DirectData mode. Such entry is defined as valid when it is allocated till data sent to Core (first chunk, IDI0). Applicable for IA Cores' requests in normal case.",
200 "PublicDescription": "Each cycle count number of 'valid' coherent Data Read entries that are in DirectData mode. Such entry is defined as valid when it is allocated till data sent to Core (first chunk, IDI0). Applicable for IA Cores' requests in normal case.",
201 "Counter": "0,",
202 "CounterMask": "0",
203 "Invert": "0",
204 "EdgeDetect": "0"
205 },
206 {
207 "Unit": "iMPH-U",
208 "EventCode": "0x81",
209 "UMask": "0x01",
210 "EventName": "UNC_ARB_TRK_REQUESTS.ALL",
211 "BriefDescription": "Total number of Core outgoing entries allocated. Accounts for Coherent and non-coherent traffic.",
212 "PublicDescription": "Total number of Core outgoing entries allocated. Accounts for Coherent and non-coherent traffic.",
213 "Counter": "0,1",
214 "CounterMask": "0",
215 "Invert": "0",
216 "EdgeDetect": "0"
217 },
218 {
219 "Unit": "iMPH-U",
220 "EventCode": "0x81",
221 "UMask": "0x02",
222 "EventName": "UNC_ARB_TRK_REQUESTS.DRD_DIRECT",
223 "BriefDescription": "Number of Core coherent Data Read entries allocated in DirectData mode",
224 "PublicDescription": "Number of Core coherent Data Read entries allocated in DirectData mode.",
225 "Counter": "0,1",
226 "CounterMask": "0",
227 "Invert": "0",
228 "EdgeDetect": "0"
229 },
230 {
231 "Unit": "iMPH-U",
232 "EventCode": "0x81",
233 "UMask": "0x20",
234 "EventName": "UNC_ARB_TRK_REQUESTS.WRITES",
235 "BriefDescription": "Number of Writes allocated - any write transactions: full/partials writes and evictions.",
236 "PublicDescription": "Number of Writes allocated - any write transactions: full/partials writes and evictions.",
237 "Counter": "0,1",
238 "CounterMask": "0",
239 "Invert": "0",
240 "EdgeDetect": "0"
241 },
242 {
243 "Unit": "iMPH-U",
244 "EventCode": "0x84",
245 "UMask": "0x01",
246 "EventName": "UNC_ARB_COH_TRK_REQUESTS.ALL",
247 "BriefDescription": "Number of entries allocated. Account for Any type: e.g. Snoop, Core aperture, etc.",
248 "PublicDescription": "Number of entries allocated. Account for Any type: e.g. Snoop, Core aperture, etc.",
249 "Counter": "0,1",
250 "CounterMask": "0",
251 "Invert": "0",
252 "EdgeDetect": "0"
253 },
254 {
255 "Unit": "iMPH-U",
256 "EventCode": "0x80",
257 "UMask": "0x01",
258 "EventName": "UNC_ARB_TRK_OCCUPANCY.CYCLES_WITH_ANY_REQUEST",
259 "BriefDescription": "Cycles with at least one request outstanding is waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.;",
260 "PublicDescription": "Cycles with at least one request outstanding is waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
261 "Counter": "0,",
262 "CounterMask": "1",
263 "Invert": "0",
264 "EdgeDetect": "0"
265 },
266 {
267 "Unit": "NCU",
268 "EventCode": "0x0",
269 "UMask": "0x01",
270 "EventName": "UNC_CLOCK.SOCKET",
271 "BriefDescription": "This 48-bit fixed counter counts the UCLK cycles",
272 "PublicDescription": "This 48-bit fixed counter counts the UCLK cycles.",
273 "Counter": "FIXED",
274 "CounterMask": "0",
275 "Invert": "0",
276 "EdgeDetect": "0"
277 }
278] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/broadwellde/uncore-cache.json b/tools/perf/pmu-events/arch/x86/broadwellde/uncore-cache.json
index 076459c51d4e..58ed6d33d1f4 100644
--- a/tools/perf/pmu-events/arch/x86/broadwellde/uncore-cache.json
+++ b/tools/perf/pmu-events/arch/x86/broadwellde/uncore-cache.json
@@ -1,13 +1,13 @@
1[ 1[
2 { 2 {
3 "BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks", 3 "BriefDescription": "Uncore cache clock ticks",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventName": "UNC_C_CLOCKTICKS", 5 "EventName": "UNC_C_CLOCKTICKS",
6 "PerPkg": "1", 6 "PerPkg": "1",
7 "Unit": "CBO" 7 "Unit": "CBO"
8 }, 8 },
9 { 9 {
10 "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any", 10 "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch)",
11 "Counter": "0,1,2,3", 11 "Counter": "0,1,2,3",
12 "EventCode": "0x34", 12 "EventCode": "0x34",
13 "EventName": "UNC_C_LLC_LOOKUP.ANY", 13 "EventName": "UNC_C_LLC_LOOKUP.ANY",
@@ -18,7 +18,7 @@
18 "Unit": "CBO" 18 "Unit": "CBO"
19 }, 19 },
20 { 20 {
21 "BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state", 21 "BriefDescription": "M line evictions from LLC (writebacks to memory)",
22 "Counter": "0,1,2,3", 22 "Counter": "0,1,2,3",
23 "EventCode": "0x37", 23 "EventCode": "0x37",
24 "EventName": "UNC_C_LLC_VICTIMS.M_STATE", 24 "EventName": "UNC_C_LLC_VICTIMS.M_STATE",
@@ -212,7 +212,7 @@
212 "Unit": "CBO" 212 "Unit": "CBO"
213 }, 213 },
214 { 214 {
215 "BriefDescription": "read requests to home agent. Derived from unc_h_requests.reads", 215 "BriefDescription": "read requests to home agent",
216 "Counter": "0,1,2,3", 216 "Counter": "0,1,2,3",
217 "EventCode": "0x1", 217 "EventCode": "0x1",
218 "EventName": "UNC_H_REQUESTS.READS", 218 "EventName": "UNC_H_REQUESTS.READS",
@@ -221,7 +221,7 @@
221 "Unit": "HA" 221 "Unit": "HA"
222 }, 222 },
223 { 223 {
224 "BriefDescription": "read requests to local home agent. Derived from unc_h_requests.reads_local", 224 "BriefDescription": "read requests to local home agent",
225 "Counter": "0,1,2,3", 225 "Counter": "0,1,2,3",
226 "EventCode": "0x1", 226 "EventCode": "0x1",
227 "EventName": "UNC_H_REQUESTS.READS_LOCAL", 227 "EventName": "UNC_H_REQUESTS.READS_LOCAL",
@@ -230,7 +230,7 @@
230 "Unit": "HA" 230 "Unit": "HA"
231 }, 231 },
232 { 232 {
233 "BriefDescription": "read requests to remote home agent. Derived from unc_h_requests.reads_remote", 233 "BriefDescription": "read requests to remote home agent",
234 "Counter": "0,1,2,3", 234 "Counter": "0,1,2,3",
235 "EventCode": "0x1", 235 "EventCode": "0x1",
236 "EventName": "UNC_H_REQUESTS.READS_REMOTE", 236 "EventName": "UNC_H_REQUESTS.READS_REMOTE",
@@ -239,7 +239,7 @@
239 "Unit": "HA" 239 "Unit": "HA"
240 }, 240 },
241 { 241 {
242 "BriefDescription": "write requests to home agent. Derived from unc_h_requests.writes", 242 "BriefDescription": "write requests to home agent",
243 "Counter": "0,1,2,3", 243 "Counter": "0,1,2,3",
244 "EventCode": "0x1", 244 "EventCode": "0x1",
245 "EventName": "UNC_H_REQUESTS.WRITES", 245 "EventName": "UNC_H_REQUESTS.WRITES",
@@ -248,7 +248,7 @@
248 "Unit": "HA" 248 "Unit": "HA"
249 }, 249 },
250 { 250 {
251 "BriefDescription": "write requests to local home agent. Derived from unc_h_requests.writes_local", 251 "BriefDescription": "write requests to local home agent",
252 "Counter": "0,1,2,3", 252 "Counter": "0,1,2,3",
253 "EventCode": "0x1", 253 "EventCode": "0x1",
254 "EventName": "UNC_H_REQUESTS.WRITES_LOCAL", 254 "EventName": "UNC_H_REQUESTS.WRITES_LOCAL",
@@ -257,7 +257,7 @@
257 "Unit": "HA" 257 "Unit": "HA"
258 }, 258 },
259 { 259 {
260 "BriefDescription": "write requests to remote home agent. Derived from unc_h_requests.writes_remote", 260 "BriefDescription": "write requests to remote home agent",
261 "Counter": "0,1,2,3", 261 "Counter": "0,1,2,3",
262 "EventCode": "0x1", 262 "EventCode": "0x1",
263 "EventName": "UNC_H_REQUESTS.WRITES_REMOTE", 263 "EventName": "UNC_H_REQUESTS.WRITES_REMOTE",
@@ -266,7 +266,7 @@
266 "Unit": "HA" 266 "Unit": "HA"
267 }, 267 },
268 { 268 {
269 "BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously). Derived from unc_h_snoop_resp.rspcnflct", 269 "BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously)",
270 "Counter": "0,1,2,3", 270 "Counter": "0,1,2,3",
271 "EventCode": "0x21", 271 "EventCode": "0x21",
272 "EventName": "UNC_H_SNOOP_RESP.RSPCNFLCT", 272 "EventName": "UNC_H_SNOOP_RESP.RSPCNFLCT",
@@ -275,7 +275,7 @@
275 "Unit": "HA" 275 "Unit": "HA"
276 }, 276 },
277 { 277 {
278 "BriefDescription": "M line forwarded from remote cache along with writeback to memory. Derived from unc_h_snoop_resp.rsp_fwd_wb", 278 "BriefDescription": "M line forwarded from remote cache along with writeback to memory",
279 "Counter": "0,1,2,3", 279 "Counter": "0,1,2,3",
280 "EventCode": "0x21", 280 "EventCode": "0x21",
281 "EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB", 281 "EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB",
@@ -285,7 +285,7 @@
285 "Unit": "HA" 285 "Unit": "HA"
286 }, 286 },
287 { 287 {
288 "BriefDescription": "M line forwarded from remote cache with no writeback to memory. Derived from unc_h_snoop_resp.rspifwd", 288 "BriefDescription": "M line forwarded from remote cache with no writeback to memory",
289 "Counter": "0,1,2,3", 289 "Counter": "0,1,2,3",
290 "EventCode": "0x21", 290 "EventCode": "0x21",
291 "EventName": "UNC_H_SNOOP_RESP.RSPIFWD", 291 "EventName": "UNC_H_SNOOP_RESP.RSPIFWD",
@@ -295,7 +295,7 @@
295 "Unit": "HA" 295 "Unit": "HA"
296 }, 296 },
297 { 297 {
298 "BriefDescription": "Shared line response from remote cache. Derived from unc_h_snoop_resp.rsps", 298 "BriefDescription": "Shared line response from remote cache",
299 "Counter": "0,1,2,3", 299 "Counter": "0,1,2,3",
300 "EventCode": "0x21", 300 "EventCode": "0x21",
301 "EventName": "UNC_H_SNOOP_RESP.RSPS", 301 "EventName": "UNC_H_SNOOP_RESP.RSPS",
@@ -305,7 +305,7 @@
305 "Unit": "HA" 305 "Unit": "HA"
306 }, 306 },
307 { 307 {
308 "BriefDescription": "Shared line forwarded from remote cache. Derived from unc_h_snoop_resp.rspsfwd", 308 "BriefDescription": "Shared line forwarded from remote cache",
309 "Counter": "0,1,2,3", 309 "Counter": "0,1,2,3",
310 "EventCode": "0x21", 310 "EventCode": "0x21",
311 "EventName": "UNC_H_SNOOP_RESP.RSPSFWD", 311 "EventName": "UNC_H_SNOOP_RESP.RSPSFWD",
diff --git a/tools/perf/pmu-events/arch/x86/broadwellde/uncore-memory.json b/tools/perf/pmu-events/arch/x86/broadwellde/uncore-memory.json
index d17dc235f734..f4b0745cdbbf 100644
--- a/tools/perf/pmu-events/arch/x86/broadwellde/uncore-memory.json
+++ b/tools/perf/pmu-events/arch/x86/broadwellde/uncore-memory.json
@@ -3,7 +3,7 @@
3 "BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd", 3 "BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventCode": "0x4", 5 "EventCode": "0x4",
6 "EventName": "UNC_M_CAS_COUNT.RD", 6 "EventName": "LLC_MISSES.MEM_READ",
7 "PerPkg": "1", 7 "PerPkg": "1",
8 "ScaleUnit": "64Bytes", 8 "ScaleUnit": "64Bytes",
9 "UMask": "0x3", 9 "UMask": "0x3",
@@ -13,48 +13,51 @@
13 "BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr", 13 "BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr",
14 "Counter": "0,1,2,3", 14 "Counter": "0,1,2,3",
15 "EventCode": "0x4", 15 "EventCode": "0x4",
16 "EventName": "UNC_M_CAS_COUNT.WR", 16 "EventName": "LLC_MISSES.MEM_WRITE",
17 "PerPkg": "1", 17 "PerPkg": "1",
18 "ScaleUnit": "64Bytes", 18 "ScaleUnit": "64Bytes",
19 "UMask": "0xC", 19 "UMask": "0xC",
20 "Unit": "iMC" 20 "Unit": "iMC"
21 }, 21 },
22 { 22 {
23 "BriefDescription": "Memory controller clock ticks. Derived from unc_m_clockticks", 23 "BriefDescription": "Memory controller clock ticks",
24 "Counter": "0,1,2,3", 24 "Counter": "0,1,2,3",
25 "EventName": "UNC_M_CLOCKTICKS", 25 "EventName": "UNC_M_DCLOCKTICKS",
26 "PerPkg": "1", 26 "PerPkg": "1",
27 "Unit": "iMC" 27 "Unit": "iMC"
28 }, 28 },
29 { 29 {
30 "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd", 30 "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode",
31 "Counter": "0,1,2,3", 31 "Counter": "0,1,2,3",
32 "EventCode": "0x85", 32 "EventCode": "0x85",
33 "EventName": "UNC_M_POWER_CHANNEL_PPD", 33 "EventName": "UNC_M_POWER_CHANNEL_PPD",
34 "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.", 34 "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_DCLOCKTICKS) * 100.",
35 "MetricName": "power_channel_ppd %",
35 "PerPkg": "1", 36 "PerPkg": "1",
36 "Unit": "iMC" 37 "Unit": "iMC"
37 }, 38 },
38 { 39 {
39 "BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles", 40 "BriefDescription": "Cycles all ranks are in critical thermal throttle",
40 "Counter": "0,1,2,3", 41 "Counter": "0,1,2,3",
41 "EventCode": "0x86", 42 "EventCode": "0x86",
42 "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES", 43 "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
43 "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.", 44 "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_DCLOCKTICKS) * 100.",
45 "MetricName": "power_critical_throttle_cycles %",
44 "PerPkg": "1", 46 "PerPkg": "1",
45 "Unit": "iMC" 47 "Unit": "iMC"
46 }, 48 },
47 { 49 {
48 "BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh", 50 "BriefDescription": "Cycles Memory is in self refresh power mode",
49 "Counter": "0,1,2,3", 51 "Counter": "0,1,2,3",
50 "EventCode": "0x43", 52 "EventCode": "0x43",
51 "EventName": "UNC_M_POWER_SELF_REFRESH", 53 "EventName": "UNC_M_POWER_SELF_REFRESH",
52 "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.", 54 "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_DCLOCKTICKS) * 100.",
55 "MetricName": "power_self_refresh %",
53 "PerPkg": "1", 56 "PerPkg": "1",
54 "Unit": "iMC" 57 "Unit": "iMC"
55 }, 58 },
56 { 59 {
57 "BriefDescription": "Pre-charges due to page misses. Derived from unc_m_pre_count.page_miss", 60 "BriefDescription": "Pre-charges due to page misses",
58 "Counter": "0,1,2,3", 61 "Counter": "0,1,2,3",
59 "EventCode": "0x2", 62 "EventCode": "0x2",
60 "EventName": "UNC_M_PRE_COUNT.PAGE_MISS", 63 "EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
@@ -63,7 +66,7 @@
63 "Unit": "iMC" 66 "Unit": "iMC"
64 }, 67 },
65 { 68 {
66 "BriefDescription": "Pre-charge for reads. Derived from unc_m_pre_count.rd", 69 "BriefDescription": "Pre-charge for reads",
67 "Counter": "0,1,2,3", 70 "Counter": "0,1,2,3",
68 "EventCode": "0x2", 71 "EventCode": "0x2",
69 "EventName": "UNC_M_PRE_COUNT.RD", 72 "EventName": "UNC_M_PRE_COUNT.RD",
@@ -72,7 +75,7 @@
72 "Unit": "iMC" 75 "Unit": "iMC"
73 }, 76 },
74 { 77 {
75 "BriefDescription": "Pre-charge for writes. Derived from unc_m_pre_count.wr", 78 "BriefDescription": "Pre-charge for writes",
76 "Counter": "0,1,2,3", 79 "Counter": "0,1,2,3",
77 "EventCode": "0x2", 80 "EventCode": "0x2",
78 "EventName": "UNC_M_PRE_COUNT.WR", 81 "EventName": "UNC_M_PRE_COUNT.WR",
diff --git a/tools/perf/pmu-events/arch/x86/broadwellde/uncore-power.json b/tools/perf/pmu-events/arch/x86/broadwellde/uncore-power.json
index b44d43088bbb..dd1b95655d1d 100644
--- a/tools/perf/pmu-events/arch/x86/broadwellde/uncore-power.json
+++ b/tools/perf/pmu-events/arch/x86/broadwellde/uncore-power.json
@@ -1,83 +1,91 @@
1[ 1[
2 { 2 {
3 "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks", 3 "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventName": "UNC_P_CLOCKTICKS", 5 "EventName": "UNC_P_CLOCKTICKS",
6 "PerPkg": "1", 6 "PerPkg": "1",
7 "Unit": "PCU" 7 "Unit": "PCU"
8 }, 8 },
9 { 9 {
10 "BriefDescription": "C0 and C1. Derived from unc_p_power_state_occupancy.cores_c0", 10 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C0. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
11 "Counter": "0,1,2,3", 11 "Counter": "0,1,2,3",
12 "EventCode": "0x80", 12 "EventCode": "0x80",
13 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0", 13 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
14 "Filter": "occ_sel=1", 14 "Filter": "occ_sel=1",
15 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.", 15 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
16 "MetricName": "power_state_occupancy.cores_c0 %",
16 "PerPkg": "1", 17 "PerPkg": "1",
17 "Unit": "PCU" 18 "Unit": "PCU"
18 }, 19 },
19 { 20 {
20 "BriefDescription": "C3. Derived from unc_p_power_state_occupancy.cores_c3", 21 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C3. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
21 "Counter": "0,1,2,3", 22 "Counter": "0,1,2,3",
22 "EventCode": "0x80", 23 "EventCode": "0x80",
23 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3", 24 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
24 "Filter": "occ_sel=2", 25 "Filter": "occ_sel=2",
25 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.", 26 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
27 "MetricName": "power_state_occupancy.cores_c3 %",
26 "PerPkg": "1", 28 "PerPkg": "1",
27 "Unit": "PCU" 29 "Unit": "PCU"
28 }, 30 },
29 { 31 {
30 "BriefDescription": "C6 and C7. Derived from unc_p_power_state_occupancy.cores_c6", 32 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C6. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events ",
31 "Counter": "0,1,2,3", 33 "Counter": "0,1,2,3",
32 "EventCode": "0x80", 34 "EventCode": "0x80",
33 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6", 35 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
34 "Filter": "occ_sel=3", 36 "Filter": "occ_sel=3",
35 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.", 37 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
38 "MetricName": "power_state_occupancy.cores_c6 %",
36 "PerPkg": "1", 39 "PerPkg": "1",
37 "Unit": "PCU" 40 "Unit": "PCU"
38 }, 41 },
39 { 42 {
40 "BriefDescription": "External Prochot. Derived from unc_p_prochot_external_cycles", 43 "BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode. This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip",
41 "Counter": "0,1,2,3", 44 "Counter": "0,1,2,3",
42 "EventCode": "0xA", 45 "EventCode": "0xA",
43 "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES", 46 "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
44 "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.", 47 "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
48 "MetricName": "prochot_external_cycles %",
45 "PerPkg": "1", 49 "PerPkg": "1",
46 "Unit": "PCU" 50 "Unit": "PCU"
47 }, 51 },
48 { 52 {
49 "BriefDescription": "Thermal Strongest Upper Limit Cycles. Derived from unc_p_freq_max_limit_thermal_cycles", 53 "BriefDescription": "Counts the number of cycles when temperature is the upper limit on frequency",
50 "Counter": "0,1,2,3", 54 "Counter": "0,1,2,3",
51 "EventCode": "0x4", 55 "EventCode": "0x4",
52 "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES", 56 "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
53 "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.", 57 "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
58 "MetricName": "freq_max_limit_thermal_cycles %",
54 "PerPkg": "1", 59 "PerPkg": "1",
55 "Unit": "PCU" 60 "Unit": "PCU"
56 }, 61 },
57 { 62 {
58 "BriefDescription": "OS Strongest Upper Limit Cycles. Derived from unc_p_freq_max_os_cycles", 63 "BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency",
59 "Counter": "0,1,2,3", 64 "Counter": "0,1,2,3",
60 "EventCode": "0x6", 65 "EventCode": "0x6",
61 "EventName": "UNC_P_FREQ_MAX_OS_CYCLES", 66 "EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
62 "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.", 67 "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
68 "MetricName": "freq_max_os_cycles %",
63 "PerPkg": "1", 69 "PerPkg": "1",
64 "Unit": "PCU" 70 "Unit": "PCU"
65 }, 71 },
66 { 72 {
67 "BriefDescription": "Power Strongest Upper Limit Cycles. Derived from unc_p_freq_max_power_cycles", 73 "BriefDescription": "Counts the number of cycles when power is the upper limit on frequency",
68 "Counter": "0,1,2,3", 74 "Counter": "0,1,2,3",
69 "EventCode": "0x5", 75 "EventCode": "0x5",
70 "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES", 76 "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
71 "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.", 77 "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
78 "MetricName": "freq_max_power_cycles %",
72 "PerPkg": "1", 79 "PerPkg": "1",
73 "Unit": "PCU" 80 "Unit": "PCU"
74 }, 81 },
75 { 82 {
76 "BriefDescription": "Cycles spent changing Frequency. Derived from unc_p_freq_trans_cycles", 83 "BriefDescription": "Counts the number of cycles when current is the upper limit on frequency",
77 "Counter": "0,1,2,3", 84 "Counter": "0,1,2,3",
78 "EventCode": "0x74", 85 "EventCode": "0x74",
79 "EventName": "UNC_P_FREQ_TRANS_CYCLES", 86 "EventName": "UNC_P_FREQ_TRANS_CYCLES",
80 "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.", 87 "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
88 "MetricName": "freq_trans_cycles %",
81 "PerPkg": "1", 89 "PerPkg": "1",
82 "Unit": "PCU" 90 "Unit": "PCU"
83 } 91 }
diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/uncore-cache.json b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-cache.json
index 076459c51d4e..58ed6d33d1f4 100644
--- a/tools/perf/pmu-events/arch/x86/broadwellx/uncore-cache.json
+++ b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-cache.json
@@ -1,13 +1,13 @@
1[ 1[
2 { 2 {
3 "BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks", 3 "BriefDescription": "Uncore cache clock ticks",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventName": "UNC_C_CLOCKTICKS", 5 "EventName": "UNC_C_CLOCKTICKS",
6 "PerPkg": "1", 6 "PerPkg": "1",
7 "Unit": "CBO" 7 "Unit": "CBO"
8 }, 8 },
9 { 9 {
10 "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any", 10 "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch)",
11 "Counter": "0,1,2,3", 11 "Counter": "0,1,2,3",
12 "EventCode": "0x34", 12 "EventCode": "0x34",
13 "EventName": "UNC_C_LLC_LOOKUP.ANY", 13 "EventName": "UNC_C_LLC_LOOKUP.ANY",
@@ -18,7 +18,7 @@
18 "Unit": "CBO" 18 "Unit": "CBO"
19 }, 19 },
20 { 20 {
21 "BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state", 21 "BriefDescription": "M line evictions from LLC (writebacks to memory)",
22 "Counter": "0,1,2,3", 22 "Counter": "0,1,2,3",
23 "EventCode": "0x37", 23 "EventCode": "0x37",
24 "EventName": "UNC_C_LLC_VICTIMS.M_STATE", 24 "EventName": "UNC_C_LLC_VICTIMS.M_STATE",
@@ -212,7 +212,7 @@
212 "Unit": "CBO" 212 "Unit": "CBO"
213 }, 213 },
214 { 214 {
215 "BriefDescription": "read requests to home agent. Derived from unc_h_requests.reads", 215 "BriefDescription": "read requests to home agent",
216 "Counter": "0,1,2,3", 216 "Counter": "0,1,2,3",
217 "EventCode": "0x1", 217 "EventCode": "0x1",
218 "EventName": "UNC_H_REQUESTS.READS", 218 "EventName": "UNC_H_REQUESTS.READS",
@@ -221,7 +221,7 @@
221 "Unit": "HA" 221 "Unit": "HA"
222 }, 222 },
223 { 223 {
224 "BriefDescription": "read requests to local home agent. Derived from unc_h_requests.reads_local", 224 "BriefDescription": "read requests to local home agent",
225 "Counter": "0,1,2,3", 225 "Counter": "0,1,2,3",
226 "EventCode": "0x1", 226 "EventCode": "0x1",
227 "EventName": "UNC_H_REQUESTS.READS_LOCAL", 227 "EventName": "UNC_H_REQUESTS.READS_LOCAL",
@@ -230,7 +230,7 @@
230 "Unit": "HA" 230 "Unit": "HA"
231 }, 231 },
232 { 232 {
233 "BriefDescription": "read requests to remote home agent. Derived from unc_h_requests.reads_remote", 233 "BriefDescription": "read requests to remote home agent",
234 "Counter": "0,1,2,3", 234 "Counter": "0,1,2,3",
235 "EventCode": "0x1", 235 "EventCode": "0x1",
236 "EventName": "UNC_H_REQUESTS.READS_REMOTE", 236 "EventName": "UNC_H_REQUESTS.READS_REMOTE",
@@ -239,7 +239,7 @@
239 "Unit": "HA" 239 "Unit": "HA"
240 }, 240 },
241 { 241 {
242 "BriefDescription": "write requests to home agent. Derived from unc_h_requests.writes", 242 "BriefDescription": "write requests to home agent",
243 "Counter": "0,1,2,3", 243 "Counter": "0,1,2,3",
244 "EventCode": "0x1", 244 "EventCode": "0x1",
245 "EventName": "UNC_H_REQUESTS.WRITES", 245 "EventName": "UNC_H_REQUESTS.WRITES",
@@ -248,7 +248,7 @@
248 "Unit": "HA" 248 "Unit": "HA"
249 }, 249 },
250 { 250 {
251 "BriefDescription": "write requests to local home agent. Derived from unc_h_requests.writes_local", 251 "BriefDescription": "write requests to local home agent",
252 "Counter": "0,1,2,3", 252 "Counter": "0,1,2,3",
253 "EventCode": "0x1", 253 "EventCode": "0x1",
254 "EventName": "UNC_H_REQUESTS.WRITES_LOCAL", 254 "EventName": "UNC_H_REQUESTS.WRITES_LOCAL",
@@ -257,7 +257,7 @@
257 "Unit": "HA" 257 "Unit": "HA"
258 }, 258 },
259 { 259 {
260 "BriefDescription": "write requests to remote home agent. Derived from unc_h_requests.writes_remote", 260 "BriefDescription": "write requests to remote home agent",
261 "Counter": "0,1,2,3", 261 "Counter": "0,1,2,3",
262 "EventCode": "0x1", 262 "EventCode": "0x1",
263 "EventName": "UNC_H_REQUESTS.WRITES_REMOTE", 263 "EventName": "UNC_H_REQUESTS.WRITES_REMOTE",
@@ -266,7 +266,7 @@
266 "Unit": "HA" 266 "Unit": "HA"
267 }, 267 },
268 { 268 {
269 "BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously). Derived from unc_h_snoop_resp.rspcnflct", 269 "BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously)",
270 "Counter": "0,1,2,3", 270 "Counter": "0,1,2,3",
271 "EventCode": "0x21", 271 "EventCode": "0x21",
272 "EventName": "UNC_H_SNOOP_RESP.RSPCNFLCT", 272 "EventName": "UNC_H_SNOOP_RESP.RSPCNFLCT",
@@ -275,7 +275,7 @@
275 "Unit": "HA" 275 "Unit": "HA"
276 }, 276 },
277 { 277 {
278 "BriefDescription": "M line forwarded from remote cache along with writeback to memory. Derived from unc_h_snoop_resp.rsp_fwd_wb", 278 "BriefDescription": "M line forwarded from remote cache along with writeback to memory",
279 "Counter": "0,1,2,3", 279 "Counter": "0,1,2,3",
280 "EventCode": "0x21", 280 "EventCode": "0x21",
281 "EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB", 281 "EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB",
@@ -285,7 +285,7 @@
285 "Unit": "HA" 285 "Unit": "HA"
286 }, 286 },
287 { 287 {
288 "BriefDescription": "M line forwarded from remote cache with no writeback to memory. Derived from unc_h_snoop_resp.rspifwd", 288 "BriefDescription": "M line forwarded from remote cache with no writeback to memory",
289 "Counter": "0,1,2,3", 289 "Counter": "0,1,2,3",
290 "EventCode": "0x21", 290 "EventCode": "0x21",
291 "EventName": "UNC_H_SNOOP_RESP.RSPIFWD", 291 "EventName": "UNC_H_SNOOP_RESP.RSPIFWD",
@@ -295,7 +295,7 @@
295 "Unit": "HA" 295 "Unit": "HA"
296 }, 296 },
297 { 297 {
298 "BriefDescription": "Shared line response from remote cache. Derived from unc_h_snoop_resp.rsps", 298 "BriefDescription": "Shared line response from remote cache",
299 "Counter": "0,1,2,3", 299 "Counter": "0,1,2,3",
300 "EventCode": "0x21", 300 "EventCode": "0x21",
301 "EventName": "UNC_H_SNOOP_RESP.RSPS", 301 "EventName": "UNC_H_SNOOP_RESP.RSPS",
@@ -305,7 +305,7 @@
305 "Unit": "HA" 305 "Unit": "HA"
306 }, 306 },
307 { 307 {
308 "BriefDescription": "Shared line forwarded from remote cache. Derived from unc_h_snoop_resp.rspsfwd", 308 "BriefDescription": "Shared line forwarded from remote cache",
309 "Counter": "0,1,2,3", 309 "Counter": "0,1,2,3",
310 "EventCode": "0x21", 310 "EventCode": "0x21",
311 "EventName": "UNC_H_SNOOP_RESP.RSPSFWD", 311 "EventName": "UNC_H_SNOOP_RESP.RSPSFWD",
diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-interconnect.json
index 39387f7909b2..824961318c1e 100644
--- a/tools/perf/pmu-events/arch/x86/broadwellx/uncore-interconnect.json
+++ b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-interconnect.json
@@ -1,6 +1,6 @@
1[ 1[
2 { 2 {
3 "BriefDescription": "QPI clock ticks. Derived from unc_q_clockticks", 3 "BriefDescription": "QPI clock ticks",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventCode": "0x14", 5 "EventCode": "0x14",
6 "EventName": "UNC_Q_CLOCKTICKS", 6 "EventName": "UNC_Q_CLOCKTICKS",
@@ -10,7 +10,7 @@
10 { 10 {
11 "BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data", 11 "BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data",
12 "Counter": "0,1,2,3", 12 "Counter": "0,1,2,3",
13 "EventName": "UNC_Q_TxL_FLITS_G0.DATA", 13 "EventName": "QPI_DATA_BANDWIDTH_TX",
14 "PerPkg": "1", 14 "PerPkg": "1",
15 "ScaleUnit": "8Bytes", 15 "ScaleUnit": "8Bytes",
16 "UMask": "0x2", 16 "UMask": "0x2",
@@ -19,7 +19,7 @@
19 { 19 {
20 "BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data", 20 "BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data",
21 "Counter": "0,1,2,3", 21 "Counter": "0,1,2,3",
22 "EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA", 22 "EventName": "QPI_CTL_BANDWIDTH_TX",
23 "PerPkg": "1", 23 "PerPkg": "1",
24 "ScaleUnit": "8Bytes", 24 "ScaleUnit": "8Bytes",
25 "UMask": "0x4", 25 "UMask": "0x4",
diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/uncore-memory.json b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-memory.json
index d17dc235f734..66eed399724c 100644
--- a/tools/perf/pmu-events/arch/x86/broadwellx/uncore-memory.json
+++ b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-memory.json
@@ -3,7 +3,7 @@
3 "BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd", 3 "BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventCode": "0x4", 5 "EventCode": "0x4",
6 "EventName": "UNC_M_CAS_COUNT.RD", 6 "EventName": "LLC_MISSES.MEM_READ",
7 "PerPkg": "1", 7 "PerPkg": "1",
8 "ScaleUnit": "64Bytes", 8 "ScaleUnit": "64Bytes",
9 "UMask": "0x3", 9 "UMask": "0x3",
@@ -13,48 +13,51 @@
13 "BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr", 13 "BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr",
14 "Counter": "0,1,2,3", 14 "Counter": "0,1,2,3",
15 "EventCode": "0x4", 15 "EventCode": "0x4",
16 "EventName": "UNC_M_CAS_COUNT.WR", 16 "EventName": "LLC_MISSES.MEM_WRITE",
17 "PerPkg": "1", 17 "PerPkg": "1",
18 "ScaleUnit": "64Bytes", 18 "ScaleUnit": "64Bytes",
19 "UMask": "0xC", 19 "UMask": "0xC",
20 "Unit": "iMC" 20 "Unit": "iMC"
21 }, 21 },
22 { 22 {
23 "BriefDescription": "Memory controller clock ticks. Derived from unc_m_clockticks", 23 "BriefDescription": "Memory controller clock ticks",
24 "Counter": "0,1,2,3", 24 "Counter": "0,1,2,3",
25 "EventName": "UNC_M_CLOCKTICKS", 25 "EventName": "UNC_M_CLOCKTICKS",
26 "PerPkg": "1", 26 "PerPkg": "1",
27 "Unit": "iMC" 27 "Unit": "iMC"
28 }, 28 },
29 { 29 {
30 "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd", 30 "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode",
31 "Counter": "0,1,2,3", 31 "Counter": "0,1,2,3",
32 "EventCode": "0x85", 32 "EventCode": "0x85",
33 "EventName": "UNC_M_POWER_CHANNEL_PPD", 33 "EventName": "UNC_M_POWER_CHANNEL_PPD",
34 "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.", 34 "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
35 "MetricName": "power_channel_ppd %",
35 "PerPkg": "1", 36 "PerPkg": "1",
36 "Unit": "iMC" 37 "Unit": "iMC"
37 }, 38 },
38 { 39 {
39 "BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles", 40 "BriefDescription": "Cycles all ranks are in critical thermal throttle",
40 "Counter": "0,1,2,3", 41 "Counter": "0,1,2,3",
41 "EventCode": "0x86", 42 "EventCode": "0x86",
42 "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES", 43 "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
43 "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.", 44 "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
45 "MetricName": "power_critical_throttle_cycles %",
44 "PerPkg": "1", 46 "PerPkg": "1",
45 "Unit": "iMC" 47 "Unit": "iMC"
46 }, 48 },
47 { 49 {
48 "BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh", 50 "BriefDescription": "Cycles Memory is in self refresh power mode",
49 "Counter": "0,1,2,3", 51 "Counter": "0,1,2,3",
50 "EventCode": "0x43", 52 "EventCode": "0x43",
51 "EventName": "UNC_M_POWER_SELF_REFRESH", 53 "EventName": "UNC_M_POWER_SELF_REFRESH",
52 "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.", 54 "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
55 "MetricName": "power_self_refresh %",
53 "PerPkg": "1", 56 "PerPkg": "1",
54 "Unit": "iMC" 57 "Unit": "iMC"
55 }, 58 },
56 { 59 {
57 "BriefDescription": "Pre-charges due to page misses. Derived from unc_m_pre_count.page_miss", 60 "BriefDescription": "Pre-charges due to page misses",
58 "Counter": "0,1,2,3", 61 "Counter": "0,1,2,3",
59 "EventCode": "0x2", 62 "EventCode": "0x2",
60 "EventName": "UNC_M_PRE_COUNT.PAGE_MISS", 63 "EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
@@ -63,7 +66,7 @@
63 "Unit": "iMC" 66 "Unit": "iMC"
64 }, 67 },
65 { 68 {
66 "BriefDescription": "Pre-charge for reads. Derived from unc_m_pre_count.rd", 69 "BriefDescription": "Pre-charge for reads",
67 "Counter": "0,1,2,3", 70 "Counter": "0,1,2,3",
68 "EventCode": "0x2", 71 "EventCode": "0x2",
69 "EventName": "UNC_M_PRE_COUNT.RD", 72 "EventName": "UNC_M_PRE_COUNT.RD",
@@ -72,7 +75,7 @@
72 "Unit": "iMC" 75 "Unit": "iMC"
73 }, 76 },
74 { 77 {
75 "BriefDescription": "Pre-charge for writes. Derived from unc_m_pre_count.wr", 78 "BriefDescription": "Pre-charge for writes",
76 "Counter": "0,1,2,3", 79 "Counter": "0,1,2,3",
77 "EventCode": "0x2", 80 "EventCode": "0x2",
78 "EventName": "UNC_M_PRE_COUNT.WR", 81 "EventName": "UNC_M_PRE_COUNT.WR",
diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/uncore-power.json b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-power.json
index b44d43088bbb..dd1b95655d1d 100644
--- a/tools/perf/pmu-events/arch/x86/broadwellx/uncore-power.json
+++ b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-power.json
@@ -1,83 +1,91 @@
1[ 1[
2 { 2 {
3 "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks", 3 "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventName": "UNC_P_CLOCKTICKS", 5 "EventName": "UNC_P_CLOCKTICKS",
6 "PerPkg": "1", 6 "PerPkg": "1",
7 "Unit": "PCU" 7 "Unit": "PCU"
8 }, 8 },
9 { 9 {
10 "BriefDescription": "C0 and C1. Derived from unc_p_power_state_occupancy.cores_c0", 10 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C0. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
11 "Counter": "0,1,2,3", 11 "Counter": "0,1,2,3",
12 "EventCode": "0x80", 12 "EventCode": "0x80",
13 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0", 13 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
14 "Filter": "occ_sel=1", 14 "Filter": "occ_sel=1",
15 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.", 15 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
16 "MetricName": "power_state_occupancy.cores_c0 %",
16 "PerPkg": "1", 17 "PerPkg": "1",
17 "Unit": "PCU" 18 "Unit": "PCU"
18 }, 19 },
19 { 20 {
20 "BriefDescription": "C3. Derived from unc_p_power_state_occupancy.cores_c3", 21 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C3. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
21 "Counter": "0,1,2,3", 22 "Counter": "0,1,2,3",
22 "EventCode": "0x80", 23 "EventCode": "0x80",
23 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3", 24 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
24 "Filter": "occ_sel=2", 25 "Filter": "occ_sel=2",
25 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.", 26 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
27 "MetricName": "power_state_occupancy.cores_c3 %",
26 "PerPkg": "1", 28 "PerPkg": "1",
27 "Unit": "PCU" 29 "Unit": "PCU"
28 }, 30 },
29 { 31 {
30 "BriefDescription": "C6 and C7. Derived from unc_p_power_state_occupancy.cores_c6", 32 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C6. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events ",
31 "Counter": "0,1,2,3", 33 "Counter": "0,1,2,3",
32 "EventCode": "0x80", 34 "EventCode": "0x80",
33 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6", 35 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
34 "Filter": "occ_sel=3", 36 "Filter": "occ_sel=3",
35 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.", 37 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
38 "MetricName": "power_state_occupancy.cores_c6 %",
36 "PerPkg": "1", 39 "PerPkg": "1",
37 "Unit": "PCU" 40 "Unit": "PCU"
38 }, 41 },
39 { 42 {
40 "BriefDescription": "External Prochot. Derived from unc_p_prochot_external_cycles", 43 "BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode. This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip",
41 "Counter": "0,1,2,3", 44 "Counter": "0,1,2,3",
42 "EventCode": "0xA", 45 "EventCode": "0xA",
43 "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES", 46 "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
44 "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.", 47 "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
48 "MetricName": "prochot_external_cycles %",
45 "PerPkg": "1", 49 "PerPkg": "1",
46 "Unit": "PCU" 50 "Unit": "PCU"
47 }, 51 },
48 { 52 {
49 "BriefDescription": "Thermal Strongest Upper Limit Cycles. Derived from unc_p_freq_max_limit_thermal_cycles", 53 "BriefDescription": "Counts the number of cycles when temperature is the upper limit on frequency",
50 "Counter": "0,1,2,3", 54 "Counter": "0,1,2,3",
51 "EventCode": "0x4", 55 "EventCode": "0x4",
52 "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES", 56 "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
53 "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.", 57 "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
58 "MetricName": "freq_max_limit_thermal_cycles %",
54 "PerPkg": "1", 59 "PerPkg": "1",
55 "Unit": "PCU" 60 "Unit": "PCU"
56 }, 61 },
57 { 62 {
58 "BriefDescription": "OS Strongest Upper Limit Cycles. Derived from unc_p_freq_max_os_cycles", 63 "BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency",
59 "Counter": "0,1,2,3", 64 "Counter": "0,1,2,3",
60 "EventCode": "0x6", 65 "EventCode": "0x6",
61 "EventName": "UNC_P_FREQ_MAX_OS_CYCLES", 66 "EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
62 "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.", 67 "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
68 "MetricName": "freq_max_os_cycles %",
63 "PerPkg": "1", 69 "PerPkg": "1",
64 "Unit": "PCU" 70 "Unit": "PCU"
65 }, 71 },
66 { 72 {
67 "BriefDescription": "Power Strongest Upper Limit Cycles. Derived from unc_p_freq_max_power_cycles", 73 "BriefDescription": "Counts the number of cycles when power is the upper limit on frequency",
68 "Counter": "0,1,2,3", 74 "Counter": "0,1,2,3",
69 "EventCode": "0x5", 75 "EventCode": "0x5",
70 "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES", 76 "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
71 "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.", 77 "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
78 "MetricName": "freq_max_power_cycles %",
72 "PerPkg": "1", 79 "PerPkg": "1",
73 "Unit": "PCU" 80 "Unit": "PCU"
74 }, 81 },
75 { 82 {
76 "BriefDescription": "Cycles spent changing Frequency. Derived from unc_p_freq_trans_cycles", 83 "BriefDescription": "Counts the number of cycles when current is the upper limit on frequency",
77 "Counter": "0,1,2,3", 84 "Counter": "0,1,2,3",
78 "EventCode": "0x74", 85 "EventCode": "0x74",
79 "EventName": "UNC_P_FREQ_TRANS_CYCLES", 86 "EventName": "UNC_P_FREQ_TRANS_CYCLES",
80 "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.", 87 "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
88 "MetricName": "freq_trans_cycles %",
81 "PerPkg": "1", 89 "PerPkg": "1",
82 "Unit": "PCU" 90 "Unit": "PCU"
83 } 91 }
diff --git a/tools/perf/pmu-events/arch/x86/haswell/uncore.json b/tools/perf/pmu-events/arch/x86/haswell/uncore.json
new file mode 100644
index 000000000000..3ef5c21fef56
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/haswell/uncore.json
@@ -0,0 +1,374 @@
1[
2 {
3 "Unit": "CBO",
4 "EventCode": "0x22",
5 "UMask": "0x21",
6 "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_EXTERNAL",
7 "BriefDescription": "An external snoop misses in some processor core.",
8 "PublicDescription": "An external snoop misses in some processor core.",
9 "Counter": "0,1",
10 "CounterMask": "0",
11 "Invert": "0",
12 "EdgeDetect": "0"
13 },
14 {
15 "Unit": "CBO",
16 "EventCode": "0x22",
17 "UMask": "0x41",
18 "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_XCORE",
19 "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which misses in some processor core.",
20 "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which misses in some processor core.",
21 "Counter": "0,1",
22 "CounterMask": "0",
23 "Invert": "0",
24 "EdgeDetect": "0"
25 },
26 {
27 "Unit": "CBO",
28 "EventCode": "0x22",
29 "UMask": "0x81",
30 "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_EVICTION",
31 "BriefDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.",
32 "PublicDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.",
33 "Counter": "0,1",
34 "CounterMask": "0",
35 "Invert": "0",
36 "EdgeDetect": "0"
37 },
38 {
39 "Unit": "CBO",
40 "EventCode": "0x22",
41 "UMask": "0x24",
42 "EventName": "UNC_CBO_XSNP_RESPONSE.HIT_EXTERNAL",
43 "BriefDescription": "An external snoop hits a non-modified line in some processor core.",
44 "PublicDescription": "An external snoop hits a non-modified line in some processor core.",
45 "Counter": "0,1",
46 "CounterMask": "0",
47 "Invert": "0",
48 "EdgeDetect": "0"
49 },
50 {
51 "Unit": "CBO",
52 "EventCode": "0x22",
53 "UMask": "0x44",
54 "EventName": "UNC_CBO_XSNP_RESPONSE.HIT_XCORE",
55 "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a non-modified line in some processor core.",
56 "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a non-modified line in some processor core.",
57 "Counter": "0,1",
58 "CounterMask": "0",
59 "Invert": "0",
60 "EdgeDetect": "0"
61 },
62 {
63 "Unit": "CBO",
64 "EventCode": "0x22",
65 "UMask": "0x84",
66 "EventName": "UNC_CBO_XSNP_RESPONSE.HIT_EVICTION",
67 "BriefDescription": "A cross-core snoop resulted from L3 Eviction which hits a non-modified line in some processor core.",
68 "PublicDescription": "A cross-core snoop resulted from L3 Eviction which hits a non-modified line in some processor core.",
69 "Counter": "0,1",
70 "CounterMask": "0",
71 "Invert": "0",
72 "EdgeDetect": "0"
73 },
74 {
75 "Unit": "CBO",
76 "EventCode": "0x22",
77 "UMask": "0x28",
78 "EventName": "UNC_CBO_XSNP_RESPONSE.HITM_EXTERNAL",
79 "BriefDescription": "An external snoop hits a modified line in some processor core.",
80 "PublicDescription": "An external snoop hits a modified line in some processor core.",
81 "Counter": "0,1",
82 "CounterMask": "0",
83 "Invert": "0",
84 "EdgeDetect": "0"
85 },
86 {
87 "Unit": "CBO",
88 "EventCode": "0x22",
89 "UMask": "0x48",
90 "EventName": "UNC_CBO_XSNP_RESPONSE.HITM_XCORE",
91 "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a modified line in some processor core.",
92 "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a modified line in some processor core.",
93 "Counter": "0,1",
94 "CounterMask": "0",
95 "Invert": "0",
96 "EdgeDetect": "0"
97 },
98 {
99 "Unit": "CBO",
100 "EventCode": "0x22",
101 "UMask": "0x88",
102 "EventName": "UNC_CBO_XSNP_RESPONSE.HITM_EVICTION",
103 "BriefDescription": "A cross-core snoop resulted from L3 Eviction which hits a modified line in some processor core.",
104 "PublicDescription": "A cross-core snoop resulted from L3 Eviction which hits a modified line in some processor core.",
105 "Counter": "0,1",
106 "CounterMask": "0",
107 "Invert": "0",
108 "EdgeDetect": "0"
109 },
110 {
111 "Unit": "CBO",
112 "EventCode": "0x34",
113 "UMask": "0x11",
114 "EventName": "UNC_CBO_CACHE_LOOKUP.READ_M",
115 "BriefDescription": "L3 Lookup read request that access cache and found line in M-state.",
116 "PublicDescription": "L3 Lookup read request that access cache and found line in M-state.",
117 "Counter": "0,1",
118 "CounterMask": "0",
119 "Invert": "0",
120 "EdgeDetect": "0"
121 },
122 {
123 "Unit": "CBO",
124 "EventCode": "0x34",
125 "UMask": "0x21",
126 "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_M",
127 "BriefDescription": "L3 Lookup write request that access cache and found line in M-state.",
128 "PublicDescription": "L3 Lookup write request that access cache and found line in M-state.",
129 "Counter": "0,1",
130 "CounterMask": "0",
131 "Invert": "0",
132 "EdgeDetect": "0"
133 },
134 {
135 "Unit": "CBO",
136 "EventCode": "0x34",
137 "UMask": "0x41",
138 "EventName": "UNC_CBO_CACHE_LOOKUP.EXTSNP_M",
139 "BriefDescription": "L3 Lookup external snoop request that access cache and found line in M-state.",
140 "PublicDescription": "L3 Lookup external snoop request that access cache and found line in M-state.",
141 "Counter": "0,1",
142 "CounterMask": "0",
143 "Invert": "0",
144 "EdgeDetect": "0"
145 },
146 {
147 "Unit": "CBO",
148 "EventCode": "0x34",
149 "UMask": "0x81",
150 "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_M",
151 "BriefDescription": "L3 Lookup any request that access cache and found line in M-state.",
152 "PublicDescription": "L3 Lookup any request that access cache and found line in M-state.",
153 "Counter": "0,1",
154 "CounterMask": "0",
155 "Invert": "0",
156 "EdgeDetect": "0"
157 },
158 {
159 "Unit": "CBO",
160 "EventCode": "0x34",
161 "UMask": "0x18",
162 "EventName": "UNC_CBO_CACHE_LOOKUP.READ_I",
163 "BriefDescription": "L3 Lookup read request that access cache and found line in I-state.",
164 "PublicDescription": "L3 Lookup read request that access cache and found line in I-state.",
165 "Counter": "0,1",
166 "CounterMask": "0",
167 "Invert": "0",
168 "EdgeDetect": "0"
169 },
170 {
171 "Unit": "CBO",
172 "EventCode": "0x34",
173 "UMask": "0x28",
174 "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_I",
175 "BriefDescription": "L3 Lookup write request that access cache and found line in I-state.",
176 "PublicDescription": "L3 Lookup write request that access cache and found line in I-state.",
177 "Counter": "0,1",
178 "CounterMask": "0",
179 "Invert": "0",
180 "EdgeDetect": "0"
181 },
182 {
183 "Unit": "CBO",
184 "EventCode": "0x34",
185 "UMask": "0x48",
186 "EventName": "UNC_CBO_CACHE_LOOKUP.EXTSNP_I",
187 "BriefDescription": "L3 Lookup external snoop request that access cache and found line in I-state.",
188 "PublicDescription": "L3 Lookup external snoop request that access cache and found line in I-state.",
189 "Counter": "0,1",
190 "CounterMask": "0",
191 "Invert": "0",
192 "EdgeDetect": "0"
193 },
194 {
195 "Unit": "CBO",
196 "EventCode": "0x34",
197 "UMask": "0x88",
198 "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_I",
199 "BriefDescription": "L3 Lookup any request that access cache and found line in I-state.",
200 "PublicDescription": "L3 Lookup any request that access cache and found line in I-state.",
201 "Counter": "0,1",
202 "CounterMask": "0",
203 "Invert": "0",
204 "EdgeDetect": "0"
205 },
206 {
207 "Unit": "CBO",
208 "EventCode": "0x34",
209 "UMask": "0x1f",
210 "EventName": "UNC_CBO_CACHE_LOOKUP.READ_MESI",
211 "BriefDescription": "L3 Lookup read request that access cache and found line in any MESI-state.",
212 "PublicDescription": "L3 Lookup read request that access cache and found line in any MESI-state.",
213 "Counter": "0,1",
214 "CounterMask": "0",
215 "Invert": "0",
216 "EdgeDetect": "0"
217 },
218 {
219 "Unit": "CBO",
220 "EventCode": "0x34",
221 "UMask": "0x2f",
222 "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_MESI",
223 "BriefDescription": "L3 Lookup write request that access cache and found line in MESI-state.",
224 "PublicDescription": "L3 Lookup write request that access cache and found line in MESI-state.",
225 "Counter": "0,1",
226 "CounterMask": "0",
227 "Invert": "0",
228 "EdgeDetect": "0"
229 },
230 {
231 "Unit": "CBO",
232 "EventCode": "0x34",
233 "UMask": "0x4f",
234 "EventName": "UNC_CBO_CACHE_LOOKUP.EXTSNP_MESI",
235 "BriefDescription": "L3 Lookup external snoop request that access cache and found line in MESI-state.",
236 "PublicDescription": "L3 Lookup external snoop request that access cache and found line in MESI-state.",
237 "Counter": "0,1",
238 "CounterMask": "0",
239 "Invert": "0",
240 "EdgeDetect": "0"
241 },
242 {
243 "Unit": "CBO",
244 "EventCode": "0x34",
245 "UMask": "0x8f",
246 "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_MESI",
247 "BriefDescription": "L3 Lookup any request that access cache and found line in MESI-state.",
248 "PublicDescription": "L3 Lookup any request that access cache and found line in MESI-state.",
249 "Counter": "0,1",
250 "CounterMask": "0",
251 "Invert": "0",
252 "EdgeDetect": "0"
253 },
254 {
255 "Unit": "CBO",
256 "EventCode": "0x34",
257 "UMask": "0x86",
258 "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_ES",
259 "BriefDescription": "L3 Lookup any request that access cache and found line in E or S-state.",
260 "PublicDescription": "L3 Lookup any request that access cache and found line in E or S-state.",
261 "Counter": "0,1",
262 "CounterMask": "0",
263 "Invert": "0",
264 "EdgeDetect": "0"
265 },
266 {
267 "Unit": "CBO",
268 "EventCode": "0x34",
269 "UMask": "0x46",
270 "EventName": "UNC_CBO_CACHE_LOOKUP.EXTSNP_ES",
271 "BriefDescription": "L3 Lookup external snoop request that access cache and found line in E or S-state.",
272 "PublicDescription": "L3 Lookup external snoop request that access cache and found line in E or S-state.",
273 "Counter": "0,1",
274 "CounterMask": "0",
275 "Invert": "0",
276 "EdgeDetect": "0"
277 },
278 {
279 "Unit": "CBO",
280 "EventCode": "0x34",
281 "UMask": "0x16",
282 "EventName": "UNC_CBO_CACHE_LOOKUP.READ_ES",
283 "BriefDescription": "L3 Lookup read request that access cache and found line in E or S-state.",
284 "PublicDescription": "L3 Lookup read request that access cache and found line in E or S-state.",
285 "Counter": "0,1",
286 "CounterMask": "0",
287 "Invert": "0",
288 "EdgeDetect": "0"
289 },
290 {
291 "Unit": "CBO",
292 "EventCode": "0x34",
293 "UMask": "0x26",
294 "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_ES",
295 "BriefDescription": "L3 Lookup write request that access cache and found line in E or S-state.",
296 "PublicDescription": "L3 Lookup write request that access cache and found line in E or S-state.",
297 "Counter": "0,1",
298 "CounterMask": "0",
299 "Invert": "0",
300 "EdgeDetect": "0"
301 },
302 {
303 "Unit": "iMPH-U",
304 "EventCode": "0x80",
305 "UMask": "0x01",
306 "EventName": "UNC_ARB_TRK_OCCUPANCY.ALL",
307 "BriefDescription": "Each cycle count number of all Core outgoing valid entries. Such entry is defined as valid from it's allocation till first of IDI0 or DRS0 messages is sent out. Accounts for Coherent and non-coherent traffic.",
308 "PublicDescription": "Each cycle count number of all Core outgoing valid entries. Such entry is defined as valid from it's allocation till first of IDI0 or DRS0 messages is sent out. Accounts for Coherent and non-coherent traffic.",
309 "Counter": "0",
310 "CounterMask": "0",
311 "Invert": "0",
312 "EdgeDetect": "0"
313 },
314 {
315 "Unit": "iMPH-U",
316 "EventCode": "0x81",
317 "UMask": "0x01",
318 "EventName": "UNC_ARB_TRK_REQUESTS.ALL",
319 "BriefDescription": "Total number of Core outgoing entries allocated. Accounts for Coherent and non-coherent traffic.",
320 "PublicDescription": "Total number of Core outgoing entries allocated. Accounts for Coherent and non-coherent traffic.",
321 "Counter": "0,1",
322 "CounterMask": "0",
323 "Invert": "0",
324 "EdgeDetect": "0"
325 },
326 {
327 "Unit": "iMPH-U",
328 "EventCode": "0x81",
329 "UMask": "0x20",
330 "EventName": "UNC_ARB_TRK_REQUESTS.WRITES",
331 "BriefDescription": "Number of Writes allocated - any write transactions: full/partials writes and evictions.",
332 "PublicDescription": "Number of Writes allocated - any write transactions: full/partials writes and evictions.",
333 "Counter": "0,1",
334 "CounterMask": "0",
335 "Invert": "0",
336 "EdgeDetect": "0"
337 },
338 {
339 "Unit": "iMPH-U",
340 "EventCode": "0x83",
341 "UMask": "0x01",
342 "EventName": "UNC_ARB_COH_TRK_OCCUPANCY.All",
343 "BriefDescription": "Each cycle count number of valid entries in Coherency Tracker queue from allocation till deallocation. Aperture requests (snoops) appear as NC decoded internally and become coherent (snoop L3, access memory)",
344 "PublicDescription": "Each cycle count number of valid entries in Coherency Tracker queue from allocation till deallocation. Aperture requests (snoops) appear as NC decoded internally and become coherent (snoop L3, access memory).",
345 "Counter": "0",
346 "CounterMask": "0",
347 "Invert": "0",
348 "EdgeDetect": "0"
349 },
350 {
351 "Unit": "iMPH-U",
352 "EventCode": "0x84",
353 "UMask": "0x01",
354 "EventName": "UNC_ARB_COH_TRK_REQUESTS.ALL",
355 "BriefDescription": "Number of entries allocated. Account for Any type: e.g. Snoop, Core aperture, etc.",
356 "PublicDescription": "Number of entries allocated. Account for Any type: e.g. Snoop, Core aperture, etc.",
357 "Counter": "0,1",
358 "CounterMask": "0",
359 "Invert": "0",
360 "EdgeDetect": "0"
361 },
362 {
363 "Unit": "NCU",
364 "EventCode": "0x0",
365 "UMask": "0x01",
366 "EventName": "UNC_CLOCK.SOCKET",
367 "BriefDescription": "This 48-bit fixed counter counts the UCLK cycles.",
368 "PublicDescription": "This 48-bit fixed counter counts the UCLK cycles.",
369 "Counter": "FIXED",
370 "CounterMask": "0",
371 "Invert": "0",
372 "EdgeDetect": "0"
373 }
374] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/haswellx/uncore-cache.json b/tools/perf/pmu-events/arch/x86/haswellx/uncore-cache.json
index 076459c51d4e..58ed6d33d1f4 100644
--- a/tools/perf/pmu-events/arch/x86/haswellx/uncore-cache.json
+++ b/tools/perf/pmu-events/arch/x86/haswellx/uncore-cache.json
@@ -1,13 +1,13 @@
1[ 1[
2 { 2 {
3 "BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks", 3 "BriefDescription": "Uncore cache clock ticks",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventName": "UNC_C_CLOCKTICKS", 5 "EventName": "UNC_C_CLOCKTICKS",
6 "PerPkg": "1", 6 "PerPkg": "1",
7 "Unit": "CBO" 7 "Unit": "CBO"
8 }, 8 },
9 { 9 {
10 "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any", 10 "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch)",
11 "Counter": "0,1,2,3", 11 "Counter": "0,1,2,3",
12 "EventCode": "0x34", 12 "EventCode": "0x34",
13 "EventName": "UNC_C_LLC_LOOKUP.ANY", 13 "EventName": "UNC_C_LLC_LOOKUP.ANY",
@@ -18,7 +18,7 @@
18 "Unit": "CBO" 18 "Unit": "CBO"
19 }, 19 },
20 { 20 {
21 "BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state", 21 "BriefDescription": "M line evictions from LLC (writebacks to memory)",
22 "Counter": "0,1,2,3", 22 "Counter": "0,1,2,3",
23 "EventCode": "0x37", 23 "EventCode": "0x37",
24 "EventName": "UNC_C_LLC_VICTIMS.M_STATE", 24 "EventName": "UNC_C_LLC_VICTIMS.M_STATE",
@@ -212,7 +212,7 @@
212 "Unit": "CBO" 212 "Unit": "CBO"
213 }, 213 },
214 { 214 {
215 "BriefDescription": "read requests to home agent. Derived from unc_h_requests.reads", 215 "BriefDescription": "read requests to home agent",
216 "Counter": "0,1,2,3", 216 "Counter": "0,1,2,3",
217 "EventCode": "0x1", 217 "EventCode": "0x1",
218 "EventName": "UNC_H_REQUESTS.READS", 218 "EventName": "UNC_H_REQUESTS.READS",
@@ -221,7 +221,7 @@
221 "Unit": "HA" 221 "Unit": "HA"
222 }, 222 },
223 { 223 {
224 "BriefDescription": "read requests to local home agent. Derived from unc_h_requests.reads_local", 224 "BriefDescription": "read requests to local home agent",
225 "Counter": "0,1,2,3", 225 "Counter": "0,1,2,3",
226 "EventCode": "0x1", 226 "EventCode": "0x1",
227 "EventName": "UNC_H_REQUESTS.READS_LOCAL", 227 "EventName": "UNC_H_REQUESTS.READS_LOCAL",
@@ -230,7 +230,7 @@
230 "Unit": "HA" 230 "Unit": "HA"
231 }, 231 },
232 { 232 {
233 "BriefDescription": "read requests to remote home agent. Derived from unc_h_requests.reads_remote", 233 "BriefDescription": "read requests to remote home agent",
234 "Counter": "0,1,2,3", 234 "Counter": "0,1,2,3",
235 "EventCode": "0x1", 235 "EventCode": "0x1",
236 "EventName": "UNC_H_REQUESTS.READS_REMOTE", 236 "EventName": "UNC_H_REQUESTS.READS_REMOTE",
@@ -239,7 +239,7 @@
239 "Unit": "HA" 239 "Unit": "HA"
240 }, 240 },
241 { 241 {
242 "BriefDescription": "write requests to home agent. Derived from unc_h_requests.writes", 242 "BriefDescription": "write requests to home agent",
243 "Counter": "0,1,2,3", 243 "Counter": "0,1,2,3",
244 "EventCode": "0x1", 244 "EventCode": "0x1",
245 "EventName": "UNC_H_REQUESTS.WRITES", 245 "EventName": "UNC_H_REQUESTS.WRITES",
@@ -248,7 +248,7 @@
248 "Unit": "HA" 248 "Unit": "HA"
249 }, 249 },
250 { 250 {
251 "BriefDescription": "write requests to local home agent. Derived from unc_h_requests.writes_local", 251 "BriefDescription": "write requests to local home agent",
252 "Counter": "0,1,2,3", 252 "Counter": "0,1,2,3",
253 "EventCode": "0x1", 253 "EventCode": "0x1",
254 "EventName": "UNC_H_REQUESTS.WRITES_LOCAL", 254 "EventName": "UNC_H_REQUESTS.WRITES_LOCAL",
@@ -257,7 +257,7 @@
257 "Unit": "HA" 257 "Unit": "HA"
258 }, 258 },
259 { 259 {
260 "BriefDescription": "write requests to remote home agent. Derived from unc_h_requests.writes_remote", 260 "BriefDescription": "write requests to remote home agent",
261 "Counter": "0,1,2,3", 261 "Counter": "0,1,2,3",
262 "EventCode": "0x1", 262 "EventCode": "0x1",
263 "EventName": "UNC_H_REQUESTS.WRITES_REMOTE", 263 "EventName": "UNC_H_REQUESTS.WRITES_REMOTE",
@@ -266,7 +266,7 @@
266 "Unit": "HA" 266 "Unit": "HA"
267 }, 267 },
268 { 268 {
269 "BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously). Derived from unc_h_snoop_resp.rspcnflct", 269 "BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously)",
270 "Counter": "0,1,2,3", 270 "Counter": "0,1,2,3",
271 "EventCode": "0x21", 271 "EventCode": "0x21",
272 "EventName": "UNC_H_SNOOP_RESP.RSPCNFLCT", 272 "EventName": "UNC_H_SNOOP_RESP.RSPCNFLCT",
@@ -275,7 +275,7 @@
275 "Unit": "HA" 275 "Unit": "HA"
276 }, 276 },
277 { 277 {
278 "BriefDescription": "M line forwarded from remote cache along with writeback to memory. Derived from unc_h_snoop_resp.rsp_fwd_wb", 278 "BriefDescription": "M line forwarded from remote cache along with writeback to memory",
279 "Counter": "0,1,2,3", 279 "Counter": "0,1,2,3",
280 "EventCode": "0x21", 280 "EventCode": "0x21",
281 "EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB", 281 "EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB",
@@ -285,7 +285,7 @@
285 "Unit": "HA" 285 "Unit": "HA"
286 }, 286 },
287 { 287 {
288 "BriefDescription": "M line forwarded from remote cache with no writeback to memory. Derived from unc_h_snoop_resp.rspifwd", 288 "BriefDescription": "M line forwarded from remote cache with no writeback to memory",
289 "Counter": "0,1,2,3", 289 "Counter": "0,1,2,3",
290 "EventCode": "0x21", 290 "EventCode": "0x21",
291 "EventName": "UNC_H_SNOOP_RESP.RSPIFWD", 291 "EventName": "UNC_H_SNOOP_RESP.RSPIFWD",
@@ -295,7 +295,7 @@
295 "Unit": "HA" 295 "Unit": "HA"
296 }, 296 },
297 { 297 {
298 "BriefDescription": "Shared line response from remote cache. Derived from unc_h_snoop_resp.rsps", 298 "BriefDescription": "Shared line response from remote cache",
299 "Counter": "0,1,2,3", 299 "Counter": "0,1,2,3",
300 "EventCode": "0x21", 300 "EventCode": "0x21",
301 "EventName": "UNC_H_SNOOP_RESP.RSPS", 301 "EventName": "UNC_H_SNOOP_RESP.RSPS",
@@ -305,7 +305,7 @@
305 "Unit": "HA" 305 "Unit": "HA"
306 }, 306 },
307 { 307 {
308 "BriefDescription": "Shared line forwarded from remote cache. Derived from unc_h_snoop_resp.rspsfwd", 308 "BriefDescription": "Shared line forwarded from remote cache",
309 "Counter": "0,1,2,3", 309 "Counter": "0,1,2,3",
310 "EventCode": "0x21", 310 "EventCode": "0x21",
311 "EventName": "UNC_H_SNOOP_RESP.RSPSFWD", 311 "EventName": "UNC_H_SNOOP_RESP.RSPSFWD",
diff --git a/tools/perf/pmu-events/arch/x86/haswellx/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/haswellx/uncore-interconnect.json
index 39387f7909b2..824961318c1e 100644
--- a/tools/perf/pmu-events/arch/x86/haswellx/uncore-interconnect.json
+++ b/tools/perf/pmu-events/arch/x86/haswellx/uncore-interconnect.json
@@ -1,6 +1,6 @@
1[ 1[
2 { 2 {
3 "BriefDescription": "QPI clock ticks. Derived from unc_q_clockticks", 3 "BriefDescription": "QPI clock ticks",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventCode": "0x14", 5 "EventCode": "0x14",
6 "EventName": "UNC_Q_CLOCKTICKS", 6 "EventName": "UNC_Q_CLOCKTICKS",
@@ -10,7 +10,7 @@
10 { 10 {
11 "BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data", 11 "BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data",
12 "Counter": "0,1,2,3", 12 "Counter": "0,1,2,3",
13 "EventName": "UNC_Q_TxL_FLITS_G0.DATA", 13 "EventName": "QPI_DATA_BANDWIDTH_TX",
14 "PerPkg": "1", 14 "PerPkg": "1",
15 "ScaleUnit": "8Bytes", 15 "ScaleUnit": "8Bytes",
16 "UMask": "0x2", 16 "UMask": "0x2",
@@ -19,7 +19,7 @@
19 { 19 {
20 "BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data", 20 "BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data",
21 "Counter": "0,1,2,3", 21 "Counter": "0,1,2,3",
22 "EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA", 22 "EventName": "QPI_CTL_BANDWIDTH_TX",
23 "PerPkg": "1", 23 "PerPkg": "1",
24 "ScaleUnit": "8Bytes", 24 "ScaleUnit": "8Bytes",
25 "UMask": "0x4", 25 "UMask": "0x4",
diff --git a/tools/perf/pmu-events/arch/x86/haswellx/uncore-memory.json b/tools/perf/pmu-events/arch/x86/haswellx/uncore-memory.json
index d17dc235f734..66eed399724c 100644
--- a/tools/perf/pmu-events/arch/x86/haswellx/uncore-memory.json
+++ b/tools/perf/pmu-events/arch/x86/haswellx/uncore-memory.json
@@ -3,7 +3,7 @@
3 "BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd", 3 "BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventCode": "0x4", 5 "EventCode": "0x4",
6 "EventName": "UNC_M_CAS_COUNT.RD", 6 "EventName": "LLC_MISSES.MEM_READ",
7 "PerPkg": "1", 7 "PerPkg": "1",
8 "ScaleUnit": "64Bytes", 8 "ScaleUnit": "64Bytes",
9 "UMask": "0x3", 9 "UMask": "0x3",
@@ -13,48 +13,51 @@
13 "BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr", 13 "BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr",
14 "Counter": "0,1,2,3", 14 "Counter": "0,1,2,3",
15 "EventCode": "0x4", 15 "EventCode": "0x4",
16 "EventName": "UNC_M_CAS_COUNT.WR", 16 "EventName": "LLC_MISSES.MEM_WRITE",
17 "PerPkg": "1", 17 "PerPkg": "1",
18 "ScaleUnit": "64Bytes", 18 "ScaleUnit": "64Bytes",
19 "UMask": "0xC", 19 "UMask": "0xC",
20 "Unit": "iMC" 20 "Unit": "iMC"
21 }, 21 },
22 { 22 {
23 "BriefDescription": "Memory controller clock ticks. Derived from unc_m_clockticks", 23 "BriefDescription": "Memory controller clock ticks",
24 "Counter": "0,1,2,3", 24 "Counter": "0,1,2,3",
25 "EventName": "UNC_M_CLOCKTICKS", 25 "EventName": "UNC_M_CLOCKTICKS",
26 "PerPkg": "1", 26 "PerPkg": "1",
27 "Unit": "iMC" 27 "Unit": "iMC"
28 }, 28 },
29 { 29 {
30 "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd", 30 "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode",
31 "Counter": "0,1,2,3", 31 "Counter": "0,1,2,3",
32 "EventCode": "0x85", 32 "EventCode": "0x85",
33 "EventName": "UNC_M_POWER_CHANNEL_PPD", 33 "EventName": "UNC_M_POWER_CHANNEL_PPD",
34 "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.", 34 "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
35 "MetricName": "power_channel_ppd %",
35 "PerPkg": "1", 36 "PerPkg": "1",
36 "Unit": "iMC" 37 "Unit": "iMC"
37 }, 38 },
38 { 39 {
39 "BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles", 40 "BriefDescription": "Cycles all ranks are in critical thermal throttle",
40 "Counter": "0,1,2,3", 41 "Counter": "0,1,2,3",
41 "EventCode": "0x86", 42 "EventCode": "0x86",
42 "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES", 43 "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
43 "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.", 44 "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
45 "MetricName": "power_critical_throttle_cycles %",
44 "PerPkg": "1", 46 "PerPkg": "1",
45 "Unit": "iMC" 47 "Unit": "iMC"
46 }, 48 },
47 { 49 {
48 "BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh", 50 "BriefDescription": "Cycles Memory is in self refresh power mode",
49 "Counter": "0,1,2,3", 51 "Counter": "0,1,2,3",
50 "EventCode": "0x43", 52 "EventCode": "0x43",
51 "EventName": "UNC_M_POWER_SELF_REFRESH", 53 "EventName": "UNC_M_POWER_SELF_REFRESH",
52 "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.", 54 "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
55 "MetricName": "power_self_refresh %",
53 "PerPkg": "1", 56 "PerPkg": "1",
54 "Unit": "iMC" 57 "Unit": "iMC"
55 }, 58 },
56 { 59 {
57 "BriefDescription": "Pre-charges due to page misses. Derived from unc_m_pre_count.page_miss", 60 "BriefDescription": "Pre-charges due to page misses",
58 "Counter": "0,1,2,3", 61 "Counter": "0,1,2,3",
59 "EventCode": "0x2", 62 "EventCode": "0x2",
60 "EventName": "UNC_M_PRE_COUNT.PAGE_MISS", 63 "EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
@@ -63,7 +66,7 @@
63 "Unit": "iMC" 66 "Unit": "iMC"
64 }, 67 },
65 { 68 {
66 "BriefDescription": "Pre-charge for reads. Derived from unc_m_pre_count.rd", 69 "BriefDescription": "Pre-charge for reads",
67 "Counter": "0,1,2,3", 70 "Counter": "0,1,2,3",
68 "EventCode": "0x2", 71 "EventCode": "0x2",
69 "EventName": "UNC_M_PRE_COUNT.RD", 72 "EventName": "UNC_M_PRE_COUNT.RD",
@@ -72,7 +75,7 @@
72 "Unit": "iMC" 75 "Unit": "iMC"
73 }, 76 },
74 { 77 {
75 "BriefDescription": "Pre-charge for writes. Derived from unc_m_pre_count.wr", 78 "BriefDescription": "Pre-charge for writes",
76 "Counter": "0,1,2,3", 79 "Counter": "0,1,2,3",
77 "EventCode": "0x2", 80 "EventCode": "0x2",
78 "EventName": "UNC_M_PRE_COUNT.WR", 81 "EventName": "UNC_M_PRE_COUNT.WR",
diff --git a/tools/perf/pmu-events/arch/x86/haswellx/uncore-power.json b/tools/perf/pmu-events/arch/x86/haswellx/uncore-power.json
index b44d43088bbb..dd1b95655d1d 100644
--- a/tools/perf/pmu-events/arch/x86/haswellx/uncore-power.json
+++ b/tools/perf/pmu-events/arch/x86/haswellx/uncore-power.json
@@ -1,83 +1,91 @@
1[ 1[
2 { 2 {
3 "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks", 3 "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventName": "UNC_P_CLOCKTICKS", 5 "EventName": "UNC_P_CLOCKTICKS",
6 "PerPkg": "1", 6 "PerPkg": "1",
7 "Unit": "PCU" 7 "Unit": "PCU"
8 }, 8 },
9 { 9 {
10 "BriefDescription": "C0 and C1. Derived from unc_p_power_state_occupancy.cores_c0", 10 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C0. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
11 "Counter": "0,1,2,3", 11 "Counter": "0,1,2,3",
12 "EventCode": "0x80", 12 "EventCode": "0x80",
13 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0", 13 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
14 "Filter": "occ_sel=1", 14 "Filter": "occ_sel=1",
15 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.", 15 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
16 "MetricName": "power_state_occupancy.cores_c0 %",
16 "PerPkg": "1", 17 "PerPkg": "1",
17 "Unit": "PCU" 18 "Unit": "PCU"
18 }, 19 },
19 { 20 {
20 "BriefDescription": "C3. Derived from unc_p_power_state_occupancy.cores_c3", 21 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C3. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
21 "Counter": "0,1,2,3", 22 "Counter": "0,1,2,3",
22 "EventCode": "0x80", 23 "EventCode": "0x80",
23 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3", 24 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
24 "Filter": "occ_sel=2", 25 "Filter": "occ_sel=2",
25 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.", 26 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
27 "MetricName": "power_state_occupancy.cores_c3 %",
26 "PerPkg": "1", 28 "PerPkg": "1",
27 "Unit": "PCU" 29 "Unit": "PCU"
28 }, 30 },
29 { 31 {
30 "BriefDescription": "C6 and C7. Derived from unc_p_power_state_occupancy.cores_c6", 32 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C6. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events ",
31 "Counter": "0,1,2,3", 33 "Counter": "0,1,2,3",
32 "EventCode": "0x80", 34 "EventCode": "0x80",
33 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6", 35 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
34 "Filter": "occ_sel=3", 36 "Filter": "occ_sel=3",
35 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.", 37 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
38 "MetricName": "power_state_occupancy.cores_c6 %",
36 "PerPkg": "1", 39 "PerPkg": "1",
37 "Unit": "PCU" 40 "Unit": "PCU"
38 }, 41 },
39 { 42 {
40 "BriefDescription": "External Prochot. Derived from unc_p_prochot_external_cycles", 43 "BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode. This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip",
41 "Counter": "0,1,2,3", 44 "Counter": "0,1,2,3",
42 "EventCode": "0xA", 45 "EventCode": "0xA",
43 "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES", 46 "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
44 "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.", 47 "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
48 "MetricName": "prochot_external_cycles %",
45 "PerPkg": "1", 49 "PerPkg": "1",
46 "Unit": "PCU" 50 "Unit": "PCU"
47 }, 51 },
48 { 52 {
49 "BriefDescription": "Thermal Strongest Upper Limit Cycles. Derived from unc_p_freq_max_limit_thermal_cycles", 53 "BriefDescription": "Counts the number of cycles when temperature is the upper limit on frequency",
50 "Counter": "0,1,2,3", 54 "Counter": "0,1,2,3",
51 "EventCode": "0x4", 55 "EventCode": "0x4",
52 "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES", 56 "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
53 "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.", 57 "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
58 "MetricName": "freq_max_limit_thermal_cycles %",
54 "PerPkg": "1", 59 "PerPkg": "1",
55 "Unit": "PCU" 60 "Unit": "PCU"
56 }, 61 },
57 { 62 {
58 "BriefDescription": "OS Strongest Upper Limit Cycles. Derived from unc_p_freq_max_os_cycles", 63 "BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency",
59 "Counter": "0,1,2,3", 64 "Counter": "0,1,2,3",
60 "EventCode": "0x6", 65 "EventCode": "0x6",
61 "EventName": "UNC_P_FREQ_MAX_OS_CYCLES", 66 "EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
62 "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.", 67 "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
68 "MetricName": "freq_max_os_cycles %",
63 "PerPkg": "1", 69 "PerPkg": "1",
64 "Unit": "PCU" 70 "Unit": "PCU"
65 }, 71 },
66 { 72 {
67 "BriefDescription": "Power Strongest Upper Limit Cycles. Derived from unc_p_freq_max_power_cycles", 73 "BriefDescription": "Counts the number of cycles when power is the upper limit on frequency",
68 "Counter": "0,1,2,3", 74 "Counter": "0,1,2,3",
69 "EventCode": "0x5", 75 "EventCode": "0x5",
70 "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES", 76 "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
71 "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.", 77 "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
78 "MetricName": "freq_max_power_cycles %",
72 "PerPkg": "1", 79 "PerPkg": "1",
73 "Unit": "PCU" 80 "Unit": "PCU"
74 }, 81 },
75 { 82 {
76 "BriefDescription": "Cycles spent changing Frequency. Derived from unc_p_freq_trans_cycles", 83 "BriefDescription": "Counts the number of cycles when current is the upper limit on frequency",
77 "Counter": "0,1,2,3", 84 "Counter": "0,1,2,3",
78 "EventCode": "0x74", 85 "EventCode": "0x74",
79 "EventName": "UNC_P_FREQ_TRANS_CYCLES", 86 "EventName": "UNC_P_FREQ_TRANS_CYCLES",
80 "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.", 87 "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
88 "MetricName": "freq_trans_cycles %",
81 "PerPkg": "1", 89 "PerPkg": "1",
82 "Unit": "PCU" 90 "Unit": "PCU"
83 } 91 }
diff --git a/tools/perf/pmu-events/arch/x86/ivybridge/uncore.json b/tools/perf/pmu-events/arch/x86/ivybridge/uncore.json
new file mode 100644
index 000000000000..42c70eed05a2
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/ivybridge/uncore.json
@@ -0,0 +1,314 @@
1[
2 {
3 "Unit": "CBO",
4 "EventCode": "0x22",
5 "UMask": "0x01",
6 "EventName": "UNC_CBO_XSNP_RESPONSE.MISS",
7 "BriefDescription": "A snoop misses in some processor core.",
8 "PublicDescription": "A snoop misses in some processor core.",
9 "Counter": "0,1",
10 "CounterMask": "0",
11 "Invert": "0",
12 "EdgeDetect": "0"
13 },
14 {
15 "Unit": "CBO",
16 "EventCode": "0x22",
17 "UMask": "0x02",
18 "EventName": "UNC_CBO_XSNP_RESPONSE.INVAL",
19 "BriefDescription": "A snoop invalidates a non-modified line in some processor core.",
20 "PublicDescription": "A snoop invalidates a non-modified line in some processor core.",
21 "Counter": "0,1",
22 "CounterMask": "0",
23 "Invert": "0",
24 "EdgeDetect": "0"
25 },
26 {
27 "Unit": "CBO",
28 "EventCode": "0x22",
29 "UMask": "0x04",
30 "EventName": "UNC_CBO_XSNP_RESPONSE.HIT",
31 "BriefDescription": "A snoop hits a non-modified line in some processor core.",
32 "PublicDescription": "A snoop hits a non-modified line in some processor core.",
33 "Counter": "0,1",
34 "CounterMask": "0",
35 "Invert": "0",
36 "EdgeDetect": "0"
37 },
38 {
39 "Unit": "CBO",
40 "EventCode": "0x22",
41 "UMask": "0x08",
42 "EventName": "UNC_CBO_XSNP_RESPONSE.HITM",
43 "BriefDescription": "A snoop hits a modified line in some processor core.",
44 "PublicDescription": "A snoop hits a modified line in some processor core.",
45 "Counter": "0,1",
46 "CounterMask": "0",
47 "Invert": "0",
48 "EdgeDetect": "0"
49 },
50 {
51 "Unit": "CBO",
52 "EventCode": "0x22",
53 "UMask": "0x10",
54 "EventName": "UNC_CBO_XSNP_RESPONSE.INVAL_M",
55 "BriefDescription": "A snoop invalidates a modified line in some processor core.",
56 "PublicDescription": "A snoop invalidates a modified line in some processor core.",
57 "Counter": "0,1",
58 "CounterMask": "0",
59 "Invert": "0",
60 "EdgeDetect": "0"
61 },
62 {
63 "Unit": "CBO",
64 "EventCode": "0x22",
65 "UMask": "0x20",
66 "EventName": "UNC_CBO_XSNP_RESPONSE.EXTERNAL_FILTER",
67 "BriefDescription": "Filter on cross-core snoops initiated by this Cbox due to external snoop request.",
68 "PublicDescription": "Filter on cross-core snoops initiated by this Cbox due to external snoop request.",
69 "Counter": "0,1",
70 "CounterMask": "0",
71 "Invert": "0",
72 "EdgeDetect": "0"
73 },
74 {
75 "Unit": "CBO",
76 "EventCode": "0x22",
77 "UMask": "0x40",
78 "EventName": "UNC_CBO_XSNP_RESPONSE.XCORE_FILTER",
79 "BriefDescription": "Filter on cross-core snoops initiated by this Cbox due to processor core memory request.",
80 "PublicDescription": "Filter on cross-core snoops initiated by this Cbox due to processor core memory request.",
81 "Counter": "0,1",
82 "CounterMask": "0",
83 "Invert": "0",
84 "EdgeDetect": "0"
85 },
86 {
87 "Unit": "CBO",
88 "EventCode": "0x22",
89 "UMask": "0x80",
90 "EventName": "UNC_CBO_XSNP_RESPONSE.EVICTION_FILTER",
91 "BriefDescription": "Filter on cross-core snoops initiated by this Cbox due to LLC eviction.",
92 "PublicDescription": "Filter on cross-core snoops initiated by this Cbox due to LLC eviction.",
93 "Counter": "0,1",
94 "CounterMask": "0",
95 "Invert": "0",
96 "EdgeDetect": "0"
97 },
98 {
99 "Unit": "CBO",
100 "EventCode": "0x34",
101 "UMask": "0x01",
102 "EventName": "UNC_CBO_CACHE_LOOKUP.M",
103 "BriefDescription": "LLC lookup request that access cache and found line in M-state.",
104 "PublicDescription": "LLC lookup request that access cache and found line in M-state.",
105 "Counter": "0,1",
106 "CounterMask": "0",
107 "Invert": "0",
108 "EdgeDetect": "0"
109 },
110 {
111 "Unit": "CBO",
112 "EventCode": "0x34",
113 "UMask": "0x02",
114 "EventName": "UNC_CBO_CACHE_LOOKUP.E",
115 "BriefDescription": "LLC lookup request that access cache and found line in E-state.",
116 "PublicDescription": "LLC lookup request that access cache and found line in E-state.",
117 "Counter": "0,1",
118 "CounterMask": "0",
119 "Invert": "0",
120 "EdgeDetect": "0"
121 },
122 {
123 "Unit": "CBO",
124 "EventCode": "0x34",
125 "UMask": "0x04",
126 "EventName": "UNC_CBO_CACHE_LOOKUP.S",
127 "BriefDescription": "LLC lookup request that access cache and found line in S-state.",
128 "PublicDescription": "LLC lookup request that access cache and found line in S-state.",
129 "Counter": "0,1",
130 "CounterMask": "0",
131 "Invert": "0",
132 "EdgeDetect": "0"
133 },
134 {
135 "Unit": "CBO",
136 "EventCode": "0x34",
137 "UMask": "0x08",
138 "EventName": "UNC_CBO_CACHE_LOOKUP.I",
139 "BriefDescription": "LLC lookup request that access cache and found line in I-state.",
140 "PublicDescription": "LLC lookup request that access cache and found line in I-state.",
141 "Counter": "0,1",
142 "CounterMask": "0",
143 "Invert": "0",
144 "EdgeDetect": "0"
145 },
146 {
147 "Unit": "CBO",
148 "EventCode": "0x34",
149 "UMask": "0x10",
150 "EventName": "UNC_CBO_CACHE_LOOKUP.READ_FILTER",
151 "BriefDescription": "Filter on processor core initiated cacheable read requests.",
152 "PublicDescription": "Filter on processor core initiated cacheable read requests.",
153 "Counter": "0,1",
154 "CounterMask": "0",
155 "Invert": "0",
156 "EdgeDetect": "0"
157 },
158 {
159 "Unit": "CBO",
160 "EventCode": "0x34",
161 "UMask": "0x20",
162 "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_FILTER",
163 "BriefDescription": "Filter on processor core initiated cacheable write requests.",
164 "PublicDescription": "Filter on processor core initiated cacheable write requests.",
165 "Counter": "0,1",
166 "CounterMask": "0",
167 "Invert": "0",
168 "EdgeDetect": "0"
169 },
170 {
171 "Unit": "CBO",
172 "EventCode": "0x34",
173 "UMask": "0x40",
174 "EventName": "UNC_CBO_CACHE_LOOKUP.EXTSNP_FILTER",
175 "BriefDescription": "Filter on external snoop requests.",
176 "PublicDescription": "Filter on external snoop requests.",
177 "Counter": "0,1",
178 "CounterMask": "0",
179 "Invert": "0",
180 "EdgeDetect": "0"
181 },
182 {
183 "Unit": "CBO",
184 "EventCode": "0x34",
185 "UMask": "0x80",
186 "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_REQUEST_FILTER",
187 "BriefDescription": "Filter on any IRQ or IPQ initiated requests including uncacheable, non-coherent requests.",
188 "PublicDescription": "Filter on any IRQ or IPQ initiated requests including uncacheable, non-coherent requests.",
189 "Counter": "0,1",
190 "CounterMask": "0",
191 "Invert": "0",
192 "EdgeDetect": "0"
193 },
194 {
195 "Unit": "ARB",
196 "EventCode": "0x80",
197 "UMask": "0x01",
198 "EventName": "UNC_ARB_TRK_OCCUPANCY.ALL",
199 "BriefDescription": "Counts cycles weighted by the number of requests waiting for data returning from the memory controller. Accounts for coherent and non-coherent requests initiated by IA cores, processor graphic units, or LLC.",
200 "PublicDescription": "Counts cycles weighted by the number of requests waiting for data returning from the memory controller. Accounts for coherent and non-coherent requests initiated by IA cores, processor graphic units, or LLC.",
201 "Counter": "0",
202 "CounterMask": "0",
203 "Invert": "0",
204 "EdgeDetect": "0"
205 },
206 {
207 "Unit": "ARB",
208 "EventCode": "0x81",
209 "UMask": "0x01",
210 "EventName": "UNC_ARB_TRK_REQUESTS.ALL",
211 "BriefDescription": "Counts the number of coherent and in-coherent requests initiated by IA cores, processor graphic units, or LLC.",
212 "PublicDescription": "Counts the number of coherent and in-coherent requests initiated by IA cores, processor graphic units, or LLC.",
213 "Counter": "0,1",
214 "CounterMask": "0",
215 "Invert": "0",
216 "EdgeDetect": "0"
217 },
218 {
219 "Unit": "ARB",
220 "EventCode": "0x81",
221 "UMask": "0x20",
222 "EventName": "UNC_ARB_TRK_REQUESTS.WRITES",
223 "BriefDescription": "Counts the number of allocated write entries, include full, partial, and LLC evictions.",
224 "PublicDescription": "Counts the number of allocated write entries, include full, partial, and LLC evictions.",
225 "Counter": "0,1",
226 "CounterMask": "0",
227 "Invert": "0",
228 "EdgeDetect": "0"
229 },
230 {
231 "Unit": "ARB",
232 "EventCode": "0x81",
233 "UMask": "0x80",
234 "EventName": "UNC_ARB_TRK_REQUESTS.EVICTIONS",
235 "BriefDescription": "Counts the number of LLC evictions allocated.",
236 "PublicDescription": "Counts the number of LLC evictions allocated.",
237 "Counter": "0,1",
238 "CounterMask": "0",
239 "Invert": "0",
240 "EdgeDetect": "0"
241 },
242 {
243 "Unit": "ARB",
244 "EventCode": "0x83",
245 "UMask": "0x01",
246 "EventName": "UNC_ARB_COH_TRK_OCCUPANCY.ALL",
247 "BriefDescription": "Cycles weighted by number of requests pending in Coherency Tracker.",
248 "PublicDescription": "Cycles weighted by number of requests pending in Coherency Tracker.",
249 "Counter": "0",
250 "CounterMask": "0",
251 "Invert": "0",
252 "EdgeDetect": "0"
253 },
254 {
255 "Unit": "ARB",
256 "EventCode": "0x84",
257 "UMask": "0x01",
258 "EventName": "UNC_ARB_COH_TRK_REQUESTS.ALL",
259 "BriefDescription": "Number of requests allocated in Coherency Tracker.",
260 "PublicDescription": "Number of requests allocated in Coherency Tracker.",
261 "Counter": "0,1",
262 "CounterMask": "0",
263 "Invert": "0",
264 "EdgeDetect": "0"
265 },
266 {
267 "Unit": "ARB",
268 "EventCode": "0x80",
269 "UMask": "0x01",
270 "EventName": "UNC_ARB_TRK_OCCUPANCY.CYCLES_WITH_ANY_REQUEST",
271 "BriefDescription": "Cycles with at least one request outstanding is waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
272 "PublicDescription": "Cycles with at least one request outstanding is waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
273 "Counter": "0,1",
274 "CounterMask": "1",
275 "Invert": "0",
276 "EdgeDetect": "0"
277 },
278 {
279 "Unit": "ARB",
280 "EventCode": "0x80",
281 "UMask": "0x01",
282 "EventName": "UNC_ARB_TRK_OCCUPANCY.CYCLES_OVER_HALF_FULL",
283 "BriefDescription": "Cycles with at least half of the requests outstanding are waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
284 "PublicDescription": "Cycles with at least half of the requests outstanding are waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
285 "Counter": "0,1",
286 "CounterMask": "10",
287 "Invert": "0",
288 "EdgeDetect": "0"
289 },
290 {
291 "Unit": "ARB",
292 "EventCode": "0x0",
293 "UMask": "0x01",
294 "EventName": "UNC_CLOCK.SOCKET",
295 "BriefDescription": "This 48-bit fixed counter counts the UCLK cycles.",
296 "PublicDescription": "This 48-bit fixed counter counts the UCLK cycles.",
297 "Counter": "Fixed",
298 "CounterMask": "0",
299 "Invert": "0",
300 "EdgeDetect": "0"
301 },
302 {
303 "Unit": "CBO",
304 "EventCode": "0x34",
305 "UMask": "0x06",
306 "EventName": "UNC_CBO_CACHE_LOOKUP.ES",
307 "BriefDescription": "LLC lookup request that access cache and found line in E-state or S-state.",
308 "PublicDescription": "LLC lookup request that access cache and found line in E-state or S-state.",
309 "Counter": "0,1",
310 "CounterMask": "0",
311 "Invert": "0",
312 "EdgeDetect": "0"
313 }
314] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/uncore-cache.json b/tools/perf/pmu-events/arch/x86/ivytown/uncore-cache.json
index 2efdc6772e0b..267410594833 100644
--- a/tools/perf/pmu-events/arch/x86/ivytown/uncore-cache.json
+++ b/tools/perf/pmu-events/arch/x86/ivytown/uncore-cache.json
@@ -1,13 +1,13 @@
1[ 1[
2 { 2 {
3 "BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks", 3 "BriefDescription": "Uncore cache clock ticks",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventName": "UNC_C_CLOCKTICKS", 5 "EventName": "UNC_C_CLOCKTICKS",
6 "PerPkg": "1", 6 "PerPkg": "1",
7 "Unit": "CBO" 7 "Unit": "CBO"
8 }, 8 },
9 { 9 {
10 "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any", 10 "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch)",
11 "Counter": "0,1", 11 "Counter": "0,1",
12 "EventCode": "0x34", 12 "EventCode": "0x34",
13 "EventName": "UNC_C_LLC_LOOKUP.ANY", 13 "EventName": "UNC_C_LLC_LOOKUP.ANY",
@@ -18,7 +18,7 @@
18 "Unit": "CBO" 18 "Unit": "CBO"
19 }, 19 },
20 { 20 {
21 "BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state", 21 "BriefDescription": "M line evictions from LLC (writebacks to memory)",
22 "Counter": "0,1", 22 "Counter": "0,1",
23 "EventCode": "0x37", 23 "EventCode": "0x37",
24 "EventName": "UNC_C_LLC_VICTIMS.M_STATE", 24 "EventName": "UNC_C_LLC_VICTIMS.M_STATE",
@@ -237,7 +237,7 @@
237 "Unit": "CBO" 237 "Unit": "CBO"
238 }, 238 },
239 { 239 {
240 "BriefDescription": "Occupancy for all LLC misses that are addressed to local memory. Derived from unc_c_tor_occupancy.miss_local", 240 "BriefDescription": "Occupancy for all LLC misses that are addressed to local memory",
241 "EventCode": "0x36", 241 "EventCode": "0x36",
242 "EventName": "UNC_C_TOR_OCCUPANCY.MISS_LOCAL", 242 "EventName": "UNC_C_TOR_OCCUPANCY.MISS_LOCAL",
243 "PerPkg": "1", 243 "PerPkg": "1",
@@ -254,7 +254,7 @@
254 "Unit": "CBO" 254 "Unit": "CBO"
255 }, 255 },
256 { 256 {
257 "BriefDescription": "Occupancy for all LLC misses that are addressed to remote memory. Derived from unc_c_tor_occupancy.miss_remote", 257 "BriefDescription": "Occupancy for all LLC misses that are addressed to remote memory",
258 "EventCode": "0x36", 258 "EventCode": "0x36",
259 "EventName": "UNC_C_TOR_OCCUPANCY.MISS_REMOTE", 259 "EventName": "UNC_C_TOR_OCCUPANCY.MISS_REMOTE",
260 "PerPkg": "1", 260 "PerPkg": "1",
@@ -262,7 +262,7 @@
262 "Unit": "CBO" 262 "Unit": "CBO"
263 }, 263 },
264 { 264 {
265 "BriefDescription": "Read requests to home agent. Derived from unc_h_requests.reads", 265 "BriefDescription": "Read requests to home agent",
266 "Counter": "0,1,2,3", 266 "Counter": "0,1,2,3",
267 "EventCode": "0x1", 267 "EventCode": "0x1",
268 "EventName": "UNC_H_REQUESTS.READS", 268 "EventName": "UNC_H_REQUESTS.READS",
@@ -271,7 +271,7 @@
271 "Unit": "HA" 271 "Unit": "HA"
272 }, 272 },
273 { 273 {
274 "BriefDescription": "Write requests to home agent. Derived from unc_h_requests.writes", 274 "BriefDescription": "Write requests to home agent",
275 "Counter": "0,1,2,3", 275 "Counter": "0,1,2,3",
276 "EventCode": "0x1", 276 "EventCode": "0x1",
277 "EventName": "UNC_H_REQUESTS.WRITES", 277 "EventName": "UNC_H_REQUESTS.WRITES",
@@ -280,7 +280,7 @@
280 "Unit": "HA" 280 "Unit": "HA"
281 }, 281 },
282 { 282 {
283 "BriefDescription": "M line forwarded from remote cache along with writeback to memory. Derived from unc_h_snoop_resp.rsp_fwd_wb", 283 "BriefDescription": "M line forwarded from remote cache along with writeback to memory",
284 "Counter": "0,1,2,3", 284 "Counter": "0,1,2,3",
285 "EventCode": "0x21", 285 "EventCode": "0x21",
286 "EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB", 286 "EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB",
@@ -290,7 +290,7 @@
290 "Unit": "HA" 290 "Unit": "HA"
291 }, 291 },
292 { 292 {
293 "BriefDescription": "M line forwarded from remote cache with no writeback to memory. Derived from unc_h_snoop_resp.rspifwd", 293 "BriefDescription": "M line forwarded from remote cache with no writeback to memory",
294 "Counter": "0,1,2,3", 294 "Counter": "0,1,2,3",
295 "EventCode": "0x21", 295 "EventCode": "0x21",
296 "EventName": "UNC_H_SNOOP_RESP.RSPIFWD", 296 "EventName": "UNC_H_SNOOP_RESP.RSPIFWD",
@@ -300,7 +300,7 @@
300 "Unit": "HA" 300 "Unit": "HA"
301 }, 301 },
302 { 302 {
303 "BriefDescription": "Shared line response from remote cache. Derived from unc_h_snoop_resp.rsps", 303 "BriefDescription": "Shared line response from remote cache",
304 "Counter": "0,1,2,3", 304 "Counter": "0,1,2,3",
305 "EventCode": "0x21", 305 "EventCode": "0x21",
306 "EventName": "UNC_H_SNOOP_RESP.RSPS", 306 "EventName": "UNC_H_SNOOP_RESP.RSPS",
@@ -310,7 +310,7 @@
310 "Unit": "HA" 310 "Unit": "HA"
311 }, 311 },
312 { 312 {
313 "BriefDescription": "Shared line forwarded from remote cache. Derived from unc_h_snoop_resp.rspsfwd", 313 "BriefDescription": "Shared line forwarded from remote cache",
314 "Counter": "0,1,2,3", 314 "Counter": "0,1,2,3",
315 "EventCode": "0x21", 315 "EventCode": "0x21",
316 "EventName": "UNC_H_SNOOP_RESP.RSPSFWD", 316 "EventName": "UNC_H_SNOOP_RESP.RSPSFWD",
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/ivytown/uncore-interconnect.json
index d7e2fda1d695..b798a860bc81 100644
--- a/tools/perf/pmu-events/arch/x86/ivytown/uncore-interconnect.json
+++ b/tools/perf/pmu-events/arch/x86/ivytown/uncore-interconnect.json
@@ -1,6 +1,6 @@
1[ 1[
2 { 2 {
3 "BriefDescription": "QPI clock ticks. Use to get percentages for QPI cycles events. Derived from unc_q_clockticks", 3 "BriefDescription": "QPI clock ticks. Use to get percentages for QPI cycles events",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventCode": "0x14", 5 "EventCode": "0x14",
6 "EventName": "UNC_Q_CLOCKTICKS", 6 "EventName": "UNC_Q_CLOCKTICKS",
@@ -8,25 +8,27 @@
8 "Unit": "QPI LL" 8 "Unit": "QPI LL"
9 }, 9 },
10 { 10 {
11 "BriefDescription": "Cycles where receiving QPI link is in half-width mode. Derived from unc_q_rxl0p_power_cycles", 11 "BriefDescription": "Cycles where receiving QPI link is in half-width mode",
12 "Counter": "0,1,2,3", 12 "Counter": "0,1,2,3",
13 "EventCode": "0x10", 13 "EventCode": "0x10",
14 "EventName": "UNC_Q_RxL0P_POWER_CYCLES", 14 "EventName": "UNC_Q_RxL0P_POWER_CYCLES",
15 "MetricExpr": "(UNC_Q_RxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.", 15 "MetricExpr": "(UNC_Q_RxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.",
16 "MetricName": "rxl0p_power_cycles %",
16 "PerPkg": "1", 17 "PerPkg": "1",
17 "Unit": "QPI LL" 18 "Unit": "QPI LL"
18 }, 19 },
19 { 20 {
20 "BriefDescription": "Cycles where transmitting QPI link is in half-width mode. Derived from unc_q_txl0p_power_cycles", 21 "BriefDescription": "Cycles where transmitting QPI link is in half-width mode",
21 "Counter": "0,1,2,3", 22 "Counter": "0,1,2,3",
22 "EventCode": "0xd", 23 "EventCode": "0xd",
23 "EventName": "UNC_Q_TxL0P_POWER_CYCLES", 24 "EventName": "UNC_Q_TxL0P_POWER_CYCLES",
24 "MetricExpr": "(UNC_Q_TxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.", 25 "MetricExpr": "(UNC_Q_TxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.",
26 "MetricName": "txl0p_power_cycles %",
25 "PerPkg": "1", 27 "PerPkg": "1",
26 "Unit": "QPI LL" 28 "Unit": "QPI LL"
27 }, 29 },
28 { 30 {
29 "BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data", 31 "BriefDescription": "Number of data flits transmitted ",
30 "Counter": "0,1,2,3", 32 "Counter": "0,1,2,3",
31 "EventName": "UNC_Q_TxL_FLITS_G0.DATA", 33 "EventName": "UNC_Q_TxL_FLITS_G0.DATA",
32 "PerPkg": "1", 34 "PerPkg": "1",
@@ -35,7 +37,7 @@
35 "Unit": "QPI LL" 37 "Unit": "QPI LL"
36 }, 38 },
37 { 39 {
38 "BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data", 40 "BriefDescription": "Number of non data (control) flits transmitted ",
39 "Counter": "0,1,2,3", 41 "Counter": "0,1,2,3",
40 "EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA", 42 "EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA",
41 "PerPkg": "1", 43 "PerPkg": "1",
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/uncore-memory.json b/tools/perf/pmu-events/arch/x86/ivytown/uncore-memory.json
index ac4ad4d6357b..df4b43294fa0 100644
--- a/tools/perf/pmu-events/arch/x86/ivytown/uncore-memory.json
+++ b/tools/perf/pmu-events/arch/x86/ivytown/uncore-memory.json
@@ -1,6 +1,6 @@
1[ 1[
2 { 2 {
3 "BriefDescription": "Memory page activates for reads and writes. Derived from unc_m_act_count.rd", 3 "BriefDescription": "Memory page activates for reads and writes",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventCode": "0x1", 5 "EventCode": "0x1",
6 "EventName": "UNC_M_ACT_COUNT.RD", 6 "EventName": "UNC_M_ACT_COUNT.RD",
@@ -13,7 +13,7 @@
13 "BriefDescription": "Read requests to memory controller. Derived from unc_m_cas_count.rd", 13 "BriefDescription": "Read requests to memory controller. Derived from unc_m_cas_count.rd",
14 "Counter": "0,1,2,3", 14 "Counter": "0,1,2,3",
15 "EventCode": "0x4", 15 "EventCode": "0x4",
16 "EventName": "UNC_M_CAS_COUNT.RD", 16 "EventName": "LLC_MISSES.MEM_READ",
17 "PerPkg": "1", 17 "PerPkg": "1",
18 "ScaleUnit": "64Bytes", 18 "ScaleUnit": "64Bytes",
19 "UMask": "0x3", 19 "UMask": "0x3",
@@ -23,48 +23,51 @@
23 "BriefDescription": "Write requests to memory controller. Derived from unc_m_cas_count.wr", 23 "BriefDescription": "Write requests to memory controller. Derived from unc_m_cas_count.wr",
24 "Counter": "0,1,2,3", 24 "Counter": "0,1,2,3",
25 "EventCode": "0x4", 25 "EventCode": "0x4",
26 "EventName": "UNC_M_CAS_COUNT.WR", 26 "EventName": "LLC_MISSES.MEM_WRITE",
27 "PerPkg": "1", 27 "PerPkg": "1",
28 "ScaleUnit": "64Bytes", 28 "ScaleUnit": "64Bytes",
29 "UMask": "0xC", 29 "UMask": "0xC",
30 "Unit": "iMC" 30 "Unit": "iMC"
31 }, 31 },
32 { 32 {
33 "BriefDescription": "Memory controller clock ticks. Use to generate percentages for memory controller CYCLES events. Derived from unc_m_clockticks", 33 "BriefDescription": "Memory controller clock ticks. Use to generate percentages for memory controller CYCLES events",
34 "Counter": "0,1,2,3", 34 "Counter": "0,1,2,3",
35 "EventName": "UNC_M_CLOCKTICKS", 35 "EventName": "UNC_M_CLOCKTICKS",
36 "PerPkg": "1", 36 "PerPkg": "1",
37 "Unit": "iMC" 37 "Unit": "iMC"
38 }, 38 },
39 { 39 {
40 "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd", 40 "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode",
41 "Counter": "0,1,2,3", 41 "Counter": "0,1,2,3",
42 "EventCode": "0x85", 42 "EventCode": "0x85",
43 "EventName": "UNC_M_POWER_CHANNEL_PPD", 43 "EventName": "UNC_M_POWER_CHANNEL_PPD",
44 "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.", 44 "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
45 "MetricName": "power_channel_ppd %",
45 "PerPkg": "1", 46 "PerPkg": "1",
46 "Unit": "iMC" 47 "Unit": "iMC"
47 }, 48 },
48 { 49 {
49 "BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles", 50 "BriefDescription": "Cycles all ranks are in critical thermal throttle",
50 "Counter": "0,1,2,3", 51 "Counter": "0,1,2,3",
51 "EventCode": "0x86", 52 "EventCode": "0x86",
52 "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES", 53 "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
53 "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.", 54 "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
55 "MetricName": "power_critical_throttle_cycles %",
54 "PerPkg": "1", 56 "PerPkg": "1",
55 "Unit": "iMC" 57 "Unit": "iMC"
56 }, 58 },
57 { 59 {
58 "BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh", 60 "BriefDescription": "Cycles Memory is in self refresh power mode",
59 "Counter": "0,1,2,3", 61 "Counter": "0,1,2,3",
60 "EventCode": "0x43", 62 "EventCode": "0x43",
61 "EventName": "UNC_M_POWER_SELF_REFRESH", 63 "EventName": "UNC_M_POWER_SELF_REFRESH",
62 "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.", 64 "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
65 "MetricName": "power_self_refresh %",
63 "PerPkg": "1", 66 "PerPkg": "1",
64 "Unit": "iMC" 67 "Unit": "iMC"
65 }, 68 },
66 { 69 {
67 "BriefDescription": "Memory page conflicts. Derived from unc_m_pre_count.page_miss", 70 "BriefDescription": "Memory page conflicts",
68 "Counter": "0,1,2,3", 71 "Counter": "0,1,2,3",
69 "EventCode": "0x2", 72 "EventCode": "0x2",
70 "EventName": "UNC_M_PRE_COUNT.PAGE_MISS", 73 "EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json b/tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json
index dc2586db0dfc..d40498f2cb1e 100644
--- a/tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json
+++ b/tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json
@@ -1,44 +1,48 @@
1[ 1[
2 { 2 {
3 "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks", 3 "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventName": "UNC_P_CLOCKTICKS", 5 "EventName": "UNC_P_CLOCKTICKS",
6 "PerPkg": "1", 6 "PerPkg": "1",
7 "Unit": "PCU" 7 "Unit": "PCU"
8 }, 8 },
9 { 9 {
10 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band0=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band0_cycles", 10 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band0=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency",
11 "Counter": "0,1,2,3", 11 "Counter": "0,1,2,3",
12 "EventCode": "0xb", 12 "EventCode": "0xb",
13 "EventName": "UNC_P_FREQ_BAND0_CYCLES", 13 "EventName": "UNC_P_FREQ_BAND0_CYCLES",
14 "MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.", 14 "MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.",
15 "MetricName": "freq_band0_cycles %",
15 "PerPkg": "1", 16 "PerPkg": "1",
16 "Unit": "PCU" 17 "Unit": "PCU"
17 }, 18 },
18 { 19 {
19 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band1=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band1_cycles", 20 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band1=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency",
20 "Counter": "0,1,2,3", 21 "Counter": "0,1,2,3",
21 "EventCode": "0xc", 22 "EventCode": "0xc",
22 "EventName": "UNC_P_FREQ_BAND1_CYCLES", 23 "EventName": "UNC_P_FREQ_BAND1_CYCLES",
23 "MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.", 24 "MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.",
25 "MetricName": "freq_band1_cycles %",
24 "PerPkg": "1", 26 "PerPkg": "1",
25 "Unit": "PCU" 27 "Unit": "PCU"
26 }, 28 },
27 { 29 {
28 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band2=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band2_cycles", 30 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band2=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency",
29 "Counter": "0,1,2,3", 31 "Counter": "0,1,2,3",
30 "EventCode": "0xd", 32 "EventCode": "0xd",
31 "EventName": "UNC_P_FREQ_BAND2_CYCLES", 33 "EventName": "UNC_P_FREQ_BAND2_CYCLES",
32 "MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.", 34 "MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.",
35 "MetricName": "freq_band2_cycles %",
33 "PerPkg": "1", 36 "PerPkg": "1",
34 "Unit": "PCU" 37 "Unit": "PCU"
35 }, 38 },
36 { 39 {
37 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band3=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band3_cycles", 40 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band3=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency",
38 "Counter": "0,1,2,3", 41 "Counter": "0,1,2,3",
39 "EventCode": "0xe", 42 "EventCode": "0xe",
40 "EventName": "UNC_P_FREQ_BAND3_CYCLES", 43 "EventName": "UNC_P_FREQ_BAND3_CYCLES",
41 "MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.", 44 "MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.",
45 "MetricName": "freq_band3_cycles %",
42 "PerPkg": "1", 46 "PerPkg": "1",
43 "Unit": "PCU" 47 "Unit": "PCU"
44 }, 48 },
@@ -49,6 +53,7 @@
49 "EventName": "UNC_P_FREQ_BAND0_TRANSITIONS", 53 "EventName": "UNC_P_FREQ_BAND0_TRANSITIONS",
50 "Filter": "edge=1", 54 "Filter": "edge=1",
51 "MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.", 55 "MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.",
56 "MetricName": "freq_band0_cycles %",
52 "PerPkg": "1", 57 "PerPkg": "1",
53 "Unit": "PCU" 58 "Unit": "PCU"
54 }, 59 },
@@ -59,6 +64,7 @@
59 "EventName": "UNC_P_FREQ_BAND1_TRANSITIONS", 64 "EventName": "UNC_P_FREQ_BAND1_TRANSITIONS",
60 "Filter": "edge=1", 65 "Filter": "edge=1",
61 "MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.", 66 "MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.",
67 "MetricName": "freq_band1_cycles %",
62 "PerPkg": "1", 68 "PerPkg": "1",
63 "Unit": "PCU" 69 "Unit": "PCU"
64 }, 70 },
@@ -69,6 +75,7 @@
69 "EventName": "UNC_P_FREQ_BAND2_TRANSITIONS", 75 "EventName": "UNC_P_FREQ_BAND2_TRANSITIONS",
70 "Filter": "edge=1", 76 "Filter": "edge=1",
71 "MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.", 77 "MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.",
78 "MetricName": "freq_band2_cycles %",
72 "PerPkg": "1", 79 "PerPkg": "1",
73 "Unit": "PCU" 80 "Unit": "PCU"
74 }, 81 },
@@ -79,90 +86,100 @@
79 "EventName": "UNC_P_FREQ_BAND3_TRANSITIONS", 86 "EventName": "UNC_P_FREQ_BAND3_TRANSITIONS",
80 "Filter": "edge=1", 87 "Filter": "edge=1",
81 "MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.", 88 "MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.",
89 "MetricName": "freq_band3_cycles %",
82 "PerPkg": "1", 90 "PerPkg": "1",
83 "Unit": "PCU" 91 "Unit": "PCU"
84 }, 92 },
85 { 93 {
86 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in the chosen C-State. It can be used by itself to get the average number of cores in that C-state with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c0", 94 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C0. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
87 "Counter": "0,1,2,3", 95 "Counter": "0,1,2,3",
88 "EventCode": "0x80", 96 "EventCode": "0x80",
89 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0", 97 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
90 "Filter": "occ_sel=1", 98 "Filter": "occ_sel=1",
91 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.", 99 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
100 "MetricName": "power_state_occupancy.cores_c0 %",
92 "PerPkg": "1", 101 "PerPkg": "1",
93 "Unit": "PCU" 102 "Unit": "PCU"
94 }, 103 },
95 { 104 {
96 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in the chosen C-State. It can be used by itself to get the average number of cores in that C-state with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c3", 105 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C3. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
97 "Counter": "0,1,2,3", 106 "Counter": "0,1,2,3",
98 "EventCode": "0x80", 107 "EventCode": "0x80",
99 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3", 108 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
100 "Filter": "occ_sel=2", 109 "Filter": "occ_sel=2",
101 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.", 110 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
111 "MetricName": "power_state_occupancy.cores_c3 %",
102 "PerPkg": "1", 112 "PerPkg": "1",
103 "Unit": "PCU" 113 "Unit": "PCU"
104 }, 114 },
105 { 115 {
106 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in the chosen C-State. It can be used by itself to get the average number of cores in that C-state with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c6", 116 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C6. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events ",
107 "Counter": "0,1,2,3", 117 "Counter": "0,1,2,3",
108 "EventCode": "0x80", 118 "EventCode": "0x80",
109 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6", 119 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
110 "Filter": "occ_sel=3", 120 "Filter": "occ_sel=3",
111 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.", 121 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
122 "MetricName": "power_state_occupancy.cores_c6 %",
112 "PerPkg": "1", 123 "PerPkg": "1",
113 "Unit": "PCU" 124 "Unit": "PCU"
114 }, 125 },
115 { 126 {
116 "BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode. This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip. Derived from unc_p_prochot_external_cycles", 127 "BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode. This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip",
117 "Counter": "0,1,2,3", 128 "Counter": "0,1,2,3",
118 "EventCode": "0xa", 129 "EventCode": "0xa",
119 "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES", 130 "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
120 "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.", 131 "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
132 "MetricName": "prochot_external_cycles %",
121 "PerPkg": "1", 133 "PerPkg": "1",
122 "Unit": "PCU" 134 "Unit": "PCU"
123 }, 135 },
124 { 136 {
125 "BriefDescription": "Counts the number of cycles when thermal conditions are the upper limit on frequency. This is related to the THERMAL_THROTTLE CYCLES_ABOVE_TEMP event, which always counts cycles when we are above the thermal temperature. This event (STRONGEST_UPPER_LIMIT) is sampled at the output of the algorithm that determines the actual frequency, while THERMAL_THROTTLE looks at the input. Derived from unc_p_freq_max_limit_thermal_cycles", 137 "BriefDescription": "Counts the number of cycles when temperature is the upper limit on frequency",
126 "Counter": "0,1,2,3", 138 "Counter": "0,1,2,3",
127 "EventCode": "0x4", 139 "EventCode": "0x4",
128 "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES", 140 "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
129 "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.", 141 "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
142 "MetricName": "freq_max_limit_thermal_cycles %",
130 "PerPkg": "1", 143 "PerPkg": "1",
131 "Unit": "PCU" 144 "Unit": "PCU"
132 }, 145 },
133 { 146 {
134 "BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency. Derived from unc_p_freq_max_os_cycles", 147 "BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency",
135 "Counter": "0,1,2,3", 148 "Counter": "0,1,2,3",
136 "EventCode": "0x6", 149 "EventCode": "0x6",
137 "EventName": "UNC_P_FREQ_MAX_OS_CYCLES", 150 "EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
138 "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.", 151 "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
152 "MetricName": "freq_max_os_cycles %",
139 "PerPkg": "1", 153 "PerPkg": "1",
140 "Unit": "PCU" 154 "Unit": "PCU"
141 }, 155 },
142 { 156 {
143 "BriefDescription": "Counts the number of cycles when power is the upper limit on frequency. Derived from unc_p_freq_max_power_cycles", 157 "BriefDescription": "Counts the number of cycles when power is the upper limit on frequency",
144 "Counter": "0,1,2,3", 158 "Counter": "0,1,2,3",
145 "EventCode": "0x5", 159 "EventCode": "0x5",
146 "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES", 160 "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
147 "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.", 161 "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
162 "MetricName": "freq_max_power_cycles %",
148 "PerPkg": "1", 163 "PerPkg": "1",
149 "Unit": "PCU" 164 "Unit": "PCU"
150 }, 165 },
151 { 166 {
152 "BriefDescription": "Counts the number of cycles when current is the upper limit on frequency. Derived from unc_p_freq_max_current_cycles", 167 "BriefDescription": "Counts the number of cycles when current is the upper limit on frequency",
153 "Counter": "0,1,2,3", 168 "Counter": "0,1,2,3",
154 "EventCode": "0x7", 169 "EventCode": "0x7",
155 "EventName": "UNC_P_FREQ_MAX_CURRENT_CYCLES", 170 "EventName": "UNC_P_FREQ_MAX_CURRENT_CYCLES",
156 "MetricExpr": "(UNC_P_FREQ_MAX_CURRENT_CYCLES / UNC_P_CLOCKTICKS) * 100.", 171 "MetricExpr": "(UNC_P_FREQ_MAX_CURRENT_CYCLES / UNC_P_CLOCKTICKS) * 100.",
172 "MetricName": "freq_max_current_cycles %",
157 "PerPkg": "1", 173 "PerPkg": "1",
158 "Unit": "PCU" 174 "Unit": "PCU"
159 }, 175 },
160 { 176 {
161 "BriefDescription": "Counts the number of cycles when the system is changing frequency. This can not be filtered by thread ID. One can also use it with the occupancy counter that monitors number of threads in C0 to estimate the performance impact that frequency transitions had on the system. Derived from unc_p_freq_trans_cycles", 177 "BriefDescription": "Cycles spent changing Frequency",
162 "Counter": "0,1,2,3", 178 "Counter": "0,1,2,3",
163 "EventCode": "0x60", 179 "EventCode": "0x60",
164 "EventName": "UNC_P_FREQ_TRANS_CYCLES", 180 "EventName": "UNC_P_FREQ_TRANS_CYCLES",
165 "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.", 181 "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
182 "MetricName": "freq_trans_cycles %",
166 "PerPkg": "1", 183 "PerPkg": "1",
167 "Unit": "PCU" 184 "Unit": "PCU"
168 }, 185 },
@@ -173,6 +190,7 @@
173 "EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES", 190 "EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES",
174 "Filter": "filter_band0=1200", 191 "Filter": "filter_band0=1200",
175 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 192 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
193 "MetricName": "freq_ge_1200mhz_cycles %",
176 "PerPkg": "1", 194 "PerPkg": "1",
177 "Unit": "PCU" 195 "Unit": "PCU"
178 }, 196 },
@@ -183,6 +201,7 @@
183 "EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES", 201 "EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES",
184 "Filter": "filter_band1=2000", 202 "Filter": "filter_band1=2000",
185 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 203 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
204 "MetricName": "freq_ge_2000mhz_cycles %",
186 "PerPkg": "1", 205 "PerPkg": "1",
187 "Unit": "PCU" 206 "Unit": "PCU"
188 }, 207 },
@@ -193,6 +212,7 @@
193 "EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES", 212 "EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES",
194 "Filter": "filter_band2=3000", 213 "Filter": "filter_band2=3000",
195 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 214 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
215 "MetricName": "freq_ge_3000mhz_cycles %",
196 "PerPkg": "1", 216 "PerPkg": "1",
197 "Unit": "PCU" 217 "Unit": "PCU"
198 }, 218 },
@@ -203,6 +223,7 @@
203 "EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES", 223 "EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES",
204 "Filter": "filter_band3=4000", 224 "Filter": "filter_band3=4000",
205 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 225 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
226 "MetricName": "freq_ge_4000mhz_cycles %",
206 "PerPkg": "1", 227 "PerPkg": "1",
207 "Unit": "PCU" 228 "Unit": "PCU"
208 }, 229 },
@@ -213,6 +234,7 @@
213 "EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS", 234 "EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS",
214 "Filter": "edge=1,filter_band0=1200", 235 "Filter": "edge=1,filter_band0=1200",
215 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 236 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
237 "MetricName": "freq_ge_1200mhz_cycles %",
216 "PerPkg": "1", 238 "PerPkg": "1",
217 "Unit": "PCU" 239 "Unit": "PCU"
218 }, 240 },
@@ -223,6 +245,7 @@
223 "EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS", 245 "EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS",
224 "Filter": "edge=1,filter_band1=2000", 246 "Filter": "edge=1,filter_band1=2000",
225 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 247 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
248 "MetricName": "freq_ge_2000mhz_cycles %",
226 "PerPkg": "1", 249 "PerPkg": "1",
227 "Unit": "PCU" 250 "Unit": "PCU"
228 }, 251 },
@@ -233,6 +256,7 @@
233 "EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS", 256 "EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS",
234 "Filter": "edge=1,filter_band2=4000", 257 "Filter": "edge=1,filter_band2=4000",
235 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 258 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
259 "MetricName": "freq_ge_3000mhz_cycles %",
236 "PerPkg": "1", 260 "PerPkg": "1",
237 "Unit": "PCU" 261 "Unit": "PCU"
238 }, 262 },
@@ -243,6 +267,7 @@
243 "EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS", 267 "EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS",
244 "Filter": "edge=1,filter_band3=4000", 268 "Filter": "edge=1,filter_band3=4000",
245 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 269 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
270 "MetricName": "freq_ge_4000mhz_cycles %",
246 "PerPkg": "1", 271 "PerPkg": "1",
247 "Unit": "PCU" 272 "Unit": "PCU"
248 } 273 }
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/uncore-cache.json b/tools/perf/pmu-events/arch/x86/jaketown/uncore-cache.json
index 2f23cf0129e7..3fa61d962607 100644
--- a/tools/perf/pmu-events/arch/x86/jaketown/uncore-cache.json
+++ b/tools/perf/pmu-events/arch/x86/jaketown/uncore-cache.json
@@ -1,13 +1,13 @@
1[ 1[
2 { 2 {
3 "BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks", 3 "BriefDescription": "Uncore cache clock ticks",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventName": "UNC_C_CLOCKTICKS", 5 "EventName": "UNC_C_CLOCKTICKS",
6 "PerPkg": "1", 6 "PerPkg": "1",
7 "Unit": "CBO" 7 "Unit": "CBO"
8 }, 8 },
9 { 9 {
10 "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any", 10 "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch)",
11 "Counter": "0,1", 11 "Counter": "0,1",
12 "EventCode": "0x34", 12 "EventCode": "0x34",
13 "EventName": "UNC_C_LLC_LOOKUP.ANY", 13 "EventName": "UNC_C_LLC_LOOKUP.ANY",
@@ -18,7 +18,7 @@
18 "Unit": "CBO" 18 "Unit": "CBO"
19 }, 19 },
20 { 20 {
21 "BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state", 21 "BriefDescription": "M line evictions from LLC (writebacks to memory)",
22 "Counter": "0,1", 22 "Counter": "0,1",
23 "EventCode": "0x37", 23 "EventCode": "0x37",
24 "EventName": "UNC_C_LLC_VICTIMS.M_STATE", 24 "EventName": "UNC_C_LLC_VICTIMS.M_STATE",
@@ -171,11 +171,12 @@
171 "Unit": "CBO" 171 "Unit": "CBO"
172 }, 172 },
173 { 173 {
174 "BriefDescription": "Occupancy counter for all LLC misses; we divide this by UNC_C_CLOCKTICKS to get average Q depth. Derived from unc_c_tor_occupancy.miss_all", 174 "BriefDescription": "Occupancy counter for all LLC misses; we divide this by UNC_C_CLOCKTICKS to get average Q depth",
175 "EventCode": "0x36", 175 "EventCode": "0x36",
176 "EventName": "UNC_C_TOR_OCCUPANCY.MISS_ALL", 176 "EventName": "UNC_C_TOR_OCCUPANCY.MISS_ALL",
177 "Filter": "filter_opc=0x182", 177 "Filter": "filter_opc=0x182",
178 "MetricExpr": "(UNC_C_TOR_OCCUPANCY.MISS_ALL / UNC_C_CLOCKTICKS) * 100.", 178 "MetricExpr": "(UNC_C_TOR_OCCUPANCY.MISS_ALL / UNC_C_CLOCKTICKS) * 100.",
179 "MetricName": "tor_occupancy.miss_all %",
179 "PerPkg": "1", 180 "PerPkg": "1",
180 "UMask": "0xa", 181 "UMask": "0xa",
181 "Unit": "CBO" 182 "Unit": "CBO"
@@ -189,7 +190,7 @@
189 "Unit": "CBO" 190 "Unit": "CBO"
190 }, 191 },
191 { 192 {
192 "BriefDescription": "read requests to home agent. Derived from unc_h_requests.reads", 193 "BriefDescription": "read requests to home agent",
193 "Counter": "0,1,2,3", 194 "Counter": "0,1,2,3",
194 "EventCode": "0x1", 195 "EventCode": "0x1",
195 "EventName": "UNC_H_REQUESTS.READS", 196 "EventName": "UNC_H_REQUESTS.READS",
@@ -198,7 +199,7 @@
198 "Unit": "HA" 199 "Unit": "HA"
199 }, 200 },
200 { 201 {
201 "BriefDescription": "write requests to home agent. Derived from unc_h_requests.writes", 202 "BriefDescription": "write requests to home agent",
202 "Counter": "0,1,2,3", 203 "Counter": "0,1,2,3",
203 "EventCode": "0x1", 204 "EventCode": "0x1",
204 "EventName": "UNC_H_REQUESTS.WRITES", 205 "EventName": "UNC_H_REQUESTS.WRITES",
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/jaketown/uncore-interconnect.json
index 63351876eb57..1b53c0e609e3 100644
--- a/tools/perf/pmu-events/arch/x86/jaketown/uncore-interconnect.json
+++ b/tools/perf/pmu-events/arch/x86/jaketown/uncore-interconnect.json
@@ -1,6 +1,6 @@
1[ 1[
2 { 2 {
3 "BriefDescription": "QPI clock ticks. Used to get percentages of QPI cycles events. Derived from unc_q_clockticks", 3 "BriefDescription": "QPI clock ticks. Used to get percentages of QPI cycles events",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventCode": "0x14", 5 "EventCode": "0x14",
6 "EventName": "UNC_Q_CLOCKTICKS", 6 "EventName": "UNC_Q_CLOCKTICKS",
@@ -8,25 +8,27 @@
8 "Unit": "QPI LL" 8 "Unit": "QPI LL"
9 }, 9 },
10 { 10 {
11 "BriefDescription": "Cycles where receiving QPI link is in half-width mode. Derived from unc_q_rxl0p_power_cycles", 11 "BriefDescription": "Cycles where receiving QPI link is in half-width mode",
12 "Counter": "0,1,2,3", 12 "Counter": "0,1,2,3",
13 "EventCode": "0x10", 13 "EventCode": "0x10",
14 "EventName": "UNC_Q_RxL0P_POWER_CYCLES", 14 "EventName": "UNC_Q_RxL0P_POWER_CYCLES",
15 "MetricExpr": "(UNC_Q_RxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.", 15 "MetricExpr": "(UNC_Q_RxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.",
16 "MetricName": "rxl0p_power_cycles %",
16 "PerPkg": "1", 17 "PerPkg": "1",
17 "Unit": "QPI LL" 18 "Unit": "QPI LL"
18 }, 19 },
19 { 20 {
20 "BriefDescription": "Cycles where transmitting QPI link is in half-width mode. Derived from unc_q_txl0p_power_cycles", 21 "BriefDescription": "Cycles where transmitting QPI link is in half-width mode",
21 "Counter": "0,1,2,3", 22 "Counter": "0,1,2,3",
22 "EventCode": "0xd", 23 "EventCode": "0xd",
23 "EventName": "UNC_Q_TxL0P_POWER_CYCLES", 24 "EventName": "UNC_Q_TxL0P_POWER_CYCLES",
24 "MetricExpr": "(UNC_Q_TxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.", 25 "MetricExpr": "(UNC_Q_TxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.",
26 "MetricName": "txl0p_power_cycles %",
25 "PerPkg": "1", 27 "PerPkg": "1",
26 "Unit": "QPI LL" 28 "Unit": "QPI LL"
27 }, 29 },
28 { 30 {
29 "BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data", 31 "BriefDescription": "Number of data flits transmitted ",
30 "Counter": "0,1,2,3", 32 "Counter": "0,1,2,3",
31 "EventName": "UNC_Q_TxL_FLITS_G0.DATA", 33 "EventName": "UNC_Q_TxL_FLITS_G0.DATA",
32 "PerPkg": "1", 34 "PerPkg": "1",
@@ -35,7 +37,7 @@
35 "Unit": "QPI LL" 37 "Unit": "QPI LL"
36 }, 38 },
37 { 39 {
38 "BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data", 40 "BriefDescription": "Number of non data (control) flits transmitted ",
39 "Counter": "0,1,2,3", 41 "Counter": "0,1,2,3",
40 "EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA", 42 "EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA",
41 "PerPkg": "1", 43 "PerPkg": "1",
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/uncore-memory.json b/tools/perf/pmu-events/arch/x86/jaketown/uncore-memory.json
index e2cf6daa7b37..8551cebeba23 100644
--- a/tools/perf/pmu-events/arch/x86/jaketown/uncore-memory.json
+++ b/tools/perf/pmu-events/arch/x86/jaketown/uncore-memory.json
@@ -1,6 +1,6 @@
1[ 1[
2 { 2 {
3 "BriefDescription": "Memory page activates. Derived from unc_m_act_count", 3 "BriefDescription": "Memory page activates",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventCode": "0x1", 5 "EventCode": "0x1",
6 "EventName": "UNC_M_ACT_COUNT", 6 "EventName": "UNC_M_ACT_COUNT",
@@ -11,7 +11,7 @@
11 "BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd", 11 "BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd",
12 "Counter": "0,1,2,3", 12 "Counter": "0,1,2,3",
13 "EventCode": "0x4", 13 "EventCode": "0x4",
14 "EventName": "UNC_M_CAS_COUNT.RD", 14 "EventName": "LLC_MISSES.MEM_READ",
15 "PerPkg": "1", 15 "PerPkg": "1",
16 "UMask": "0x3", 16 "UMask": "0x3",
17 "Unit": "iMC" 17 "Unit": "iMC"
@@ -20,47 +20,50 @@
20 "BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr", 20 "BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr",
21 "Counter": "0,1,2,3", 21 "Counter": "0,1,2,3",
22 "EventCode": "0x4", 22 "EventCode": "0x4",
23 "EventName": "UNC_M_CAS_COUNT.WR", 23 "EventName": "LLC_MISSES.MEM_WRITE",
24 "PerPkg": "1", 24 "PerPkg": "1",
25 "UMask": "0xc", 25 "UMask": "0xc",
26 "Unit": "iMC" 26 "Unit": "iMC"
27 }, 27 },
28 { 28 {
29 "BriefDescription": "Memory controller clock ticks. Used to get percentages of memory controller cycles events. Derived from unc_m_clockticks", 29 "BriefDescription": "Memory controller clock ticks. Used to get percentages of memory controller cycles events",
30 "Counter": "0,1,2,3", 30 "Counter": "0,1,2,3",
31 "EventName": "UNC_M_CLOCKTICKS", 31 "EventName": "UNC_M_CLOCKTICKS",
32 "PerPkg": "1", 32 "PerPkg": "1",
33 "Unit": "iMC" 33 "Unit": "iMC"
34 }, 34 },
35 { 35 {
36 "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd", 36 "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode",
37 "Counter": "0,1,2,3", 37 "Counter": "0,1,2,3",
38 "EventCode": "0x85", 38 "EventCode": "0x85",
39 "EventName": "UNC_M_POWER_CHANNEL_PPD", 39 "EventName": "UNC_M_POWER_CHANNEL_PPD",
40 "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.", 40 "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
41 "MetricName": "power_channel_ppd %",
41 "PerPkg": "1", 42 "PerPkg": "1",
42 "Unit": "iMC" 43 "Unit": "iMC"
43 }, 44 },
44 { 45 {
45 "BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles", 46 "BriefDescription": "Cycles all ranks are in critical thermal throttle",
46 "Counter": "0,1,2,3", 47 "Counter": "0,1,2,3",
47 "EventCode": "0x86", 48 "EventCode": "0x86",
48 "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES", 49 "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
49 "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.", 50 "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
51 "MetricName": "power_critical_throttle_cycles %",
50 "PerPkg": "1", 52 "PerPkg": "1",
51 "Unit": "iMC" 53 "Unit": "iMC"
52 }, 54 },
53 { 55 {
54 "BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh", 56 "BriefDescription": "Cycles Memory is in self refresh power mode",
55 "Counter": "0,1,2,3", 57 "Counter": "0,1,2,3",
56 "EventCode": "0x43", 58 "EventCode": "0x43",
57 "EventName": "UNC_M_POWER_SELF_REFRESH", 59 "EventName": "UNC_M_POWER_SELF_REFRESH",
58 "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.", 60 "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
61 "MetricName": "power_self_refresh %",
59 "PerPkg": "1", 62 "PerPkg": "1",
60 "Unit": "iMC" 63 "Unit": "iMC"
61 }, 64 },
62 { 65 {
63 "BriefDescription": "Memory page conflicts. Derived from unc_m_pre_count.page_miss", 66 "BriefDescription": "Memory page conflicts",
64 "Counter": "0,1,2,3", 67 "Counter": "0,1,2,3",
65 "EventCode": "0x2", 68 "EventCode": "0x2",
66 "EventName": "UNC_M_PRE_COUNT.PAGE_MISS", 69 "EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
@@ -69,7 +72,7 @@
69 "Unit": "iMC" 72 "Unit": "iMC"
70 }, 73 },
71 { 74 {
72 "BriefDescription": "Occupancy counter for memory read queue. Derived from unc_m_rpq_occupancy", 75 "BriefDescription": "Occupancy counter for memory read queue",
73 "Counter": "0,1,2,3", 76 "Counter": "0,1,2,3",
74 "EventCode": "0x80", 77 "EventCode": "0x80",
75 "EventName": "UNC_M_RPQ_OCCUPANCY", 78 "EventName": "UNC_M_RPQ_OCCUPANCY",
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json b/tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json
index bbe36d547386..16034bfd06dd 100644
--- a/tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json
+++ b/tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json
@@ -1,44 +1,48 @@
1[ 1[
2 { 2 {
3 "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks", 3 "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events",
4 "Counter": "0,1,2,3", 4 "Counter": "0,1,2,3",
5 "EventName": "UNC_P_CLOCKTICKS", 5 "EventName": "UNC_P_CLOCKTICKS",
6 "PerPkg": "1", 6 "PerPkg": "1",
7 "Unit": "PCU" 7 "Unit": "PCU"
8 }, 8 },
9 { 9 {
10 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band0=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band0_cycles", 10 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band0=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency",
11 "Counter": "0,1,2,3", 11 "Counter": "0,1,2,3",
12 "EventCode": "0xb", 12 "EventCode": "0xb",
13 "EventName": "UNC_P_FREQ_BAND0_CYCLES", 13 "EventName": "UNC_P_FREQ_BAND0_CYCLES",
14 "MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.", 14 "MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.",
15 "MetricName": "freq_band0_cycles %",
15 "PerPkg": "1", 16 "PerPkg": "1",
16 "Unit": "PCU" 17 "Unit": "PCU"
17 }, 18 },
18 { 19 {
19 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band1=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band1_cycles", 20 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band1=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency",
20 "Counter": "0,1,2,3", 21 "Counter": "0,1,2,3",
21 "EventCode": "0xc", 22 "EventCode": "0xc",
22 "EventName": "UNC_P_FREQ_BAND1_CYCLES", 23 "EventName": "UNC_P_FREQ_BAND1_CYCLES",
23 "MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.", 24 "MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.",
25 "MetricName": "freq_band1_cycles %",
24 "PerPkg": "1", 26 "PerPkg": "1",
25 "Unit": "PCU" 27 "Unit": "PCU"
26 }, 28 },
27 { 29 {
28 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band2=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band2_cycles", 30 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band2=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency",
29 "Counter": "0,1,2,3", 31 "Counter": "0,1,2,3",
30 "EventCode": "0xd", 32 "EventCode": "0xd",
31 "EventName": "UNC_P_FREQ_BAND2_CYCLES", 33 "EventName": "UNC_P_FREQ_BAND2_CYCLES",
32 "MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.", 34 "MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.",
35 "MetricName": "freq_band2_cycles %",
33 "PerPkg": "1", 36 "PerPkg": "1",
34 "Unit": "PCU" 37 "Unit": "PCU"
35 }, 38 },
36 { 39 {
37 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band3=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band3_cycles", 40 "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band3=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency",
38 "Counter": "0,1,2,3", 41 "Counter": "0,1,2,3",
39 "EventCode": "0xe", 42 "EventCode": "0xe",
40 "EventName": "UNC_P_FREQ_BAND3_CYCLES", 43 "EventName": "UNC_P_FREQ_BAND3_CYCLES",
41 "MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.", 44 "MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.",
45 "MetricName": "freq_band3_cycles %",
42 "PerPkg": "1", 46 "PerPkg": "1",
43 "Unit": "PCU" 47 "Unit": "PCU"
44 }, 48 },
@@ -49,6 +53,7 @@
49 "EventName": "UNC_P_FREQ_BAND0_TRANSITIONS", 53 "EventName": "UNC_P_FREQ_BAND0_TRANSITIONS",
50 "Filter": "edge=1", 54 "Filter": "edge=1",
51 "MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.", 55 "MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.",
56 "MetricName": "freq_band0_cycles %",
52 "PerPkg": "1", 57 "PerPkg": "1",
53 "Unit": "PCU" 58 "Unit": "PCU"
54 }, 59 },
@@ -59,6 +64,7 @@
59 "EventName": "UNC_P_FREQ_BAND1_TRANSITIONS", 64 "EventName": "UNC_P_FREQ_BAND1_TRANSITIONS",
60 "Filter": "edge=1", 65 "Filter": "edge=1",
61 "MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.", 66 "MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.",
67 "MetricName": "freq_band1_cycles %",
62 "PerPkg": "1", 68 "PerPkg": "1",
63 "Unit": "PCU" 69 "Unit": "PCU"
64 }, 70 },
@@ -69,6 +75,7 @@
69 "EventName": "UNC_P_FREQ_BAND2_TRANSITIONS", 75 "EventName": "UNC_P_FREQ_BAND2_TRANSITIONS",
70 "Filter": "edge=1", 76 "Filter": "edge=1",
71 "MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.", 77 "MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.",
78 "MetricName": "freq_band2_cycles %",
72 "PerPkg": "1", 79 "PerPkg": "1",
73 "Unit": "PCU" 80 "Unit": "PCU"
74 }, 81 },
@@ -79,89 +86,99 @@
79 "EventName": "UNC_P_FREQ_BAND3_TRANSITIONS", 86 "EventName": "UNC_P_FREQ_BAND3_TRANSITIONS",
80 "Filter": "edge=1", 87 "Filter": "edge=1",
81 "MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.", 88 "MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.",
89 "MetricName": "freq_band3_cycles %",
82 "PerPkg": "1", 90 "PerPkg": "1",
83 "Unit": "PCU" 91 "Unit": "PCU"
84 }, 92 },
85 { 93 {
86 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C0. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c0", 94 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C0. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
87 "Counter": "0,1,2,3", 95 "Counter": "0,1,2,3",
88 "EventCode": "0x80", 96 "EventCode": "0x80",
89 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0", 97 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
90 "Filter": "occ_sel=1", 98 "Filter": "occ_sel=1",
91 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.", 99 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
100 "MetricName": "power_state_occupancy.cores_c0 %",
92 "PerPkg": "1", 101 "PerPkg": "1",
93 "Unit": "PCU" 102 "Unit": "PCU"
94 }, 103 },
95 { 104 {
96 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C3. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c3", 105 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C3. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
97 "Counter": "0,1,2,3", 106 "Counter": "0,1,2,3",
98 "EventCode": "0x80", 107 "EventCode": "0x80",
99 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3", 108 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
100 "Filter": "occ_sel=2", 109 "Filter": "occ_sel=2",
101 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.", 110 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
111 "MetricName": "power_state_occupancy.cores_c3 %",
102 "PerPkg": "1", 112 "PerPkg": "1",
103 "Unit": "PCU" 113 "Unit": "PCU"
104 }, 114 },
105 { 115 {
106 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C6. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events . Derived from unc_p_power_state_occupancy.cores_c6", 116 "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C6. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events ",
107 "Counter": "0,1,2,3", 117 "Counter": "0,1,2,3",
108 "EventCode": "0x80", 118 "EventCode": "0x80",
109 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6", 119 "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
110 "Filter": "occ_sel=3", 120 "Filter": "occ_sel=3",
111 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.", 121 "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
122 "MetricName": "power_state_occupancy.cores_c6 %",
112 "PerPkg": "1", 123 "PerPkg": "1",
113 "Unit": "PCU" 124 "Unit": "PCU"
114 }, 125 },
115 { 126 {
116 "BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode. This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip. Derived from unc_p_prochot_external_cycles", 127 "BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode. This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip",
117 "Counter": "0,1,2,3", 128 "Counter": "0,1,2,3",
118 "EventCode": "0xa", 129 "EventCode": "0xa",
119 "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES", 130 "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
120 "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.", 131 "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
132 "MetricName": "prochot_external_cycles %",
121 "PerPkg": "1", 133 "PerPkg": "1",
122 "Unit": "PCU" 134 "Unit": "PCU"
123 }, 135 },
124 { 136 {
125 "BriefDescription": "Counts the number of cycles when temperature is the upper limit on frequency. Derived from unc_p_freq_max_limit_thermal_cycles", 137 "BriefDescription": "Counts the number of cycles when temperature is the upper limit on frequency",
126 "Counter": "0,1,2,3", 138 "Counter": "0,1,2,3",
127 "EventCode": "0x4", 139 "EventCode": "0x4",
128 "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES", 140 "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
129 "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.", 141 "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
142 "MetricName": "freq_max_limit_thermal_cycles %",
130 "PerPkg": "1", 143 "PerPkg": "1",
131 "Unit": "PCU" 144 "Unit": "PCU"
132 }, 145 },
133 { 146 {
134 "BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency. Derived from unc_p_freq_max_os_cycles", 147 "BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency",
135 "Counter": "0,1,2,3", 148 "Counter": "0,1,2,3",
136 "EventCode": "0x6", 149 "EventCode": "0x6",
137 "EventName": "UNC_P_FREQ_MAX_OS_CYCLES", 150 "EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
138 "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.", 151 "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
152 "MetricName": "freq_max_os_cycles %",
139 "PerPkg": "1", 153 "PerPkg": "1",
140 "Unit": "PCU" 154 "Unit": "PCU"
141 }, 155 },
142 { 156 {
143 "BriefDescription": "Counts the number of cycles when power is the upper limit on frequency. Derived from unc_p_freq_max_power_cycles", 157 "BriefDescription": "Counts the number of cycles when power is the upper limit on frequency",
144 "Counter": "0,1,2,3", 158 "Counter": "0,1,2,3",
145 "EventCode": "0x5", 159 "EventCode": "0x5",
146 "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES", 160 "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
147 "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.", 161 "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
162 "MetricName": "freq_max_power_cycles %",
148 "PerPkg": "1", 163 "PerPkg": "1",
149 "Unit": "PCU" 164 "Unit": "PCU"
150 }, 165 },
151 { 166 {
152 "BriefDescription": "Counts the number of cycles when current is the upper limit on frequency. Derived from unc_p_freq_max_current_cycles", 167 "BriefDescription": "Counts the number of cycles when current is the upper limit on frequency",
153 "Counter": "0,1,2,3", 168 "Counter": "0,1,2,3",
154 "EventCode": "0x7", 169 "EventCode": "0x7",
155 "EventName": "UNC_P_FREQ_MAX_CURRENT_CYCLES", 170 "EventName": "UNC_P_FREQ_MAX_CURRENT_CYCLES",
156 "MetricExpr": "(UNC_P_FREQ_MAX_CURRENT_CYCLES / UNC_P_CLOCKTICKS) * 100.", 171 "MetricExpr": "(UNC_P_FREQ_MAX_CURRENT_CYCLES / UNC_P_CLOCKTICKS) * 100.",
172 "MetricName": "freq_max_current_cycles %",
157 "PerPkg": "1", 173 "PerPkg": "1",
158 "Unit": "PCU" 174 "Unit": "PCU"
159 }, 175 },
160 { 176 {
161 "BriefDescription": "Cycles spent changing Frequency. Derived from unc_p_freq_trans_cycles", 177 "BriefDescription": "Cycles spent changing Frequency",
162 "Counter": "0,1,2,3", 178 "Counter": "0,1,2,3",
163 "EventName": "UNC_P_FREQ_TRANS_CYCLES", 179 "EventName": "UNC_P_FREQ_TRANS_CYCLES",
164 "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.", 180 "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
181 "MetricName": "freq_trans_cycles %",
165 "PerPkg": "1", 182 "PerPkg": "1",
166 "Unit": "PCU" 183 "Unit": "PCU"
167 }, 184 },
@@ -172,6 +189,7 @@
172 "EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES", 189 "EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES",
173 "Filter": "filter_band0=1200", 190 "Filter": "filter_band0=1200",
174 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 191 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
192 "MetricName": "freq_ge_1200mhz_cycles %",
175 "PerPkg": "1", 193 "PerPkg": "1",
176 "Unit": "PCU" 194 "Unit": "PCU"
177 }, 195 },
@@ -182,6 +200,7 @@
182 "EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES", 200 "EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES",
183 "Filter": "filter_band1=2000", 201 "Filter": "filter_band1=2000",
184 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 202 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
203 "MetricName": "freq_ge_2000mhz_cycles %",
185 "PerPkg": "1", 204 "PerPkg": "1",
186 "Unit": "PCU" 205 "Unit": "PCU"
187 }, 206 },
@@ -192,6 +211,7 @@
192 "EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES", 211 "EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES",
193 "Filter": "filter_band2=3000", 212 "Filter": "filter_band2=3000",
194 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 213 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
214 "MetricName": "freq_ge_3000mhz_cycles %",
195 "PerPkg": "1", 215 "PerPkg": "1",
196 "Unit": "PCU" 216 "Unit": "PCU"
197 }, 217 },
@@ -202,6 +222,7 @@
202 "EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES", 222 "EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES",
203 "Filter": "filter_band3=4000", 223 "Filter": "filter_band3=4000",
204 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 224 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
225 "MetricName": "freq_ge_4000mhz_cycles %",
205 "PerPkg": "1", 226 "PerPkg": "1",
206 "Unit": "PCU" 227 "Unit": "PCU"
207 }, 228 },
@@ -212,6 +233,7 @@
212 "EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS", 233 "EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS",
213 "Filter": "edge=1,filter_band0=1200", 234 "Filter": "edge=1,filter_band0=1200",
214 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 235 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
236 "MetricName": "freq_ge_1200mhz_cycles %",
215 "PerPkg": "1", 237 "PerPkg": "1",
216 "Unit": "PCU" 238 "Unit": "PCU"
217 }, 239 },
@@ -222,6 +244,7 @@
222 "EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS", 244 "EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS",
223 "Filter": "edge=1,filter_band1=2000", 245 "Filter": "edge=1,filter_band1=2000",
224 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 246 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
247 "MetricName": "freq_ge_2000mhz_cycles %",
225 "PerPkg": "1", 248 "PerPkg": "1",
226 "Unit": "PCU" 249 "Unit": "PCU"
227 }, 250 },
@@ -232,6 +255,7 @@
232 "EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS", 255 "EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS",
233 "Filter": "edge=1,filter_band2=4000", 256 "Filter": "edge=1,filter_band2=4000",
234 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 257 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
258 "MetricName": "freq_ge_3000mhz_cycles %",
235 "PerPkg": "1", 259 "PerPkg": "1",
236 "Unit": "PCU" 260 "Unit": "PCU"
237 }, 261 },
@@ -242,6 +266,7 @@
242 "EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS", 266 "EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS",
243 "Filter": "edge=1,filter_band3=4000", 267 "Filter": "edge=1,filter_band3=4000",
244 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 268 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
269 "MetricName": "freq_ge_4000mhz_cycles %",
245 "PerPkg": "1", 270 "PerPkg": "1",
246 "Unit": "PCU" 271 "Unit": "PCU"
247 } 272 }
diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv
index 12181bb1da2a..d1a12e584c1b 100644
--- a/tools/perf/pmu-events/arch/x86/mapfile.csv
+++ b/tools/perf/pmu-events/arch/x86/mapfile.csv
@@ -17,6 +17,7 @@ GenuineIntel-6-3A,v18,ivybridge,core
17GenuineIntel-6-3E,v19,ivytown,core 17GenuineIntel-6-3E,v19,ivytown,core
18GenuineIntel-6-2D,v20,jaketown,core 18GenuineIntel-6-2D,v20,jaketown,core
19GenuineIntel-6-57,v9,knightslanding,core 19GenuineIntel-6-57,v9,knightslanding,core
20GenuineIntel-6-85,v9,knightslanding,core
20GenuineIntel-6-1E,v2,nehalemep,core 21GenuineIntel-6-1E,v2,nehalemep,core
21GenuineIntel-6-1F,v2,nehalemep,core 22GenuineIntel-6-1F,v2,nehalemep,core
22GenuineIntel-6-1A,v2,nehalemep,core 23GenuineIntel-6-1A,v2,nehalemep,core
diff --git a/tools/perf/pmu-events/arch/x86/sandybridge/uncore.json b/tools/perf/pmu-events/arch/x86/sandybridge/uncore.json
new file mode 100644
index 000000000000..42c70eed05a2
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/sandybridge/uncore.json
@@ -0,0 +1,314 @@
1[
2 {
3 "Unit": "CBO",
4 "EventCode": "0x22",
5 "UMask": "0x01",
6 "EventName": "UNC_CBO_XSNP_RESPONSE.MISS",
7 "BriefDescription": "A snoop misses in some processor core.",
8 "PublicDescription": "A snoop misses in some processor core.",
9 "Counter": "0,1",
10 "CounterMask": "0",
11 "Invert": "0",
12 "EdgeDetect": "0"
13 },
14 {
15 "Unit": "CBO",
16 "EventCode": "0x22",
17 "UMask": "0x02",
18 "EventName": "UNC_CBO_XSNP_RESPONSE.INVAL",
19 "BriefDescription": "A snoop invalidates a non-modified line in some processor core.",
20 "PublicDescription": "A snoop invalidates a non-modified line in some processor core.",
21 "Counter": "0,1",
22 "CounterMask": "0",
23 "Invert": "0",
24 "EdgeDetect": "0"
25 },
26 {
27 "Unit": "CBO",
28 "EventCode": "0x22",
29 "UMask": "0x04",
30 "EventName": "UNC_CBO_XSNP_RESPONSE.HIT",
31 "BriefDescription": "A snoop hits a non-modified line in some processor core.",
32 "PublicDescription": "A snoop hits a non-modified line in some processor core.",
33 "Counter": "0,1",
34 "CounterMask": "0",
35 "Invert": "0",
36 "EdgeDetect": "0"
37 },
38 {
39 "Unit": "CBO",
40 "EventCode": "0x22",
41 "UMask": "0x08",
42 "EventName": "UNC_CBO_XSNP_RESPONSE.HITM",
43 "BriefDescription": "A snoop hits a modified line in some processor core.",
44 "PublicDescription": "A snoop hits a modified line in some processor core.",
45 "Counter": "0,1",
46 "CounterMask": "0",
47 "Invert": "0",
48 "EdgeDetect": "0"
49 },
50 {
51 "Unit": "CBO",
52 "EventCode": "0x22",
53 "UMask": "0x10",
54 "EventName": "UNC_CBO_XSNP_RESPONSE.INVAL_M",
55 "BriefDescription": "A snoop invalidates a modified line in some processor core.",
56 "PublicDescription": "A snoop invalidates a modified line in some processor core.",
57 "Counter": "0,1",
58 "CounterMask": "0",
59 "Invert": "0",
60 "EdgeDetect": "0"
61 },
62 {
63 "Unit": "CBO",
64 "EventCode": "0x22",
65 "UMask": "0x20",
66 "EventName": "UNC_CBO_XSNP_RESPONSE.EXTERNAL_FILTER",
67 "BriefDescription": "Filter on cross-core snoops initiated by this Cbox due to external snoop request.",
68 "PublicDescription": "Filter on cross-core snoops initiated by this Cbox due to external snoop request.",
69 "Counter": "0,1",
70 "CounterMask": "0",
71 "Invert": "0",
72 "EdgeDetect": "0"
73 },
74 {
75 "Unit": "CBO",
76 "EventCode": "0x22",
77 "UMask": "0x40",
78 "EventName": "UNC_CBO_XSNP_RESPONSE.XCORE_FILTER",
79 "BriefDescription": "Filter on cross-core snoops initiated by this Cbox due to processor core memory request.",
80 "PublicDescription": "Filter on cross-core snoops initiated by this Cbox due to processor core memory request.",
81 "Counter": "0,1",
82 "CounterMask": "0",
83 "Invert": "0",
84 "EdgeDetect": "0"
85 },
86 {
87 "Unit": "CBO",
88 "EventCode": "0x22",
89 "UMask": "0x80",
90 "EventName": "UNC_CBO_XSNP_RESPONSE.EVICTION_FILTER",
91 "BriefDescription": "Filter on cross-core snoops initiated by this Cbox due to LLC eviction.",
92 "PublicDescription": "Filter on cross-core snoops initiated by this Cbox due to LLC eviction.",
93 "Counter": "0,1",
94 "CounterMask": "0",
95 "Invert": "0",
96 "EdgeDetect": "0"
97 },
98 {
99 "Unit": "CBO",
100 "EventCode": "0x34",
101 "UMask": "0x01",
102 "EventName": "UNC_CBO_CACHE_LOOKUP.M",
103 "BriefDescription": "LLC lookup request that access cache and found line in M-state.",
104 "PublicDescription": "LLC lookup request that access cache and found line in M-state.",
105 "Counter": "0,1",
106 "CounterMask": "0",
107 "Invert": "0",
108 "EdgeDetect": "0"
109 },
110 {
111 "Unit": "CBO",
112 "EventCode": "0x34",
113 "UMask": "0x02",
114 "EventName": "UNC_CBO_CACHE_LOOKUP.E",
115 "BriefDescription": "LLC lookup request that access cache and found line in E-state.",
116 "PublicDescription": "LLC lookup request that access cache and found line in E-state.",
117 "Counter": "0,1",
118 "CounterMask": "0",
119 "Invert": "0",
120 "EdgeDetect": "0"
121 },
122 {
123 "Unit": "CBO",
124 "EventCode": "0x34",
125 "UMask": "0x04",
126 "EventName": "UNC_CBO_CACHE_LOOKUP.S",
127 "BriefDescription": "LLC lookup request that access cache and found line in S-state.",
128 "PublicDescription": "LLC lookup request that access cache and found line in S-state.",
129 "Counter": "0,1",
130 "CounterMask": "0",
131 "Invert": "0",
132 "EdgeDetect": "0"
133 },
134 {
135 "Unit": "CBO",
136 "EventCode": "0x34",
137 "UMask": "0x08",
138 "EventName": "UNC_CBO_CACHE_LOOKUP.I",
139 "BriefDescription": "LLC lookup request that access cache and found line in I-state.",
140 "PublicDescription": "LLC lookup request that access cache and found line in I-state.",
141 "Counter": "0,1",
142 "CounterMask": "0",
143 "Invert": "0",
144 "EdgeDetect": "0"
145 },
146 {
147 "Unit": "CBO",
148 "EventCode": "0x34",
149 "UMask": "0x10",
150 "EventName": "UNC_CBO_CACHE_LOOKUP.READ_FILTER",
151 "BriefDescription": "Filter on processor core initiated cacheable read requests.",
152 "PublicDescription": "Filter on processor core initiated cacheable read requests.",
153 "Counter": "0,1",
154 "CounterMask": "0",
155 "Invert": "0",
156 "EdgeDetect": "0"
157 },
158 {
159 "Unit": "CBO",
160 "EventCode": "0x34",
161 "UMask": "0x20",
162 "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_FILTER",
163 "BriefDescription": "Filter on processor core initiated cacheable write requests.",
164 "PublicDescription": "Filter on processor core initiated cacheable write requests.",
165 "Counter": "0,1",
166 "CounterMask": "0",
167 "Invert": "0",
168 "EdgeDetect": "0"
169 },
170 {
171 "Unit": "CBO",
172 "EventCode": "0x34",
173 "UMask": "0x40",
174 "EventName": "UNC_CBO_CACHE_LOOKUP.EXTSNP_FILTER",
175 "BriefDescription": "Filter on external snoop requests.",
176 "PublicDescription": "Filter on external snoop requests.",
177 "Counter": "0,1",
178 "CounterMask": "0",
179 "Invert": "0",
180 "EdgeDetect": "0"
181 },
182 {
183 "Unit": "CBO",
184 "EventCode": "0x34",
185 "UMask": "0x80",
186 "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_REQUEST_FILTER",
187 "BriefDescription": "Filter on any IRQ or IPQ initiated requests including uncacheable, non-coherent requests.",
188 "PublicDescription": "Filter on any IRQ or IPQ initiated requests including uncacheable, non-coherent requests.",
189 "Counter": "0,1",
190 "CounterMask": "0",
191 "Invert": "0",
192 "EdgeDetect": "0"
193 },
194 {
195 "Unit": "ARB",
196 "EventCode": "0x80",
197 "UMask": "0x01",
198 "EventName": "UNC_ARB_TRK_OCCUPANCY.ALL",
199 "BriefDescription": "Counts cycles weighted by the number of requests waiting for data returning from the memory controller. Accounts for coherent and non-coherent requests initiated by IA cores, processor graphic units, or LLC.",
200 "PublicDescription": "Counts cycles weighted by the number of requests waiting for data returning from the memory controller. Accounts for coherent and non-coherent requests initiated by IA cores, processor graphic units, or LLC.",
201 "Counter": "0",
202 "CounterMask": "0",
203 "Invert": "0",
204 "EdgeDetect": "0"
205 },
206 {
207 "Unit": "ARB",
208 "EventCode": "0x81",
209 "UMask": "0x01",
210 "EventName": "UNC_ARB_TRK_REQUESTS.ALL",
211 "BriefDescription": "Counts the number of coherent and in-coherent requests initiated by IA cores, processor graphic units, or LLC.",
212 "PublicDescription": "Counts the number of coherent and in-coherent requests initiated by IA cores, processor graphic units, or LLC.",
213 "Counter": "0,1",
214 "CounterMask": "0",
215 "Invert": "0",
216 "EdgeDetect": "0"
217 },
218 {
219 "Unit": "ARB",
220 "EventCode": "0x81",
221 "UMask": "0x20",
222 "EventName": "UNC_ARB_TRK_REQUESTS.WRITES",
223 "BriefDescription": "Counts the number of allocated write entries, include full, partial, and LLC evictions.",
224 "PublicDescription": "Counts the number of allocated write entries, include full, partial, and LLC evictions.",
225 "Counter": "0,1",
226 "CounterMask": "0",
227 "Invert": "0",
228 "EdgeDetect": "0"
229 },
230 {
231 "Unit": "ARB",
232 "EventCode": "0x81",
233 "UMask": "0x80",
234 "EventName": "UNC_ARB_TRK_REQUESTS.EVICTIONS",
235 "BriefDescription": "Counts the number of LLC evictions allocated.",
236 "PublicDescription": "Counts the number of LLC evictions allocated.",
237 "Counter": "0,1",
238 "CounterMask": "0",
239 "Invert": "0",
240 "EdgeDetect": "0"
241 },
242 {
243 "Unit": "ARB",
244 "EventCode": "0x83",
245 "UMask": "0x01",
246 "EventName": "UNC_ARB_COH_TRK_OCCUPANCY.ALL",
247 "BriefDescription": "Cycles weighted by number of requests pending in Coherency Tracker.",
248 "PublicDescription": "Cycles weighted by number of requests pending in Coherency Tracker.",
249 "Counter": "0",
250 "CounterMask": "0",
251 "Invert": "0",
252 "EdgeDetect": "0"
253 },
254 {
255 "Unit": "ARB",
256 "EventCode": "0x84",
257 "UMask": "0x01",
258 "EventName": "UNC_ARB_COH_TRK_REQUESTS.ALL",
259 "BriefDescription": "Number of requests allocated in Coherency Tracker.",
260 "PublicDescription": "Number of requests allocated in Coherency Tracker.",
261 "Counter": "0,1",
262 "CounterMask": "0",
263 "Invert": "0",
264 "EdgeDetect": "0"
265 },
266 {
267 "Unit": "ARB",
268 "EventCode": "0x80",
269 "UMask": "0x01",
270 "EventName": "UNC_ARB_TRK_OCCUPANCY.CYCLES_WITH_ANY_REQUEST",
271 "BriefDescription": "Cycles with at least one request outstanding is waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
272 "PublicDescription": "Cycles with at least one request outstanding is waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
273 "Counter": "0,1",
274 "CounterMask": "1",
275 "Invert": "0",
276 "EdgeDetect": "0"
277 },
278 {
279 "Unit": "ARB",
280 "EventCode": "0x80",
281 "UMask": "0x01",
282 "EventName": "UNC_ARB_TRK_OCCUPANCY.CYCLES_OVER_HALF_FULL",
283 "BriefDescription": "Cycles with at least half of the requests outstanding are waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
284 "PublicDescription": "Cycles with at least half of the requests outstanding are waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
285 "Counter": "0,1",
286 "CounterMask": "10",
287 "Invert": "0",
288 "EdgeDetect": "0"
289 },
290 {
291 "Unit": "ARB",
292 "EventCode": "0x0",
293 "UMask": "0x01",
294 "EventName": "UNC_CLOCK.SOCKET",
295 "BriefDescription": "This 48-bit fixed counter counts the UCLK cycles.",
296 "PublicDescription": "This 48-bit fixed counter counts the UCLK cycles.",
297 "Counter": "Fixed",
298 "CounterMask": "0",
299 "Invert": "0",
300 "EdgeDetect": "0"
301 },
302 {
303 "Unit": "CBO",
304 "EventCode": "0x34",
305 "UMask": "0x06",
306 "EventName": "UNC_CBO_CACHE_LOOKUP.ES",
307 "BriefDescription": "LLC lookup request that access cache and found line in E-state or S-state.",
308 "PublicDescription": "LLC lookup request that access cache and found line in E-state or S-state.",
309 "Counter": "0,1",
310 "CounterMask": "0",
311 "Invert": "0",
312 "EdgeDetect": "0"
313 }
314] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylake/uncore.json b/tools/perf/pmu-events/arch/x86/skylake/uncore.json
new file mode 100644
index 000000000000..dbc193252fb3
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/skylake/uncore.json
@@ -0,0 +1,254 @@
1[
2 {
3 "Unit": "CBO",
4 "EventCode": "0x22",
5 "UMask": "0x41",
6 "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_XCORE",
7 "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which misses in some processor core.",
8 "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which misses in some processor core.",
9 "Counter": "0,1",
10 "CounterMask": "0",
11 "Invert": "0",
12 "EdgeDetect": "0"
13 },
14 {
15 "Unit": "CBO",
16 "EventCode": "0x22",
17 "UMask": "0x81",
18 "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_EVICTION",
19 "BriefDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.",
20 "PublicDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.",
21 "Counter": "0,1",
22 "CounterMask": "0",
23 "Invert": "0",
24 "EdgeDetect": "0"
25 },
26 {
27 "Unit": "CBO",
28 "EventCode": "0x22",
29 "UMask": "0x44",
30 "EventName": "UNC_CBO_XSNP_RESPONSE.HIT_XCORE",
31 "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a non-modified line in some processor core.",
32 "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a non-modified line in some processor core.",
33 "Counter": "0,1",
34 "CounterMask": "0",
35 "Invert": "0",
36 "EdgeDetect": "0"
37 },
38 {
39 "Unit": "CBO",
40 "EventCode": "0x22",
41 "UMask": "0x48",
42 "EventName": "UNC_CBO_XSNP_RESPONSE.HITM_XCORE",
43 "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a modified line in some processor core.",
44 "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a modified line in some processor core.",
45 "Counter": "0,1",
46 "CounterMask": "0",
47 "Invert": "0",
48 "EdgeDetect": "0"
49 },
50 {
51 "Unit": "CBO",
52 "EventCode": "0x34",
53 "UMask": "0x21",
54 "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_M",
55 "BriefDescription": "L3 Lookup write request that access cache and found line in M-state",
56 "PublicDescription": "L3 Lookup write request that access cache and found line in M-state.",
57 "Counter": "0,1",
58 "CounterMask": "0",
59 "Invert": "0",
60 "EdgeDetect": "0"
61 },
62 {
63 "Unit": "CBO",
64 "EventCode": "0x34",
65 "UMask": "0x81",
66 "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_M",
67 "BriefDescription": "L3 Lookup any request that access cache and found line in M-state",
68 "PublicDescription": "L3 Lookup any request that access cache and found line in M-state.",
69 "Counter": "0,1",
70 "CounterMask": "0",
71 "Invert": "0",
72 "EdgeDetect": "0"
73 },
74 {
75 "Unit": "CBO",
76 "EventCode": "0x34",
77 "UMask": "0x18",
78 "EventName": "UNC_CBO_CACHE_LOOKUP.READ_I",
79 "BriefDescription": "L3 Lookup read request that access cache and found line in I-state",
80 "PublicDescription": "L3 Lookup read request that access cache and found line in I-state.",
81 "Counter": "0,1",
82 "CounterMask": "0",
83 "Invert": "0",
84 "EdgeDetect": "0"
85 },
86 {
87 "Unit": "CBO",
88 "EventCode": "0x34",
89 "UMask": "0x88",
90 "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_I",
91 "BriefDescription": "L3 Lookup any request that access cache and found line in I-state",
92 "PublicDescription": "L3 Lookup any request that access cache and found line in I-state.",
93 "Counter": "0,1",
94 "CounterMask": "0",
95 "Invert": "0",
96 "EdgeDetect": "0"
97 },
98 {
99 "Unit": "CBO",
100 "EventCode": "0x34",
101 "UMask": "0x1f",
102 "EventName": "UNC_CBO_CACHE_LOOKUP.READ_MESI",
103 "BriefDescription": "L3 Lookup read request that access cache and found line in any MESI-state",
104 "PublicDescription": "L3 Lookup read request that access cache and found line in any MESI-state.",
105 "Counter": "0,1",
106 "CounterMask": "0",
107 "Invert": "0",
108 "EdgeDetect": "0"
109 },
110 {
111 "Unit": "CBO",
112 "EventCode": "0x34",
113 "UMask": "0x2f",
114 "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_MESI",
115 "BriefDescription": "L3 Lookup write request that access cache and found line in MESI-state",
116 "PublicDescription": "L3 Lookup write request that access cache and found line in MESI-state.",
117 "Counter": "0,1",
118 "CounterMask": "0",
119 "Invert": "0",
120 "EdgeDetect": "0"
121 },
122 {
123 "Unit": "CBO",
124 "EventCode": "0x34",
125 "UMask": "0x8f",
126 "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_MESI",
127 "BriefDescription": "L3 Lookup any request that access cache and found line in MESI-state",
128 "PublicDescription": "L3 Lookup any request that access cache and found line in MESI-state.",
129 "Counter": "0,1",
130 "CounterMask": "0",
131 "Invert": "0",
132 "EdgeDetect": "0"
133 },
134 {
135 "Unit": "CBO",
136 "EventCode": "0x34",
137 "UMask": "0x86",
138 "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_ES",
139 "BriefDescription": "L3 Lookup any request that access cache and found line in E or S-state",
140 "PublicDescription": "L3 Lookup any request that access cache and found line in E or S-state.",
141 "Counter": "0,1",
142 "CounterMask": "0",
143 "Invert": "0",
144 "EdgeDetect": "0"
145 },
146 {
147 "Unit": "CBO",
148 "EventCode": "0x34",
149 "UMask": "0x16",
150 "EventName": "UNC_CBO_CACHE_LOOKUP.READ_ES",
151 "BriefDescription": "L3 Lookup read request that access cache and found line in E or S-state",
152 "PublicDescription": "L3 Lookup read request that access cache and found line in E or S-state.",
153 "Counter": "0,1",
154 "CounterMask": "0",
155 "Invert": "0",
156 "EdgeDetect": "0"
157 },
158 {
159 "Unit": "CBO",
160 "EventCode": "0x34",
161 "UMask": "0x26",
162 "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_ES",
163 "BriefDescription": "L3 Lookup write request that access cache and found line in E or S-state",
164 "PublicDescription": "L3 Lookup write request that access cache and found line in E or S-state.",
165 "Counter": "0,1",
166 "CounterMask": "0",
167 "Invert": "0",
168 "EdgeDetect": "0"
169 },
170 {
171 "Unit": "iMPH-U",
172 "EventCode": "0x80",
173 "UMask": "0x01",
174 "EventName": "UNC_ARB_TRK_OCCUPANCY.ALL",
175 "BriefDescription": "Each cycle count number of all Core outgoing valid entries. Such entry is defined as valid from its allocation till first of IDI0 or DRS0 messages is sent out. Accounts for Coherent and non-coherent traffic.",
176 "PublicDescription": "Each cycle count number of all Core outgoing valid entries. Such entry is defined as valid from its allocation till first of IDI0 or DRS0 messages is sent out. Accounts for Coherent and non-coherent traffic.",
177 "Counter": "0",
178 "CounterMask": "0",
179 "Invert": "0",
180 "EdgeDetect": "0"
181 },
182 {
183 "Unit": "iMPH-U",
184 "EventCode": "0x81",
185 "UMask": "0x01",
186 "EventName": "UNC_ARB_TRK_REQUESTS.ALL",
187 "BriefDescription": "Total number of Core outgoing entries allocated. Accounts for Coherent and non-coherent traffic.",
188 "PublicDescription": "Total number of Core outgoing entries allocated. Accounts for Coherent and non-coherent traffic.",
189 "Counter": "0,1",
190 "CounterMask": "0",
191 "Invert": "0",
192 "EdgeDetect": "0"
193 },
194 {
195 "Unit": "iMPH-U",
196 "EventCode": "0x81",
197 "UMask": "0x02",
198 "EventName": "UNC_ARB_TRK_REQUESTS.DRD_DIRECT",
199 "BriefDescription": "Number of Core coherent Data Read entries allocated in DirectData mode",
200 "PublicDescription": "Number of Core coherent Data Read entries allocated in DirectData mode.",
201 "Counter": "0,1",
202 "CounterMask": "0",
203 "Invert": "0",
204 "EdgeDetect": "0"
205 },
206 {
207 "Unit": "iMPH-U",
208 "EventCode": "0x81",
209 "UMask": "0x20",
210 "EventName": "UNC_ARB_TRK_REQUESTS.WRITES",
211 "BriefDescription": "Number of Writes allocated - any write transactions: full/partials writes and evictions.",
212 "PublicDescription": "Number of Writes allocated - any write transactions: full/partials writes and evictions.",
213 "Counter": "0,1",
214 "CounterMask": "0",
215 "Invert": "0",
216 "EdgeDetect": "0"
217 },
218 {
219 "Unit": "iMPH-U",
220 "EventCode": "0x84",
221 "UMask": "0x01",
222 "EventName": "UNC_ARB_COH_TRK_REQUESTS.ALL",
223 "BriefDescription": "Number of entries allocated. Account for Any type: e.g. Snoop, Core aperture, etc.",
224 "PublicDescription": "Number of entries allocated. Account for Any type: e.g. Snoop, Core aperture, etc.",
225 "Counter": "0,1",
226 "CounterMask": "0",
227 "Invert": "0",
228 "EdgeDetect": "0"
229 },
230 {
231 "Unit": "iMPH-U",
232 "EventCode": "0x80",
233 "UMask": "0x01",
234 "EventName": "UNC_ARB_TRK_OCCUPANCY.CYCLES_WITH_ANY_REQUEST",
235 "BriefDescription": "Cycles with at least one request outstanding is waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.;",
236 "PublicDescription": "Cycles with at least one request outstanding is waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
237 "Counter": "0",
238 "CounterMask": "1",
239 "Invert": "0",
240 "EdgeDetect": "0"
241 },
242 {
243 "Unit": "NCU",
244 "EventCode": "0x0",
245 "UMask": "0x01",
246 "EventName": "UNC_CLOCK.SOCKET",
247 "BriefDescription": "This 48-bit fixed counter counts the UCLK cycles",
248 "PublicDescription": "This 48-bit fixed counter counts the UCLK cycles.",
249 "Counter": "FIXED",
250 "CounterMask": "0",
251 "Invert": "0",
252 "EdgeDetect": "0"
253 }
254] \ No newline at end of file
diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
index eed09346a72a..baa073f38334 100644
--- a/tools/perf/pmu-events/jevents.c
+++ b/tools/perf/pmu-events/jevents.c
@@ -195,6 +195,7 @@ static struct map {
195 { "CBO", "uncore_cbox" }, 195 { "CBO", "uncore_cbox" },
196 { "QPI LL", "uncore_qpi" }, 196 { "QPI LL", "uncore_qpi" },
197 { "SBO", "uncore_sbox" }, 197 { "SBO", "uncore_sbox" },
198 { "iMPH-U", "uncore_arb" },
198 {} 199 {}
199}; 200};
200 201
@@ -291,7 +292,9 @@ static void print_events_table_prefix(FILE *fp, const char *tblname)
291 292
292static int print_events_table_entry(void *data, char *name, char *event, 293static int print_events_table_entry(void *data, char *name, char *event,
293 char *desc, char *long_desc, 294 char *desc, char *long_desc,
294 char *pmu, char *unit, char *perpkg) 295 char *pmu, char *unit, char *perpkg,
296 char *metric_expr,
297 char *metric_name)
295{ 298{
296 struct perf_entry_data *pd = data; 299 struct perf_entry_data *pd = data;
297 FILE *outfp = pd->outfp; 300 FILE *outfp = pd->outfp;
@@ -315,6 +318,10 @@ static int print_events_table_entry(void *data, char *name, char *event,
315 fprintf(outfp, "\t.unit = \"%s\",\n", unit); 318 fprintf(outfp, "\t.unit = \"%s\",\n", unit);
316 if (perpkg) 319 if (perpkg)
317 fprintf(outfp, "\t.perpkg = \"%s\",\n", perpkg); 320 fprintf(outfp, "\t.perpkg = \"%s\",\n", perpkg);
321 if (metric_expr)
322 fprintf(outfp, "\t.metric_expr = \"%s\",\n", metric_expr);
323 if (metric_name)
324 fprintf(outfp, "\t.metric_name = \"%s\",\n", metric_name);
318 fprintf(outfp, "},\n"); 325 fprintf(outfp, "},\n");
319 326
320 return 0; 327 return 0;
@@ -362,7 +369,9 @@ static char *real_event(const char *name, char *event)
362int json_events(const char *fn, 369int json_events(const char *fn,
363 int (*func)(void *data, char *name, char *event, char *desc, 370 int (*func)(void *data, char *name, char *event, char *desc,
364 char *long_desc, 371 char *long_desc,
365 char *pmu, char *unit, char *perpkg), 372 char *pmu, char *unit, char *perpkg,
373 char *metric_expr,
374 char *metric_name),
366 void *data) 375 void *data)
367{ 376{
368 int err = -EIO; 377 int err = -EIO;
@@ -388,6 +397,8 @@ int json_events(const char *fn,
388 char *filter = NULL; 397 char *filter = NULL;
389 char *perpkg = NULL; 398 char *perpkg = NULL;
390 char *unit = NULL; 399 char *unit = NULL;
400 char *metric_expr = NULL;
401 char *metric_name = NULL;
391 unsigned long long eventcode = 0; 402 unsigned long long eventcode = 0;
392 struct msrmap *msr = NULL; 403 struct msrmap *msr = NULL;
393 jsmntok_t *msrval = NULL; 404 jsmntok_t *msrval = NULL;
@@ -398,6 +409,7 @@ int json_events(const char *fn,
398 for (j = 0; j < obj->size; j += 2) { 409 for (j = 0; j < obj->size; j += 2) {
399 jsmntok_t *field, *val; 410 jsmntok_t *field, *val;
400 int nz; 411 int nz;
412 char *s;
401 413
402 field = tok + j; 414 field = tok + j;
403 EXPECT(field->type == JSMN_STRING, tok + j, 415 EXPECT(field->type == JSMN_STRING, tok + j,
@@ -444,7 +456,6 @@ int json_events(const char *fn,
444 NULL); 456 NULL);
445 } else if (json_streq(map, field, "Unit")) { 457 } else if (json_streq(map, field, "Unit")) {
446 const char *ppmu; 458 const char *ppmu;
447 char *s;
448 459
449 ppmu = field_to_perf(unit_to_pmu, map, val); 460 ppmu = field_to_perf(unit_to_pmu, map, val);
450 if (ppmu) { 461 if (ppmu) {
@@ -458,12 +469,19 @@ int json_events(const char *fn,
458 } 469 }
459 addfield(map, &desc, ". ", "Unit: ", NULL); 470 addfield(map, &desc, ". ", "Unit: ", NULL);
460 addfield(map, &desc, "", pmu, NULL); 471 addfield(map, &desc, "", pmu, NULL);
472 addfield(map, &desc, "", " ", NULL);
461 } else if (json_streq(map, field, "Filter")) { 473 } else if (json_streq(map, field, "Filter")) {
462 addfield(map, &filter, "", "", val); 474 addfield(map, &filter, "", "", val);
463 } else if (json_streq(map, field, "ScaleUnit")) { 475 } else if (json_streq(map, field, "ScaleUnit")) {
464 addfield(map, &unit, "", "", val); 476 addfield(map, &unit, "", "", val);
465 } else if (json_streq(map, field, "PerPkg")) { 477 } else if (json_streq(map, field, "PerPkg")) {
466 addfield(map, &perpkg, "", "", val); 478 addfield(map, &perpkg, "", "", val);
479 } else if (json_streq(map, field, "MetricName")) {
480 addfield(map, &metric_name, "", "", val);
481 } else if (json_streq(map, field, "MetricExpr")) {
482 addfield(map, &metric_expr, "", "", val);
483 for (s = metric_expr; *s; s++)
484 *s = tolower(*s);
467 } 485 }
468 /* ignore unknown fields */ 486 /* ignore unknown fields */
469 } 487 }
@@ -488,7 +506,7 @@ int json_events(const char *fn,
488 fixname(name); 506 fixname(name);
489 507
490 err = func(data, name, real_event(name, event), desc, long_desc, 508 err = func(data, name, real_event(name, event), desc, long_desc,
491 pmu, unit, perpkg); 509 pmu, unit, perpkg, metric_expr, metric_name);
492 free(event); 510 free(event);
493 free(desc); 511 free(desc);
494 free(name); 512 free(name);
@@ -498,6 +516,8 @@ int json_events(const char *fn,
498 free(filter); 516 free(filter);
499 free(perpkg); 517 free(perpkg);
500 free(unit); 518 free(unit);
519 free(metric_expr);
520 free(metric_name);
501 if (err) 521 if (err)
502 break; 522 break;
503 tok += j; 523 tok += j;
diff --git a/tools/perf/pmu-events/jevents.h b/tools/perf/pmu-events/jevents.h
index 71e13de31092..611fac01913d 100644
--- a/tools/perf/pmu-events/jevents.h
+++ b/tools/perf/pmu-events/jevents.h
@@ -5,7 +5,8 @@ int json_events(const char *fn,
5 int (*func)(void *data, char *name, char *event, char *desc, 5 int (*func)(void *data, char *name, char *event, char *desc,
6 char *long_desc, 6 char *long_desc,
7 char *pmu, 7 char *pmu,
8 char *unit, char *perpkg), 8 char *unit, char *perpkg, char *metric_expr,
9 char *metric_name),
9 void *data); 10 void *data);
10char *get_cpu_str(void); 11char *get_cpu_str(void);
11 12
diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h
index c669a3cdb9f0..569eab3688dd 100644
--- a/tools/perf/pmu-events/pmu-events.h
+++ b/tools/perf/pmu-events/pmu-events.h
@@ -13,6 +13,8 @@ struct pmu_event {
13 const char *pmu; 13 const char *pmu;
14 const char *unit; 14 const char *unit;
15 const char *perpkg; 15 const char *perpkg;
16 const char *metric_expr;
17 const char *metric_name;
16}; 18};
17 19
18/* 20/*
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 1cb3d9b540e9..af58ebc243ef 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -38,6 +38,7 @@ perf-y += cpumap.o
38perf-y += stat.o 38perf-y += stat.o
39perf-y += event_update.o 39perf-y += event_update.o
40perf-y += event-times.o 40perf-y += event-times.o
41perf-y += expr.o
41perf-y += backward-ring-buffer.o 42perf-y += backward-ring-buffer.o
42perf-y += sdt.o 43perf-y += sdt.o
43perf-y += is_printable_array.o 44perf-y += is_printable_array.o
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c
index 88dc51f4c27b..0dd77494bb58 100644
--- a/tools/perf/tests/attr.c
+++ b/tools/perf/tests/attr.c
@@ -18,10 +18,16 @@
18 * permissions. All the event text files are stored there. 18 * permissions. All the event text files are stored there.
19 */ 19 */
20 20
21#include <errno.h>
22#include <inttypes.h>
21#include <stdlib.h> 23#include <stdlib.h>
22#include <stdio.h> 24#include <stdio.h>
23#include <linux/types.h> 25#include <linux/types.h>
24#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <sys/param.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
25#include "../perf.h" 31#include "../perf.h"
26#include "util.h" 32#include "util.h"
27#include <subcmd/exec-cmd.h> 33#include <subcmd/exec-cmd.h>
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c
index 42e892b1e979..50f6d7afee58 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -8,6 +8,7 @@
8#include <sys/prctl.h> 8#include <sys/prctl.h>
9#include "tests.h" 9#include "tests.h"
10#include "debug.h" 10#include "debug.h"
11#include <errno.h>
11 12
12#define NR_ITERS 111 13#define NR_ITERS 111
13 14
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index 1a04fe77487d..5876da126b58 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -1,10 +1,14 @@
1#include <errno.h>
1#include <stdio.h> 2#include <stdio.h>
2#include <sys/epoll.h> 3#include <sys/epoll.h>
4#include <sys/types.h>
5#include <sys/stat.h>
3#include <util/util.h> 6#include <util/util.h>
4#include <util/bpf-loader.h> 7#include <util/bpf-loader.h>
5#include <util/evlist.h> 8#include <util/evlist.h>
6#include <linux/bpf.h> 9#include <linux/bpf.h>
7#include <linux/filter.h> 10#include <linux/filter.h>
11#include <linux/kernel.h>
8#include <api/fs/fs.h> 12#include <api/fs/fs.h>
9#include <bpf/bpf.h> 13#include <bpf/bpf.h>
10#include "tests.h" 14#include "tests.h"
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 83c4669cbc5b..9e08d297f1a9 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -3,8 +3,10 @@
3 * 3 *
4 * Builtin regression testing command: ever growing number of sanity tests 4 * Builtin regression testing command: ever growing number of sanity tests
5 */ 5 */
6#include <errno.h>
6#include <unistd.h> 7#include <unistd.h>
7#include <string.h> 8#include <string.h>
9#include <sys/wait.h>
8#include "builtin.h" 10#include "builtin.h"
9#include "hist.h" 11#include "hist.h"
10#include "intlist.h" 12#include "intlist.h"
@@ -13,6 +15,7 @@
13#include "color.h" 15#include "color.h"
14#include <subcmd/parse-options.h> 16#include <subcmd/parse-options.h>
15#include "symbol.h" 17#include "symbol.h"
18#include <linux/kernel.h>
16 19
17static bool dont_fork; 20static bool dont_fork;
18 21
@@ -44,6 +47,10 @@ static struct test generic_tests[] = {
44 .func = test__parse_events, 47 .func = test__parse_events,
45 }, 48 },
46 { 49 {
50 .desc = "Simple expression parser",
51 .func = test__expr,
52 },
53 {
47 .desc = "PERF_RECORD_* events & perf_sample fields", 54 .desc = "PERF_RECORD_* events & perf_sample fields",
48 .func = test__PERF_RECORD, 55 .func = test__PERF_RECORD,
49 }, 56 },
@@ -460,7 +467,7 @@ static int perf_test__list(int argc, const char **argv)
460 return 0; 467 return 0;
461} 468}
462 469
463int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused) 470int cmd_test(int argc, const char **argv)
464{ 471{
465 const char *test_usage[] = { 472 const char *test_usage[] = {
466 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]", 473 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c
index f853e242a86c..c5bb2203f5a9 100644
--- a/tools/perf/tests/clang.c
+++ b/tools/perf/tests/clang.c
@@ -2,6 +2,7 @@
2#include "debug.h" 2#include "debug.h"
3#include "util.h" 3#include "util.h"
4#include "c++/clang-c.h" 4#include "c++/clang-c.h"
5#include <linux/kernel.h>
5 6
6static struct { 7static struct {
7 int (*func)(void); 8 int (*func)(void);
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index d1f693041324..1f14e7612cbb 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -1,9 +1,12 @@
1#include <errno.h>
2#include <linux/kernel.h>
1#include <linux/types.h> 3#include <linux/types.h>
4#include <inttypes.h>
2#include <stdlib.h> 5#include <stdlib.h>
3#include <unistd.h> 6#include <unistd.h>
4#include <stdio.h> 7#include <stdio.h>
5#include <ctype.h>
6#include <string.h> 8#include <string.h>
9#include <sys/param.h>
7 10
8#include "parse-events.h" 11#include "parse-events.h"
9#include "evlist.h" 12#include "evlist.h"
@@ -16,6 +19,8 @@
16 19
17#include "tests.h" 20#include "tests.h"
18 21
22#include "sane_ctype.h"
23
19#define BUFSZ 1024 24#define BUFSZ 1024
20#define READLEN 128 25#define READLEN 128
21 26
diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c
index f168a85992d0..4478773cdb97 100644
--- a/tools/perf/tests/cpumap.c
+++ b/tools/perf/tests/cpumap.c
@@ -66,7 +66,7 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
66 TEST_ASSERT_VAL("wrong nr", map->nr == 2); 66 TEST_ASSERT_VAL("wrong nr", map->nr == 2);
67 TEST_ASSERT_VAL("wrong cpu", map->map[0] == 1); 67 TEST_ASSERT_VAL("wrong cpu", map->map[0] == 1);
68 TEST_ASSERT_VAL("wrong cpu", map->map[1] == 256); 68 TEST_ASSERT_VAL("wrong cpu", map->map[1] == 256);
69 TEST_ASSERT_VAL("wrong refcnt", atomic_read(&map->refcnt) == 1); 69 TEST_ASSERT_VAL("wrong refcnt", refcount_read(&map->refcnt) == 1);
70 cpu_map__put(map); 70 cpu_map__put(map);
71 return 0; 71 return 0;
72} 72}
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index 13725e09ba22..8f08df5861cb 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -1,4 +1,6 @@
1#include <dirent.h>
1#include <stdlib.h> 2#include <stdlib.h>
3#include <linux/kernel.h>
2#include <linux/types.h> 4#include <linux/types.h>
3#include <sys/stat.h> 5#include <sys/stat.h>
4#include <fcntl.h> 6#include <fcntl.h>
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 1046491de4b2..dfe5c89e2049 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -1,5 +1,6 @@
1#include <linux/compiler.h> 1#include <linux/compiler.h>
2#include <linux/types.h> 2#include <linux/types.h>
3#include <inttypes.h>
3#include <unistd.h> 4#include <unistd.h>
4#include "tests.h" 5#include "tests.h"
5#include "debug.h" 6#include "debug.h"
diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c
index 19ef77bd6eb4..634f20c631d8 100644
--- a/tools/perf/tests/event-times.c
+++ b/tools/perf/tests/event-times.c
@@ -1,5 +1,8 @@
1#include <linux/compiler.h> 1#include <linux/compiler.h>
2#include <errno.h>
3#include <inttypes.h>
2#include <string.h> 4#include <string.h>
5#include <sys/wait.h>
3#include "tests.h" 6#include "tests.h"
4#include "evlist.h" 7#include "evlist.h"
5#include "evsel.h" 8#include "evsel.h"
diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c
index 60926a1f6fd7..d2bea6f780f8 100644
--- a/tools/perf/tests/evsel-roundtrip-name.c
+++ b/tools/perf/tests/evsel-roundtrip-name.c
@@ -3,6 +3,8 @@
3#include "parse-events.h" 3#include "parse-events.h"
4#include "tests.h" 4#include "tests.h"
5#include "debug.h" 5#include "debug.h"
6#include <errno.h>
7#include <linux/kernel.h>
6 8
7static int perf_evsel__roundtrip_cache_name_test(void) 9static int perf_evsel__roundtrip_cache_name_test(void)
8{ 10{
diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c
new file mode 100644
index 000000000000..6c6a3749aaf6
--- /dev/null
+++ b/tools/perf/tests/expr.c
@@ -0,0 +1,56 @@
1#include "util/debug.h"
2#include "util/expr.h"
3#include "tests.h"
4#include <stdlib.h>
5
6static int test(struct parse_ctx *ctx, const char *e, double val2)
7{
8 double val;
9
10 if (expr__parse(&val, ctx, &e))
11 TEST_ASSERT_VAL("parse test failed", 0);
12 TEST_ASSERT_VAL("unexpected value", val == val2);
13 return 0;
14}
15
16int test__expr(int subtest __maybe_unused)
17{
18 const char *p;
19 const char **other;
20 double val;
21 int ret;
22 struct parse_ctx ctx;
23 int num_other;
24
25 expr__ctx_init(&ctx);
26 expr__add_id(&ctx, "FOO", 1);
27 expr__add_id(&ctx, "BAR", 2);
28
29 ret = test(&ctx, "1+1", 2);
30 ret |= test(&ctx, "FOO+BAR", 3);
31 ret |= test(&ctx, "(BAR/2)%2", 1);
32 ret |= test(&ctx, "1 - -4", 5);
33 ret |= test(&ctx, "(FOO-1)*2 + (BAR/2)%2 - -4", 5);
34
35 if (ret)
36 return ret;
37
38 p = "FOO/0";
39 ret = expr__parse(&val, &ctx, &p);
40 TEST_ASSERT_VAL("division by zero", ret == 1);
41
42 p = "BAR/";
43 ret = expr__parse(&val, &ctx, &p);
44 TEST_ASSERT_VAL("missing operand", ret == 1);
45
46 TEST_ASSERT_VAL("find other",
47 expr__find_other("FOO + BAR + BAZ + BOZO", "FOO", &other, &num_other) == 0);
48 TEST_ASSERT_VAL("find other", num_other == 3);
49 TEST_ASSERT_VAL("find other", !strcmp(other[0], "BAR"));
50 TEST_ASSERT_VAL("find other", !strcmp(other[1], "BAZ"));
51 TEST_ASSERT_VAL("find other", !strcmp(other[2], "BOZO"));
52 TEST_ASSERT_VAL("find other", other[3] == NULL);
53 free((void *)other);
54
55 return 0;
56}
diff --git a/tools/perf/tests/hists_common.c b/tools/perf/tests/hists_common.c
index 6b21746d6eec..00b8dc50f3db 100644
--- a/tools/perf/tests/hists_common.c
+++ b/tools/perf/tests/hists_common.c
@@ -1,3 +1,4 @@
1#include <inttypes.h>
1#include "perf.h" 2#include "perf.h"
2#include "util/debug.h" 3#include "util/debug.h"
3#include "util/symbol.h" 4#include "util/symbol.h"
@@ -7,6 +8,7 @@
7#include "util/machine.h" 8#include "util/machine.h"
8#include "util/thread.h" 9#include "util/thread.h"
9#include "tests/hists_common.h" 10#include "tests/hists_common.h"
11#include <linux/kernel.h>
10 12
11static struct { 13static struct {
12 u32 pid; 14 u32 pid;
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index 9fd54b79a788..d549a9f2c41b 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -1,5 +1,6 @@
1#include "perf.h" 1#include "perf.h"
2#include "util/debug.h" 2#include "util/debug.h"
3#include "util/event.h"
3#include "util/symbol.h" 4#include "util/symbol.h"
4#include "util/sort.h" 5#include "util/sort.h"
5#include "util/evsel.h" 6#include "util/evsel.h"
@@ -9,6 +10,7 @@
9#include "util/parse-events.h" 10#include "util/parse-events.h"
10#include "tests/tests.h" 11#include "tests/tests.h"
11#include "tests/hists_common.h" 12#include "tests/hists_common.h"
13#include <linux/kernel.h>
12 14
13struct sample { 15struct sample {
14 u32 pid; 16 u32 pid;
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index 62efb14f3a5a..df9c91f49af1 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -3,12 +3,14 @@
3#include "util/symbol.h" 3#include "util/symbol.h"
4#include "util/sort.h" 4#include "util/sort.h"
5#include "util/evsel.h" 5#include "util/evsel.h"
6#include "util/event.h"
6#include "util/evlist.h" 7#include "util/evlist.h"
7#include "util/machine.h" 8#include "util/machine.h"
8#include "util/thread.h" 9#include "util/thread.h"
9#include "util/parse-events.h" 10#include "util/parse-events.h"
10#include "tests/tests.h" 11#include "tests/tests.h"
11#include "tests/hists_common.h" 12#include "tests/hists_common.h"
13#include <linux/kernel.h>
12 14
13struct sample { 15struct sample {
14 u32 pid; 16 u32 pid;
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index eddc7407ff8a..a26cbb79e988 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -9,6 +9,8 @@
9#include "thread.h" 9#include "thread.h"
10#include "parse-events.h" 10#include "parse-events.h"
11#include "hists_common.h" 11#include "hists_common.h"
12#include <errno.h>
13#include <linux/kernel.h>
12 14
13struct sample { 15struct sample {
14 u32 pid; 16 u32 pid;
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index 63c5efaba1b5..06e5080182d3 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -1,5 +1,6 @@
1#include "perf.h" 1#include "perf.h"
2#include "util/debug.h" 2#include "util/debug.h"
3#include "util/event.h"
3#include "util/symbol.h" 4#include "util/symbol.h"
4#include "util/sort.h" 5#include "util/sort.h"
5#include "util/evsel.h" 6#include "util/evsel.h"
@@ -9,6 +10,7 @@
9#include "util/parse-events.h" 10#include "util/parse-events.h"
10#include "tests/tests.h" 11#include "tests/tests.h"
11#include "tests/hists_common.h" 12#include "tests/hists_common.h"
13#include <linux/kernel.h>
12 14
13struct sample { 15struct sample {
14 u32 cpu; 16 u32 cpu;
diff --git a/tools/perf/tests/is_printable_array.c b/tools/perf/tests/is_printable_array.c
index 42e13393e502..a5192f6a20d7 100644
--- a/tools/perf/tests/is_printable_array.c
+++ b/tools/perf/tests/is_printable_array.c
@@ -1,7 +1,8 @@
1#include <linux/compiler.h> 1#include <linux/compiler.h>
2#include <linux/kernel.h>
2#include "tests.h" 3#include "tests.h"
3#include "debug.h" 4#include "debug.h"
4#include "util.h" 5#include "print_binary.h"
5 6
6int test__is_printable_array(int subtest __maybe_unused) 7int test__is_printable_array(int subtest __maybe_unused)
7{ 8{
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 634bce9caebd..15c770856aac 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -1,3 +1,5 @@
1#include <errno.h>
2#include <inttypes.h>
1/* For the CLR_() macros */ 3/* For the CLR_() macros */
2#include <pthread.h> 4#include <pthread.h>
3 5
@@ -7,6 +9,7 @@
7#include "cpumap.h" 9#include "cpumap.h"
8#include "tests.h" 10#include "tests.h"
9#include <linux/err.h> 11#include <linux/err.h>
12#include <linux/kernel.h>
10 13
11/* 14/*
12 * This test will generate random numbers of calls to some getpid syscalls, 15 * This test will generate random numbers of calls to some getpid syscalls,
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c
index 0c5ce44f723f..6ea4d8a5d26b 100644
--- a/tools/perf/tests/mmap-thread-lookup.c
+++ b/tools/perf/tests/mmap-thread-lookup.c
@@ -1,3 +1,4 @@
1#include <inttypes.h>
1#include <unistd.h> 2#include <unistd.h>
2#include <sys/syscall.h> 3#include <sys/syscall.h>
3#include <sys/types.h> 4#include <sys/types.h>
@@ -11,6 +12,7 @@
11#include "thread_map.h" 12#include "thread_map.h"
12#include "symbol.h" 13#include "symbol.h"
13#include "thread.h" 14#include "thread.h"
15#include "util.h"
14 16
15#define THREADS 4 17#define THREADS 4
16 18
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index c8d9592eb142..1a74dd9fd067 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -1,8 +1,14 @@
1#include <errno.h>
2#include <inttypes.h>
1/* For the CPU_* macros */ 3/* For the CPU_* macros */
2#include <pthread.h> 4#include <pthread.h>
3 5
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <fcntl.h>
4#include <api/fs/fs.h> 9#include <api/fs/fs.h>
5#include <linux/err.h> 10#include <linux/err.h>
11#include <api/fs/tracing_path.h>
6#include "evsel.h" 12#include "evsel.h"
7#include "tests.h" 13#include "tests.h"
8#include "thread_map.h" 14#include "thread_map.h"
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
index f52239fed361..9788fac91095 100644
--- a/tools/perf/tests/openat-syscall-tp-fields.c
+++ b/tools/perf/tests/openat-syscall-tp-fields.c
@@ -5,6 +5,7 @@
5#include "thread_map.h" 5#include "thread_map.h"
6#include "tests.h" 6#include "tests.h"
7#include "debug.h" 7#include "debug.h"
8#include <errno.h>
8 9
9#ifndef O_DIRECTORY 10#ifndef O_DIRECTORY
10#define O_DIRECTORY 00200000 11#define O_DIRECTORY 00200000
diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c
index d7414128d7fe..e44506e21ee7 100644
--- a/tools/perf/tests/openat-syscall.c
+++ b/tools/perf/tests/openat-syscall.c
@@ -1,5 +1,10 @@
1#include <errno.h>
2#include <inttypes.h>
1#include <api/fs/tracing_path.h> 3#include <api/fs/tracing_path.h>
2#include <linux/err.h> 4#include <linux/err.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <fcntl.h>
3#include "thread_map.h" 8#include "thread_map.h"
4#include "evsel.h" 9#include "evsel.h"
5#include "debug.h" 10#include "debug.h"
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 1dc838014422..7fad885491c5 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -1,4 +1,3 @@
1
2#include "parse-events.h" 1#include "parse-events.h"
3#include "evsel.h" 2#include "evsel.h"
4#include "evlist.h" 3#include "evlist.h"
@@ -6,8 +5,15 @@
6#include "tests.h" 5#include "tests.h"
7#include "debug.h" 6#include "debug.h"
8#include "util.h" 7#include "util.h"
8#include <dirent.h>
9#include <errno.h>
10#include <sys/types.h>
11#include <sys/stat.h>
12#include <unistd.h>
13#include <linux/kernel.h>
9#include <linux/hw_breakpoint.h> 14#include <linux/hw_breakpoint.h>
10#include <api/fs/fs.h> 15#include <api/fs/fs.h>
16#include <api/fs/tracing_path.h>
11 17
12#define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \ 18#define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \
13 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) 19 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD)
diff --git a/tools/perf/tests/parse-no-sample-id-all.c b/tools/perf/tests/parse-no-sample-id-all.c
index 65dcf48a92fb..c6207db09f12 100644
--- a/tools/perf/tests/parse-no-sample-id-all.c
+++ b/tools/perf/tests/parse-no-sample-id-all.c
@@ -1,3 +1,4 @@
1#include <linux/kernel.h>
1#include <linux/types.h> 2#include <linux/types.h>
2#include <stddef.h> 3#include <stddef.h>
3 4
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 87893f3ba5f1..d37cd9588cc0 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -1,3 +1,5 @@
1#include <errno.h>
2#include <inttypes.h>
1/* For the CLR_() macros */ 3/* For the CLR_() macros */
2#include <pthread.h> 4#include <pthread.h>
3 5
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index 1e2ba2602930..a6d7aef30030 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -2,6 +2,8 @@
2#include "pmu.h" 2#include "pmu.h"
3#include "util.h" 3#include "util.h"
4#include "tests.h" 4#include "tests.h"
5#include <errno.h>
6#include <linux/kernel.h>
5 7
6/* Simulated format definitions. */ 8/* Simulated format definitions. */
7static struct test_format { 9static struct test_format {
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index 5f23710b9fee..bac5c3885b3b 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -1,4 +1,6 @@
1#include <stdbool.h> 1#include <stdbool.h>
2#include <inttypes.h>
3#include <linux/kernel.h>
2#include <linux/types.h> 4#include <linux/types.h>
3 5
4#include "util.h" 6#include "util.h"
diff --git a/tools/perf/tests/sdt.c b/tools/perf/tests/sdt.c
index f59d210e1baf..06eda675ae2c 100644
--- a/tools/perf/tests/sdt.c
+++ b/tools/perf/tests/sdt.c
@@ -1,6 +1,6 @@
1#include <errno.h>
1#include <stdio.h> 2#include <stdio.h>
2#include <sys/epoll.h> 3#include <sys/epoll.h>
3#include <util/util.h>
4#include <util/evlist.h> 4#include <util/evlist.h>
5#include <linux/filter.h> 5#include <linux/filter.h>
6#include "tests.h" 6#include "tests.h"
@@ -43,7 +43,7 @@ static char *get_self_path(void)
43{ 43{
44 char *buf = calloc(PATH_MAX, sizeof(char)); 44 char *buf = calloc(PATH_MAX, sizeof(char));
45 45
46 if (buf && readlink("/proc/self/exe", buf, PATH_MAX) < 0) { 46 if (buf && readlink("/proc/self/exe", buf, PATH_MAX - 1) < 0) {
47 pr_debug("Failed to get correct path of perf\n"); 47 pr_debug("Failed to get correct path of perf\n");
48 free(buf); 48 free(buf);
49 return NULL; 49 return NULL;
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index 4c9fd046d57b..828494db4a19 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -1,3 +1,5 @@
1#include <errno.h>
2#include <inttypes.h>
1#include <unistd.h> 3#include <unistd.h>
2#include <stdlib.h> 4#include <stdlib.h>
3#include <signal.h> 5#include <signal.h>
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
index 7ddbe267d0ac..65474fd80da7 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -1,5 +1,6 @@
1#include <sys/time.h> 1#include <sys/time.h>
2#include <sys/prctl.h> 2#include <sys/prctl.h>
3#include <errno.h>
3#include <time.h> 4#include <time.h>
4#include <stdlib.h> 5#include <stdlib.h>
5 6
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index 01a5ba2788c6..32873ec91a4e 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -4,6 +4,7 @@
4#include "cpumap.h" 4#include "cpumap.h"
5#include "tests.h" 5#include "tests.h"
6 6
7#include <errno.h>
7#include <signal.h> 8#include <signal.h>
8 9
9static int exited; 10static int exited;
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 1fa9b9d83aa5..631859629403 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -62,6 +62,7 @@ int test__sample_parsing(int subtest);
62int test__keep_tracking(int subtest); 62int test__keep_tracking(int subtest);
63int test__parse_no_sample_id_all(int subtest); 63int test__parse_no_sample_id_all(int subtest);
64int test__dwarf_unwind(int subtest); 64int test__dwarf_unwind(int subtest);
65int test__expr(int subtest);
65int test__hists_filter(int subtest); 66int test__hists_filter(int subtest);
66int test__mmap_thread_lookup(int subtest); 67int test__mmap_thread_lookup(int subtest);
67int test__thread_mg_share(int subtest); 68int test__thread_mg_share(int subtest);
diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
index f2d2e542d0ee..a63d6945807b 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -29,7 +29,7 @@ int test__thread_map(int subtest __maybe_unused)
29 thread_map__comm(map, 0) && 29 thread_map__comm(map, 0) &&
30 !strcmp(thread_map__comm(map, 0), NAME)); 30 !strcmp(thread_map__comm(map, 0), NAME));
31 TEST_ASSERT_VAL("wrong refcnt", 31 TEST_ASSERT_VAL("wrong refcnt",
32 atomic_read(&map->refcnt) == 1); 32 refcount_read(&map->refcnt) == 1);
33 thread_map__put(map); 33 thread_map__put(map);
34 34
35 /* test dummy pid */ 35 /* test dummy pid */
@@ -44,7 +44,7 @@ int test__thread_map(int subtest __maybe_unused)
44 thread_map__comm(map, 0) && 44 thread_map__comm(map, 0) &&
45 !strcmp(thread_map__comm(map, 0), "dummy")); 45 !strcmp(thread_map__comm(map, 0), "dummy"));
46 TEST_ASSERT_VAL("wrong refcnt", 46 TEST_ASSERT_VAL("wrong refcnt",
47 atomic_read(&map->refcnt) == 1); 47 refcount_read(&map->refcnt) == 1);
48 thread_map__put(map); 48 thread_map__put(map);
49 return 0; 49 return 0;
50} 50}
@@ -71,7 +71,7 @@ static int process_event(struct perf_tool *tool __maybe_unused,
71 thread_map__comm(threads, 0) && 71 thread_map__comm(threads, 0) &&
72 !strcmp(thread_map__comm(threads, 0), NAME)); 72 !strcmp(thread_map__comm(threads, 0), NAME));
73 TEST_ASSERT_VAL("wrong refcnt", 73 TEST_ASSERT_VAL("wrong refcnt",
74 atomic_read(&threads->refcnt) == 1); 74 refcount_read(&threads->refcnt) == 1);
75 thread_map__put(threads); 75 thread_map__put(threads);
76 return 0; 76 return 0;
77} 77}
diff --git a/tools/perf/tests/thread-mg-share.c b/tools/perf/tests/thread-mg-share.c
index 188b63140fc8..76686dd6f5ec 100644
--- a/tools/perf/tests/thread-mg-share.c
+++ b/tools/perf/tests/thread-mg-share.c
@@ -43,7 +43,7 @@ int test__thread_mg_share(int subtest __maybe_unused)
43 leader && t1 && t2 && t3 && other); 43 leader && t1 && t2 && t3 && other);
44 44
45 mg = leader->mg; 45 mg = leader->mg;
46 TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 4); 46 TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&mg->refcnt), 4);
47 47
48 /* test the map groups pointer is shared */ 48 /* test the map groups pointer is shared */
49 TEST_ASSERT_VAL("map groups don't match", mg == t1->mg); 49 TEST_ASSERT_VAL("map groups don't match", mg == t1->mg);
@@ -71,25 +71,25 @@ int test__thread_mg_share(int subtest __maybe_unused)
71 machine__remove_thread(machine, other_leader); 71 machine__remove_thread(machine, other_leader);
72 72
73 other_mg = other->mg; 73 other_mg = other->mg;
74 TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&other_mg->refcnt), 2); 74 TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&other_mg->refcnt), 2);
75 75
76 TEST_ASSERT_VAL("map groups don't match", other_mg == other_leader->mg); 76 TEST_ASSERT_VAL("map groups don't match", other_mg == other_leader->mg);
77 77
78 /* release thread group */ 78 /* release thread group */
79 thread__put(leader); 79 thread__put(leader);
80 TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 3); 80 TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&mg->refcnt), 3);
81 81
82 thread__put(t1); 82 thread__put(t1);
83 TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 2); 83 TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&mg->refcnt), 2);
84 84
85 thread__put(t2); 85 thread__put(t2);
86 TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 1); 86 TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&mg->refcnt), 1);
87 87
88 thread__put(t3); 88 thread__put(t3);
89 89
90 /* release other group */ 90 /* release other group */
91 thread__put(other_leader); 91 thread__put(other_leader);
92 TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&other_mg->refcnt), 1); 92 TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&other_mg->refcnt), 1);
93 93
94 thread__put(other); 94 thread__put(other);
95 95
diff --git a/tools/perf/tests/unit_number__scnprintf.c b/tools/perf/tests/unit_number__scnprintf.c
index 623c2aa53c4a..44589de084b8 100644
--- a/tools/perf/tests/unit_number__scnprintf.c
+++ b/tools/perf/tests/unit_number__scnprintf.c
@@ -1,7 +1,8 @@
1#include <inttypes.h>
1#include <linux/compiler.h> 2#include <linux/compiler.h>
2#include <linux/types.h> 3#include <linux/types.h>
3#include "tests.h" 4#include "tests.h"
4#include "util.h" 5#include "units.h"
5#include "debug.h" 6#include "debug.h"
6 7
7int test__unit_number__scnprint(int subtest __maybe_unused) 8int test__unit_number__scnprint(int subtest __maybe_unused)
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index 862b043e5924..8456175fc234 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -1,5 +1,6 @@
1#include <linux/compiler.h> 1#include <linux/compiler.h>
2#include <linux/rbtree.h> 2#include <linux/rbtree.h>
3#include <inttypes.h>
3#include <string.h> 4#include <string.h>
4#include "map.h" 5#include "map.h"
5#include "symbol.h" 6#include "symbol.h"
diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build
new file mode 100644
index 000000000000..be95ac6ce845
--- /dev/null
+++ b/tools/perf/trace/beauty/Build
@@ -0,0 +1 @@
libperf-y += statx.o
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
new file mode 100644
index 000000000000..cf50be3f17a4
--- /dev/null
+++ b/tools/perf/trace/beauty/beauty.h
@@ -0,0 +1,24 @@
1#ifndef _PERF_TRACE_BEAUTY_H
2#define _PERF_TRACE_BEAUTY_H
3
4#include <linux/types.h>
5
6struct trace;
7struct thread;
8
9struct syscall_arg {
10 unsigned long val;
11 struct thread *thread;
12 struct trace *trace;
13 void *parm;
14 u8 idx;
15 u8 mask;
16};
17
18size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg);
19#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags
20
21size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_arg *arg);
22#define SCA_STATX_MASK syscall_arg__scnprintf_statx_mask
23
24#endif /* _PERF_TRACE_BEAUTY_H */
diff --git a/tools/perf/trace/beauty/signum.c b/tools/perf/trace/beauty/signum.c
index d3b0b1fab077..fde8f2fc6558 100644
--- a/tools/perf/trace/beauty/signum.c
+++ b/tools/perf/trace/beauty/signum.c
@@ -1,3 +1,4 @@
1#include <signal.h>
1 2
2static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg) 3static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
3{ 4{
diff --git a/tools/perf/trace/beauty/statx.c b/tools/perf/trace/beauty/statx.c
new file mode 100644
index 000000000000..5643b692af4c
--- /dev/null
+++ b/tools/perf/trace/beauty/statx.c
@@ -0,0 +1,72 @@
1/*
2 * trace/beauty/statx.c
3 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */
8
9#include "trace/beauty/beauty.h"
10#include <linux/kernel.h>
11#include <sys/types.h>
12#include <uapi/linux/fcntl.h>
13#include <uapi/linux/stat.h>
14
15size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg)
16{
17 int printed = 0, flags = arg->val;
18
19 if (flags == 0)
20 return scnprintf(bf, size, "SYNC_AS_STAT");
21#define P_FLAG(n) \
22 if (flags & AT_##n) { \
23 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
24 flags &= ~AT_##n; \
25 }
26
27 P_FLAG(SYMLINK_NOFOLLOW);
28 P_FLAG(REMOVEDIR);
29 P_FLAG(SYMLINK_FOLLOW);
30 P_FLAG(NO_AUTOMOUNT);
31 P_FLAG(EMPTY_PATH);
32 P_FLAG(STATX_FORCE_SYNC);
33 P_FLAG(STATX_DONT_SYNC);
34
35#undef P_FLAG
36
37 if (flags)
38 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
39
40 return printed;
41}
42
43size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_arg *arg)
44{
45 int printed = 0, flags = arg->val;
46
47#define P_FLAG(n) \
48 if (flags & STATX_##n) { \
49 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
50 flags &= ~STATX_##n; \
51 }
52
53 P_FLAG(TYPE);
54 P_FLAG(MODE);
55 P_FLAG(NLINK);
56 P_FLAG(UID);
57 P_FLAG(GID);
58 P_FLAG(ATIME);
59 P_FLAG(MTIME);
60 P_FLAG(CTIME);
61 P_FLAG(INO);
62 P_FLAG(SIZE);
63 P_FLAG(BLOCKS);
64 P_FLAG(BTIME);
65
66#undef P_FLAG
67
68 if (flags)
69 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
70
71 return printed;
72}
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index 3eb3edb307a4..a4d3762cd825 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -1,4 +1,5 @@
1#include "../util.h" 1#include "../util.h"
2#include "../string2.h"
2#include "../config.h" 3#include "../config.h"
3#include "../../perf.h" 4#include "../../perf.h"
4#include "libslang.h" 5#include "libslang.h"
@@ -13,6 +14,7 @@
13#include "helpline.h" 14#include "helpline.h"
14#include "keysyms.h" 15#include "keysyms.h"
15#include "../color.h" 16#include "../color.h"
17#include "sane_ctype.h"
16 18
17static int ui_browser__percent_color(struct ui_browser *browser, 19static int ui_browser__percent_color(struct ui_browser *browser,
18 double percent, bool current) 20 double percent, bool current)
@@ -579,7 +581,7 @@ static int ui_browser__color_config(const char *var, const char *value,
579 break; 581 break;
580 582
581 *bg = '\0'; 583 *bg = '\0';
582 while (isspace(*++bg)); 584 bg = ltrim(++bg);
583 ui_browser__colorsets[i].bg = bg; 585 ui_browser__colorsets[i].bg = bg;
584 ui_browser__colorsets[i].fg = fg; 586 ui_browser__colorsets[i].fg = fg;
585 return 0; 587 return 0;
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index ba36aac340bc..d990ad08a3c6 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -9,7 +9,10 @@
9#include "../../util/symbol.h" 9#include "../../util/symbol.h"
10#include "../../util/evsel.h" 10#include "../../util/evsel.h"
11#include "../../util/config.h" 11#include "../../util/config.h"
12#include <inttypes.h>
12#include <pthread.h> 13#include <pthread.h>
14#include <linux/kernel.h>
15#include <sys/ttydefaults.h>
13 16
14struct disasm_line_samples { 17struct disasm_line_samples {
15 double percent; 18 double percent;
diff --git a/tools/perf/ui/browsers/header.c b/tools/perf/ui/browsers/header.c
index edbeaaf31ace..e2c9390ff4c5 100644
--- a/tools/perf/ui/browsers/header.c
+++ b/tools/perf/ui/browsers/header.c
@@ -8,6 +8,8 @@
8#include "util/header.h" 8#include "util/header.h"
9#include "util/session.h" 9#include "util/session.h"
10 10
11#include <sys/ttydefaults.h>
12
11static void ui_browser__argv_write(struct ui_browser *browser, 13static void ui_browser__argv_write(struct ui_browser *browser,
12 void *entry, int row) 14 void *entry, int row)
13{ 15{
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index fc4fb669ceee..69f4570bd4f9 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1,7 +1,11 @@
1#include <dirent.h>
2#include <errno.h>
3#include <inttypes.h>
1#include <stdio.h> 4#include <stdio.h>
2#include <stdlib.h> 5#include <stdlib.h>
3#include <string.h> 6#include <string.h>
4#include <linux/rbtree.h> 7#include <linux/rbtree.h>
8#include <sys/ttydefaults.h>
5 9
6#include "../../util/evsel.h" 10#include "../../util/evsel.h"
7#include "../../util/evlist.h" 11#include "../../util/evlist.h"
@@ -10,6 +14,7 @@
10#include "../../util/sort.h" 14#include "../../util/sort.h"
11#include "../../util/util.h" 15#include "../../util/util.h"
12#include "../../util/top.h" 16#include "../../util/top.h"
17#include "../../util/thread.h"
13#include "../../arch/common.h" 18#include "../../arch/common.h"
14 19
15#include "../browsers/hists.h" 20#include "../browsers/hists.h"
@@ -18,6 +23,11 @@
18#include "../ui.h" 23#include "../ui.h"
19#include "map.h" 24#include "map.h"
20#include "annotate.h" 25#include "annotate.h"
26#include "srcline.h"
27#include "string2.h"
28#include "units.h"
29
30#include "sane_ctype.h"
21 31
22extern void hist_browser__init_hpp(void); 32extern void hist_browser__init_hpp(void);
23 33
@@ -144,9 +154,60 @@ static void callchain_list__set_folding(struct callchain_list *cl, bool unfold)
144 cl->unfolded = unfold ? cl->has_children : false; 154 cl->unfolded = unfold ? cl->has_children : false;
145} 155}
146 156
157static struct inline_node *inline_node__create(struct map *map, u64 ip)
158{
159 struct dso *dso;
160 struct inline_node *node;
161
162 if (map == NULL)
163 return NULL;
164
165 dso = map->dso;
166 if (dso == NULL)
167 return NULL;
168
169 if (dso->kernel != DSO_TYPE_USER)
170 return NULL;
171
172 node = dso__parse_addr_inlines(dso,
173 map__rip_2objdump(map, ip));
174
175 return node;
176}
177
178static int inline__count_rows(struct inline_node *node)
179{
180 struct inline_list *ilist;
181 int i = 0;
182
183 if (node == NULL)
184 return 0;
185
186 list_for_each_entry(ilist, &node->val, list) {
187 if ((ilist->filename != NULL) || (ilist->funcname != NULL))
188 i++;
189 }
190
191 return i;
192}
193
194static int callchain_list__inline_rows(struct callchain_list *chain)
195{
196 struct inline_node *node;
197 int rows;
198
199 node = inline_node__create(chain->ms.map, chain->ip);
200 if (node == NULL)
201 return 0;
202
203 rows = inline__count_rows(node);
204 inline_node__delete(node);
205 return rows;
206}
207
147static int callchain_node__count_rows_rb_tree(struct callchain_node *node) 208static int callchain_node__count_rows_rb_tree(struct callchain_node *node)
148{ 209{
149 int n = 0; 210 int n = 0, inline_rows;
150 struct rb_node *nd; 211 struct rb_node *nd;
151 212
152 for (nd = rb_first(&node->rb_root); nd; nd = rb_next(nd)) { 213 for (nd = rb_first(&node->rb_root); nd; nd = rb_next(nd)) {
@@ -156,6 +217,13 @@ static int callchain_node__count_rows_rb_tree(struct callchain_node *node)
156 217
157 list_for_each_entry(chain, &child->val, list) { 218 list_for_each_entry(chain, &child->val, list) {
158 ++n; 219 ++n;
220
221 if (symbol_conf.inline_name) {
222 inline_rows =
223 callchain_list__inline_rows(chain);
224 n += inline_rows;
225 }
226
159 /* We need this because we may not have children */ 227 /* We need this because we may not have children */
160 folded_sign = callchain_list__folded(chain); 228 folded_sign = callchain_list__folded(chain);
161 if (folded_sign == '+') 229 if (folded_sign == '+')
@@ -207,7 +275,7 @@ static int callchain_node__count_rows(struct callchain_node *node)
207{ 275{
208 struct callchain_list *chain; 276 struct callchain_list *chain;
209 bool unfolded = false; 277 bool unfolded = false;
210 int n = 0; 278 int n = 0, inline_rows;
211 279
212 if (callchain_param.mode == CHAIN_FLAT) 280 if (callchain_param.mode == CHAIN_FLAT)
213 return callchain_node__count_flat_rows(node); 281 return callchain_node__count_flat_rows(node);
@@ -216,6 +284,11 @@ static int callchain_node__count_rows(struct callchain_node *node)
216 284
217 list_for_each_entry(chain, &node->val, list) { 285 list_for_each_entry(chain, &node->val, list) {
218 ++n; 286 ++n;
287 if (symbol_conf.inline_name) {
288 inline_rows = callchain_list__inline_rows(chain);
289 n += inline_rows;
290 }
291
219 unfolded = chain->unfolded; 292 unfolded = chain->unfolded;
220 } 293 }
221 294
@@ -362,6 +435,19 @@ static void hist_entry__init_have_children(struct hist_entry *he)
362 he->init_have_children = true; 435 he->init_have_children = true;
363} 436}
364 437
438static void hist_entry_init_inline_node(struct hist_entry *he)
439{
440 if (he->inline_node)
441 return;
442
443 he->inline_node = inline_node__create(he->ms.map, he->ip);
444
445 if (he->inline_node == NULL)
446 return;
447
448 he->has_children = true;
449}
450
365static bool hist_browser__toggle_fold(struct hist_browser *browser) 451static bool hist_browser__toggle_fold(struct hist_browser *browser)
366{ 452{
367 struct hist_entry *he = browser->he_selection; 453 struct hist_entry *he = browser->he_selection;
@@ -393,7 +479,12 @@ static bool hist_browser__toggle_fold(struct hist_browser *browser)
393 479
394 if (he->unfolded) { 480 if (he->unfolded) {
395 if (he->leaf) 481 if (he->leaf)
396 he->nr_rows = callchain__count_rows(&he->sorted_chain); 482 if (he->inline_node)
483 he->nr_rows = inline__count_rows(
484 he->inline_node);
485 else
486 he->nr_rows = callchain__count_rows(
487 &he->sorted_chain);
397 else 488 else
398 he->nr_rows = hierarchy_count_rows(browser, he, false); 489 he->nr_rows = hierarchy_count_rows(browser, he, false);
399 490
@@ -753,6 +844,71 @@ static bool hist_browser__check_dump_full(struct hist_browser *browser __maybe_u
753 844
754#define LEVEL_OFFSET_STEP 3 845#define LEVEL_OFFSET_STEP 3
755 846
847static int hist_browser__show_inline(struct hist_browser *browser,
848 struct inline_node *node,
849 unsigned short row,
850 int offset)
851{
852 struct inline_list *ilist;
853 char buf[1024];
854 int color, width, first_row;
855
856 first_row = row;
857 width = browser->b.width - (LEVEL_OFFSET_STEP + 2);
858 list_for_each_entry(ilist, &node->val, list) {
859 if ((ilist->filename != NULL) || (ilist->funcname != NULL)) {
860 color = HE_COLORSET_NORMAL;
861 if (ui_browser__is_current_entry(&browser->b, row))
862 color = HE_COLORSET_SELECTED;
863
864 if (callchain_param.key == CCKEY_ADDRESS ||
865 callchain_param.key == CCKEY_SRCLINE) {
866 if (ilist->filename != NULL)
867 scnprintf(buf, sizeof(buf),
868 "%s:%d (inline)",
869 ilist->filename,
870 ilist->line_nr);
871 else
872 scnprintf(buf, sizeof(buf), "??");
873 } else if (ilist->funcname != NULL)
874 scnprintf(buf, sizeof(buf), "%s (inline)",
875 ilist->funcname);
876 else if (ilist->filename != NULL)
877 scnprintf(buf, sizeof(buf),
878 "%s:%d (inline)",
879 ilist->filename,
880 ilist->line_nr);
881 else
882 scnprintf(buf, sizeof(buf), "??");
883
884 ui_browser__set_color(&browser->b, color);
885 hist_browser__gotorc(browser, row, 0);
886 ui_browser__write_nstring(&browser->b, " ",
887 LEVEL_OFFSET_STEP + offset);
888 ui_browser__write_nstring(&browser->b, buf, width);
889 row++;
890 }
891 }
892
893 return row - first_row;
894}
895
896static size_t show_inline_list(struct hist_browser *browser, struct map *map,
897 u64 ip, int row, int offset)
898{
899 struct inline_node *node;
900 int ret;
901
902 node = inline_node__create(map, ip);
903 if (node == NULL)
904 return 0;
905
906 ret = hist_browser__show_inline(browser, node, row, offset);
907
908 inline_node__delete(node);
909 return ret;
910}
911
756static int hist_browser__show_callchain_list(struct hist_browser *browser, 912static int hist_browser__show_callchain_list(struct hist_browser *browser,
757 struct callchain_node *node, 913 struct callchain_node *node,
758 struct callchain_list *chain, 914 struct callchain_list *chain,
@@ -764,6 +920,7 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
764 char bf[1024], *alloc_str; 920 char bf[1024], *alloc_str;
765 char buf[64], *alloc_str2; 921 char buf[64], *alloc_str2;
766 const char *str; 922 const char *str;
923 int inline_rows = 0, ret = 1;
767 924
768 if (arg->row_offset != 0) { 925 if (arg->row_offset != 0) {
769 arg->row_offset--; 926 arg->row_offset--;
@@ -801,10 +958,15 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
801 } 958 }
802 959
803 print(browser, chain, str, offset, row, arg); 960 print(browser, chain, str, offset, row, arg);
804
805 free(alloc_str); 961 free(alloc_str);
806 free(alloc_str2); 962 free(alloc_str2);
807 return 1; 963
964 if (symbol_conf.inline_name) {
965 inline_rows = show_inline_list(browser, chain->ms.map,
966 chain->ip, row + 1, offset);
967 }
968
969 return ret + inline_rows;
808} 970}
809 971
810static bool check_percent_display(struct rb_node *node, u64 parent_total) 972static bool check_percent_display(struct rb_node *node, u64 parent_total)
@@ -1228,6 +1390,12 @@ static int hist_browser__show_entry(struct hist_browser *browser,
1228 folded_sign = hist_entry__folded(entry); 1390 folded_sign = hist_entry__folded(entry);
1229 } 1391 }
1230 1392
1393 if (symbol_conf.inline_name &&
1394 (!entry->has_children)) {
1395 hist_entry_init_inline_node(entry);
1396 folded_sign = hist_entry__folded(entry);
1397 }
1398
1231 if (row_offset == 0) { 1399 if (row_offset == 0) {
1232 struct hpp_arg arg = { 1400 struct hpp_arg arg = {
1233 .b = &browser->b, 1401 .b = &browser->b,
@@ -1259,7 +1427,8 @@ static int hist_browser__show_entry(struct hist_browser *browser,
1259 } 1427 }
1260 1428
1261 if (first) { 1429 if (first) {
1262 if (symbol_conf.use_callchain) { 1430 if (symbol_conf.use_callchain ||
1431 symbol_conf.inline_name) {
1263 ui_browser__printf(&browser->b, "%c ", folded_sign); 1432 ui_browser__printf(&browser->b, "%c ", folded_sign);
1264 width -= 2; 1433 width -= 2;
1265 } 1434 }
@@ -1301,8 +1470,14 @@ static int hist_browser__show_entry(struct hist_browser *browser,
1301 .is_current_entry = current_entry, 1470 .is_current_entry = current_entry,
1302 }; 1471 };
1303 1472
1304 printed += hist_browser__show_callchain(browser, entry, 1, row, 1473 if (entry->inline_node)
1305 hist_browser__show_callchain_entry, &arg, 1474 printed += hist_browser__show_inline(browser,
1475 entry->inline_node, row, 0);
1476 else
1477 printed += hist_browser__show_callchain(browser,
1478 entry, 1, row,
1479 hist_browser__show_callchain_entry,
1480 &arg,
1306 hist_browser__check_output_full); 1481 hist_browser__check_output_full);
1307 } 1482 }
1308 1483
@@ -2308,7 +2483,7 @@ static int switch_data_file(void)
2308 return ret; 2483 return ret;
2309 2484
2310 memset(options, 0, sizeof(options)); 2485 memset(options, 0, sizeof(options));
2311 memset(options, 0, sizeof(abs_path)); 2486 memset(abs_path, 0, sizeof(abs_path));
2312 2487
2313 while ((dent = readdir(pwd_dir))) { 2488 while ((dent = readdir(pwd_dir))) {
2314 char path[PATH_MAX]; 2489 char path[PATH_MAX];
diff --git a/tools/perf/ui/browsers/map.c b/tools/perf/ui/browsers/map.c
index 9ce142de536d..ffa5addf631d 100644
--- a/tools/perf/ui/browsers/map.c
+++ b/tools/perf/ui/browsers/map.c
@@ -11,6 +11,8 @@
11#include "../keysyms.h" 11#include "../keysyms.h"
12#include "map.h" 12#include "map.h"
13 13
14#include "sane_ctype.h"
15
14struct map_browser { 16struct map_browser {
15 struct ui_browser b; 17 struct ui_browser b;
16 struct map *map; 18 struct map *map;
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index 8c9308ac30b7..e99ba86158d2 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -3,7 +3,8 @@
3#include "util/annotate.h" 3#include "util/annotate.h"
4#include "util/evsel.h" 4#include "util/evsel.h"
5#include "ui/helpline.h" 5#include "ui/helpline.h"
6 6#include <inttypes.h>
7#include <signal.h>
7 8
8enum { 9enum {
9 ANN_COL__PERCENT, 10 ANN_COL__PERCENT,
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index a4f02de7c1b5..e24f83957705 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -4,7 +4,9 @@
4#include "../sort.h" 4#include "../sort.h"
5#include "../hist.h" 5#include "../hist.h"
6#include "../helpline.h" 6#include "../helpline.h"
7#include "../string2.h"
7#include "gtk.h" 8#include "gtk.h"
9#include <signal.h>
8 10
9#define MAX_COLUMNS 32 11#define MAX_COLUMNS 32
10 12
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 5d632dca672a..59addd52d9cd 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -1,3 +1,4 @@
1#include <inttypes.h>
1#include <math.h> 2#include <math.h>
2#include <linux/compiler.h> 3#include <linux/compiler.h>
3 4
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index 50d13e58210f..caf1ce6f5152 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -4,12 +4,16 @@
4#include "../util/cache.h" 4#include "../util/cache.h"
5#include "../util/debug.h" 5#include "../util/debug.h"
6#include "../util/hist.h" 6#include "../util/hist.h"
7#include "../util/util.h"
7 8
8pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER; 9pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
9void *perf_gtk_handle; 10void *perf_gtk_handle;
10int use_browser = -1; 11int use_browser = -1;
11 12
13#define PERF_GTK_DSO "libperf-gtk.so"
14
12#ifdef HAVE_GTK2_SUPPORT 15#ifdef HAVE_GTK2_SUPPORT
16
13static int setup_gtk_browser(void) 17static int setup_gtk_browser(void)
14{ 18{
15 int (*perf_ui_init)(void); 19 int (*perf_ui_init)(void);
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 668f4aecf2e6..42e432bd2eb4 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -4,7 +4,10 @@
4#include "../../util/hist.h" 4#include "../../util/hist.h"
5#include "../../util/sort.h" 5#include "../../util/sort.h"
6#include "../../util/evsel.h" 6#include "../../util/evsel.h"
7 7#include "../../util/srcline.h"
8#include "../../util/string2.h"
9#include "../../util/thread.h"
10#include "../../util/sane_ctype.h"
8 11
9static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) 12static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
10{ 13{
@@ -17,6 +20,67 @@ static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
17 return ret; 20 return ret;
18} 21}
19 22
23static size_t inline__fprintf(struct map *map, u64 ip, int left_margin,
24 int depth, int depth_mask, FILE *fp)
25{
26 struct dso *dso;
27 struct inline_node *node;
28 struct inline_list *ilist;
29 int ret = 0, i;
30
31 if (map == NULL)
32 return 0;
33
34 dso = map->dso;
35 if (dso == NULL)
36 return 0;
37
38 if (dso->kernel != DSO_TYPE_USER)
39 return 0;
40
41 node = dso__parse_addr_inlines(dso,
42 map__rip_2objdump(map, ip));
43 if (node == NULL)
44 return 0;
45
46 list_for_each_entry(ilist, &node->val, list) {
47 if ((ilist->filename != NULL) || (ilist->funcname != NULL)) {
48 ret += callchain__fprintf_left_margin(fp, left_margin);
49
50 for (i = 0; i < depth; i++) {
51 if (depth_mask & (1 << i))
52 ret += fprintf(fp, "|");
53 else
54 ret += fprintf(fp, " ");
55 ret += fprintf(fp, " ");
56 }
57
58 if (callchain_param.key == CCKEY_ADDRESS ||
59 callchain_param.key == CCKEY_SRCLINE) {
60 if (ilist->filename != NULL)
61 ret += fprintf(fp, "%s:%d (inline)",
62 ilist->filename,
63 ilist->line_nr);
64 else
65 ret += fprintf(fp, "??");
66 } else if (ilist->funcname != NULL)
67 ret += fprintf(fp, "%s (inline)",
68 ilist->funcname);
69 else if (ilist->filename != NULL)
70 ret += fprintf(fp, "%s:%d (inline)",
71 ilist->filename,
72 ilist->line_nr);
73 else
74 ret += fprintf(fp, "??");
75
76 ret += fprintf(fp, "\n");
77 }
78 }
79
80 inline_node__delete(node);
81 return ret;
82}
83
20static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask, 84static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
21 int left_margin) 85 int left_margin)
22{ 86{
@@ -78,6 +142,10 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
78 fputs(str, fp); 142 fputs(str, fp);
79 fputc('\n', fp); 143 fputc('\n', fp);
80 free(alloc_str); 144 free(alloc_str);
145
146 if (symbol_conf.inline_name)
147 ret += inline__fprintf(chain->ms.map, chain->ip,
148 left_margin, depth, depth_mask, fp);
81 return ret; 149 return ret;
82} 150}
83 151
@@ -229,6 +297,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
229 if (!i++ && field_order == NULL && 297 if (!i++ && field_order == NULL &&
230 sort_order && !prefixcmp(sort_order, "sym")) 298 sort_order && !prefixcmp(sort_order, "sym"))
231 continue; 299 continue;
300
232 if (!printed) { 301 if (!printed) {
233 ret += callchain__fprintf_left_margin(fp, left_margin); 302 ret += callchain__fprintf_left_margin(fp, left_margin);
234 ret += fprintf(fp, "|\n"); 303 ret += fprintf(fp, "|\n");
@@ -251,6 +320,13 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
251 320
252 if (++entries_printed == callchain_param.print_limit) 321 if (++entries_printed == callchain_param.print_limit)
253 break; 322 break;
323
324 if (symbol_conf.inline_name)
325 ret += inline__fprintf(chain->ms.map,
326 chain->ip,
327 left_margin,
328 0, 0,
329 fp);
254 } 330 }
255 root = &cnode->rb_root; 331 root = &cnode->rb_root;
256 } 332 }
@@ -529,6 +605,8 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
529 bool use_callchain) 605 bool use_callchain)
530{ 606{
531 int ret; 607 int ret;
608 int callchain_ret = 0;
609 int inline_ret = 0;
532 struct perf_hpp hpp = { 610 struct perf_hpp hpp = {
533 .buf = bf, 611 .buf = bf,
534 .size = size, 612 .size = size,
@@ -547,7 +625,16 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
547 ret = fprintf(fp, "%s\n", bf); 625 ret = fprintf(fp, "%s\n", bf);
548 626
549 if (use_callchain) 627 if (use_callchain)
550 ret += hist_entry_callchain__fprintf(he, total_period, 0, fp); 628 callchain_ret = hist_entry_callchain__fprintf(he, total_period,
629 0, fp);
630
631 if (callchain_ret == 0 && symbol_conf.inline_name) {
632 inline_ret = inline__fprintf(he->ms.map, he->ip, 0, 0, 0, fp);
633 ret += inline_ret;
634 if (inline_ret > 0)
635 ret += fprintf(fp, "\n");
636 } else
637 ret += callchain_ret;
551 638
552 return ret; 639 return ret;
553} 640}
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index 4ea2ba861fc2..d9350a1da48b 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -1,6 +1,7 @@
1#include <errno.h> 1#include <errno.h>
2#include <signal.h> 2#include <signal.h>
3#include <stdbool.h> 3#include <stdbool.h>
4#include <linux/kernel.h>
4#ifdef HAVE_BACKTRACE_SUPPORT 5#ifdef HAVE_BACKTRACE_SUPPORT
5#include <execinfo.h> 6#include <execinfo.h>
6#endif 7#endif
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 5da376bc1afc..79dea95a7f68 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -1,4 +1,3 @@
1libperf-y += alias.o
2libperf-y += annotate.o 1libperf-y += annotate.o
3libperf-y += block-range.o 2libperf-y += block-range.o
4libperf-y += build-id.o 3libperf-y += build-id.o
@@ -14,9 +13,11 @@ libperf-y += find_bit.o
14libperf-y += kallsyms.o 13libperf-y += kallsyms.o
15libperf-y += levenshtein.o 14libperf-y += levenshtein.o
16libperf-y += llvm-utils.o 15libperf-y += llvm-utils.o
16libperf-y += memswap.o
17libperf-y += parse-events.o 17libperf-y += parse-events.o
18libperf-y += perf_regs.o 18libperf-y += perf_regs.o
19libperf-y += path.o 19libperf-y += path.o
20libperf-y += print_binary.o
20libperf-y += rbtree.o 21libperf-y += rbtree.o
21libperf-y += libstring.o 22libperf-y += libstring.o
22libperf-y += bitmap.o 23libperf-y += bitmap.o
@@ -42,6 +43,7 @@ libperf-y += pstack.o
42libperf-y += session.o 43libperf-y += session.o
43libperf-$(CONFIG_AUDIT) += syscalltbl.o 44libperf-$(CONFIG_AUDIT) += syscalltbl.o
44libperf-y += ordered-events.o 45libperf-y += ordered-events.o
46libperf-y += namespaces.o
45libperf-y += comm.o 47libperf-y += comm.o
46libperf-y += thread.o 48libperf-y += thread.o
47libperf-y += thread_map.o 49libperf-y += thread_map.o
@@ -81,13 +83,16 @@ libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/
81libperf-$(CONFIG_AUXTRACE) += intel-pt.o 83libperf-$(CONFIG_AUXTRACE) += intel-pt.o
82libperf-$(CONFIG_AUXTRACE) += intel-bts.o 84libperf-$(CONFIG_AUXTRACE) += intel-bts.o
83libperf-y += parse-branch-options.o 85libperf-y += parse-branch-options.o
86libperf-y += dump-insn.o
84libperf-y += parse-regs-options.o 87libperf-y += parse-regs-options.o
85libperf-y += term.o 88libperf-y += term.o
86libperf-y += help-unknown-cmd.o 89libperf-y += help-unknown-cmd.o
87libperf-y += mem-events.o 90libperf-y += mem-events.o
88libperf-y += vsprintf.o 91libperf-y += vsprintf.o
89libperf-y += drv_configs.o 92libperf-y += drv_configs.o
93libperf-y += units.o
90libperf-y += time-utils.o 94libperf-y += time-utils.o
95libperf-y += expr-bison.o
91 96
92libperf-$(CONFIG_LIBBPF) += bpf-loader.o 97libperf-$(CONFIG_LIBBPF) += bpf-loader.o
93libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o 98libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
@@ -140,6 +145,10 @@ $(OUTPUT)util/parse-events-bison.c: util/parse-events.y
140 $(call rule_mkdir) 145 $(call rule_mkdir)
141 $(Q)$(call echo-cmd,bison)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ 146 $(Q)$(call echo-cmd,bison)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_
142 147
148$(OUTPUT)util/expr-bison.c: util/expr.y
149 $(call rule_mkdir)
150 $(Q)$(call echo-cmd,bison)$(BISON) -v util/expr.y -d $(PARSER_DEBUG_BISON) -o $@ -p expr__
151
143$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c 152$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
144 $(call rule_mkdir) 153 $(call rule_mkdir)
145 $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l 154 $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l
@@ -152,6 +161,7 @@ CFLAGS_parse-events-flex.o += -w
152CFLAGS_pmu-flex.o += -w 161CFLAGS_pmu-flex.o += -w
153CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -w 162CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -w
154CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w 163CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w
164CFLAGS_expr-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w
155 165
156$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c 166$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
157$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c 167$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
diff --git a/tools/perf/util/alias.c b/tools/perf/util/alias.c
deleted file mode 100644
index 6455471d9cd1..000000000000
--- a/tools/perf/util/alias.c
+++ /dev/null
@@ -1,78 +0,0 @@
1#include "cache.h"
2#include "util.h"
3#include "config.h"
4
5static const char *alias_key;
6static char *alias_val;
7
8static int alias_lookup_cb(const char *k, const char *v,
9 void *cb __maybe_unused)
10{
11 if (!prefixcmp(k, "alias.") && !strcmp(k+6, alias_key)) {
12 if (!v)
13 return config_error_nonbool(k);
14 alias_val = strdup(v);
15 return 0;
16 }
17 return 0;
18}
19
20char *alias_lookup(const char *alias)
21{
22 alias_key = alias;
23 alias_val = NULL;
24 perf_config(alias_lookup_cb, NULL);
25 return alias_val;
26}
27
28int split_cmdline(char *cmdline, const char ***argv)
29{
30 int src, dst, count = 0, size = 16;
31 char quoted = 0;
32
33 *argv = malloc(sizeof(char*) * size);
34
35 /* split alias_string */
36 (*argv)[count++] = cmdline;
37 for (src = dst = 0; cmdline[src];) {
38 char c = cmdline[src];
39 if (!quoted && isspace(c)) {
40 cmdline[dst++] = 0;
41 while (cmdline[++src]
42 && isspace(cmdline[src]))
43 ; /* skip */
44 if (count >= size) {
45 size += 16;
46 *argv = realloc(*argv, sizeof(char*) * size);
47 }
48 (*argv)[count++] = cmdline + dst;
49 } else if (!quoted && (c == '\'' || c == '"')) {
50 quoted = c;
51 src++;
52 } else if (c == quoted) {
53 quoted = 0;
54 src++;
55 } else {
56 if (c == '\\' && quoted != '\'') {
57 src++;
58 c = cmdline[src];
59 if (!c) {
60 zfree(argv);
61 return error("cmdline ends with \\");
62 }
63 }
64 cmdline[dst++] = c;
65 src++;
66 }
67 }
68
69 cmdline[dst] = 0;
70
71 if (quoted) {
72 zfree(argv);
73 return error("unclosed quote");
74 }
75
76 return count;
77}
78
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 7aa57225cbf7..683f8340460c 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -7,6 +7,8 @@
7 * Released under the GPL v2. (and only v2, not any later version) 7 * Released under the GPL v2. (and only v2, not any later version)
8 */ 8 */
9 9
10#include <errno.h>
11#include <inttypes.h>
10#include "util.h" 12#include "util.h"
11#include "ui/ui.h" 13#include "ui/ui.h"
12#include "sort.h" 14#include "sort.h"
@@ -18,12 +20,16 @@
18#include "annotate.h" 20#include "annotate.h"
19#include "evsel.h" 21#include "evsel.h"
20#include "block-range.h" 22#include "block-range.h"
23#include "string2.h"
21#include "arch/common.h" 24#include "arch/common.h"
22#include <regex.h> 25#include <regex.h>
23#include <pthread.h> 26#include <pthread.h>
24#include <linux/bitops.h> 27#include <linux/bitops.h>
28#include <linux/kernel.h>
25#include <sys/utsname.h> 29#include <sys/utsname.h>
26 30
31#include "sane_ctype.h"
32
27const char *disassembler_style; 33const char *disassembler_style;
28const char *objdump_path; 34const char *objdump_path;
29static regex_t file_lineno; 35static regex_t file_lineno;
@@ -108,6 +114,7 @@ static int arch__associate_ins_ops(struct arch* arch, const char *name, struct i
108#include "arch/arm64/annotate/instructions.c" 114#include "arch/arm64/annotate/instructions.c"
109#include "arch/x86/annotate/instructions.c" 115#include "arch/x86/annotate/instructions.c"
110#include "arch/powerpc/annotate/instructions.c" 116#include "arch/powerpc/annotate/instructions.c"
117#include "arch/s390/annotate/instructions.c"
111 118
112static struct arch architectures[] = { 119static struct arch architectures[] = {
113 { 120 {
@@ -132,6 +139,7 @@ static struct arch architectures[] = {
132 }, 139 },
133 { 140 {
134 .name = "s390", 141 .name = "s390",
142 .init = s390__annotate_init,
135 .objdump = { 143 .objdump = {
136 .comment_char = '#', 144 .comment_char = '#',
137 }, 145 },
@@ -385,9 +393,7 @@ static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map *m
385 if (comment == NULL) 393 if (comment == NULL)
386 return 0; 394 return 0;
387 395
388 while (comment[0] != '\0' && isspace(comment[0])) 396 comment = ltrim(comment);
389 ++comment;
390
391 comment__symbol(ops->source.raw, comment, &ops->source.addr, &ops->source.name); 397 comment__symbol(ops->source.raw, comment, &ops->source.addr, &ops->source.name);
392 comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name); 398 comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name);
393 399
@@ -432,9 +438,7 @@ static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops
432 if (comment == NULL) 438 if (comment == NULL)
433 return 0; 439 return 0;
434 440
435 while (comment[0] != '\0' && isspace(comment[0])) 441 comment = ltrim(comment);
436 ++comment;
437
438 comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name); 442 comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name);
439 443
440 return 0; 444 return 0;
@@ -783,10 +787,7 @@ static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, str
783 787
784static int disasm_line__parse(char *line, const char **namep, char **rawp) 788static int disasm_line__parse(char *line, const char **namep, char **rawp)
785{ 789{
786 char *name = line, tmp; 790 char tmp, *name = ltrim(line);
787
788 while (isspace(name[0]))
789 ++name;
790 791
791 if (name[0] == '\0') 792 if (name[0] == '\0')
792 return -1; 793 return -1;
@@ -804,12 +805,7 @@ static int disasm_line__parse(char *line, const char **namep, char **rawp)
804 goto out_free_name; 805 goto out_free_name;
805 806
806 (*rawp)[0] = tmp; 807 (*rawp)[0] = tmp;
807 808 *rawp = ltrim(*rawp);
808 if ((*rawp)[0] != '\0') {
809 (*rawp)++;
810 while (isspace((*rawp)[0]))
811 ++(*rawp);
812 }
813 809
814 return 0; 810 return 0;
815 811
@@ -1154,7 +1150,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
1154{ 1150{
1155 struct annotation *notes = symbol__annotation(sym); 1151 struct annotation *notes = symbol__annotation(sym);
1156 struct disasm_line *dl; 1152 struct disasm_line *dl;
1157 char *line = NULL, *parsed_line, *tmp, *tmp2, *c; 1153 char *line = NULL, *parsed_line, *tmp, *tmp2;
1158 size_t line_len; 1154 size_t line_len;
1159 s64 line_ip, offset = -1; 1155 s64 line_ip, offset = -1;
1160 regmatch_t match[2]; 1156 regmatch_t match[2];
@@ -1165,32 +1161,16 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
1165 if (!line) 1161 if (!line)
1166 return -1; 1162 return -1;
1167 1163
1168 while (line_len != 0 && isspace(line[line_len - 1]))
1169 line[--line_len] = '\0';
1170
1171 c = strchr(line, '\n');
1172 if (c)
1173 *c = 0;
1174
1175 line_ip = -1; 1164 line_ip = -1;
1176 parsed_line = line; 1165 parsed_line = rtrim(line);
1177 1166
1178 /* /filename:linenr ? Save line number and ignore. */ 1167 /* /filename:linenr ? Save line number and ignore. */
1179 if (regexec(&file_lineno, line, 2, match, 0) == 0) { 1168 if (regexec(&file_lineno, parsed_line, 2, match, 0) == 0) {
1180 *line_nr = atoi(line + match[1].rm_so); 1169 *line_nr = atoi(parsed_line + match[1].rm_so);
1181 return 0; 1170 return 0;
1182 } 1171 }
1183 1172
1184 /* 1173 tmp = ltrim(parsed_line);
1185 * Strip leading spaces:
1186 */
1187 tmp = line;
1188 while (*tmp) {
1189 if (*tmp != ' ')
1190 break;
1191 tmp++;
1192 }
1193
1194 if (*tmp) { 1174 if (*tmp) {
1195 /* 1175 /*
1196 * Parse hexa addresses followed by ':' 1176 * Parse hexa addresses followed by ':'
@@ -1313,6 +1293,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
1313{ 1293{
1314 char linkname[PATH_MAX]; 1294 char linkname[PATH_MAX];
1315 char *build_id_filename; 1295 char *build_id_filename;
1296 char *build_id_path = NULL;
1316 1297
1317 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && 1298 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
1318 !dso__is_kcore(dso)) 1299 !dso__is_kcore(dso))
@@ -1328,8 +1309,14 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
1328 goto fallback; 1309 goto fallback;
1329 } 1310 }
1330 1311
1312 build_id_path = strdup(filename);
1313 if (!build_id_path)
1314 return -1;
1315
1316 dirname(build_id_path);
1317
1331 if (dso__is_kcore(dso) || 1318 if (dso__is_kcore(dso) ||
1332 readlink(filename, linkname, sizeof(linkname)) < 0 || 1319 readlink(build_id_path, linkname, sizeof(linkname)) < 0 ||
1333 strstr(linkname, DSO__NAME_KALLSYMS) || 1320 strstr(linkname, DSO__NAME_KALLSYMS) ||
1334 access(filename, R_OK)) { 1321 access(filename, R_OK)) {
1335fallback: 1322fallback:
@@ -1341,6 +1328,7 @@ fallback:
1341 __symbol__join_symfs(filename, filename_size, dso->long_name); 1328 __symbol__join_symfs(filename, filename_size, dso->long_name);
1342 } 1329 }
1343 1330
1331 free(build_id_path);
1344 return 0; 1332 return 0;
1345} 1333}
1346 1334
@@ -1441,7 +1429,7 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
1441 snprintf(command, sizeof(command), 1429 snprintf(command, sizeof(command),
1442 "%s %s%s --start-address=0x%016" PRIx64 1430 "%s %s%s --start-address=0x%016" PRIx64
1443 " --stop-address=0x%016" PRIx64 1431 " --stop-address=0x%016" PRIx64
1444 " -l -d %s %s -C %s 2>/dev/null|grep -v %s|expand", 1432 " -l -d %s %s -C %s 2>/dev/null|grep -v %s:|expand",
1445 objdump_path ? objdump_path : "objdump", 1433 objdump_path ? objdump_path : "objdump",
1446 disassembler_style ? "-M " : "", 1434 disassembler_style ? "-M " : "",
1447 disassembler_style ? disassembler_style : "", 1435 disassembler_style ? disassembler_style : "",
@@ -1488,6 +1476,12 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
1488 1476
1489 nline = 0; 1477 nline = 0;
1490 while (!feof(file)) { 1478 while (!feof(file)) {
1479 /*
1480 * The source code line number (lineno) needs to be kept in
1481 * accross calls to symbol__parse_objdump_line(), so that it
1482 * can associate it with the instructions till the next one.
1483 * See disasm_line__new() and struct disasm_line::line_nr.
1484 */
1491 if (symbol__parse_objdump_line(sym, map, arch, file, privsize, 1485 if (symbol__parse_objdump_line(sym, map, arch, file, privsize,
1492 &lineno) < 0) 1486 &lineno) < 0)
1493 break; 1487 break;
@@ -1657,24 +1651,31 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1657 start = map__rip_2objdump(map, sym->start); 1651 start = map__rip_2objdump(map, sym->start);
1658 1652
1659 for (i = 0; i < len; i++) { 1653 for (i = 0; i < len; i++) {
1660 u64 offset; 1654 u64 offset, nr_samples;
1661 double percent_max = 0.0; 1655 double percent_max = 0.0;
1662 1656
1663 src_line->nr_pcnt = nr_pcnt; 1657 src_line->nr_pcnt = nr_pcnt;
1664 1658
1665 for (k = 0; k < nr_pcnt; k++) { 1659 for (k = 0; k < nr_pcnt; k++) {
1660 double percent = 0.0;
1661
1666 h = annotation__histogram(notes, evidx + k); 1662 h = annotation__histogram(notes, evidx + k);
1667 src_line->samples[k].percent = 100.0 * h->addr[i] / h->sum; 1663 nr_samples = h->addr[i];
1664 if (h->sum)
1665 percent = 100.0 * nr_samples / h->sum;
1668 1666
1669 if (src_line->samples[k].percent > percent_max) 1667 if (percent > percent_max)
1670 percent_max = src_line->samples[k].percent; 1668 percent_max = percent;
1669 src_line->samples[k].percent = percent;
1670 src_line->samples[k].nr = nr_samples;
1671 } 1671 }
1672 1672
1673 if (percent_max <= 0.5) 1673 if (percent_max <= 0.5)
1674 goto next; 1674 goto next;
1675 1675
1676 offset = start + i; 1676 offset = start + i;
1677 src_line->path = get_srcline(map->dso, offset, NULL, false); 1677 src_line->path = get_srcline(map->dso, offset, NULL,
1678 false, true);
1678 insert_source_line(&tmp_root, src_line); 1679 insert_source_line(&tmp_root, src_line);
1679 1680
1680 next: 1681 next:
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 09776b5af991..948aa8e6fd39 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -98,7 +98,7 @@ struct cyc_hist {
98struct source_line_samples { 98struct source_line_samples {
99 double percent; 99 double percent;
100 double percent_sum; 100 double percent_sum;
101 double nr; 101 u64 nr;
102}; 102};
103 103
104struct source_line { 104struct source_line {
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index c5a6e0b12452..0daf63b9ee3e 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -13,10 +13,10 @@
13 * 13 *
14 */ 14 */
15 15
16#include <inttypes.h>
16#include <sys/types.h> 17#include <sys/types.h>
17#include <sys/mman.h> 18#include <sys/mman.h>
18#include <stdbool.h> 19#include <stdbool.h>
19#include <ctype.h>
20#include <string.h> 20#include <string.h>
21#include <limits.h> 21#include <limits.h>
22#include <errno.h> 22#include <errno.h>
@@ -46,7 +46,6 @@
46#include "cpumap.h" 46#include "cpumap.h"
47#include "thread_map.h" 47#include "thread_map.h"
48#include "asm/bug.h" 48#include "asm/bug.h"
49#include "symbol/kallsyms.h"
50#include "auxtrace.h" 49#include "auxtrace.h"
51 50
52#include <linux/hash.h> 51#include <linux/hash.h>
@@ -59,6 +58,9 @@
59#include "intel-pt.h" 58#include "intel-pt.h"
60#include "intel-bts.h" 59#include "intel-bts.h"
61 60
61#include "sane_ctype.h"
62#include "symbol/kallsyms.h"
63
62int auxtrace_mmap__mmap(struct auxtrace_mmap *mm, 64int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
63 struct auxtrace_mmap_params *mp, 65 struct auxtrace_mmap_params *mp,
64 void *userpg, int fd) 66 void *userpg, int fd)
@@ -1826,7 +1828,7 @@ static int addr_filter__resolve_kernel_syms(struct addr_filter *filt)
1826 filt->addr = start; 1828 filt->addr = start;
1827 if (filt->range && !filt->size && !filt->sym_to) { 1829 if (filt->range && !filt->size && !filt->sym_to) {
1828 filt->size = size; 1830 filt->size = size;
1829 no_size = !!size; 1831 no_size = !size;
1830 } 1832 }
1831 } 1833 }
1832 1834
@@ -1840,7 +1842,7 @@ static int addr_filter__resolve_kernel_syms(struct addr_filter *filt)
1840 if (err) 1842 if (err)
1841 return err; 1843 return err;
1842 filt->size = start + size - filt->addr; 1844 filt->size = start + size - filt->addr;
1843 no_size = !!size; 1845 no_size = !size;
1844 } 1846 }
1845 1847
1846 /* The very last symbol in kallsyms does not imply a particular size */ 1848 /* The very last symbol in kallsyms does not imply a particular size */
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 26fb1ee5746a..9f0de72d58e2 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -17,6 +17,7 @@
17#define __PERF_AUXTRACE_H 17#define __PERF_AUXTRACE_H
18 18
19#include <sys/types.h> 19#include <sys/types.h>
20#include <errno.h>
20#include <stdbool.h> 21#include <stdbool.h>
21#include <stddef.h> 22#include <stddef.h>
22#include <linux/list.h> 23#include <linux/list.h>
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index bc6bc7062eb4..4bd2d1d882af 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -9,7 +9,9 @@
9#include <bpf/libbpf.h> 9#include <bpf/libbpf.h>
10#include <bpf/bpf.h> 10#include <bpf/bpf.h>
11#include <linux/err.h> 11#include <linux/err.h>
12#include <linux/kernel.h>
12#include <linux/string.h> 13#include <linux/string.h>
14#include <errno.h>
13#include "perf.h" 15#include "perf.h"
14#include "debug.h" 16#include "debug.h"
15#include "bpf-loader.h" 17#include "bpf-loader.h"
@@ -17,6 +19,7 @@
17#include "probe-event.h" 19#include "probe-event.h"
18#include "probe-finder.h" // for MAX_PROBES 20#include "probe-finder.h" // for MAX_PROBES
19#include "parse-events.h" 21#include "parse-events.h"
22#include "strfilter.h"
20#include "llvm-utils.h" 23#include "llvm-utils.h"
21#include "c++/clang-c.h" 24#include "c++/clang-c.h"
22 25
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index f2b737b225f2..48863867878b 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -85,6 +85,8 @@ int bpf__strerror_setup_stdout(struct perf_evlist *evlist, int err,
85 char *buf, size_t size); 85 char *buf, size_t size);
86 86
87#else 87#else
88#include <errno.h>
89
88static inline struct bpf_object * 90static inline struct bpf_object *
89bpf__prepare_load(const char *filename __maybe_unused, 91bpf__prepare_load(const char *filename __maybe_unused,
90 bool source __maybe_unused) 92 bool source __maybe_unused)
diff --git a/tools/perf/util/bpf-prologue.c b/tools/perf/util/bpf-prologue.c
index 6cdbee119ceb..1356220a9f1b 100644
--- a/tools/perf/util/bpf-prologue.c
+++ b/tools/perf/util/bpf-prologue.c
@@ -12,6 +12,7 @@
12#include "bpf-loader.h" 12#include "bpf-loader.h"
13#include "bpf-prologue.h" 13#include "bpf-prologue.h"
14#include "probe-finder.h" 14#include "probe-finder.h"
15#include <errno.h>
15#include <dwarf-regs.h> 16#include <dwarf-regs.h>
16#include <linux/filter.h> 17#include <linux/filter.h>
17 18
diff --git a/tools/perf/util/bpf-prologue.h b/tools/perf/util/bpf-prologue.h
index d94cbea12899..ba564838375f 100644
--- a/tools/perf/util/bpf-prologue.h
+++ b/tools/perf/util/bpf-prologue.h
@@ -18,6 +18,8 @@ int bpf__gen_prologue(struct probe_trace_arg *args, int nargs,
18 struct bpf_insn *new_prog, size_t *new_cnt, 18 struct bpf_insn *new_prog, size_t *new_cnt,
19 size_t cnt_space); 19 size_t cnt_space);
20#else 20#else
21#include <errno.h>
22
21static inline int 23static inline int
22bpf__gen_prologue(struct probe_trace_arg *args __maybe_unused, 24bpf__gen_prologue(struct probe_trace_arg *args __maybe_unused,
23 int nargs __maybe_unused, 25 int nargs __maybe_unused,
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index e528c40739cc..168cc49654e7 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -7,18 +7,26 @@
7 * Copyright (C) 2009, 2010 Arnaldo Carvalho de Melo <acme@redhat.com> 7 * Copyright (C) 2009, 2010 Arnaldo Carvalho de Melo <acme@redhat.com>
8 */ 8 */
9#include "util.h" 9#include "util.h"
10#include <dirent.h>
11#include <errno.h>
10#include <stdio.h> 12#include <stdio.h>
13#include <sys/stat.h>
14#include <sys/types.h>
11#include "build-id.h" 15#include "build-id.h"
12#include "event.h" 16#include "event.h"
13#include "symbol.h" 17#include "symbol.h"
18#include "thread.h"
14#include <linux/kernel.h> 19#include <linux/kernel.h>
15#include "debug.h" 20#include "debug.h"
16#include "session.h" 21#include "session.h"
17#include "tool.h" 22#include "tool.h"
18#include "header.h" 23#include "header.h"
19#include "vdso.h" 24#include "vdso.h"
25#include "path.h"
20#include "probe-file.h" 26#include "probe-file.h"
27#include "strlist.h"
21 28
29#include "sane_ctype.h"
22 30
23static bool no_buildid_cache; 31static bool no_buildid_cache;
24 32
@@ -182,13 +190,17 @@ char *build_id_cache__origname(const char *sbuild_id)
182 char buf[PATH_MAX]; 190 char buf[PATH_MAX];
183 char *ret = NULL, *p; 191 char *ret = NULL, *p;
184 size_t offs = 5; /* == strlen("../..") */ 192 size_t offs = 5; /* == strlen("../..") */
193 ssize_t len;
185 194
186 linkname = build_id_cache__linkname(sbuild_id, NULL, 0); 195 linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
187 if (!linkname) 196 if (!linkname)
188 return NULL; 197 return NULL;
189 198
190 if (readlink(linkname, buf, PATH_MAX) < 0) 199 len = readlink(linkname, buf, sizeof(buf) - 1);
200 if (len <= 0)
191 goto out; 201 goto out;
202 buf[len] = '\0';
203
192 /* The link should be "../..<origpath>/<sbuild_id>" */ 204 /* The link should be "../..<origpath>/<sbuild_id>" */
193 p = strrchr(buf, '/'); /* Cut off the "/<sbuild_id>" */ 205 p = strrchr(buf, '/'); /* Cut off the "/<sbuild_id>" */
194 if (p && (p > buf + offs)) { 206 if (p && (p > buf + offs)) {
@@ -443,14 +455,14 @@ void disable_buildid_cache(void)
443} 455}
444 456
445static bool lsdir_bid_head_filter(const char *name __maybe_unused, 457static bool lsdir_bid_head_filter(const char *name __maybe_unused,
446 struct dirent *d __maybe_unused) 458 struct dirent *d)
447{ 459{
448 return (strlen(d->d_name) == 2) && 460 return (strlen(d->d_name) == 2) &&
449 isxdigit(d->d_name[0]) && isxdigit(d->d_name[1]); 461 isxdigit(d->d_name[0]) && isxdigit(d->d_name[1]);
450} 462}
451 463
452static bool lsdir_bid_tail_filter(const char *name __maybe_unused, 464static bool lsdir_bid_tail_filter(const char *name __maybe_unused,
453 struct dirent *d __maybe_unused) 465 struct dirent *d)
454{ 466{
455 int i = 0; 467 int i = 0;
456 while (isxdigit(d->d_name[i]) && i < SBUILD_ID_SIZE - 3) 468 while (isxdigit(d->d_name[i]) && i < SBUILD_ID_SIZE - 3)
@@ -690,7 +702,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
690 err = 0; 702 err = 0;
691 703
692 /* Update SDT cache : error is just warned */ 704 /* Update SDT cache : error is just warned */
693 if (build_id_cache__add_sdt_cache(sbuild_id, realname) < 0) 705 if (realname && build_id_cache__add_sdt_cache(sbuild_id, realname) < 0)
694 pr_debug4("Failed to update/scan SDT cache for %s\n", realname); 706 pr_debug4("Failed to update/scan SDT cache for %s\n", realname);
695 707
696out_free: 708out_free:
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index d27990610f9f..8a89b195c1fc 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -5,7 +5,6 @@
5#define SBUILD_ID_SIZE (BUILD_ID_SIZE * 2 + 1) 5#define SBUILD_ID_SIZE (BUILD_ID_SIZE * 2 + 1)
6 6
7#include "tool.h" 7#include "tool.h"
8#include "strlist.h"
9#include <linux/types.h> 8#include <linux/types.h>
10 9
11extern struct perf_tool build_id__mark_dso_hit_ops; 10extern struct perf_tool build_id__mark_dso_hit_ops;
@@ -34,6 +33,9 @@ char *build_id_cache__origname(const char *sbuild_id);
34char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size); 33char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size);
35char *build_id_cache__cachedir(const char *sbuild_id, const char *name, 34char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
36 bool is_kallsyms, bool is_vdso); 35 bool is_kallsyms, bool is_vdso);
36
37struct strlist;
38
37struct strlist *build_id_cache__list_all(bool validonly); 39struct strlist *build_id_cache__list_all(bool validonly);
38char *build_id_cache__complement(const char *incomplete_sbuild_id); 40char *build_id_cache__complement(const char *incomplete_sbuild_id);
39int build_id_cache__list_build_ids(const char *pathname, 41int build_id_cache__list_build_ids(const char *pathname,
@@ -42,6 +44,10 @@ bool build_id_cache__cached(const char *sbuild_id);
42int build_id_cache__add_s(const char *sbuild_id, 44int build_id_cache__add_s(const char *sbuild_id,
43 const char *name, bool is_kallsyms, bool is_vdso); 45 const char *name, bool is_kallsyms, bool is_vdso);
44int build_id_cache__remove_s(const char *sbuild_id); 46int build_id_cache__remove_s(const char *sbuild_id);
47
48extern char buildid_dir[];
49
50void set_buildid_dir(const char *dir);
45void disable_buildid_cache(void); 51void disable_buildid_cache(void);
46 52
47#endif 53#endif
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index 0eadd792ab1f..ccafcf72b37a 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -20,6 +20,7 @@ extern int perf_clang__compile_bpf(const char *filename,
20 size_t *p_obj_buf_sz); 20 size_t *p_obj_buf_sz);
21#else 21#else
22 22
23#include <errno.h>
23 24
24static inline void perf_clang__init(void) { } 25static inline void perf_clang__init(void) { }
25static inline void perf_clang__cleanup(void) { } 26static inline void perf_clang__cleanup(void) { }
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 512c0c83fbc6..0328f297a748 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -15,7 +15,6 @@
15#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR" 15#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
16#define PERF_PAGER_ENVIRONMENT "PERF_PAGER" 16#define PERF_PAGER_ENVIRONMENT "PERF_PAGER"
17 17
18char *alias_lookup(const char *alias);
19int split_cmdline(char *cmdline, const char ***argv); 18int split_cmdline(char *cmdline, const char ***argv);
20 19
21#define alloc_nr(x) (((x)+16)*3/2) 20#define alloc_nr(x) (((x)+16)*3/2)
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index aba953421a03..81fc29ac798f 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -9,6 +9,7 @@
9 * 9 *
10 */ 10 */
11 11
12#include <inttypes.h>
12#include <stdlib.h> 13#include <stdlib.h>
13#include <stdio.h> 14#include <stdio.h>
14#include <stdbool.h> 15#include <stdbool.h>
@@ -23,6 +24,21 @@
23#include "machine.h" 24#include "machine.h"
24#include "callchain.h" 25#include "callchain.h"
25 26
27#define CALLCHAIN_PARAM_DEFAULT \
28 .mode = CHAIN_GRAPH_ABS, \
29 .min_percent = 0.5, \
30 .order = ORDER_CALLEE, \
31 .key = CCKEY_FUNCTION, \
32 .value = CCVAL_PERCENT, \
33
34struct callchain_param callchain_param = {
35 CALLCHAIN_PARAM_DEFAULT
36};
37
38struct callchain_param callchain_param_default = {
39 CALLCHAIN_PARAM_DEFAULT
40};
41
26__thread struct callchain_cursor callchain_cursor; 42__thread struct callchain_cursor callchain_cursor;
27 43
28int parse_callchain_record_opt(const char *arg, struct callchain_param *param) 44int parse_callchain_record_opt(const char *arg, struct callchain_param *param)
@@ -80,6 +96,10 @@ static int parse_callchain_sort_key(const char *value)
80 callchain_param.key = CCKEY_ADDRESS; 96 callchain_param.key = CCKEY_ADDRESS;
81 return 0; 97 return 0;
82 } 98 }
99 if (!strncmp(value, "srcline", strlen(value))) {
100 callchain_param.key = CCKEY_SRCLINE;
101 return 0;
102 }
83 if (!strncmp(value, "branch", strlen(value))) { 103 if (!strncmp(value, "branch", strlen(value))) {
84 callchain_param.branch_callstack = 1; 104 callchain_param.branch_callstack = 1;
85 return 0; 105 return 0;
@@ -108,11 +128,37 @@ static int parse_callchain_value(const char *value)
108 return -1; 128 return -1;
109} 129}
110 130
131static int get_stack_size(const char *str, unsigned long *_size)
132{
133 char *endptr;
134 unsigned long size;
135 unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
136
137 size = strtoul(str, &endptr, 0);
138
139 do {
140 if (*endptr)
141 break;
142
143 size = round_up(size, sizeof(u64));
144 if (!size || size > max_size)
145 break;
146
147 *_size = size;
148 return 0;
149
150 } while (0);
151
152 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
153 max_size, str);
154 return -1;
155}
156
111static int 157static int
112__parse_callchain_report_opt(const char *arg, bool allow_record_opt) 158__parse_callchain_report_opt(const char *arg, bool allow_record_opt)
113{ 159{
114 char *tok; 160 char *tok;
115 char *endptr; 161 char *endptr, *saveptr = NULL;
116 bool minpcnt_set = false; 162 bool minpcnt_set = false;
117 bool record_opt_set = false; 163 bool record_opt_set = false;
118 bool try_stack_size = false; 164 bool try_stack_size = false;
@@ -123,7 +169,7 @@ __parse_callchain_report_opt(const char *arg, bool allow_record_opt)
123 if (!arg) 169 if (!arg)
124 return 0; 170 return 0;
125 171
126 while ((tok = strtok((char *)arg, ",")) != NULL) { 172 while ((tok = strtok_r((char *)arg, ",", &saveptr)) != NULL) {
127 if (!strncmp(tok, "none", strlen(tok))) { 173 if (!strncmp(tok, "none", strlen(tok))) {
128 callchain_param.mode = CHAIN_NONE; 174 callchain_param.mode = CHAIN_NONE;
129 callchain_param.enabled = false; 175 callchain_param.enabled = false;
@@ -191,6 +237,68 @@ int parse_callchain_top_opt(const char *arg)
191 return __parse_callchain_report_opt(arg, true); 237 return __parse_callchain_report_opt(arg, true);
192} 238}
193 239
240int parse_callchain_record(const char *arg, struct callchain_param *param)
241{
242 char *tok, *name, *saveptr = NULL;
243 char *buf;
244 int ret = -1;
245
246 /* We need buffer that we know we can write to. */
247 buf = malloc(strlen(arg) + 1);
248 if (!buf)
249 return -ENOMEM;
250
251 strcpy(buf, arg);
252
253 tok = strtok_r((char *)buf, ",", &saveptr);
254 name = tok ? : (char *)buf;
255
256 do {
257 /* Framepointer style */
258 if (!strncmp(name, "fp", sizeof("fp"))) {
259 if (!strtok_r(NULL, ",", &saveptr)) {
260 param->record_mode = CALLCHAIN_FP;
261 ret = 0;
262 } else
263 pr_err("callchain: No more arguments "
264 "needed for --call-graph fp\n");
265 break;
266
267 /* Dwarf style */
268 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
269 const unsigned long default_stack_dump_size = 8192;
270
271 ret = 0;
272 param->record_mode = CALLCHAIN_DWARF;
273 param->dump_size = default_stack_dump_size;
274
275 tok = strtok_r(NULL, ",", &saveptr);
276 if (tok) {
277 unsigned long size = 0;
278
279 ret = get_stack_size(tok, &size);
280 param->dump_size = size;
281 }
282 } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
283 if (!strtok_r(NULL, ",", &saveptr)) {
284 param->record_mode = CALLCHAIN_LBR;
285 ret = 0;
286 } else
287 pr_err("callchain: No more arguments "
288 "needed for --call-graph lbr\n");
289 break;
290 } else {
291 pr_err("callchain: Unknown --call-graph option "
292 "value: %s\n", arg);
293 break;
294 }
295
296 } while (0);
297
298 free(buf);
299 return ret;
300}
301
194int perf_callchain_config(const char *var, const char *value) 302int perf_callchain_config(const char *var, const char *value)
195{ 303{
196 char *endptr; 304 char *endptr;
@@ -510,14 +618,51 @@ enum match_result {
510 MATCH_GT, 618 MATCH_GT,
511}; 619};
512 620
621static enum match_result match_chain_srcline(struct callchain_cursor_node *node,
622 struct callchain_list *cnode)
623{
624 char *left = get_srcline(cnode->ms.map->dso,
625 map__rip_2objdump(cnode->ms.map, cnode->ip),
626 cnode->ms.sym, true, false);
627 char *right = get_srcline(node->map->dso,
628 map__rip_2objdump(node->map, node->ip),
629 node->sym, true, false);
630 enum match_result ret = MATCH_EQ;
631 int cmp;
632
633 if (left && right)
634 cmp = strcmp(left, right);
635 else if (!left && right)
636 cmp = 1;
637 else if (left && !right)
638 cmp = -1;
639 else if (cnode->ip == node->ip)
640 cmp = 0;
641 else
642 cmp = (cnode->ip < node->ip) ? -1 : 1;
643
644 if (cmp != 0)
645 ret = cmp < 0 ? MATCH_LT : MATCH_GT;
646
647 free_srcline(left);
648 free_srcline(right);
649 return ret;
650}
651
513static enum match_result match_chain(struct callchain_cursor_node *node, 652static enum match_result match_chain(struct callchain_cursor_node *node,
514 struct callchain_list *cnode) 653 struct callchain_list *cnode)
515{ 654{
516 struct symbol *sym = node->sym; 655 struct symbol *sym = node->sym;
517 u64 left, right; 656 u64 left, right;
518 657
519 if (cnode->ms.sym && sym && 658 if (callchain_param.key == CCKEY_SRCLINE) {
520 callchain_param.key == CCKEY_FUNCTION) { 659 enum match_result match = match_chain_srcline(node, cnode);
660
661 if (match != MATCH_ERROR)
662 return match;
663 }
664
665 if (cnode->ms.sym && sym && callchain_param.key == CCKEY_FUNCTION) {
521 left = cnode->ms.sym->start; 666 left = cnode->ms.sym->start;
522 right = sym->start; 667 right = sym->start;
523 } else { 668 } else {
@@ -911,15 +1056,16 @@ out:
911char *callchain_list__sym_name(struct callchain_list *cl, 1056char *callchain_list__sym_name(struct callchain_list *cl,
912 char *bf, size_t bfsize, bool show_dso) 1057 char *bf, size_t bfsize, bool show_dso)
913{ 1058{
1059 bool show_addr = callchain_param.key == CCKEY_ADDRESS;
1060 bool show_srcline = show_addr || callchain_param.key == CCKEY_SRCLINE;
914 int printed; 1061 int printed;
915 1062
916 if (cl->ms.sym) { 1063 if (cl->ms.sym) {
917 if (callchain_param.key == CCKEY_ADDRESS && 1064 if (show_srcline && cl->ms.map && !cl->srcline)
918 cl->ms.map && !cl->srcline)
919 cl->srcline = get_srcline(cl->ms.map->dso, 1065 cl->srcline = get_srcline(cl->ms.map->dso,
920 map__rip_2objdump(cl->ms.map, 1066 map__rip_2objdump(cl->ms.map,
921 cl->ip), 1067 cl->ip),
922 cl->ms.sym, false); 1068 cl->ms.sym, false, show_addr);
923 if (cl->srcline) 1069 if (cl->srcline)
924 printed = scnprintf(bf, bfsize, "%s %s", 1070 printed = scnprintf(bf, bfsize, "%s %s",
925 cl->ms.sym->name, cl->srcline); 1071 cl->ms.sym->name, cl->srcline);
@@ -1063,63 +1209,100 @@ int callchain_branch_counts(struct callchain_root *root,
1063 cycles_count); 1209 cycles_count);
1064} 1210}
1065 1211
1066static int callchain_counts_printf(FILE *fp, char *bf, int bfsize, 1212static int counts_str_build(char *bf, int bfsize,
1067 u64 branch_count, u64 predicted_count, 1213 u64 branch_count, u64 predicted_count,
1068 u64 abort_count, u64 cycles_count, 1214 u64 abort_count, u64 cycles_count,
1069 u64 iter_count, u64 samples_count) 1215 u64 iter_count, u64 samples_count)
1070{ 1216{
1071 double predicted_percent = 0.0; 1217 double predicted_percent = 0.0;
1072 const char *null_str = ""; 1218 const char *null_str = "";
1073 char iter_str[32]; 1219 char iter_str[32];
1074 char *str; 1220 char cycle_str[32];
1075 u64 cycles = 0; 1221 char *istr, *cstr;
1076 1222 u64 cycles;
1077 if (branch_count == 0) {
1078 if (fp)
1079 return fprintf(fp, " (calltrace)");
1080 1223
1224 if (branch_count == 0)
1081 return scnprintf(bf, bfsize, " (calltrace)"); 1225 return scnprintf(bf, bfsize, " (calltrace)");
1082 } 1226
1227 cycles = cycles_count / branch_count;
1083 1228
1084 if (iter_count && samples_count) { 1229 if (iter_count && samples_count) {
1085 scnprintf(iter_str, sizeof(iter_str), 1230 if (cycles > 0)
1086 ", iterations:%" PRId64 "", 1231 scnprintf(iter_str, sizeof(iter_str),
1087 iter_count / samples_count); 1232 " iterations:%" PRId64 "",
1088 str = iter_str; 1233 iter_count / samples_count);
1234 else
1235 scnprintf(iter_str, sizeof(iter_str),
1236 "iterations:%" PRId64 "",
1237 iter_count / samples_count);
1238 istr = iter_str;
1239 } else
1240 istr = (char *)null_str;
1241
1242 if (cycles > 0) {
1243 scnprintf(cycle_str, sizeof(cycle_str),
1244 "cycles:%" PRId64 "", cycles);
1245 cstr = cycle_str;
1089 } else 1246 } else
1090 str = (char *)null_str; 1247 cstr = (char *)null_str;
1091 1248
1092 predicted_percent = predicted_count * 100.0 / branch_count; 1249 predicted_percent = predicted_count * 100.0 / branch_count;
1093 cycles = cycles_count / branch_count;
1094 1250
1095 if ((predicted_percent >= 100.0) && (abort_count == 0)) { 1251 if ((predicted_count == branch_count) && (abort_count == 0)) {
1096 if (fp) 1252 if ((cycles > 0) || (istr != (char *)null_str))
1097 return fprintf(fp, " (cycles:%" PRId64 "%s)", 1253 return scnprintf(bf, bfsize, " (%s%s)", cstr, istr);
1098 cycles, str); 1254 else
1255 return scnprintf(bf, bfsize, "%s", (char *)null_str);
1256 }
1099 1257
1100 return scnprintf(bf, bfsize, " (cycles:%" PRId64 "%s)", 1258 if ((predicted_count < branch_count) && (abort_count == 0)) {
1101 cycles, str); 1259 if ((cycles > 0) || (istr != (char *)null_str))
1260 return scnprintf(bf, bfsize,
1261 " (predicted:%.1f%% %s%s)",
1262 predicted_percent, cstr, istr);
1263 else {
1264 return scnprintf(bf, bfsize,
1265 " (predicted:%.1f%%)",
1266 predicted_percent);
1267 }
1102 } 1268 }
1103 1269
1104 if ((predicted_percent < 100.0) && (abort_count == 0)) { 1270 if ((predicted_count == branch_count) && (abort_count > 0)) {
1105 if (fp) 1271 if ((cycles > 0) || (istr != (char *)null_str))
1106 return fprintf(fp, 1272 return scnprintf(bf, bfsize,
1107 " (predicted:%.1f%%, cycles:%" PRId64 "%s)", 1273 " (abort:%" PRId64 " %s%s)",
1108 predicted_percent, cycles, str); 1274 abort_count, cstr, istr);
1275 else
1276 return scnprintf(bf, bfsize,
1277 " (abort:%" PRId64 ")",
1278 abort_count);
1279 }
1109 1280
1281 if ((cycles > 0) || (istr != (char *)null_str))
1110 return scnprintf(bf, bfsize, 1282 return scnprintf(bf, bfsize,
1111 " (predicted:%.1f%%, cycles:%" PRId64 "%s)", 1283 " (predicted:%.1f%% abort:%" PRId64 " %s%s)",
1112 predicted_percent, cycles, str); 1284 predicted_percent, abort_count, cstr, istr);
1113 } 1285
1286 return scnprintf(bf, bfsize,
1287 " (predicted:%.1f%% abort:%" PRId64 ")",
1288 predicted_percent, abort_count);
1289}
1290
1291static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
1292 u64 branch_count, u64 predicted_count,
1293 u64 abort_count, u64 cycles_count,
1294 u64 iter_count, u64 samples_count)
1295{
1296 char str[128];
1297
1298 counts_str_build(str, sizeof(str), branch_count,
1299 predicted_count, abort_count, cycles_count,
1300 iter_count, samples_count);
1114 1301
1115 if (fp) 1302 if (fp)
1116 return fprintf(fp, 1303 return fprintf(fp, "%s", str);
1117 " (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)",
1118 predicted_percent, abort_count, cycles, str);
1119 1304
1120 return scnprintf(bf, bfsize, 1305 return scnprintf(bf, bfsize, "%s", str);
1121 " (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)",
1122 predicted_percent, abort_count, cycles, str);
1123} 1306}
1124 1307
1125int callchain_list_counts__printf_value(struct callchain_node *node, 1308int callchain_list_counts__printf_value(struct callchain_node *node,
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 4f4b60f1558a..c56c23dbbf72 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -77,7 +77,8 @@ typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_root *,
77 77
78enum chain_key { 78enum chain_key {
79 CCKEY_FUNCTION, 79 CCKEY_FUNCTION,
80 CCKEY_ADDRESS 80 CCKEY_ADDRESS,
81 CCKEY_SRCLINE
81}; 82};
82 83
83enum chain_value { 84enum chain_value {
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index eafbf11442b2..03347748f3fa 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -4,6 +4,7 @@
4#include "evsel.h" 4#include "evsel.h"
5#include "cgroup.h" 5#include "cgroup.h"
6#include "evlist.h" 6#include "evlist.h"
7#include <linux/stringify.h>
7 8
8int nr_cgroups; 9int nr_cgroups;
9 10
@@ -27,8 +28,8 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
27 path_v1[0] = '\0'; 28 path_v1[0] = '\0';
28 path_v2[0] = '\0'; 29 path_v2[0] = '\0';
29 30
30 while (fscanf(fp, "%*s %"STR(PATH_MAX)"s %"STR(PATH_MAX)"s %" 31 while (fscanf(fp, "%*s %"__stringify(PATH_MAX)"s %"__stringify(PATH_MAX)"s %"
31 STR(PATH_MAX)"s %*d %*d\n", 32 __stringify(PATH_MAX)"s %*d %*d\n",
32 mountpoint, type, tokens) == 3) { 33 mountpoint, type, tokens) == 3) {
33 34
34 if (!path_v1[0] && !strcmp(type, "cgroup")) { 35 if (!path_v1[0] && !strcmp(type, "cgroup")) {
@@ -127,19 +128,19 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
127 goto found; 128 goto found;
128 n++; 129 n++;
129 } 130 }
130 if (atomic_read(&cgrp->refcnt) == 0) 131 if (refcount_read(&cgrp->refcnt) == 0)
131 free(cgrp); 132 free(cgrp);
132 133
133 return -1; 134 return -1;
134found: 135found:
135 atomic_inc(&cgrp->refcnt); 136 refcount_inc(&cgrp->refcnt);
136 counter->cgrp = cgrp; 137 counter->cgrp = cgrp;
137 return 0; 138 return 0;
138} 139}
139 140
140void close_cgroup(struct cgroup_sel *cgrp) 141void close_cgroup(struct cgroup_sel *cgrp)
141{ 142{
142 if (cgrp && atomic_dec_and_test(&cgrp->refcnt)) { 143 if (cgrp && refcount_dec_and_test(&cgrp->refcnt)) {
143 close(cgrp->fd); 144 close(cgrp->fd);
144 zfree(&cgrp->name); 145 zfree(&cgrp->name);
145 free(cgrp); 146 free(cgrp);
diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h
index 31f8dcdbd7ef..d91966b97cbd 100644
--- a/tools/perf/util/cgroup.h
+++ b/tools/perf/util/cgroup.h
@@ -1,14 +1,14 @@
1#ifndef __CGROUP_H__ 1#ifndef __CGROUP_H__
2#define __CGROUP_H__ 2#define __CGROUP_H__
3 3
4#include <linux/atomic.h> 4#include <linux/refcount.h>
5 5
6struct option; 6struct option;
7 7
8struct cgroup_sel { 8struct cgroup_sel {
9 char *name; 9 char *name;
10 int fd; 10 int fd;
11 atomic_t refcnt; 11 refcount_t refcnt;
12}; 12};
13 13
14 14
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
index f0dcd0ee0afa..4b4f00df58a8 100644
--- a/tools/perf/util/cloexec.c
+++ b/tools/perf/util/cloexec.c
@@ -1,3 +1,4 @@
1#include <errno.h>
1#include <sched.h> 2#include <sched.h>
2#include "util.h" 3#include "util.h"
3#include "../perf.h" 4#include "../perf.h"
diff --git a/tools/perf/util/cloexec.h b/tools/perf/util/cloexec.h
index d0d465953d36..94a5a7d829d5 100644
--- a/tools/perf/util/cloexec.h
+++ b/tools/perf/util/cloexec.h
@@ -3,10 +3,4 @@
3 3
4unsigned long perf_event_open_cloexec_flag(void); 4unsigned long perf_event_open_cloexec_flag(void);
5 5
6#ifdef __GLIBC_PREREQ
7#if !__GLIBC_PREREQ(2, 6) && !defined(__UCLIBC__)
8int sched_getcpu(void) __THROW;
9#endif
10#endif
11
12#endif /* __PERF_CLOEXEC_H */ 6#endif /* __PERF_CLOEXEC_H */
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index a93997f16dec..52122bcc3170 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -1,6 +1,8 @@
1#ifndef __PERF_COLOR_H 1#ifndef __PERF_COLOR_H
2#define __PERF_COLOR_H 2#define __PERF_COLOR_H
3 3
4#include <stdio.h>
5
4/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */ 6/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
5#define COLOR_MAXLEN 24 7#define COLOR_MAXLEN 24
6 8
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
index 21b7ff382c3f..7bc981b6bf29 100644
--- a/tools/perf/util/comm.c
+++ b/tools/perf/util/comm.c
@@ -1,13 +1,15 @@
1#include "comm.h" 1#include "comm.h"
2#include "util.h" 2#include "util.h"
3#include <errno.h>
3#include <stdlib.h> 4#include <stdlib.h>
4#include <stdio.h> 5#include <stdio.h>
5#include <linux/atomic.h> 6#include <string.h>
7#include <linux/refcount.h>
6 8
7struct comm_str { 9struct comm_str {
8 char *str; 10 char *str;
9 struct rb_node rb_node; 11 struct rb_node rb_node;
10 atomic_t refcnt; 12 refcount_t refcnt;
11}; 13};
12 14
13/* Should perhaps be moved to struct machine */ 15/* Should perhaps be moved to struct machine */
@@ -16,13 +18,13 @@ static struct rb_root comm_str_root;
16static struct comm_str *comm_str__get(struct comm_str *cs) 18static struct comm_str *comm_str__get(struct comm_str *cs)
17{ 19{
18 if (cs) 20 if (cs)
19 atomic_inc(&cs->refcnt); 21 refcount_inc(&cs->refcnt);
20 return cs; 22 return cs;
21} 23}
22 24
23static void comm_str__put(struct comm_str *cs) 25static void comm_str__put(struct comm_str *cs)
24{ 26{
25 if (cs && atomic_dec_and_test(&cs->refcnt)) { 27 if (cs && refcount_dec_and_test(&cs->refcnt)) {
26 rb_erase(&cs->rb_node, &comm_str_root); 28 rb_erase(&cs->rb_node, &comm_str_root);
27 zfree(&cs->str); 29 zfree(&cs->str);
28 free(cs); 30 free(cs);
@@ -43,7 +45,7 @@ static struct comm_str *comm_str__alloc(const char *str)
43 return NULL; 45 return NULL;
44 } 46 }
45 47
46 atomic_set(&cs->refcnt, 0); 48 refcount_set(&cs->refcnt, 1);
47 49
48 return cs; 50 return cs;
49} 51}
@@ -61,7 +63,7 @@ static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
61 63
62 cmp = strcmp(str, iter->str); 64 cmp = strcmp(str, iter->str);
63 if (!cmp) 65 if (!cmp)
64 return iter; 66 return comm_str__get(iter);
65 67
66 if (cmp < 0) 68 if (cmp < 0)
67 p = &(*p)->rb_left; 69 p = &(*p)->rb_left;
@@ -95,8 +97,6 @@ struct comm *comm__new(const char *str, u64 timestamp, bool exec)
95 return NULL; 97 return NULL;
96 } 98 }
97 99
98 comm_str__get(comm->comm_str);
99
100 return comm; 100 return comm;
101} 101}
102 102
@@ -108,7 +108,6 @@ int comm__override(struct comm *comm, const char *str, u64 timestamp, bool exec)
108 if (!new) 108 if (!new)
109 return -ENOMEM; 109 return -ENOMEM;
110 110
111 comm_str__get(new);
112 comm_str__put(old); 111 comm_str__put(old);
113 comm->comm_str = new; 112 comm->comm_str = new;
114 comm->start = timestamp; 113 comm->start = timestamp;
diff --git a/tools/perf/util/compress.h b/tools/perf/util/compress.h
new file mode 100644
index 000000000000..67fd1bb7c2b7
--- /dev/null
+++ b/tools/perf/util/compress.h
@@ -0,0 +1,12 @@
1#ifndef PERF_COMPRESS_H
2#define PERF_COMPRESS_H
3
4#ifdef HAVE_ZLIB_SUPPORT
5int gzip_decompress_to_file(const char *input, int output_fd);
6#endif
7
8#ifdef HAVE_LZMA_SUPPORT
9int lzma_decompress_to_file(const char *input, int output_fd);
10#endif
11
12#endif /* PERF_COMPRESS_H */
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 0c7d5a4975cd..8d724f0fa5a8 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -8,12 +8,19 @@
8 * Copyright (C) Johannes Schindelin, 2005 8 * Copyright (C) Johannes Schindelin, 2005
9 * 9 *
10 */ 10 */
11#include <errno.h>
12#include <sys/param.h>
11#include "util.h" 13#include "util.h"
12#include "cache.h" 14#include "cache.h"
13#include <subcmd/exec-cmd.h> 15#include <subcmd/exec-cmd.h>
14#include "util/hist.h" /* perf_hist_config */ 16#include "util/hist.h" /* perf_hist_config */
15#include "util/llvm-utils.h" /* perf_llvm_config */ 17#include "util/llvm-utils.h" /* perf_llvm_config */
16#include "config.h" 18#include "config.h"
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <unistd.h>
22
23#include "sane_ctype.h"
17 24
18#define MAXNAME (256) 25#define MAXNAME (256)
19 26
@@ -627,6 +634,8 @@ static int perf_config_set__init(struct perf_config_set *set)
627{ 634{
628 int ret = -1; 635 int ret = -1;
629 const char *home = NULL; 636 const char *home = NULL;
637 char *user_config;
638 struct stat st;
630 639
631 /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ 640 /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */
632 if (config_exclusive_filename) 641 if (config_exclusive_filename)
@@ -637,35 +646,41 @@ static int perf_config_set__init(struct perf_config_set *set)
637 } 646 }
638 647
639 home = getenv("HOME"); 648 home = getenv("HOME");
640 if (perf_config_global() && home) {
641 char *user_config = strdup(mkpath("%s/.perfconfig", home));
642 struct stat st;
643 649
644 if (user_config == NULL) { 650 /*
645 warning("Not enough memory to process %s/.perfconfig, " 651 * Skip reading user config if:
646 "ignoring it.", home); 652 * - there is no place to read it from (HOME)
647 goto out; 653 * - we are asked not to (PERF_CONFIG_NOGLOBAL=1)
648 } 654 */
655 if (!home || !*home || !perf_config_global())
656 return 0;
649 657
650 if (stat(user_config, &st) < 0) { 658 user_config = strdup(mkpath("%s/.perfconfig", home));
651 if (errno == ENOENT) 659 if (user_config == NULL) {
652 ret = 0; 660 warning("Not enough memory to process %s/.perfconfig, "
653 goto out_free; 661 "ignoring it.", home);
654 } 662 goto out;
663 }
655 664
656 ret = 0; 665 if (stat(user_config, &st) < 0) {
666 if (errno == ENOENT)
667 ret = 0;
668 goto out_free;
669 }
657 670
658 if (st.st_uid && (st.st_uid != geteuid())) { 671 ret = 0;
659 warning("File %s not owned by current user or root, "
660 "ignoring it.", user_config);
661 goto out_free;
662 }
663 672
664 if (st.st_size) 673 if (st.st_uid && (st.st_uid != geteuid())) {
665 ret = perf_config_from_file(collect_config, user_config, set); 674 warning("File %s not owned by current user or root, "
666out_free: 675 "ignoring it.", user_config);
667 free(user_config); 676 goto out_free;
668 } 677 }
678
679 if (st.st_size)
680 ret = perf_config_from_file(collect_config, user_config, set);
681
682out_free:
683 free(user_config);
669out: 684out:
670 return ret; 685 return ret;
671} 686}
diff --git a/tools/perf/util/counts.c b/tools/perf/util/counts.c
index e3fde313deb2..c4af82ab7808 100644
--- a/tools/perf/util/counts.c
+++ b/tools/perf/util/counts.c
@@ -1,6 +1,8 @@
1#include <errno.h>
1#include <stdlib.h> 2#include <stdlib.h>
2#include "evsel.h" 3#include "evsel.h"
3#include "counts.h" 4#include "counts.h"
5#include "util.h"
4 6
5struct perf_counts *perf_counts__new(int ncpus, int nthreads) 7struct perf_counts *perf_counts__new(int ncpus, int nthreads)
6{ 8{
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 8c7504939113..37b3bb79ee08 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -3,11 +3,14 @@
3#include "../perf.h" 3#include "../perf.h"
4#include "cpumap.h" 4#include "cpumap.h"
5#include <assert.h> 5#include <assert.h>
6#include <dirent.h>
6#include <stdio.h> 7#include <stdio.h>
7#include <stdlib.h> 8#include <stdlib.h>
8#include <linux/bitmap.h> 9#include <linux/bitmap.h>
9#include "asm/bug.h" 10#include "asm/bug.h"
10 11
12#include "sane_ctype.h"
13
11static int max_cpu_num; 14static int max_cpu_num;
12static int max_present_cpu_num; 15static int max_present_cpu_num;
13static int max_node_num; 16static int max_node_num;
@@ -29,7 +32,7 @@ static struct cpu_map *cpu_map__default_new(void)
29 cpus->map[i] = i; 32 cpus->map[i] = i;
30 33
31 cpus->nr = nr_cpus; 34 cpus->nr = nr_cpus;
32 atomic_set(&cpus->refcnt, 1); 35 refcount_set(&cpus->refcnt, 1);
33 } 36 }
34 37
35 return cpus; 38 return cpus;
@@ -43,7 +46,7 @@ static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
43 if (cpus != NULL) { 46 if (cpus != NULL) {
44 cpus->nr = nr_cpus; 47 cpus->nr = nr_cpus;
45 memcpy(cpus->map, tmp_cpus, payload_size); 48 memcpy(cpus->map, tmp_cpus, payload_size);
46 atomic_set(&cpus->refcnt, 1); 49 refcount_set(&cpus->refcnt, 1);
47 } 50 }
48 51
49 return cpus; 52 return cpus;
@@ -252,7 +255,7 @@ struct cpu_map *cpu_map__dummy_new(void)
252 if (cpus != NULL) { 255 if (cpus != NULL) {
253 cpus->nr = 1; 256 cpus->nr = 1;
254 cpus->map[0] = -1; 257 cpus->map[0] = -1;
255 atomic_set(&cpus->refcnt, 1); 258 refcount_set(&cpus->refcnt, 1);
256 } 259 }
257 260
258 return cpus; 261 return cpus;
@@ -269,7 +272,7 @@ struct cpu_map *cpu_map__empty_new(int nr)
269 for (i = 0; i < nr; i++) 272 for (i = 0; i < nr; i++)
270 cpus->map[i] = -1; 273 cpus->map[i] = -1;
271 274
272 atomic_set(&cpus->refcnt, 1); 275 refcount_set(&cpus->refcnt, 1);
273 } 276 }
274 277
275 return cpus; 278 return cpus;
@@ -278,7 +281,7 @@ struct cpu_map *cpu_map__empty_new(int nr)
278static void cpu_map__delete(struct cpu_map *map) 281static void cpu_map__delete(struct cpu_map *map)
279{ 282{
280 if (map) { 283 if (map) {
281 WARN_ONCE(atomic_read(&map->refcnt) != 0, 284 WARN_ONCE(refcount_read(&map->refcnt) != 0,
282 "cpu_map refcnt unbalanced\n"); 285 "cpu_map refcnt unbalanced\n");
283 free(map); 286 free(map);
284 } 287 }
@@ -287,13 +290,13 @@ static void cpu_map__delete(struct cpu_map *map)
287struct cpu_map *cpu_map__get(struct cpu_map *map) 290struct cpu_map *cpu_map__get(struct cpu_map *map)
288{ 291{
289 if (map) 292 if (map)
290 atomic_inc(&map->refcnt); 293 refcount_inc(&map->refcnt);
291 return map; 294 return map;
292} 295}
293 296
294void cpu_map__put(struct cpu_map *map) 297void cpu_map__put(struct cpu_map *map)
295{ 298{
296 if (map && atomic_dec_and_test(&map->refcnt)) 299 if (map && refcount_dec_and_test(&map->refcnt))
297 cpu_map__delete(map); 300 cpu_map__delete(map);
298} 301}
299 302
@@ -357,7 +360,7 @@ int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
357 /* ensure we process id in increasing order */ 360 /* ensure we process id in increasing order */
358 qsort(c->map, c->nr, sizeof(int), cmp_ids); 361 qsort(c->map, c->nr, sizeof(int), cmp_ids);
359 362
360 atomic_set(&c->refcnt, 1); 363 refcount_set(&c->refcnt, 1);
361 *res = c; 364 *res = c;
362 return 0; 365 return 0;
363} 366}
@@ -673,3 +676,49 @@ size_t cpu_map__snprint(struct cpu_map *map, char *buf, size_t size)
673 pr_debug("cpumask list: %s\n", buf); 676 pr_debug("cpumask list: %s\n", buf);
674 return ret; 677 return ret;
675} 678}
679
680static char hex_char(unsigned char val)
681{
682 if (val < 10)
683 return val + '0';
684 if (val < 16)
685 return val - 10 + 'a';
686 return '?';
687}
688
689size_t cpu_map__snprint_mask(struct cpu_map *map, char *buf, size_t size)
690{
691 int i, cpu;
692 char *ptr = buf;
693 unsigned char *bitmap;
694 int last_cpu = cpu_map__cpu(map, map->nr - 1);
695
696 bitmap = zalloc((last_cpu + 7) / 8);
697 if (bitmap == NULL) {
698 buf[0] = '\0';
699 return 0;
700 }
701
702 for (i = 0; i < map->nr; i++) {
703 cpu = cpu_map__cpu(map, i);
704 bitmap[cpu / 8] |= 1 << (cpu % 8);
705 }
706
707 for (cpu = last_cpu / 4 * 4; cpu >= 0; cpu -= 4) {
708 unsigned char bits = bitmap[cpu / 8];
709
710 if (cpu % 8)
711 bits >>= 4;
712 else
713 bits &= 0xf;
714
715 *ptr++ = hex_char(bits);
716 if ((cpu % 32) == 0 && cpu > 0)
717 *ptr++ = ',';
718 }
719 *ptr = '\0';
720 free(bitmap);
721
722 buf[size - 1] = '\0';
723 return ptr - buf;
724}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 1a0549af8f5c..6b8bff87481d 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -3,13 +3,13 @@
3 3
4#include <stdio.h> 4#include <stdio.h>
5#include <stdbool.h> 5#include <stdbool.h>
6#include <linux/atomic.h> 6#include <linux/refcount.h>
7 7
8#include "perf.h" 8#include "perf.h"
9#include "util/debug.h" 9#include "util/debug.h"
10 10
11struct cpu_map { 11struct cpu_map {
12 atomic_t refcnt; 12 refcount_t refcnt;
13 int nr; 13 int nr;
14 int map[]; 14 int map[];
15}; 15};
@@ -20,6 +20,7 @@ struct cpu_map *cpu_map__dummy_new(void);
20struct cpu_map *cpu_map__new_data(struct cpu_map_data *data); 20struct cpu_map *cpu_map__new_data(struct cpu_map_data *data);
21struct cpu_map *cpu_map__read(FILE *file); 21struct cpu_map *cpu_map__read(FILE *file);
22size_t cpu_map__snprint(struct cpu_map *map, char *buf, size_t size); 22size_t cpu_map__snprint(struct cpu_map *map, char *buf, size_t size);
23size_t cpu_map__snprint_mask(struct cpu_map *map, char *buf, size_t size);
23size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); 24size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
24int cpu_map__get_socket_id(int cpu); 25int cpu_map__get_socket_id(int cpu);
25int cpu_map__get_socket(struct cpu_map *map, int idx, void *data); 26int cpu_map__get_socket(struct cpu_map *map, int idx, void *data);
diff --git a/tools/perf/util/ctype.c b/tools/perf/util/ctype.c
index d4a5a21c2a7e..4b261c2ec0f1 100644
--- a/tools/perf/util/ctype.c
+++ b/tools/perf/util/ctype.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * No surprises, and works with signed and unsigned chars. 4 * No surprises, and works with signed and unsigned chars.
5 */ 5 */
6#include "util.h" 6#include "sane_ctype.h"
7 7
8enum { 8enum {
9 S = GIT_SPACE, 9 S = GIT_SPACE,
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 4e6cbc99f08e..89d50318833d 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -7,7 +7,10 @@
7 * Released under the GPL v2. (and only v2, not any later version) 7 * Released under the GPL v2. (and only v2, not any later version)
8 */ 8 */
9 9
10#include <errno.h>
11#include <inttypes.h>
10#include <linux/compiler.h> 12#include <linux/compiler.h>
13#include <linux/kernel.h>
11#include <babeltrace/ctf-writer/writer.h> 14#include <babeltrace/ctf-writer/writer.h>
12#include <babeltrace/ctf-writer/clock.h> 15#include <babeltrace/ctf-writer/clock.h>
13#include <babeltrace/ctf-writer/stream.h> 16#include <babeltrace/ctf-writer/stream.h>
@@ -27,6 +30,7 @@
27#include "evsel.h" 30#include "evsel.h"
28#include "machine.h" 31#include "machine.h"
29#include "config.h" 32#include "config.h"
33#include "sane_ctype.h"
30 34
31#define pr_N(n, fmt, ...) \ 35#define pr_N(n, fmt, ...) \
32 eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__) 36 eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
@@ -1468,6 +1472,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1468 .lost = perf_event__process_lost, 1472 .lost = perf_event__process_lost,
1469 .tracing_data = perf_event__process_tracing_data, 1473 .tracing_data = perf_event__process_tracing_data,
1470 .build_id = perf_event__process_build_id, 1474 .build_id = perf_event__process_build_id,
1475 .namespaces = perf_event__process_namespaces,
1471 .ordered_events = true, 1476 .ordered_events = true,
1472 .ordering_requires_timestamps = true, 1477 .ordering_requires_timestamps = true,
1473 }, 1478 },
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 60bfc9ca1e22..e84bbc8ec058 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -2,6 +2,7 @@
2#include <linux/kernel.h> 2#include <linux/kernel.h>
3#include <sys/types.h> 3#include <sys/types.h>
4#include <sys/stat.h> 4#include <sys/stat.h>
5#include <errno.h>
5#include <unistd.h> 6#include <unistd.h>
6#include <string.h> 7#include <string.h>
7 8
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 03eb81f30d0d..a5b3777ffee6 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -2,19 +2,26 @@
2 2
3#include "../perf.h" 3#include "../perf.h"
4 4
5#include <inttypes.h>
5#include <string.h> 6#include <string.h>
6#include <stdarg.h> 7#include <stdarg.h>
7#include <stdio.h> 8#include <stdio.h>
9#include <sys/wait.h>
8#include <api/debug.h> 10#include <api/debug.h>
9#include <linux/time64.h> 11#include <linux/time64.h>
10 12#ifdef HAVE_BACKTRACE_SUPPORT
13#include <execinfo.h>
14#endif
11#include "cache.h" 15#include "cache.h"
12#include "color.h" 16#include "color.h"
13#include "event.h" 17#include "event.h"
14#include "debug.h" 18#include "debug.h"
19#include "print_binary.h"
15#include "util.h" 20#include "util.h"
16#include "target.h" 21#include "target.h"
17 22
23#include "sane_ctype.h"
24
18int verbose; 25int verbose;
19bool dump_trace = false, quiet = false; 26bool dump_trace = false, quiet = false;
20int debug_ordered_events; 27int debug_ordered_events;
@@ -244,3 +251,31 @@ void perf_debug_setup(void)
244{ 251{
245 libapi_set_print(pr_warning_wrapper, pr_warning_wrapper, pr_debug_wrapper); 252 libapi_set_print(pr_warning_wrapper, pr_warning_wrapper, pr_debug_wrapper);
246} 253}
254
255/* Obtain a backtrace and print it to stdout. */
256#ifdef HAVE_BACKTRACE_SUPPORT
257void dump_stack(void)
258{
259 void *array[16];
260 size_t size = backtrace(array, ARRAY_SIZE(array));
261 char **strings = backtrace_symbols(array, size);
262 size_t i;
263
264 printf("Obtained %zd stack frames.\n", size);
265
266 for (i = 0; i < size; i++)
267 printf("%s\n", strings[i]);
268
269 free(strings);
270}
271#else
272void dump_stack(void) {}
273#endif
274
275void sighandler_dump_stack(int sig)
276{
277 psignal(sig, "perf");
278 dump_stack();
279 signal(sig, SIG_DFL);
280 raise(sig);
281}
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 98832f5531d3..8a23ea1a71c7 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -56,4 +56,7 @@ int perf_debug_option(const char *str);
56void perf_debug_setup(void); 56void perf_debug_setup(void);
57int perf_quiet_option(void); 57int perf_quiet_option(void);
58 58
59void dump_stack(void);
60void sighandler_dump_stack(int sig);
61
59#endif /* __PERF_DEBUG_H */ 62#endif /* __PERF_DEBUG_H */
diff --git a/tools/perf/util/demangle-java.c b/tools/perf/util/demangle-java.c
index 3e6062ab2cdd..cb66d334f532 100644
--- a/tools/perf/util/demangle-java.c
+++ b/tools/perf/util/demangle-java.c
@@ -7,6 +7,8 @@
7 7
8#include "demangle-java.h" 8#include "demangle-java.h"
9 9
10#include "sane_ctype.h"
11
10enum { 12enum {
11 MODE_PREFIX = 0, 13 MODE_PREFIX = 0,
12 MODE_CLASS = 1, 14 MODE_CLASS = 1,
diff --git a/tools/perf/util/drv_configs.c b/tools/perf/util/drv_configs.c
index 1647f285c629..eec754243f4d 100644
--- a/tools/perf/util/drv_configs.c
+++ b/tools/perf/util/drv_configs.c
@@ -17,6 +17,7 @@
17#include "evlist.h" 17#include "evlist.h"
18#include "evsel.h" 18#include "evsel.h"
19#include "pmu.h" 19#include "pmu.h"
20#include <errno.h>
20 21
21static int 22static int
22perf_evsel__apply_drv_configs(struct perf_evsel *evsel, 23perf_evsel__apply_drv_configs(struct perf_evsel *evsel,
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index d38b62a700ca..a96a99d2369f 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -1,12 +1,20 @@
1#include <asm/bug.h> 1#include <asm/bug.h>
2#include <linux/kernel.h>
2#include <sys/time.h> 3#include <sys/time.h>
3#include <sys/resource.h> 4#include <sys/resource.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <unistd.h>
8#include <errno.h>
9#include "compress.h"
10#include "path.h"
4#include "symbol.h" 11#include "symbol.h"
5#include "dso.h" 12#include "dso.h"
6#include "machine.h" 13#include "machine.h"
7#include "auxtrace.h" 14#include "auxtrace.h"
8#include "util.h" 15#include "util.h"
9#include "debug.h" 16#include "debug.h"
17#include "string2.h"
10#include "vdso.h" 18#include "vdso.h"
11 19
12static const char * const debuglink_paths[] = { 20static const char * const debuglink_paths[] = {
@@ -1109,7 +1117,7 @@ struct dso *dso__new(const char *name)
1109 INIT_LIST_HEAD(&dso->node); 1117 INIT_LIST_HEAD(&dso->node);
1110 INIT_LIST_HEAD(&dso->data.open_entry); 1118 INIT_LIST_HEAD(&dso->data.open_entry);
1111 pthread_mutex_init(&dso->lock, NULL); 1119 pthread_mutex_init(&dso->lock, NULL);
1112 atomic_set(&dso->refcnt, 1); 1120 refcount_set(&dso->refcnt, 1);
1113 } 1121 }
1114 1122
1115 return dso; 1123 return dso;
@@ -1147,13 +1155,13 @@ void dso__delete(struct dso *dso)
1147struct dso *dso__get(struct dso *dso) 1155struct dso *dso__get(struct dso *dso)
1148{ 1156{
1149 if (dso) 1157 if (dso)
1150 atomic_inc(&dso->refcnt); 1158 refcount_inc(&dso->refcnt);
1151 return dso; 1159 return dso;
1152} 1160}
1153 1161
1154void dso__put(struct dso *dso) 1162void dso__put(struct dso *dso)
1155{ 1163{
1156 if (dso && atomic_dec_and_test(&dso->refcnt)) 1164 if (dso && refcount_dec_and_test(&dso->refcnt))
1157 dso__delete(dso); 1165 dso__delete(dso);
1158} 1166}
1159 1167
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index ecc4bbd3f82e..12350b171727 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -1,7 +1,7 @@
1#ifndef __PERF_DSO 1#ifndef __PERF_DSO
2#define __PERF_DSO 2#define __PERF_DSO
3 3
4#include <linux/atomic.h> 4#include <linux/refcount.h>
5#include <linux/types.h> 5#include <linux/types.h>
6#include <linux/rbtree.h> 6#include <linux/rbtree.h>
7#include <sys/types.h> 7#include <sys/types.h>
@@ -187,7 +187,7 @@ struct dso {
187 void *priv; 187 void *priv;
188 u64 db_id; 188 u64 db_id;
189 }; 189 };
190 atomic_t refcnt; 190 refcount_t refcnt;
191 char name[0]; 191 char name[0];
192}; 192};
193 193
diff --git a/tools/perf/util/dump-insn.c b/tools/perf/util/dump-insn.c
new file mode 100644
index 000000000000..ffbdb19f05d0
--- /dev/null
+++ b/tools/perf/util/dump-insn.c
@@ -0,0 +1,14 @@
1#include <linux/compiler.h>
2#include "dump-insn.h"
3
4/* Fallback code */
5
6__weak
7const char *dump_insn(struct perf_insn *x __maybe_unused,
8 u64 ip __maybe_unused, u8 *inbuf __maybe_unused,
9 int inlen __maybe_unused, int *lenp)
10{
11 if (lenp)
12 *lenp = 0;
13 return "?";
14}
diff --git a/tools/perf/util/dump-insn.h b/tools/perf/util/dump-insn.h
new file mode 100644
index 000000000000..90fb115981cf
--- /dev/null
+++ b/tools/perf/util/dump-insn.h
@@ -0,0 +1,22 @@
1#ifndef __PERF_DUMP_INSN_H
2#define __PERF_DUMP_INSN_H 1
3
4#define MAXINSN 15
5
6#include <linux/types.h>
7
8struct thread;
9
10struct perf_insn {
11 /* Initialized by callers: */
12 struct thread *thread;
13 u8 cpumode;
14 bool is64bit;
15 int cpu;
16 /* Temporary */
17 char out[256];
18};
19
20const char *dump_insn(struct perf_insn *x, u64 ip,
21 u8 *inbuf, int inlen, int *lenp);
22#endif
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index 41e068e94349..f5acda13dcfa 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -17,10 +17,13 @@
17 * 17 *
18 */ 18 */
19 19
20#include <errno.h>
21#include <inttypes.h>
20#include <stdbool.h> 22#include <stdbool.h>
21#include "util.h" 23#include "util.h"
22#include "debug.h" 24#include "debug.h"
23#include "dwarf-aux.h" 25#include "dwarf-aux.h"
26#include "string2.h"
24 27
25/** 28/**
26 * cu_find_realpath - Find the realpath of the target file 29 * cu_find_realpath - Find the realpath of the target file
diff --git a/tools/perf/util/dwarf-regs.c b/tools/perf/util/dwarf-regs.c
index 62bc4a86a970..c708395b3cb6 100644
--- a/tools/perf/util/dwarf-regs.c
+++ b/tools/perf/util/dwarf-regs.c
@@ -8,6 +8,7 @@
8#include <debug.h> 8#include <debug.h>
9#include <dwarf-regs.h> 9#include <dwarf-regs.h>
10#include <elf.h> 10#include <elf.h>
11#include <linux/kernel.h>
11 12
12#ifndef EM_AARCH64 13#ifndef EM_AARCH64
13#define EM_AARCH64 183 /* ARM 64 bit */ 14#define EM_AARCH64 183 /* ARM 64 bit */
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index 075fc77286bf..9e21538c42ae 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -1,6 +1,7 @@
1#include "cpumap.h" 1#include "cpumap.h"
2#include "env.h" 2#include "env.h"
3#include "util.h" 3#include "util.h"
4#include <errno.h>
4 5
5struct perf_env perf_env; 6struct perf_env perf_env;
6 7
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 4ea7ce72ed9c..dc5c3bb69d73 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1,15 +1,24 @@
1#include <dirent.h>
2#include <errno.h>
3#include <inttypes.h>
4#include <linux/kernel.h>
1#include <linux/types.h> 5#include <linux/types.h>
2#include <linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */ 6#include <sys/types.h>
7#include <sys/stat.h>
8#include <unistd.h>
9#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
3#include <api/fs/fs.h> 10#include <api/fs/fs.h>
11#include <linux/perf_event.h>
4#include "event.h" 12#include "event.h"
5#include "debug.h" 13#include "debug.h"
6#include "hist.h" 14#include "hist.h"
7#include "machine.h" 15#include "machine.h"
8#include "sort.h" 16#include "sort.h"
9#include "string.h" 17#include "string2.h"
10#include "strlist.h" 18#include "strlist.h"
11#include "thread.h" 19#include "thread.h"
12#include "thread_map.h" 20#include "thread_map.h"
21#include "sane_ctype.h"
13#include "symbol/kallsyms.h" 22#include "symbol/kallsyms.h"
14#include "asm/bug.h" 23#include "asm/bug.h"
15#include "stat.h" 24#include "stat.h"
@@ -31,6 +40,7 @@ static const char *perf_event__names[] = {
31 [PERF_RECORD_LOST_SAMPLES] = "LOST_SAMPLES", 40 [PERF_RECORD_LOST_SAMPLES] = "LOST_SAMPLES",
32 [PERF_RECORD_SWITCH] = "SWITCH", 41 [PERF_RECORD_SWITCH] = "SWITCH",
33 [PERF_RECORD_SWITCH_CPU_WIDE] = "SWITCH_CPU_WIDE", 42 [PERF_RECORD_SWITCH_CPU_WIDE] = "SWITCH_CPU_WIDE",
43 [PERF_RECORD_NAMESPACES] = "NAMESPACES",
34 [PERF_RECORD_HEADER_ATTR] = "ATTR", 44 [PERF_RECORD_HEADER_ATTR] = "ATTR",
35 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", 45 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE",
36 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", 46 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
@@ -49,6 +59,16 @@ static const char *perf_event__names[] = {
49 [PERF_RECORD_TIME_CONV] = "TIME_CONV", 59 [PERF_RECORD_TIME_CONV] = "TIME_CONV",
50}; 60};
51 61
62static const char *perf_ns__names[] = {
63 [NET_NS_INDEX] = "net",
64 [UTS_NS_INDEX] = "uts",
65 [IPC_NS_INDEX] = "ipc",
66 [PID_NS_INDEX] = "pid",
67 [USER_NS_INDEX] = "user",
68 [MNT_NS_INDEX] = "mnt",
69 [CGROUP_NS_INDEX] = "cgroup",
70};
71
52const char *perf_event__name(unsigned int id) 72const char *perf_event__name(unsigned int id)
53{ 73{
54 if (id >= ARRAY_SIZE(perf_event__names)) 74 if (id >= ARRAY_SIZE(perf_event__names))
@@ -58,6 +78,13 @@ const char *perf_event__name(unsigned int id)
58 return perf_event__names[id]; 78 return perf_event__names[id];
59} 79}
60 80
81static const char *perf_ns__name(unsigned int id)
82{
83 if (id >= ARRAY_SIZE(perf_ns__names))
84 return "UNKNOWN";
85 return perf_ns__names[id];
86}
87
61static int perf_tool__process_synth_event(struct perf_tool *tool, 88static int perf_tool__process_synth_event(struct perf_tool *tool,
62 union perf_event *event, 89 union perf_event *event,
63 struct machine *machine, 90 struct machine *machine,
@@ -88,7 +115,7 @@ static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len,
88 int fd; 115 int fd;
89 size_t size = 0; 116 size_t size = 0;
90 ssize_t n; 117 ssize_t n;
91 char *nl, *name, *tgids, *ppids; 118 char *name, *tgids, *ppids;
92 119
93 *tgid = -1; 120 *tgid = -1;
94 *ppid = -1; 121 *ppid = -1;
@@ -115,10 +142,10 @@ static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len,
115 ppids = strstr(bf, "PPid:"); 142 ppids = strstr(bf, "PPid:");
116 143
117 if (name) { 144 if (name) {
118 name += 5; /* strlen("Name:") */ 145 char *nl;
119 146
120 while (*name && isspace(*name)) 147 name += 5; /* strlen("Name:") */
121 ++name; 148 name = ltrim(name);
122 149
123 nl = strchr(name, '\n'); 150 nl = strchr(name, '\n');
124 if (nl) 151 if (nl)
@@ -203,6 +230,58 @@ pid_t perf_event__synthesize_comm(struct perf_tool *tool,
203 return tgid; 230 return tgid;
204} 231}
205 232
233static void perf_event__get_ns_link_info(pid_t pid, const char *ns,
234 struct perf_ns_link_info *ns_link_info)
235{
236 struct stat64 st;
237 char proc_ns[128];
238
239 sprintf(proc_ns, "/proc/%u/ns/%s", pid, ns);
240 if (stat64(proc_ns, &st) == 0) {
241 ns_link_info->dev = st.st_dev;
242 ns_link_info->ino = st.st_ino;
243 }
244}
245
246int perf_event__synthesize_namespaces(struct perf_tool *tool,
247 union perf_event *event,
248 pid_t pid, pid_t tgid,
249 perf_event__handler_t process,
250 struct machine *machine)
251{
252 u32 idx;
253 struct perf_ns_link_info *ns_link_info;
254
255 if (!tool || !tool->namespace_events)
256 return 0;
257
258 memset(&event->namespaces, 0, (sizeof(event->namespaces) +
259 (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
260 machine->id_hdr_size));
261
262 event->namespaces.pid = tgid;
263 event->namespaces.tid = pid;
264
265 event->namespaces.nr_namespaces = NR_NAMESPACES;
266
267 ns_link_info = event->namespaces.link_info;
268
269 for (idx = 0; idx < event->namespaces.nr_namespaces; idx++)
270 perf_event__get_ns_link_info(pid, perf_ns__name(idx),
271 &ns_link_info[idx]);
272
273 event->namespaces.header.type = PERF_RECORD_NAMESPACES;
274
275 event->namespaces.header.size = (sizeof(event->namespaces) +
276 (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
277 machine->id_hdr_size);
278
279 if (perf_tool__process_synth_event(tool, event, machine, process) != 0)
280 return -1;
281
282 return 0;
283}
284
206static int perf_event__synthesize_fork(struct perf_tool *tool, 285static int perf_event__synthesize_fork(struct perf_tool *tool,
207 union perf_event *event, 286 union perf_event *event,
208 pid_t pid, pid_t tgid, pid_t ppid, 287 pid_t pid, pid_t tgid, pid_t ppid,
@@ -255,8 +334,8 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
255 if (machine__is_default_guest(machine)) 334 if (machine__is_default_guest(machine))
256 return 0; 335 return 0;
257 336
258 snprintf(filename, sizeof(filename), "%s/proc/%d/maps", 337 snprintf(filename, sizeof(filename), "%s/proc/%d/task/%d/maps",
259 machine->root_dir, pid); 338 machine->root_dir, pid, pid);
260 339
261 fp = fopen(filename, "r"); 340 fp = fopen(filename, "r");
262 if (fp == NULL) { 341 if (fp == NULL) {
@@ -434,8 +513,9 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
434static int __event__synthesize_thread(union perf_event *comm_event, 513static int __event__synthesize_thread(union perf_event *comm_event,
435 union perf_event *mmap_event, 514 union perf_event *mmap_event,
436 union perf_event *fork_event, 515 union perf_event *fork_event,
516 union perf_event *namespaces_event,
437 pid_t pid, int full, 517 pid_t pid, int full,
438 perf_event__handler_t process, 518 perf_event__handler_t process,
439 struct perf_tool *tool, 519 struct perf_tool *tool,
440 struct machine *machine, 520 struct machine *machine,
441 bool mmap_data, 521 bool mmap_data,
@@ -455,6 +535,11 @@ static int __event__synthesize_thread(union perf_event *comm_event,
455 if (tgid == -1) 535 if (tgid == -1)
456 return -1; 536 return -1;
457 537
538 if (perf_event__synthesize_namespaces(tool, namespaces_event, pid,
539 tgid, process, machine) < 0)
540 return -1;
541
542
458 return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 543 return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
459 process, machine, mmap_data, 544 process, machine, mmap_data,
460 proc_map_timeout); 545 proc_map_timeout);
@@ -488,6 +573,11 @@ static int __event__synthesize_thread(union perf_event *comm_event,
488 if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid, 573 if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
489 ppid, process, machine) < 0) 574 ppid, process, machine) < 0)
490 break; 575 break;
576
577 if (perf_event__synthesize_namespaces(tool, namespaces_event, _pid,
578 tgid, process, machine) < 0)
579 break;
580
491 /* 581 /*
492 * Send the prepared comm event 582 * Send the prepared comm event
493 */ 583 */
@@ -516,6 +606,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
516 unsigned int proc_map_timeout) 606 unsigned int proc_map_timeout)
517{ 607{
518 union perf_event *comm_event, *mmap_event, *fork_event; 608 union perf_event *comm_event, *mmap_event, *fork_event;
609 union perf_event *namespaces_event;
519 int err = -1, thread, j; 610 int err = -1, thread, j;
520 611
521 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size); 612 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
@@ -530,10 +621,16 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
530 if (fork_event == NULL) 621 if (fork_event == NULL)
531 goto out_free_mmap; 622 goto out_free_mmap;
532 623
624 namespaces_event = malloc(sizeof(namespaces_event->namespaces) +
625 (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
626 machine->id_hdr_size);
627 if (namespaces_event == NULL)
628 goto out_free_fork;
629
533 err = 0; 630 err = 0;
534 for (thread = 0; thread < threads->nr; ++thread) { 631 for (thread = 0; thread < threads->nr; ++thread) {
535 if (__event__synthesize_thread(comm_event, mmap_event, 632 if (__event__synthesize_thread(comm_event, mmap_event,
536 fork_event, 633 fork_event, namespaces_event,
537 thread_map__pid(threads, thread), 0, 634 thread_map__pid(threads, thread), 0,
538 process, tool, machine, 635 process, tool, machine,
539 mmap_data, proc_map_timeout)) { 636 mmap_data, proc_map_timeout)) {
@@ -559,7 +656,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
559 /* if not, generate events for it */ 656 /* if not, generate events for it */
560 if (need_leader && 657 if (need_leader &&
561 __event__synthesize_thread(comm_event, mmap_event, 658 __event__synthesize_thread(comm_event, mmap_event,
562 fork_event, 659 fork_event, namespaces_event,
563 comm_event->comm.pid, 0, 660 comm_event->comm.pid, 0,
564 process, tool, machine, 661 process, tool, machine,
565 mmap_data, proc_map_timeout)) { 662 mmap_data, proc_map_timeout)) {
@@ -568,6 +665,8 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
568 } 665 }
569 } 666 }
570 } 667 }
668 free(namespaces_event);
669out_free_fork:
571 free(fork_event); 670 free(fork_event);
572out_free_mmap: 671out_free_mmap:
573 free(mmap_event); 672 free(mmap_event);
@@ -587,6 +686,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
587 char proc_path[PATH_MAX]; 686 char proc_path[PATH_MAX];
588 struct dirent *dirent; 687 struct dirent *dirent;
589 union perf_event *comm_event, *mmap_event, *fork_event; 688 union perf_event *comm_event, *mmap_event, *fork_event;
689 union perf_event *namespaces_event;
590 int err = -1; 690 int err = -1;
591 691
592 if (machine__is_default_guest(machine)) 692 if (machine__is_default_guest(machine))
@@ -604,11 +704,17 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
604 if (fork_event == NULL) 704 if (fork_event == NULL)
605 goto out_free_mmap; 705 goto out_free_mmap;
606 706
707 namespaces_event = malloc(sizeof(namespaces_event->namespaces) +
708 (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
709 machine->id_hdr_size);
710 if (namespaces_event == NULL)
711 goto out_free_fork;
712
607 snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir); 713 snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
608 proc = opendir(proc_path); 714 proc = opendir(proc_path);
609 715
610 if (proc == NULL) 716 if (proc == NULL)
611 goto out_free_fork; 717 goto out_free_namespaces;
612 718
613 while ((dirent = readdir(proc)) != NULL) { 719 while ((dirent = readdir(proc)) != NULL) {
614 char *end; 720 char *end;
@@ -620,13 +726,16 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
620 * We may race with exiting thread, so don't stop just because 726 * We may race with exiting thread, so don't stop just because
621 * one thread couldn't be synthesized. 727 * one thread couldn't be synthesized.
622 */ 728 */
623 __event__synthesize_thread(comm_event, mmap_event, fork_event, pid, 729 __event__synthesize_thread(comm_event, mmap_event, fork_event,
624 1, process, tool, machine, mmap_data, 730 namespaces_event, pid, 1, process,
731 tool, machine, mmap_data,
625 proc_map_timeout); 732 proc_map_timeout);
626 } 733 }
627 734
628 err = 0; 735 err = 0;
629 closedir(proc); 736 closedir(proc);
737out_free_namespaces:
738 free(namespaces_event);
630out_free_fork: 739out_free_fork:
631 free(fork_event); 740 free(fork_event);
632out_free_mmap: 741out_free_mmap:
@@ -659,15 +768,16 @@ static int find_symbol_cb(void *arg, const char *name, char type,
659 return 1; 768 return 1;
660} 769}
661 770
662u64 kallsyms__get_function_start(const char *kallsyms_filename, 771int kallsyms__get_function_start(const char *kallsyms_filename,
663 const char *symbol_name) 772 const char *symbol_name, u64 *addr)
664{ 773{
665 struct process_symbol_args args = { .name = symbol_name, }; 774 struct process_symbol_args args = { .name = symbol_name, };
666 775
667 if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0) 776 if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0)
668 return 0; 777 return -1;
669 778
670 return args.start; 779 *addr = args.start;
780 return 0;
671} 781}
672 782
673int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, 783int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
@@ -1008,6 +1118,33 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
1008 return fprintf(fp, "%s: %s:%d/%d\n", s, event->comm.comm, event->comm.pid, event->comm.tid); 1118 return fprintf(fp, "%s: %s:%d/%d\n", s, event->comm.comm, event->comm.pid, event->comm.tid);
1009} 1119}
1010 1120
1121size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp)
1122{
1123 size_t ret = 0;
1124 struct perf_ns_link_info *ns_link_info;
1125 u32 nr_namespaces, idx;
1126
1127 ns_link_info = event->namespaces.link_info;
1128 nr_namespaces = event->namespaces.nr_namespaces;
1129
1130 ret += fprintf(fp, " %d/%d - nr_namespaces: %u\n\t\t[",
1131 event->namespaces.pid,
1132 event->namespaces.tid,
1133 nr_namespaces);
1134
1135 for (idx = 0; idx < nr_namespaces; idx++) {
1136 if (idx && (idx % 4 == 0))
1137 ret += fprintf(fp, "\n\t\t ");
1138
1139 ret += fprintf(fp, "%u/%s: %" PRIu64 "/%#" PRIx64 "%s", idx,
1140 perf_ns__name(idx), (u64)ns_link_info[idx].dev,
1141 (u64)ns_link_info[idx].ino,
1142 ((idx + 1) != nr_namespaces) ? ", " : "]\n");
1143 }
1144
1145 return ret;
1146}
1147
1011int perf_event__process_comm(struct perf_tool *tool __maybe_unused, 1148int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
1012 union perf_event *event, 1149 union perf_event *event,
1013 struct perf_sample *sample, 1150 struct perf_sample *sample,
@@ -1016,6 +1153,14 @@ int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
1016 return machine__process_comm_event(machine, event, sample); 1153 return machine__process_comm_event(machine, event, sample);
1017} 1154}
1018 1155
1156int perf_event__process_namespaces(struct perf_tool *tool __maybe_unused,
1157 union perf_event *event,
1158 struct perf_sample *sample,
1159 struct machine *machine)
1160{
1161 return machine__process_namespaces_event(machine, event, sample);
1162}
1163
1019int perf_event__process_lost(struct perf_tool *tool __maybe_unused, 1164int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
1020 union perf_event *event, 1165 union perf_event *event,
1021 struct perf_sample *sample, 1166 struct perf_sample *sample,
@@ -1153,11 +1298,12 @@ int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
1153 1298
1154size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp) 1299size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp)
1155{ 1300{
1156 return fprintf(fp, " offset: %#"PRIx64" size: %#"PRIx64" flags: %#"PRIx64" [%s%s]\n", 1301 return fprintf(fp, " offset: %#"PRIx64" size: %#"PRIx64" flags: %#"PRIx64" [%s%s%s]\n",
1157 event->aux.aux_offset, event->aux.aux_size, 1302 event->aux.aux_offset, event->aux.aux_size,
1158 event->aux.flags, 1303 event->aux.flags,
1159 event->aux.flags & PERF_AUX_FLAG_TRUNCATED ? "T" : "", 1304 event->aux.flags & PERF_AUX_FLAG_TRUNCATED ? "T" : "",
1160 event->aux.flags & PERF_AUX_FLAG_OVERWRITE ? "O" : ""); 1305 event->aux.flags & PERF_AUX_FLAG_OVERWRITE ? "O" : "",
1306 event->aux.flags & PERF_AUX_FLAG_PARTIAL ? "P" : "");
1161} 1307}
1162 1308
1163size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp) 1309size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp)
@@ -1196,6 +1342,9 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
1196 case PERF_RECORD_MMAP: 1342 case PERF_RECORD_MMAP:
1197 ret += perf_event__fprintf_mmap(event, fp); 1343 ret += perf_event__fprintf_mmap(event, fp);
1198 break; 1344 break;
1345 case PERF_RECORD_NAMESPACES:
1346 ret += perf_event__fprintf_namespaces(event, fp);
1347 break;
1199 case PERF_RECORD_MMAP2: 1348 case PERF_RECORD_MMAP2:
1200 ret += perf_event__fprintf_mmap2(event, fp); 1349 ret += perf_event__fprintf_mmap2(event, fp);
1201 break; 1350 break;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index c735c53a26f8..27ac047490c3 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -3,9 +3,9 @@
3 3
4#include <limits.h> 4#include <limits.h>
5#include <stdio.h> 5#include <stdio.h>
6#include <linux/kernel.h>
6 7
7#include "../perf.h" 8#include "../perf.h"
8#include "map.h"
9#include "build-id.h" 9#include "build-id.h"
10#include "perf_regs.h" 10#include "perf_regs.h"
11 11
@@ -39,6 +39,13 @@ struct comm_event {
39 char comm[16]; 39 char comm[16];
40}; 40};
41 41
42struct namespaces_event {
43 struct perf_event_header header;
44 u32 pid, tid;
45 u64 nr_namespaces;
46 struct perf_ns_link_info link_info[];
47};
48
42struct fork_event { 49struct fork_event {
43 struct perf_event_header header; 50 struct perf_event_header header;
44 u32 pid, ppid; 51 u32 pid, ppid;
@@ -269,6 +276,7 @@ struct events_stats {
269 u64 total_lost; 276 u64 total_lost;
270 u64 total_lost_samples; 277 u64 total_lost_samples;
271 u64 total_aux_lost; 278 u64 total_aux_lost;
279 u64 total_aux_partial;
272 u64 total_invalid_chains; 280 u64 total_invalid_chains;
273 u32 nr_events[PERF_RECORD_HEADER_MAX]; 281 u32 nr_events[PERF_RECORD_HEADER_MAX];
274 u32 nr_non_filtered_samples; 282 u32 nr_non_filtered_samples;
@@ -485,6 +493,7 @@ union perf_event {
485 struct mmap_event mmap; 493 struct mmap_event mmap;
486 struct mmap2_event mmap2; 494 struct mmap2_event mmap2;
487 struct comm_event comm; 495 struct comm_event comm;
496 struct namespaces_event namespaces;
488 struct fork_event fork; 497 struct fork_event fork;
489 struct lost_event lost; 498 struct lost_event lost;
490 struct lost_samples_event lost_samples; 499 struct lost_samples_event lost_samples;
@@ -587,6 +596,10 @@ int perf_event__process_switch(struct perf_tool *tool,
587 union perf_event *event, 596 union perf_event *event,
588 struct perf_sample *sample, 597 struct perf_sample *sample,
589 struct machine *machine); 598 struct machine *machine);
599int perf_event__process_namespaces(struct perf_tool *tool,
600 union perf_event *event,
601 struct perf_sample *sample,
602 struct machine *machine);
590int perf_event__process_mmap(struct perf_tool *tool, 603int perf_event__process_mmap(struct perf_tool *tool,
591 union perf_event *event, 604 union perf_event *event,
592 struct perf_sample *sample, 605 struct perf_sample *sample,
@@ -636,6 +649,12 @@ pid_t perf_event__synthesize_comm(struct perf_tool *tool,
636 perf_event__handler_t process, 649 perf_event__handler_t process,
637 struct machine *machine); 650 struct machine *machine);
638 651
652int perf_event__synthesize_namespaces(struct perf_tool *tool,
653 union perf_event *event,
654 pid_t pid, pid_t tgid,
655 perf_event__handler_t process,
656 struct machine *machine);
657
639int perf_event__synthesize_mmap_events(struct perf_tool *tool, 658int perf_event__synthesize_mmap_events(struct perf_tool *tool,
640 union perf_event *event, 659 union perf_event *event,
641 pid_t pid, pid_t tgid, 660 pid_t pid, pid_t tgid,
@@ -653,12 +672,21 @@ size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp);
653size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp); 672size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp);
654size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp); 673size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp);
655size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp); 674size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp);
675size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp);
656size_t perf_event__fprintf(union perf_event *event, FILE *fp); 676size_t perf_event__fprintf(union perf_event *event, FILE *fp);
657 677
658u64 kallsyms__get_function_start(const char *kallsyms_filename, 678int kallsyms__get_function_start(const char *kallsyms_filename,
659 const char *symbol_name); 679 const char *symbol_name, u64 *addr);
660 680
661void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max); 681void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max);
662void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map, 682void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map,
663 u16 type, int max); 683 u16 type, int max);
684
685void event_attr_init(struct perf_event_attr *attr);
686
687int perf_event_paranoid(void);
688
689extern int sysctl_perf_event_max_stack;
690extern int sysctl_perf_event_max_contexts_per_stack;
691
664#endif /* __PERF_RECORD_H */ 692#endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index b601f2814a30..46c0faf6c502 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -8,6 +8,8 @@
8 */ 8 */
9#include "util.h" 9#include "util.h"
10#include <api/fs/fs.h> 10#include <api/fs/fs.h>
11#include <errno.h>
12#include <inttypes.h>
11#include <poll.h> 13#include <poll.h>
12#include "cpumap.h" 14#include "cpumap.h"
13#include "thread_map.h" 15#include "thread_map.h"
@@ -15,12 +17,15 @@
15#include "evlist.h" 17#include "evlist.h"
16#include "evsel.h" 18#include "evsel.h"
17#include "debug.h" 19#include "debug.h"
20#include "units.h"
18#include "asm/bug.h" 21#include "asm/bug.h"
22#include <signal.h>
19#include <unistd.h> 23#include <unistd.h>
20 24
21#include "parse-events.h" 25#include "parse-events.h"
22#include <subcmd/parse-options.h> 26#include <subcmd/parse-options.h>
23 27
28#include <sys/ioctl.h>
24#include <sys/mman.h> 29#include <sys/mman.h>
25 30
26#include <linux/bitops.h> 31#include <linux/bitops.h>
@@ -777,7 +782,7 @@ union perf_event *perf_mmap__read_forward(struct perf_mmap *md, bool check_messu
777 /* 782 /*
778 * Check if event was unmapped due to a POLLHUP/POLLERR. 783 * Check if event was unmapped due to a POLLHUP/POLLERR.
779 */ 784 */
780 if (!atomic_read(&md->refcnt)) 785 if (!refcount_read(&md->refcnt))
781 return NULL; 786 return NULL;
782 787
783 head = perf_mmap__read_head(md); 788 head = perf_mmap__read_head(md);
@@ -794,7 +799,7 @@ perf_mmap__read_backward(struct perf_mmap *md)
794 /* 799 /*
795 * Check if event was unmapped due to a POLLHUP/POLLERR. 800 * Check if event was unmapped due to a POLLHUP/POLLERR.
796 */ 801 */
797 if (!atomic_read(&md->refcnt)) 802 if (!refcount_read(&md->refcnt))
798 return NULL; 803 return NULL;
799 804
800 head = perf_mmap__read_head(md); 805 head = perf_mmap__read_head(md);
@@ -856,7 +861,7 @@ void perf_mmap__read_catchup(struct perf_mmap *md)
856{ 861{
857 u64 head; 862 u64 head;
858 863
859 if (!atomic_read(&md->refcnt)) 864 if (!refcount_read(&md->refcnt))
860 return; 865 return;
861 866
862 head = perf_mmap__read_head(md); 867 head = perf_mmap__read_head(md);
@@ -875,14 +880,14 @@ static bool perf_mmap__empty(struct perf_mmap *md)
875 880
876static void perf_mmap__get(struct perf_mmap *map) 881static void perf_mmap__get(struct perf_mmap *map)
877{ 882{
878 atomic_inc(&map->refcnt); 883 refcount_inc(&map->refcnt);
879} 884}
880 885
881static void perf_mmap__put(struct perf_mmap *md) 886static void perf_mmap__put(struct perf_mmap *md)
882{ 887{
883 BUG_ON(md->base && atomic_read(&md->refcnt) == 0); 888 BUG_ON(md->base && refcount_read(&md->refcnt) == 0);
884 889
885 if (atomic_dec_and_test(&md->refcnt)) 890 if (refcount_dec_and_test(&md->refcnt))
886 perf_mmap__munmap(md); 891 perf_mmap__munmap(md);
887} 892}
888 893
@@ -894,7 +899,7 @@ void perf_mmap__consume(struct perf_mmap *md, bool overwrite)
894 perf_mmap__write_tail(md, old); 899 perf_mmap__write_tail(md, old);
895 } 900 }
896 901
897 if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md)) 902 if (refcount_read(&md->refcnt) == 1 && perf_mmap__empty(md))
898 perf_mmap__put(md); 903 perf_mmap__put(md);
899} 904}
900 905
@@ -937,7 +942,7 @@ static void perf_mmap__munmap(struct perf_mmap *map)
937 munmap(map->base, perf_mmap__mmap_len(map)); 942 munmap(map->base, perf_mmap__mmap_len(map));
938 map->base = NULL; 943 map->base = NULL;
939 map->fd = -1; 944 map->fd = -1;
940 atomic_set(&map->refcnt, 0); 945 refcount_set(&map->refcnt, 0);
941 } 946 }
942 auxtrace_mmap__munmap(&map->auxtrace_mmap); 947 auxtrace_mmap__munmap(&map->auxtrace_mmap);
943} 948}
@@ -974,8 +979,19 @@ static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist)
974 if (!map) 979 if (!map)
975 return NULL; 980 return NULL;
976 981
977 for (i = 0; i < evlist->nr_mmaps; i++) 982 for (i = 0; i < evlist->nr_mmaps; i++) {
978 map[i].fd = -1; 983 map[i].fd = -1;
984 /*
985 * When the perf_mmap() call is made we grab one refcount, plus
986 * one extra to let perf_evlist__mmap_consume() get the last
987 * events after all real references (perf_mmap__get()) are
988 * dropped.
989 *
990 * Each PERF_EVENT_IOC_SET_OUTPUT points to this mmap and
991 * thus does perf_mmap__get() on it.
992 */
993 refcount_set(&map[i].refcnt, 0);
994 }
979 return map; 995 return map;
980} 996}
981 997
@@ -1001,7 +1017,7 @@ static int perf_mmap__mmap(struct perf_mmap *map,
1001 * evlist layer can't just drop it when filtering events in 1017 * evlist layer can't just drop it when filtering events in
1002 * perf_evlist__filter_pollfd(). 1018 * perf_evlist__filter_pollfd().
1003 */ 1019 */
1004 atomic_set(&map->refcnt, 2); 1020 refcount_set(&map->refcnt, 2);
1005 map->prev = 0; 1021 map->prev = 0;
1006 map->mask = mp->mask; 1022 map->mask = mp->mask;
1007 map->base = mmap(NULL, perf_mmap__mmap_len(map), mp->prot, 1023 map->base = mmap(NULL, perf_mmap__mmap_len(map), mp->prot,
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 389b9ccdf8c7..94cea4398a13 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -1,7 +1,8 @@
1#ifndef __PERF_EVLIST_H 1#ifndef __PERF_EVLIST_H
2#define __PERF_EVLIST_H 1 2#define __PERF_EVLIST_H 1
3 3
4#include <linux/atomic.h> 4#include <linux/kernel.h>
5#include <linux/refcount.h>
5#include <linux/list.h> 6#include <linux/list.h>
6#include <api/fd/array.h> 7#include <api/fd/array.h>
7#include <stdio.h> 8#include <stdio.h>
@@ -10,6 +11,7 @@
10#include "evsel.h" 11#include "evsel.h"
11#include "util.h" 12#include "util.h"
12#include "auxtrace.h" 13#include "auxtrace.h"
14#include <signal.h>
13#include <unistd.h> 15#include <unistd.h>
14 16
15struct pollfd; 17struct pollfd;
@@ -29,7 +31,7 @@ struct perf_mmap {
29 void *base; 31 void *base;
30 int mask; 32 int mask;
31 int fd; 33 int fd;
32 atomic_t refcnt; 34 refcount_t refcnt;
33 u64 prev; 35 u64 prev;
34 struct auxtrace_mmap auxtrace_mmap; 36 struct auxtrace_mmap auxtrace_mmap;
35 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8))); 37 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ac59710b79e0..e4f7902d5afa 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -8,16 +8,20 @@
8 */ 8 */
9 9
10#include <byteswap.h> 10#include <byteswap.h>
11#include <errno.h>
12#include <inttypes.h>
11#include <linux/bitops.h> 13#include <linux/bitops.h>
12#include <api/fs/tracing_path.h> 14#include <api/fs/tracing_path.h>
13#include <traceevent/event-parse.h> 15#include <traceevent/event-parse.h>
14#include <linux/hw_breakpoint.h> 16#include <linux/hw_breakpoint.h>
15#include <linux/perf_event.h> 17#include <linux/perf_event.h>
16#include <linux/err.h> 18#include <linux/err.h>
19#include <sys/ioctl.h>
17#include <sys/resource.h> 20#include <sys/resource.h>
18#include "asm/bug.h" 21#include "asm/bug.h"
19#include "callchain.h" 22#include "callchain.h"
20#include "cgroup.h" 23#include "cgroup.h"
24#include "event.h"
21#include "evsel.h" 25#include "evsel.h"
22#include "evlist.h" 26#include "evlist.h"
23#include "util.h" 27#include "util.h"
@@ -30,6 +34,8 @@
30#include "stat.h" 34#include "stat.h"
31#include "util/parse-branch-options.h" 35#include "util/parse-branch-options.h"
32 36
37#include "sane_ctype.h"
38
33static struct { 39static struct {
34 bool sample_id_all; 40 bool sample_id_all;
35 bool exclude_guest; 41 bool exclude_guest;
@@ -236,6 +242,10 @@ void perf_evsel__init(struct perf_evsel *evsel,
236 evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); 242 evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
237 perf_evsel__calc_id_pos(evsel); 243 perf_evsel__calc_id_pos(evsel);
238 evsel->cmdline_group_boundary = false; 244 evsel->cmdline_group_boundary = false;
245 evsel->metric_expr = NULL;
246 evsel->metric_name = NULL;
247 evsel->metric_events = NULL;
248 evsel->collect_stat = false;
239} 249}
240 250
241struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) 251struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
@@ -932,6 +942,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
932 attr->mmap2 = track && !perf_missing_features.mmap2; 942 attr->mmap2 = track && !perf_missing_features.mmap2;
933 attr->comm = track; 943 attr->comm = track;
934 944
945 if (opts->record_namespaces)
946 attr->namespaces = track;
947
935 if (opts->record_switch_events) 948 if (opts->record_switch_events)
936 attr->context_switch = track; 949 attr->context_switch = track;
937 950
@@ -1232,7 +1245,7 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
1232 if (FD(evsel, cpu, thread) < 0) 1245 if (FD(evsel, cpu, thread) < 0)
1233 return -EINVAL; 1246 return -EINVAL;
1234 1247
1235 if (readn(FD(evsel, cpu, thread), count, sizeof(*count)) < 0) 1248 if (readn(FD(evsel, cpu, thread), count, sizeof(*count)) <= 0)
1236 return -errno; 1249 return -errno;
1237 1250
1238 return 0; 1251 return 0;
@@ -1250,7 +1263,7 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
1250 if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1, thread + 1) < 0) 1263 if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1, thread + 1) < 0)
1251 return -ENOMEM; 1264 return -ENOMEM;
1252 1265
1253 if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0) 1266 if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) <= 0)
1254 return -errno; 1267 return -errno;
1255 1268
1256 perf_evsel__compute_deltas(evsel, cpu, thread, &count); 1269 perf_evsel__compute_deltas(evsel, cpu, thread, &count);
@@ -2450,11 +2463,17 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2450 int err, char *msg, size_t size) 2463 int err, char *msg, size_t size)
2451{ 2464{
2452 char sbuf[STRERR_BUFSIZE]; 2465 char sbuf[STRERR_BUFSIZE];
2466 int printed = 0;
2453 2467
2454 switch (err) { 2468 switch (err) {
2455 case EPERM: 2469 case EPERM:
2456 case EACCES: 2470 case EACCES:
2457 return scnprintf(msg, size, 2471 if (err == EPERM)
2472 printed = scnprintf(msg, size,
2473 "No permission to enable %s event.\n\n",
2474 perf_evsel__name(evsel));
2475
2476 return scnprintf(msg + printed, size - printed,
2458 "You may not have permission to collect %sstats.\n\n" 2477 "You may not have permission to collect %sstats.\n\n"
2459 "Consider tweaking /proc/sys/kernel/perf_event_paranoid,\n" 2478 "Consider tweaking /proc/sys/kernel/perf_event_paranoid,\n"
2460 "which controls use of the performance events system by\n" 2479 "which controls use of the performance events system by\n"
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 06ef6f29efa1..d101695c482c 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -131,6 +131,11 @@ struct perf_evsel {
131 bool cmdline_group_boundary; 131 bool cmdline_group_boundary;
132 struct list_head config_terms; 132 struct list_head config_terms;
133 int bpf_fd; 133 int bpf_fd;
134 bool merged_stat;
135 const char * metric_expr;
136 const char * metric_name;
137 struct perf_evsel **metric_events;
138 bool collect_stat;
134}; 139};
135 140
136union u64_swap { 141union u64_swap {
diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
index 4ef5184819a0..e415aee6a245 100644
--- a/tools/perf/util/evsel_fprintf.c
+++ b/tools/perf/util/evsel_fprintf.c
@@ -1,9 +1,11 @@
1#include <inttypes.h>
1#include <stdio.h> 2#include <stdio.h>
2#include <stdbool.h> 3#include <stdbool.h>
3#include <traceevent/event-parse.h> 4#include <traceevent/event-parse.h>
4#include "evsel.h" 5#include "evsel.h"
5#include "callchain.h" 6#include "callchain.h"
6#include "map.h" 7#include "map.h"
8#include "strlist.h"
7#include "symbol.h" 9#include "symbol.h"
8 10
9static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...) 11static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h
new file mode 100644
index 000000000000..9c2760a1a96e
--- /dev/null
+++ b/tools/perf/util/expr.h
@@ -0,0 +1,25 @@
1#ifndef PARSE_CTX_H
2#define PARSE_CTX_H 1
3
4#define EXPR_MAX_OTHER 8
5#define MAX_PARSE_ID EXPR_MAX_OTHER
6
7struct parse_id {
8 const char *name;
9 double val;
10};
11
12struct parse_ctx {
13 int num_ids;
14 struct parse_id ids[MAX_PARSE_ID];
15};
16
17void expr__ctx_init(struct parse_ctx *ctx);
18void expr__add_id(struct parse_ctx *ctx, const char *id, double val);
19#ifndef IN_EXPR_Y
20int expr__parse(double *final_val, struct parse_ctx *ctx, const char **pp);
21#endif
22int expr__find_other(const char *p, const char *one, const char ***other,
23 int *num_other);
24
25#endif
diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y
new file mode 100644
index 000000000000..954556bea36e
--- /dev/null
+++ b/tools/perf/util/expr.y
@@ -0,0 +1,173 @@
1/* Simple expression parser */
2%{
3#include "util.h"
4#include "util/debug.h"
5#define IN_EXPR_Y 1
6#include "expr.h"
7#include <string.h>
8
9#define MAXIDLEN 256
10%}
11
12%pure-parser
13%parse-param { double *final_val }
14%parse-param { struct parse_ctx *ctx }
15%parse-param { const char **pp }
16%lex-param { const char **pp }
17
18%union {
19 double num;
20 char id[MAXIDLEN+1];
21}
22
23%token <num> NUMBER
24%token <id> ID
25%left '|'
26%left '^'
27%left '&'
28%left '-' '+'
29%left '*' '/' '%'
30%left NEG NOT
31%type <num> expr
32
33%{
34static int expr__lex(YYSTYPE *res, const char **pp);
35
36static void expr__error(double *final_val __maybe_unused,
37 struct parse_ctx *ctx __maybe_unused,
38 const char **pp __maybe_unused,
39 const char *s)
40{
41 pr_debug("%s\n", s);
42}
43
44static int lookup_id(struct parse_ctx *ctx, char *id, double *val)
45{
46 int i;
47
48 for (i = 0; i < ctx->num_ids; i++) {
49 if (!strcasecmp(ctx->ids[i].name, id)) {
50 *val = ctx->ids[i].val;
51 return 0;
52 }
53 }
54 return -1;
55}
56
57%}
58%%
59
60all_expr: expr { *final_val = $1; }
61 ;
62
63expr: NUMBER
64 | ID { if (lookup_id(ctx, $1, &$$) < 0) {
65 pr_debug("%s not found", $1);
66 YYABORT;
67 }
68 }
69 | expr '+' expr { $$ = $1 + $3; }
70 | expr '-' expr { $$ = $1 - $3; }
71 | expr '*' expr { $$ = $1 * $3; }
72 | expr '/' expr { if ($3 == 0) YYABORT; $$ = $1 / $3; }
73 | expr '%' expr { if ((long)$3 == 0) YYABORT; $$ = (long)$1 % (long)$3; }
74 | '-' expr %prec NEG { $$ = -$2; }
75 | '(' expr ')' { $$ = $2; }
76 ;
77
78%%
79
80static int expr__symbol(YYSTYPE *res, const char *p, const char **pp)
81{
82 char *dst = res->id;
83 const char *s = p;
84
85 while (isalnum(*p) || *p == '_' || *p == '.') {
86 if (p - s >= MAXIDLEN)
87 return -1;
88 *dst++ = *p++;
89 }
90 *dst = 0;
91 *pp = p;
92 return ID;
93}
94
95static int expr__lex(YYSTYPE *res, const char **pp)
96{
97 int tok;
98 const char *s;
99 const char *p = *pp;
100
101 while (isspace(*p))
102 p++;
103 s = p;
104 switch (*p++) {
105 case 'a' ... 'z':
106 case 'A' ... 'Z':
107 return expr__symbol(res, p - 1, pp);
108 case '0' ... '9': case '.':
109 res->num = strtod(s, (char **)&p);
110 tok = NUMBER;
111 break;
112 default:
113 tok = *s;
114 break;
115 }
116 *pp = p;
117 return tok;
118}
119
120/* Caller must make sure id is allocated */
121void expr__add_id(struct parse_ctx *ctx, const char *name, double val)
122{
123 int idx;
124 assert(ctx->num_ids < MAX_PARSE_ID);
125 idx = ctx->num_ids++;
126 ctx->ids[idx].name = name;
127 ctx->ids[idx].val = val;
128}
129
130void expr__ctx_init(struct parse_ctx *ctx)
131{
132 ctx->num_ids = 0;
133}
134
135int expr__find_other(const char *p, const char *one, const char ***other,
136 int *num_otherp)
137{
138 const char *orig = p;
139 int err = -1;
140 int num_other;
141
142 *other = malloc((EXPR_MAX_OTHER + 1) * sizeof(char *));
143 if (!*other)
144 return -1;
145
146 num_other = 0;
147 for (;;) {
148 YYSTYPE val;
149 int tok = expr__lex(&val, &p);
150 if (tok == 0) {
151 err = 0;
152 break;
153 }
154 if (tok == ID && strcasecmp(one, val.id)) {
155 if (num_other >= EXPR_MAX_OTHER - 1) {
156 pr_debug("Too many extra events in %s\n", orig);
157 break;
158 }
159 (*other)[num_other] = strdup(val.id);
160 if (!(*other)[num_other])
161 return -1;
162 num_other++;
163 }
164 }
165 (*other)[num_other] = NULL;
166 *num_otherp = num_other;
167 if (err) {
168 *num_otherp = 0;
169 free(*other);
170 *other = NULL;
171 }
172 return err;
173}
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 05714d548584..314a07151fb7 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1,4 +1,8 @@
1#include <errno.h>
2#include <inttypes.h>
1#include "util.h" 3#include "util.h"
4#include "string2.h"
5#include <sys/param.h>
2#include <sys/types.h> 6#include <sys/types.h>
3#include <byteswap.h> 7#include <byteswap.h>
4#include <unistd.h> 8#include <unistd.h>
@@ -7,11 +11,15 @@
7#include <linux/list.h> 11#include <linux/list.h>
8#include <linux/kernel.h> 12#include <linux/kernel.h>
9#include <linux/bitops.h> 13#include <linux/bitops.h>
14#include <sys/stat.h>
15#include <sys/types.h>
10#include <sys/utsname.h> 16#include <sys/utsname.h>
17#include <unistd.h>
11 18
12#include "evlist.h" 19#include "evlist.h"
13#include "evsel.h" 20#include "evsel.h"
14#include "header.h" 21#include "header.h"
22#include "memswap.h"
15#include "../perf.h" 23#include "../perf.h"
16#include "trace-event.h" 24#include "trace-event.h"
17#include "session.h" 25#include "session.h"
@@ -26,6 +34,8 @@
26#include <api/fs/fs.h> 34#include <api/fs/fs.h>
27#include "asm/bug.h" 35#include "asm/bug.h"
28 36
37#include "sane_ctype.h"
38
29/* 39/*
30 * magic2 = "PERFILE2" 40 * magic2 = "PERFILE2"
31 * must be a numerical value to let the endianness 41 * must be a numerical value to let the endianness
@@ -370,15 +380,11 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
370 struct perf_evlist *evlist __maybe_unused) 380 struct perf_evlist *evlist __maybe_unused)
371{ 381{
372 char buf[MAXPATHLEN]; 382 char buf[MAXPATHLEN];
373 char proc[32];
374 u32 n; 383 u32 n;
375 int i, ret; 384 int i, ret;
376 385
377 /* 386 /* actual path to perf binary */
378 * actual atual path to perf binary 387 ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
379 */
380 sprintf(proc, "/proc/%d/exe", getpid());
381 ret = readlink(proc, buf, sizeof(buf));
382 if (ret <= 0) 388 if (ret <= 0)
383 return -1; 389 return -1;
384 390
@@ -2274,6 +2280,9 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
2274 perf_header__process_sections(header, fd, &hd, 2280 perf_header__process_sections(header, fd, &hd,
2275 perf_file_section__fprintf_info); 2281 perf_file_section__fprintf_info);
2276 2282
2283 if (session->file->is_pipe)
2284 return 0;
2285
2277 fprintf(fp, "# missing features: "); 2286 fprintf(fp, "# missing features: ");
2278 for_each_clear_bit(bit, header->adds_features, HEADER_LAST_FEATURE) { 2287 for_each_clear_bit(bit, header->adds_features, HEADER_LAST_FEATURE) {
2279 if (bit) 2288 if (bit)
diff --git a/tools/perf/util/help-unknown-cmd.c b/tools/perf/util/help-unknown-cmd.c
index 2821f8d77e52..1c88ad6425b8 100644
--- a/tools/perf/util/help-unknown-cmd.c
+++ b/tools/perf/util/help-unknown-cmd.c
@@ -1,21 +1,18 @@
1#include "cache.h" 1#include "cache.h"
2#include "config.h" 2#include "config.h"
3#include <poll.h>
3#include <stdio.h> 4#include <stdio.h>
4#include <subcmd/help.h> 5#include <subcmd/help.h>
5#include "../builtin.h" 6#include "../builtin.h"
6#include "levenshtein.h" 7#include "levenshtein.h"
7 8
8static int autocorrect; 9static int autocorrect;
9static struct cmdnames aliases;
10 10
11static int perf_unknown_cmd_config(const char *var, const char *value, 11static int perf_unknown_cmd_config(const char *var, const char *value,
12 void *cb __maybe_unused) 12 void *cb __maybe_unused)
13{ 13{
14 if (!strcmp(var, "help.autocorrect")) 14 if (!strcmp(var, "help.autocorrect"))
15 autocorrect = perf_config_int(var,value); 15 autocorrect = perf_config_int(var,value);
16 /* Also use aliases for command lookup */
17 if (!prefixcmp(var, "alias."))
18 add_cmdname(&aliases, var + 6, strlen(var + 6));
19 16
20 return 0; 17 return 0;
21} 18}
@@ -59,14 +56,12 @@ const char *help_unknown_cmd(const char *cmd)
59 56
60 memset(&main_cmds, 0, sizeof(main_cmds)); 57 memset(&main_cmds, 0, sizeof(main_cmds));
61 memset(&other_cmds, 0, sizeof(main_cmds)); 58 memset(&other_cmds, 0, sizeof(main_cmds));
62 memset(&aliases, 0, sizeof(aliases));
63 59
64 perf_config(perf_unknown_cmd_config, NULL); 60 perf_config(perf_unknown_cmd_config, NULL);
65 61
66 load_command_list("perf-", &main_cmds, &other_cmds); 62 load_command_list("perf-", &main_cmds, &other_cmds);
67 63
68 if (add_cmd_list(&main_cmds, &aliases) < 0 || 64 if (add_cmd_list(&main_cmds, &other_cmds) < 0) {
69 add_cmd_list(&main_cmds, &other_cmds) < 0) {
70 fprintf(stderr, "ERROR: Failed to allocate command list for unknown command.\n"); 65 fprintf(stderr, "ERROR: Failed to allocate command list for unknown command.\n");
71 goto end; 66 goto end;
72 } 67 }
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index eaf72a938fb4..cf0186a088c1 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -3,12 +3,17 @@
3#include "hist.h" 3#include "hist.h"
4#include "map.h" 4#include "map.h"
5#include "session.h" 5#include "session.h"
6#include "namespaces.h"
6#include "sort.h" 7#include "sort.h"
7#include "evlist.h" 8#include "evlist.h"
8#include "evsel.h" 9#include "evsel.h"
9#include "annotate.h" 10#include "annotate.h"
11#include "srcline.h"
12#include "thread.h"
10#include "ui/progress.h" 13#include "ui/progress.h"
14#include <errno.h>
11#include <math.h> 15#include <math.h>
16#include <sys/param.h>
12 17
13static bool hists__filter_entry_by_dso(struct hists *hists, 18static bool hists__filter_entry_by_dso(struct hists *hists,
14 struct hist_entry *he); 19 struct hist_entry *he);
@@ -169,6 +174,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
169 hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO); 174 hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
170 } 175 }
171 176
177 hists__new_col_len(hists, HISTC_CGROUP_ID, 20);
172 hists__new_col_len(hists, HISTC_CPU, 3); 178 hists__new_col_len(hists, HISTC_CPU, 3);
173 hists__new_col_len(hists, HISTC_SOCKET, 6); 179 hists__new_col_len(hists, HISTC_SOCKET, 6);
174 hists__new_col_len(hists, HISTC_MEM_LOCKED, 6); 180 hists__new_col_len(hists, HISTC_MEM_LOCKED, 6);
@@ -574,9 +580,14 @@ __hists__add_entry(struct hists *hists,
574 bool sample_self, 580 bool sample_self,
575 struct hist_entry_ops *ops) 581 struct hist_entry_ops *ops)
576{ 582{
583 struct namespaces *ns = thread__namespaces(al->thread);
577 struct hist_entry entry = { 584 struct hist_entry entry = {
578 .thread = al->thread, 585 .thread = al->thread,
579 .comm = thread__comm(al->thread), 586 .comm = thread__comm(al->thread),
587 .cgroup_id = {
588 .dev = ns ? ns->link_info[CGROUP_NS_INDEX].dev : 0,
589 .ino = ns ? ns->link_info[CGROUP_NS_INDEX].ino : 0,
590 },
580 .ms = { 591 .ms = {
581 .map = al->map, 592 .map = al->map,
582 .sym = al->sym, 593 .sym = al->sym,
@@ -1129,6 +1140,11 @@ void hist_entry__delete(struct hist_entry *he)
1129 zfree(&he->mem_info); 1140 zfree(&he->mem_info);
1130 } 1141 }
1131 1142
1143 if (he->inline_node) {
1144 inline_node__delete(he->inline_node);
1145 he->inline_node = NULL;
1146 }
1147
1132 zfree(&he->stat_acc); 1148 zfree(&he->stat_acc);
1133 free_srcline(he->srcline); 1149 free_srcline(he->srcline);
1134 if (he->srcfile && he->srcfile[0]) 1150 if (he->srcfile && he->srcfile[0])
@@ -2447,7 +2463,7 @@ int parse_filter_percentage(const struct option *opt __maybe_unused,
2447 else if (!strcmp(arg, "absolute")) 2463 else if (!strcmp(arg, "absolute"))
2448 symbol_conf.filter_relative = false; 2464 symbol_conf.filter_relative = false;
2449 else { 2465 else {
2450 pr_debug("Invalud percentage: %s\n", arg); 2466 pr_debug("Invalid percentage: %s\n", arg);
2451 return -1; 2467 return -1;
2452 } 2468 }
2453 2469
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 28c216e3d5b7..ee3670a388df 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -30,6 +30,7 @@ enum hist_column {
30 HISTC_DSO, 30 HISTC_DSO,
31 HISTC_THREAD, 31 HISTC_THREAD,
32 HISTC_COMM, 32 HISTC_COMM,
33 HISTC_CGROUP_ID,
33 HISTC_PARENT, 34 HISTC_PARENT,
34 HISTC_CPU, 35 HISTC_CPU,
35 HISTC_SOCKET, 36 HISTC_SOCKET,
@@ -57,6 +58,7 @@ enum hist_column {
57 HISTC_SRCLINE_FROM, 58 HISTC_SRCLINE_FROM,
58 HISTC_SRCLINE_TO, 59 HISTC_SRCLINE_TO,
59 HISTC_TRACE, 60 HISTC_TRACE,
61 HISTC_SYM_SIZE,
60 HISTC_NR_COLS, /* Last entry */ 62 HISTC_NR_COLS, /* Last entry */
61}; 63};
62 64
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index 6c2eb5da4afc..b2834ac7b1f5 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -14,7 +14,9 @@
14 */ 14 */
15 15
16#include <endian.h> 16#include <endian.h>
17#include <errno.h>
17#include <byteswap.h> 18#include <byteswap.h>
19#include <inttypes.h>
18#include <linux/kernel.h> 20#include <linux/kernel.h>
19#include <linux/types.h> 21#include <linux/types.h>
20#include <linux/bitops.h> 22#include <linux/bitops.h>
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
index 4f3c758d875d..54818828023b 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
@@ -26,6 +26,7 @@
26#include "insn.c" 26#include "insn.c"
27 27
28#include "intel-pt-insn-decoder.h" 28#include "intel-pt-insn-decoder.h"
29#include "dump-insn.h"
29 30
30#if INTEL_PT_INSN_BUF_SZ < MAX_INSN_SIZE || INTEL_PT_INSN_BUF_SZ > MAX_INSN 31#if INTEL_PT_INSN_BUF_SZ < MAX_INSN_SIZE || INTEL_PT_INSN_BUF_SZ > MAX_INSN
31#error Instruction buffer size too small 32#error Instruction buffer size too small
@@ -39,6 +40,8 @@ static void intel_pt_insn_decoder(struct insn *insn,
39 enum intel_pt_insn_branch branch = INTEL_PT_BR_NO_BRANCH; 40 enum intel_pt_insn_branch branch = INTEL_PT_BR_NO_BRANCH;
40 int ext; 41 int ext;
41 42
43 intel_pt_insn->rel = 0;
44
42 if (insn_is_avx(insn)) { 45 if (insn_is_avx(insn)) {
43 intel_pt_insn->op = INTEL_PT_OP_OTHER; 46 intel_pt_insn->op = INTEL_PT_OP_OTHER;
44 intel_pt_insn->branch = INTEL_PT_BR_NO_BRANCH; 47 intel_pt_insn->branch = INTEL_PT_BR_NO_BRANCH;
@@ -177,6 +180,29 @@ int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64,
177 return 0; 180 return 0;
178} 181}
179 182
183const char *dump_insn(struct perf_insn *x, uint64_t ip __maybe_unused,
184 u8 *inbuf, int inlen, int *lenp)
185{
186 struct insn insn;
187 int n, i;
188 int left;
189
190 insn_init(&insn, inbuf, inlen, x->is64bit);
191 insn_get_length(&insn);
192 if (!insn_complete(&insn) || insn.length > inlen)
193 return "<bad>";
194 if (lenp)
195 *lenp = insn.length;
196 left = sizeof(x->out);
197 n = snprintf(x->out, left, "insn: ");
198 left -= n;
199 for (i = 0; i < insn.length; i++) {
200 n += snprintf(x->out + n, left, "%02x ", inbuf[i]);
201 left -= n;
202 }
203 return x->out;
204}
205
180const char *branch_name[] = { 206const char *branch_name[] = {
181 [INTEL_PT_OP_OTHER] = "Other", 207 [INTEL_PT_OP_OTHER] = "Other",
182 [INTEL_PT_OP_CALL] = "Call", 208 [INTEL_PT_OP_CALL] = "Call",
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index da20cd5612e9..4c7718f87a08 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -13,6 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16#include <inttypes.h>
16#include <stdio.h> 17#include <stdio.h>
17#include <stdbool.h> 18#include <stdbool.h>
18#include <errno.h> 19#include <errno.h>
@@ -22,6 +23,7 @@
22#include "../perf.h" 23#include "../perf.h"
23#include "session.h" 24#include "session.h"
24#include "machine.h" 25#include "machine.h"
26#include "memswap.h"
25#include "sort.h" 27#include "sort.h"
26#include "tool.h" 28#include "tool.h"
27#include "event.h" 29#include "event.h"
diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c
index c9a941ef0f6d..9084930e1757 100644
--- a/tools/perf/util/jitdump.c
+++ b/tools/perf/util/jitdump.c
@@ -1,5 +1,6 @@
1#include <sys/sysmacros.h> 1#include <sys/sysmacros.h>
2#include <sys/types.h> 2#include <sys/types.h>
3#include <errno.h>
3#include <stdio.h> 4#include <stdio.h>
4#include <stdlib.h> 5#include <stdlib.h>
5#include <string.h> 6#include <string.h>
@@ -9,13 +10,13 @@
9#include <byteswap.h> 10#include <byteswap.h>
10#include <sys/stat.h> 11#include <sys/stat.h>
11#include <sys/mman.h> 12#include <sys/mman.h>
13#include <linux/stringify.h>
12 14
13#include "util.h" 15#include "util.h"
14#include "event.h" 16#include "event.h"
15#include "debug.h" 17#include "debug.h"
16#include "evlist.h" 18#include "evlist.h"
17#include "symbol.h" 19#include "symbol.h"
18#include "strlist.h"
19#include <elf.h> 20#include <elf.h>
20 21
21#include "tsc.h" 22#include "tsc.h"
@@ -25,6 +26,8 @@
25#include "genelf.h" 26#include "genelf.h"
26#include "../builtin.h" 27#include "../builtin.h"
27 28
29#include "sane_ctype.h"
30
28struct jit_buf_desc { 31struct jit_buf_desc {
29 struct perf_data_file *output; 32 struct perf_data_file *output;
30 struct perf_session *session; 33 struct perf_session *session;
@@ -181,7 +184,7 @@ jit_open(struct jit_buf_desc *jd, const char *name)
181 jd->use_arch_timestamp); 184 jd->use_arch_timestamp);
182 185
183 if (header.version > JITHEADER_VERSION) { 186 if (header.version > JITHEADER_VERSION) {
184 pr_err("wrong jitdump version %u, expected " STR(JITHEADER_VERSION), 187 pr_err("wrong jitdump version %u, expected " __stringify(JITHEADER_VERSION),
185 header.version); 188 header.version);
186 goto error; 189 goto error;
187 } 190 }
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 824356488ce6..c6a15f204c03 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -12,6 +12,7 @@
12#include "llvm-utils.h" 12#include "llvm-utils.h"
13#include "config.h" 13#include "config.h"
14#include "util.h" 14#include "util.h"
15#include <sys/wait.h>
15 16
16#define CLANG_BPF_CMD_DEFAULT_TEMPLATE \ 17#define CLANG_BPF_CMD_DEFAULT_TEMPLATE \
17 "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\ 18 "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\
diff --git a/tools/perf/util/lzma.c b/tools/perf/util/lzma.c
index 9ddea5cecd94..4ca7c5c6cdcd 100644
--- a/tools/perf/util/lzma.c
+++ b/tools/perf/util/lzma.c
@@ -1,6 +1,8 @@
1#include <errno.h>
1#include <lzma.h> 2#include <lzma.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <linux/compiler.h> 4#include <linux/compiler.h>
5#include "compress.h"
4#include "util.h" 6#include "util.h"
5#include "debug.h" 7#include "debug.h"
6 8
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 71c9720d4973..d97e014c3df3 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1,3 +1,7 @@
1#include <dirent.h>
2#include <errno.h>
3#include <inttypes.h>
4#include <regex.h>
1#include "callchain.h" 5#include "callchain.h"
2#include "debug.h" 6#include "debug.h"
3#include "event.h" 7#include "event.h"
@@ -10,9 +14,15 @@
10#include "thread.h" 14#include "thread.h"
11#include "vdso.h" 15#include "vdso.h"
12#include <stdbool.h> 16#include <stdbool.h>
13#include <symbol/kallsyms.h> 17#include <sys/types.h>
18#include <sys/stat.h>
19#include <unistd.h>
14#include "unwind.h" 20#include "unwind.h"
15#include "linux/hash.h" 21#include "linux/hash.h"
22#include "asm/bug.h"
23
24#include "sane_ctype.h"
25#include <symbol/kallsyms.h>
16 26
17static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock); 27static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock);
18 28
@@ -501,6 +511,37 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event
501 return err; 511 return err;
502} 512}
503 513
514int machine__process_namespaces_event(struct machine *machine __maybe_unused,
515 union perf_event *event,
516 struct perf_sample *sample __maybe_unused)
517{
518 struct thread *thread = machine__findnew_thread(machine,
519 event->namespaces.pid,
520 event->namespaces.tid);
521 int err = 0;
522
523 WARN_ONCE(event->namespaces.nr_namespaces > NR_NAMESPACES,
524 "\nWARNING: kernel seems to support more namespaces than perf"
525 " tool.\nTry updating the perf tool..\n\n");
526
527 WARN_ONCE(event->namespaces.nr_namespaces < NR_NAMESPACES,
528 "\nWARNING: perf tool seems to support more namespaces than"
529 " the kernel.\nTry updating the kernel..\n\n");
530
531 if (dump_trace)
532 perf_event__fprintf_namespaces(event, stdout);
533
534 if (thread == NULL ||
535 thread__set_namespaces(thread, sample->time, &event->namespaces)) {
536 dump_printf("problem processing PERF_RECORD_NAMESPACES, skipping event.\n");
537 err = -1;
538 }
539
540 thread__put(thread);
541
542 return err;
543}
544
504int machine__process_lost_event(struct machine *machine __maybe_unused, 545int machine__process_lost_event(struct machine *machine __maybe_unused,
505 union perf_event *event, struct perf_sample *sample __maybe_unused) 546 union perf_event *event, struct perf_sample *sample __maybe_unused)
506{ 547{
@@ -755,11 +796,11 @@ const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
755 * Returns the name of the start symbol in *symbol_name. Pass in NULL as 796 * Returns the name of the start symbol in *symbol_name. Pass in NULL as
756 * symbol_name if it's not that important. 797 * symbol_name if it's not that important.
757 */ 798 */
758static u64 machine__get_running_kernel_start(struct machine *machine, 799static int machine__get_running_kernel_start(struct machine *machine,
759 const char **symbol_name) 800 const char **symbol_name, u64 *start)
760{ 801{
761 char filename[PATH_MAX]; 802 char filename[PATH_MAX];
762 int i; 803 int i, err = -1;
763 const char *name; 804 const char *name;
764 u64 addr = 0; 805 u64 addr = 0;
765 806
@@ -769,21 +810,28 @@ static u64 machine__get_running_kernel_start(struct machine *machine,
769 return 0; 810 return 0;
770 811
771 for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) { 812 for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
772 addr = kallsyms__get_function_start(filename, name); 813 err = kallsyms__get_function_start(filename, name, &addr);
773 if (addr) 814 if (!err)
774 break; 815 break;
775 } 816 }
776 817
818 if (err)
819 return -1;
820
777 if (symbol_name) 821 if (symbol_name)
778 *symbol_name = name; 822 *symbol_name = name;
779 823
780 return addr; 824 *start = addr;
825 return 0;
781} 826}
782 827
783int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) 828int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
784{ 829{
785 int type; 830 int type;
786 u64 start = machine__get_running_kernel_start(machine, NULL); 831 u64 start = 0;
832
833 if (machine__get_running_kernel_start(machine, NULL, &start))
834 return -1;
787 835
788 /* In case of renewal the kernel map, destroy previous one */ 836 /* In case of renewal the kernel map, destroy previous one */
789 machine__destroy_kernel_maps(machine); 837 machine__destroy_kernel_maps(machine);
@@ -1144,8 +1192,8 @@ static int machine__create_modules(struct machine *machine)
1144int machine__create_kernel_maps(struct machine *machine) 1192int machine__create_kernel_maps(struct machine *machine)
1145{ 1193{
1146 struct dso *kernel = machine__get_kernel(machine); 1194 struct dso *kernel = machine__get_kernel(machine);
1147 const char *name; 1195 const char *name = NULL;
1148 u64 addr; 1196 u64 addr = 0;
1149 int ret; 1197 int ret;
1150 1198
1151 if (kernel == NULL) 1199 if (kernel == NULL)
@@ -1170,8 +1218,7 @@ int machine__create_kernel_maps(struct machine *machine)
1170 */ 1218 */
1171 map_groups__fixup_end(&machine->kmaps); 1219 map_groups__fixup_end(&machine->kmaps);
1172 1220
1173 addr = machine__get_running_kernel_start(machine, &name); 1221 if (machine__get_running_kernel_start(machine, &name, &addr)) {
1174 if (!addr) {
1175 } else if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) { 1222 } else if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) {
1176 machine__destroy_kernel_maps(machine); 1223 machine__destroy_kernel_maps(machine);
1177 return -1; 1224 return -1;
@@ -1439,7 +1486,7 @@ static void __machine__remove_thread(struct machine *machine, struct thread *th,
1439 if (machine->last_match == th) 1486 if (machine->last_match == th)
1440 machine->last_match = NULL; 1487 machine->last_match = NULL;
1441 1488
1442 BUG_ON(atomic_read(&th->refcnt) == 0); 1489 BUG_ON(refcount_read(&th->refcnt) == 0);
1443 if (lock) 1490 if (lock)
1444 pthread_rwlock_wrlock(&machine->threads_lock); 1491 pthread_rwlock_wrlock(&machine->threads_lock);
1445 rb_erase_init(&th->rb_node, &machine->threads); 1492 rb_erase_init(&th->rb_node, &machine->threads);
@@ -1538,6 +1585,8 @@ int machine__process_event(struct machine *machine, union perf_event *event,
1538 ret = machine__process_comm_event(machine, event, sample); break; 1585 ret = machine__process_comm_event(machine, event, sample); break;
1539 case PERF_RECORD_MMAP: 1586 case PERF_RECORD_MMAP:
1540 ret = machine__process_mmap_event(machine, event, sample); break; 1587 ret = machine__process_mmap_event(machine, event, sample); break;
1588 case PERF_RECORD_NAMESPACES:
1589 ret = machine__process_namespaces_event(machine, event, sample); break;
1541 case PERF_RECORD_MMAP2: 1590 case PERF_RECORD_MMAP2:
1542 ret = machine__process_mmap2_event(machine, event, sample); break; 1591 ret = machine__process_mmap2_event(machine, event, sample); break;
1543 case PERF_RECORD_FORK: 1592 case PERF_RECORD_FORK:
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index a28305029711..3cdb1340f917 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -97,6 +97,9 @@ int machine__process_itrace_start_event(struct machine *machine,
97 union perf_event *event); 97 union perf_event *event);
98int machine__process_switch_event(struct machine *machine, 98int machine__process_switch_event(struct machine *machine,
99 union perf_event *event); 99 union perf_event *event);
100int machine__process_namespaces_event(struct machine *machine,
101 union perf_event *event,
102 struct perf_sample *sample);
100int machine__process_mmap_event(struct machine *machine, union perf_event *event, 103int machine__process_mmap_event(struct machine *machine, union perf_event *event,
101 struct perf_sample *sample); 104 struct perf_sample *sample);
102int machine__process_mmap2_event(struct machine *machine, union perf_event *event, 105int machine__process_mmap2_event(struct machine *machine, union perf_event *event,
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 0a943e7b1ea7..2179b2deb730 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -9,13 +9,13 @@
9#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */ 9#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
10#include "map.h" 10#include "map.h"
11#include "thread.h" 11#include "thread.h"
12#include "strlist.h"
13#include "vdso.h" 12#include "vdso.h"
14#include "build-id.h" 13#include "build-id.h"
15#include "util.h" 14#include "util.h"
16#include "debug.h" 15#include "debug.h"
17#include "machine.h" 16#include "machine.h"
18#include <linux/string.h> 17#include <linux/string.h>
18#include "srcline.h"
19#include "unwind.h" 19#include "unwind.h"
20 20
21static void __maps__insert(struct maps *maps, struct map *map); 21static void __maps__insert(struct maps *maps, struct map *map);
@@ -141,7 +141,7 @@ void map__init(struct map *map, enum map_type type,
141 RB_CLEAR_NODE(&map->rb_node); 141 RB_CLEAR_NODE(&map->rb_node);
142 map->groups = NULL; 142 map->groups = NULL;
143 map->erange_warned = false; 143 map->erange_warned = false;
144 atomic_set(&map->refcnt, 1); 144 refcount_set(&map->refcnt, 1);
145} 145}
146 146
147struct map *map__new(struct machine *machine, u64 start, u64 len, 147struct map *map__new(struct machine *machine, u64 start, u64 len,
@@ -255,7 +255,7 @@ void map__delete(struct map *map)
255 255
256void map__put(struct map *map) 256void map__put(struct map *map)
257{ 257{
258 if (map && atomic_dec_and_test(&map->refcnt)) 258 if (map && refcount_dec_and_test(&map->refcnt))
259 map__delete(map); 259 map__delete(map);
260} 260}
261 261
@@ -325,11 +325,6 @@ int map__load(struct map *map)
325 return 0; 325 return 0;
326} 326}
327 327
328int __weak arch__compare_symbol_names(const char *namea, const char *nameb)
329{
330 return strcmp(namea, nameb);
331}
332
333struct symbol *map__find_symbol(struct map *map, u64 addr) 328struct symbol *map__find_symbol(struct map *map, u64 addr)
334{ 329{
335 if (map__load(map) < 0) 330 if (map__load(map) < 0)
@@ -354,7 +349,7 @@ struct map *map__clone(struct map *from)
354 struct map *map = memdup(from, sizeof(*map)); 349 struct map *map = memdup(from, sizeof(*map));
355 350
356 if (map != NULL) { 351 if (map != NULL) {
357 atomic_set(&map->refcnt, 1); 352 refcount_set(&map->refcnt, 1);
358 RB_CLEAR_NODE(&map->rb_node); 353 RB_CLEAR_NODE(&map->rb_node);
359 dso__get(map->dso); 354 dso__get(map->dso);
360 map->groups = NULL; 355 map->groups = NULL;
@@ -405,7 +400,8 @@ int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
405 400
406 if (map && map->dso) { 401 if (map && map->dso) {
407 srcline = get_srcline(map->dso, 402 srcline = get_srcline(map->dso,
408 map__rip_2objdump(map, addr), NULL, true); 403 map__rip_2objdump(map, addr), NULL,
404 true, true);
409 if (srcline != SRCLINE_UNKNOWN) 405 if (srcline != SRCLINE_UNKNOWN)
410 ret = fprintf(fp, "%s%s", prefix, srcline); 406 ret = fprintf(fp, "%s%s", prefix, srcline);
411 free_srcline(srcline); 407 free_srcline(srcline);
@@ -485,7 +481,7 @@ void map_groups__init(struct map_groups *mg, struct machine *machine)
485 maps__init(&mg->maps[i]); 481 maps__init(&mg->maps[i]);
486 } 482 }
487 mg->machine = machine; 483 mg->machine = machine;
488 atomic_set(&mg->refcnt, 1); 484 refcount_set(&mg->refcnt, 1);
489} 485}
490 486
491static void __maps__purge(struct maps *maps) 487static void __maps__purge(struct maps *maps)
@@ -547,7 +543,7 @@ void map_groups__delete(struct map_groups *mg)
547 543
548void map_groups__put(struct map_groups *mg) 544void map_groups__put(struct map_groups *mg)
549{ 545{
550 if (mg && atomic_dec_and_test(&mg->refcnt)) 546 if (mg && refcount_dec_and_test(&mg->refcnt))
551 map_groups__delete(mg); 547 map_groups__delete(mg);
552} 548}
553 549
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index abdacf800c98..f9e8ac8a52cd 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -1,7 +1,7 @@
1#ifndef __PERF_MAP_H 1#ifndef __PERF_MAP_H
2#define __PERF_MAP_H 2#define __PERF_MAP_H
3 3
4#include <linux/atomic.h> 4#include <linux/refcount.h>
5#include <linux/compiler.h> 5#include <linux/compiler.h>
6#include <linux/list.h> 6#include <linux/list.h>
7#include <linux/rbtree.h> 7#include <linux/rbtree.h>
@@ -51,7 +51,7 @@ struct map {
51 51
52 struct dso *dso; 52 struct dso *dso;
53 struct map_groups *groups; 53 struct map_groups *groups;
54 atomic_t refcnt; 54 refcount_t refcnt;
55}; 55};
56 56
57struct kmap { 57struct kmap {
@@ -67,7 +67,7 @@ struct maps {
67struct map_groups { 67struct map_groups {
68 struct maps maps[MAP__NR_TYPES]; 68 struct maps maps[MAP__NR_TYPES];
69 struct machine *machine; 69 struct machine *machine;
70 atomic_t refcnt; 70 refcount_t refcnt;
71}; 71};
72 72
73struct map_groups *map_groups__new(struct machine *machine); 73struct map_groups *map_groups__new(struct machine *machine);
@@ -77,7 +77,7 @@ bool map_groups__empty(struct map_groups *mg);
77static inline struct map_groups *map_groups__get(struct map_groups *mg) 77static inline struct map_groups *map_groups__get(struct map_groups *mg)
78{ 78{
79 if (mg) 79 if (mg)
80 atomic_inc(&mg->refcnt); 80 refcount_inc(&mg->refcnt);
81 return mg; 81 return mg;
82} 82}
83 83
@@ -130,13 +130,14 @@ struct thread;
130 */ 130 */
131#define __map__for_each_symbol_by_name(map, sym_name, pos) \ 131#define __map__for_each_symbol_by_name(map, sym_name, pos) \
132 for (pos = map__find_symbol_by_name(map, sym_name); \ 132 for (pos = map__find_symbol_by_name(map, sym_name); \
133 pos && arch__compare_symbol_names(pos->name, sym_name) == 0; \ 133 pos && \
134 !symbol__match_symbol_name(pos->name, sym_name, \
135 SYMBOL_TAG_INCLUDE__DEFAULT_ONLY); \
134 pos = symbol__next_by_name(pos)) 136 pos = symbol__next_by_name(pos))
135 137
136#define map__for_each_symbol_by_name(map, sym_name, pos) \ 138#define map__for_each_symbol_by_name(map, sym_name, pos) \
137 __map__for_each_symbol_by_name(map, sym_name, (pos)) 139 __map__for_each_symbol_by_name(map, sym_name, (pos))
138 140
139int arch__compare_symbol_names(const char *namea, const char *nameb);
140void map__init(struct map *map, enum map_type type, 141void map__init(struct map *map, enum map_type type,
141 u64 start, u64 end, u64 pgoff, struct dso *dso); 142 u64 start, u64 end, u64 pgoff, struct dso *dso);
142struct map *map__new(struct machine *machine, u64 start, u64 len, 143struct map *map__new(struct machine *machine, u64 start, u64 len,
@@ -150,7 +151,7 @@ struct map *map__clone(struct map *map);
150static inline struct map *map__get(struct map *map) 151static inline struct map *map__get(struct map *map)
151{ 152{
152 if (map) 153 if (map)
153 atomic_inc(&map->refcnt); 154 refcount_inc(&map->refcnt);
154 return map; 155 return map;
155} 156}
156 157
diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c
index 1d4ab53c60ca..06f5a3a4295c 100644
--- a/tools/perf/util/mem-events.c
+++ b/tools/perf/util/mem-events.c
@@ -6,6 +6,7 @@
6#include <sys/stat.h> 6#include <sys/stat.h>
7#include <unistd.h> 7#include <unistd.h>
8#include <api/fs/fs.h> 8#include <api/fs/fs.h>
9#include <linux/kernel.h>
9#include "mem-events.h" 10#include "mem-events.h"
10#include "debug.h" 11#include "debug.h"
11#include "symbol.h" 12#include "symbol.h"
@@ -205,8 +206,8 @@ int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
205static const char * const snoop_access[] = { 206static const char * const snoop_access[] = {
206 "N/A", 207 "N/A",
207 "None", 208 "None",
208 "Miss",
209 "Hit", 209 "Hit",
210 "Miss",
210 "HitM", 211 "HitM",
211}; 212};
212 213
diff --git a/tools/perf/util/memswap.c b/tools/perf/util/memswap.c
new file mode 100644
index 000000000000..55f7faa8d9ec
--- /dev/null
+++ b/tools/perf/util/memswap.c
@@ -0,0 +1,24 @@
1#include <byteswap.h>
2#include "memswap.h"
3#include <linux/types.h>
4
5void mem_bswap_32(void *src, int byte_size)
6{
7 u32 *m = src;
8 while (byte_size > 0) {
9 *m = bswap_32(*m);
10 byte_size -= sizeof(u32);
11 ++m;
12 }
13}
14
15void mem_bswap_64(void *src, int byte_size)
16{
17 u64 *m = src;
18
19 while (byte_size > 0) {
20 *m = bswap_64(*m);
21 byte_size -= sizeof(u64);
22 ++m;
23 }
24}
diff --git a/tools/perf/util/memswap.h b/tools/perf/util/memswap.h
new file mode 100644
index 000000000000..7d1b1c34bb57
--- /dev/null
+++ b/tools/perf/util/memswap.h
@@ -0,0 +1,7 @@
1#ifndef PERF_MEMSWAP_H_
2#define PERF_MEMSWAP_H_
3
4void mem_bswap_64(void *src, int byte_size);
5void mem_bswap_32(void *src, int byte_size);
6
7#endif /* PERF_MEMSWAP_H_ */
diff --git a/tools/perf/util/namespaces.c b/tools/perf/util/namespaces.c
new file mode 100644
index 000000000000..67dcbcc73c7d
--- /dev/null
+++ b/tools/perf/util/namespaces.c
@@ -0,0 +1,37 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2, as
4 * published by the Free Software Foundation.
5 *
6 * Copyright (C) 2017 Hari Bathini, IBM Corporation
7 */
8
9#include "namespaces.h"
10#include "util.h"
11#include "event.h"
12#include <stdlib.h>
13#include <stdio.h>
14#include <string.h>
15
16struct namespaces *namespaces__new(struct namespaces_event *event)
17{
18 struct namespaces *namespaces;
19 u64 link_info_size = ((event ? event->nr_namespaces : NR_NAMESPACES) *
20 sizeof(struct perf_ns_link_info));
21
22 namespaces = zalloc(sizeof(struct namespaces) + link_info_size);
23 if (!namespaces)
24 return NULL;
25
26 namespaces->end_time = -1;
27
28 if (event)
29 memcpy(namespaces->link_info, event->link_info, link_info_size);
30
31 return namespaces;
32}
33
34void namespaces__free(struct namespaces *namespaces)
35{
36 free(namespaces);
37}
diff --git a/tools/perf/util/namespaces.h b/tools/perf/util/namespaces.h
new file mode 100644
index 000000000000..468f1e9a1484
--- /dev/null
+++ b/tools/perf/util/namespaces.h
@@ -0,0 +1,26 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2, as
4 * published by the Free Software Foundation.
5 *
6 * Copyright (C) 2017 Hari Bathini, IBM Corporation
7 */
8
9#ifndef __PERF_NAMESPACES_H
10#define __PERF_NAMESPACES_H
11
12#include "../perf.h"
13#include <linux/list.h>
14
15struct namespaces_event;
16
17struct namespaces {
18 struct list_head list;
19 u64 end_time;
20 struct perf_ns_link_info link_info[];
21};
22
23struct namespaces *namespaces__new(struct namespaces_event *event);
24void namespaces__free(struct namespaces *namespaces);
25
26#endif /* __PERF_NAMESPACES_H */
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index fe84df1875aa..4de398cfb577 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -1,3 +1,5 @@
1#include <errno.h>
2#include <inttypes.h>
1#include <linux/list.h> 3#include <linux/list.h>
2#include <linux/compiler.h> 4#include <linux/compiler.h>
3#include <linux/string.h> 5#include <linux/string.h>
@@ -79,7 +81,7 @@ static union perf_event *dup_event(struct ordered_events *oe,
79 81
80static void free_dup_event(struct ordered_events *oe, union perf_event *event) 82static void free_dup_event(struct ordered_events *oe, union perf_event *event)
81{ 83{
82 if (oe->copy_on_queue) { 84 if (event && oe->copy_on_queue) {
83 oe->cur_alloc_size -= event->header.size; 85 oe->cur_alloc_size -= event->header.size;
84 free(event); 86 free(event);
85 } 87 }
@@ -150,6 +152,7 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve
150 list_move(&event->list, &oe->cache); 152 list_move(&event->list, &oe->cache);
151 oe->nr_events--; 153 oe->nr_events--;
152 free_dup_event(oe, event->event); 154 free_dup_event(oe, event->event);
155 event->event = NULL;
153} 156}
154 157
155int ordered_events__queue(struct ordered_events *oe, union perf_event *event, 158int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 67a8aebc67ab..01e779b91c8e 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,13 +1,18 @@
1#include <linux/hw_breakpoint.h> 1#include <linux/hw_breakpoint.h>
2#include <linux/err.h> 2#include <linux/err.h>
3#include "util.h" 3#include <dirent.h>
4#include <errno.h>
5#include <sys/ioctl.h>
6#include <sys/param.h>
7#include "term.h"
4#include "../perf.h" 8#include "../perf.h"
5#include "evlist.h" 9#include "evlist.h"
6#include "evsel.h" 10#include "evsel.h"
7#include <subcmd/parse-options.h> 11#include <subcmd/parse-options.h>
8#include "parse-events.h" 12#include "parse-events.h"
9#include <subcmd/exec-cmd.h> 13#include <subcmd/exec-cmd.h>
10#include "string.h" 14#include "string2.h"
15#include "strlist.h"
11#include "symbol.h" 16#include "symbol.h"
12#include "cache.h" 17#include "cache.h"
13#include "header.h" 18#include "header.h"
@@ -316,8 +321,9 @@ __add_event(struct list_head *list, int *idx,
316 return NULL; 321 return NULL;
317 322
318 (*idx)++; 323 (*idx)++;
319 evsel->cpus = cpu_map__get(cpus); 324 evsel->cpus = cpu_map__get(cpus);
320 evsel->own_cpus = cpu_map__get(cpus); 325 evsel->own_cpus = cpu_map__get(cpus);
326 evsel->system_wide = !!cpus;
321 327
322 if (name) 328 if (name)
323 evsel->name = strdup(name); 329 evsel->name = strdup(name);
@@ -1254,11 +1260,59 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
1254 evsel->scale = info.scale; 1260 evsel->scale = info.scale;
1255 evsel->per_pkg = info.per_pkg; 1261 evsel->per_pkg = info.per_pkg;
1256 evsel->snapshot = info.snapshot; 1262 evsel->snapshot = info.snapshot;
1263 evsel->metric_expr = info.metric_expr;
1264 evsel->metric_name = info.metric_name;
1257 } 1265 }
1258 1266
1259 return evsel ? 0 : -ENOMEM; 1267 return evsel ? 0 : -ENOMEM;
1260} 1268}
1261 1269
1270int parse_events_multi_pmu_add(struct parse_events_evlist *data,
1271 char *str, struct list_head **listp)
1272{
1273 struct list_head *head;
1274 struct parse_events_term *term;
1275 struct list_head *list;
1276 struct perf_pmu *pmu = NULL;
1277 int ok = 0;
1278
1279 *listp = NULL;
1280 /* Add it for all PMUs that support the alias */
1281 list = malloc(sizeof(struct list_head));
1282 if (!list)
1283 return -1;
1284 INIT_LIST_HEAD(list);
1285 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
1286 struct perf_pmu_alias *alias;
1287
1288 list_for_each_entry(alias, &pmu->aliases, list) {
1289 if (!strcasecmp(alias->name, str)) {
1290 head = malloc(sizeof(struct list_head));
1291 if (!head)
1292 return -1;
1293 INIT_LIST_HEAD(head);
1294 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
1295 str, 1, false, &str, NULL) < 0)
1296 return -1;
1297 list_add_tail(&term->list, head);
1298
1299 if (!parse_events_add_pmu(data, list,
1300 pmu->name, head)) {
1301 pr_debug("%s -> %s/%s/\n", str,
1302 pmu->name, alias->str);
1303 ok++;
1304 }
1305
1306 parse_events_terms__delete(head);
1307 }
1308 }
1309 }
1310 if (!ok)
1311 return -1;
1312 *listp = list;
1313 return 0;
1314}
1315
1262int parse_events__modifier_group(struct list_head *list, 1316int parse_events__modifier_group(struct list_head *list,
1263 char *event_mod) 1317 char *event_mod)
1264{ 1318{
@@ -2276,7 +2330,7 @@ out_enomem:
2276 * Print the help text for the event symbols: 2330 * Print the help text for the event symbols:
2277 */ 2331 */
2278void print_events(const char *event_glob, bool name_only, bool quiet_flag, 2332void print_events(const char *event_glob, bool name_only, bool quiet_flag,
2279 bool long_desc) 2333 bool long_desc, bool details_flag)
2280{ 2334{
2281 print_symbol_events(event_glob, PERF_TYPE_HARDWARE, 2335 print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
2282 event_symbols_hw, PERF_COUNT_HW_MAX, name_only); 2336 event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
@@ -2286,7 +2340,8 @@ void print_events(const char *event_glob, bool name_only, bool quiet_flag,
2286 2340
2287 print_hwcache_events(event_glob, name_only); 2341 print_hwcache_events(event_glob, name_only);
2288 2342
2289 print_pmu_events(event_glob, name_only, quiet_flag, long_desc); 2343 print_pmu_events(event_glob, name_only, quiet_flag, long_desc,
2344 details_flag);
2290 2345
2291 if (event_glob != NULL) 2346 if (event_glob != NULL)
2292 return; 2347 return;
@@ -2415,6 +2470,31 @@ int parse_events_term__clone(struct parse_events_term **new,
2415 return new_term(new, &temp, term->val.str, term->val.num); 2470 return new_term(new, &temp, term->val.str, term->val.num);
2416} 2471}
2417 2472
2473int parse_events_copy_term_list(struct list_head *old,
2474 struct list_head **new)
2475{
2476 struct parse_events_term *term, *n;
2477 int ret;
2478
2479 if (!old) {
2480 *new = NULL;
2481 return 0;
2482 }
2483
2484 *new = malloc(sizeof(struct list_head));
2485 if (!*new)
2486 return -ENOMEM;
2487 INIT_LIST_HEAD(*new);
2488
2489 list_for_each_entry (term, old, list) {
2490 ret = parse_events_term__clone(&n, term);
2491 if (ret)
2492 return ret;
2493 list_add_tail(&n->list, *new);
2494 }
2495 return 0;
2496}
2497
2418void parse_events_terms__purge(struct list_head *terms) 2498void parse_events_terms__purge(struct list_head *terms)
2419{ 2499{
2420 struct parse_events_term *term, *h; 2500 struct parse_events_term *term, *h;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 1af6a267c21b..a235f4d6d5e5 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -8,6 +8,7 @@
8#include <stdbool.h> 8#include <stdbool.h>
9#include <linux/types.h> 9#include <linux/types.h>
10#include <linux/perf_event.h> 10#include <linux/perf_event.h>
11#include <string.h>
11 12
12struct list_head; 13struct list_head;
13struct perf_evsel; 14struct perf_evsel;
@@ -166,6 +167,14 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
166int parse_events_add_pmu(struct parse_events_evlist *data, 167int parse_events_add_pmu(struct parse_events_evlist *data,
167 struct list_head *list, char *name, 168 struct list_head *list, char *name,
168 struct list_head *head_config); 169 struct list_head *head_config);
170
171int parse_events_multi_pmu_add(struct parse_events_evlist *data,
172 char *str,
173 struct list_head **listp);
174
175int parse_events_copy_term_list(struct list_head *old,
176 struct list_head **new);
177
169enum perf_pmu_event_symbol_type 178enum perf_pmu_event_symbol_type
170perf_pmu__parse_check(const char *name); 179perf_pmu__parse_check(const char *name);
171void parse_events__set_leader(char *name, struct list_head *list); 180void parse_events__set_leader(char *name, struct list_head *list);
@@ -175,7 +184,7 @@ void parse_events_evlist_error(struct parse_events_evlist *data,
175 int idx, const char *str); 184 int idx, const char *str);
176 185
177void print_events(const char *event_glob, bool name_only, bool quiet, 186void print_events(const char *event_glob, bool name_only, bool quiet,
178 bool long_desc); 187 bool long_desc, bool details_flag);
179 188
180struct event_symbol { 189struct event_symbol {
181 const char *symbol; 190 const char *symbol;
@@ -196,4 +205,23 @@ int is_valid_tracepoint(const char *event_string);
196int valid_event_mount(const char *eventfs); 205int valid_event_mount(const char *eventfs);
197char *parse_events_formats_error_string(char *additional_terms); 206char *parse_events_formats_error_string(char *additional_terms);
198 207
208#ifdef HAVE_LIBELF_SUPPORT
209/*
210 * If the probe point starts with '%',
211 * or starts with "sdt_" and has a ':' but no '=',
212 * then it should be a SDT/cached probe point.
213 */
214static inline bool is_sdt_event(char *str)
215{
216 return (str[0] == '%' ||
217 (!strncmp(str, "sdt_", 4) &&
218 !!strchr(str, ':') && !strchr(str, '=')));
219}
220#else
221static inline bool is_sdt_event(char *str __maybe_unused)
222{
223 return false;
224}
225#endif /* HAVE_LIBELF_SUPPORT */
226
199#endif /* __PERF_PARSE_EVENTS_H */ 227#endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 30f018ea1370..04fd8c9af9f9 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -226,68 +226,55 @@ event_pmu:
226PE_NAME opt_event_config 226PE_NAME opt_event_config
227{ 227{
228 struct parse_events_evlist *data = _data; 228 struct parse_events_evlist *data = _data;
229 struct list_head *list; 229 struct list_head *list, *orig_terms, *terms;
230
231 if (parse_events_copy_term_list($2, &orig_terms))
232 YYABORT;
230 233
231 ALLOC_LIST(list); 234 ALLOC_LIST(list);
232 ABORT_ON(parse_events_add_pmu(data, list, $1, $2)); 235 if (parse_events_add_pmu(data, list, $1, $2)) {
236 struct perf_pmu *pmu = NULL;
237 int ok = 0;
238
239 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
240 char *name = pmu->name;
241
242 if (!strncmp(name, "uncore_", 7) &&
243 strncmp($1, "uncore_", 7))
244 name += 7;
245 if (!strncmp($1, name, strlen($1))) {
246 if (parse_events_copy_term_list(orig_terms, &terms))
247 YYABORT;
248 if (!parse_events_add_pmu(data, list, pmu->name, terms))
249 ok++;
250 parse_events_terms__delete(terms);
251 }
252 }
253 if (!ok)
254 YYABORT;
255 }
233 parse_events_terms__delete($2); 256 parse_events_terms__delete($2);
257 parse_events_terms__delete(orig_terms);
234 $$ = list; 258 $$ = list;
235} 259}
236| 260|
237PE_KERNEL_PMU_EVENT sep_dc 261PE_KERNEL_PMU_EVENT sep_dc
238{ 262{
239 struct parse_events_evlist *data = _data;
240 struct list_head *head;
241 struct parse_events_term *term;
242 struct list_head *list; 263 struct list_head *list;
243 struct perf_pmu *pmu = NULL;
244 int ok = 0;
245
246 /* Add it for all PMUs that support the alias */
247 ALLOC_LIST(list);
248 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
249 struct perf_pmu_alias *alias;
250
251 list_for_each_entry(alias, &pmu->aliases, list) {
252 if (!strcasecmp(alias->name, $1)) {
253 ALLOC_LIST(head);
254 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
255 $1, 1, false, &@1, NULL));
256 list_add_tail(&term->list, head);
257
258 if (!parse_events_add_pmu(data, list,
259 pmu->name, head)) {
260 pr_debug("%s -> %s/%s/\n", $1,
261 pmu->name, alias->str);
262 ok++;
263 }
264 264
265 parse_events_terms__delete(head); 265 if (parse_events_multi_pmu_add(_data, $1, &list) < 0)
266 }
267 }
268 }
269 if (!ok)
270 YYABORT; 266 YYABORT;
271 $$ = list; 267 $$ = list;
272} 268}
273| 269|
274PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc 270PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
275{ 271{
276 struct parse_events_evlist *data = _data;
277 struct list_head *head;
278 struct parse_events_term *term;
279 struct list_head *list; 272 struct list_head *list;
280 char pmu_name[128]; 273 char pmu_name[128];
281 snprintf(&pmu_name, 128, "%s-%s", $1, $3);
282 274
283 ALLOC_LIST(head); 275 snprintf(&pmu_name, 128, "%s-%s", $1, $3);
284 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 276 if (parse_events_multi_pmu_add(_data, pmu_name, &list) < 0)
285 &pmu_name, 1, false, &@1, NULL)); 277 YYABORT;
286 list_add_tail(&term->list, head);
287
288 ALLOC_LIST(list);
289 ABORT_ON(parse_events_add_pmu(data, list, "cpu", head));
290 parse_events_terms__delete(head);
291 $$ = list; 278 $$ = list;
292} 279}
293 280
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index 7c7630be5a89..50ec3bc87a60 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -11,8 +11,13 @@
11 * which is what it's designed for. 11 * which is what it's designed for.
12 */ 12 */
13#include "cache.h" 13#include "cache.h"
14#include "util.h" 14#include "path.h"
15#include <linux/kernel.h>
15#include <limits.h> 16#include <limits.h>
17#include <stdio.h>
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <unistd.h>
16 21
17static char bad_path[] = "/bad-path/"; 22static char bad_path[] = "/bad-path/";
18/* 23/*
@@ -50,3 +55,24 @@ char *mkpath(const char *fmt, ...)
50 return bad_path; 55 return bad_path;
51 return cleanup_path(pathname); 56 return cleanup_path(pathname);
52} 57}
58
59int path__join(char *bf, size_t size, const char *path1, const char *path2)
60{
61 return scnprintf(bf, size, "%s%s%s", path1, path1[0] ? "/" : "", path2);
62}
63
64int path__join3(char *bf, size_t size, const char *path1, const char *path2, const char *path3)
65{
66 return scnprintf(bf, size, "%s%s%s%s%s", path1, path1[0] ? "/" : "",
67 path2, path2[0] ? "/" : "", path3);
68}
69
70bool is_regular_file(const char *file)
71{
72 struct stat st;
73
74 if (stat(file, &st))
75 return false;
76
77 return S_ISREG(st.st_mode);
78}
diff --git a/tools/perf/util/path.h b/tools/perf/util/path.h
new file mode 100644
index 000000000000..9a276a58e3c2
--- /dev/null
+++ b/tools/perf/util/path.h
@@ -0,0 +1,9 @@
1#ifndef _PERF_PATH_H
2#define _PERF_PATH_H
3
4int path__join(char *bf, size_t size, const char *path1, const char *path2);
5int path__join3(char *bf, size_t size, const char *path1, const char *path2, const char *path3);
6
7bool is_regular_file(const char *file);
8
9#endif /* _PERF_PATH_H */
diff --git a/tools/perf/util/perf-hooks.c b/tools/perf/util/perf-hooks.c
index cb368306b12b..d55092964da2 100644
--- a/tools/perf/util/perf-hooks.c
+++ b/tools/perf/util/perf-hooks.c
@@ -9,6 +9,7 @@
9#include <stdlib.h> 9#include <stdlib.h>
10#include <setjmp.h> 10#include <setjmp.h>
11#include <linux/err.h> 11#include <linux/err.h>
12#include <linux/kernel.h>
12#include "util/util.h" 13#include "util/util.h"
13#include "util/debug.h" 14#include "util/debug.h"
14#include "util/perf-hooks.h" 15#include "util/perf-hooks.h"
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index c4023f22f287..b2ae039eff85 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -6,6 +6,12 @@ const struct sample_reg __weak sample_reg_masks[] = {
6 SMPL_REG_END 6 SMPL_REG_END
7}; 7};
8 8
9int __weak arch_sdt_arg_parse_op(char *old_op __maybe_unused,
10 char **new_op __maybe_unused)
11{
12 return SDT_ARG_SKIP;
13}
14
9#ifdef HAVE_PERF_REGS_SUPPORT 15#ifdef HAVE_PERF_REGS_SUPPORT
10int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) 16int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
11{ 17{
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 679d6e493962..32b37d19dcc3 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -15,6 +15,13 @@ struct sample_reg {
15 15
16extern const struct sample_reg sample_reg_masks[]; 16extern const struct sample_reg sample_reg_masks[];
17 17
18enum {
19 SDT_ARG_VALID = 0,
20 SDT_ARG_SKIP,
21};
22
23int arch_sdt_arg_parse_op(char *old_op, char **new_op);
24
18#ifdef HAVE_PERF_REGS_SUPPORT 25#ifdef HAVE_PERF_REGS_SUPPORT
19#include <perf_regs.h> 26#include <perf_regs.h>
20 27
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 12f84dd2ac5d..ac16a9db1fb5 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -1,6 +1,8 @@
1#include <linux/list.h> 1#include <linux/list.h>
2#include <linux/compiler.h> 2#include <linux/compiler.h>
3#include <sys/types.h> 3#include <sys/types.h>
4#include <errno.h>
5#include <sys/stat.h>
4#include <unistd.h> 6#include <unistd.h>
5#include <stdio.h> 7#include <stdio.h>
6#include <stdbool.h> 8#include <stdbool.h>
@@ -15,6 +17,7 @@
15#include "header.h" 17#include "header.h"
16#include "pmu-events/pmu-events.h" 18#include "pmu-events/pmu-events.h"
17#include "cache.h" 19#include "cache.h"
20#include "string2.h"
18 21
19struct perf_pmu_format { 22struct perf_pmu_format {
20 char *name; 23 char *name;
@@ -231,7 +234,9 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
231static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, 234static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
232 char *desc, char *val, 235 char *desc, char *val,
233 char *long_desc, char *topic, 236 char *long_desc, char *topic,
234 char *unit, char *perpkg) 237 char *unit, char *perpkg,
238 char *metric_expr,
239 char *metric_name)
235{ 240{
236 struct perf_pmu_alias *alias; 241 struct perf_pmu_alias *alias;
237 int ret; 242 int ret;
@@ -265,6 +270,8 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
265 perf_pmu__parse_snapshot(alias, dir, name); 270 perf_pmu__parse_snapshot(alias, dir, name);
266 } 271 }
267 272
273 alias->metric_expr = metric_expr ? strdup(metric_expr) : NULL;
274 alias->metric_name = metric_name ? strdup(metric_name): NULL;
268 alias->desc = desc ? strdup(desc) : NULL; 275 alias->desc = desc ? strdup(desc) : NULL;
269 alias->long_desc = long_desc ? strdup(long_desc) : 276 alias->long_desc = long_desc ? strdup(long_desc) :
270 desc ? strdup(desc) : NULL; 277 desc ? strdup(desc) : NULL;
@@ -294,7 +301,7 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
294 buf[ret] = 0; 301 buf[ret] = 0;
295 302
296 return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL, 303 return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL,
297 NULL); 304 NULL, NULL, NULL);
298} 305}
299 306
300static inline bool pmu_alias_info_file(char *name) 307static inline bool pmu_alias_info_file(char *name)
@@ -564,7 +571,9 @@ static void pmu_add_cpu_aliases(struct list_head *head, const char *name)
564 __perf_pmu__new_alias(head, NULL, (char *)pe->name, 571 __perf_pmu__new_alias(head, NULL, (char *)pe->name,
565 (char *)pe->desc, (char *)pe->event, 572 (char *)pe->desc, (char *)pe->event,
566 (char *)pe->long_desc, (char *)pe->topic, 573 (char *)pe->long_desc, (char *)pe->topic,
567 (char *)pe->unit, (char *)pe->perpkg); 574 (char *)pe->unit, (char *)pe->perpkg,
575 (char *)pe->metric_expr,
576 (char *)pe->metric_name);
568 } 577 }
569 578
570out: 579out:
@@ -991,6 +1000,8 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
991 info->unit = NULL; 1000 info->unit = NULL;
992 info->scale = 0.0; 1001 info->scale = 0.0;
993 info->snapshot = false; 1002 info->snapshot = false;
1003 info->metric_expr = NULL;
1004 info->metric_name = NULL;
994 1005
995 list_for_each_entry_safe(term, h, head_terms, list) { 1006 list_for_each_entry_safe(term, h, head_terms, list) {
996 alias = pmu_find_alias(pmu, term); 1007 alias = pmu_find_alias(pmu, term);
@@ -1006,6 +1017,8 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
1006 1017
1007 if (alias->per_pkg) 1018 if (alias->per_pkg)
1008 info->per_pkg = true; 1019 info->per_pkg = true;
1020 info->metric_expr = alias->metric_expr;
1021 info->metric_name = alias->metric_name;
1009 1022
1010 list_del(&term->list); 1023 list_del(&term->list);
1011 free(term); 1024 free(term);
@@ -1100,6 +1113,8 @@ struct sevent {
1100 char *topic; 1113 char *topic;
1101 char *str; 1114 char *str;
1102 char *pmu; 1115 char *pmu;
1116 char *metric_expr;
1117 char *metric_name;
1103}; 1118};
1104 1119
1105static int cmp_sevent(const void *a, const void *b) 1120static int cmp_sevent(const void *a, const void *b)
@@ -1136,13 +1151,12 @@ static void wordwrap(char *s, int start, int max, int corr)
1136 break; 1151 break;
1137 s += wlen; 1152 s += wlen;
1138 column += n; 1153 column += n;
1139 while (isspace(*s)) 1154 s = ltrim(s);
1140 s++;
1141 } 1155 }
1142} 1156}
1143 1157
1144void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, 1158void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
1145 bool long_desc) 1159 bool long_desc, bool details_flag)
1146{ 1160{
1147 struct perf_pmu *pmu; 1161 struct perf_pmu *pmu;
1148 struct perf_pmu_alias *alias; 1162 struct perf_pmu_alias *alias;
@@ -1198,6 +1212,8 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
1198 aliases[j].topic = alias->topic; 1212 aliases[j].topic = alias->topic;
1199 aliases[j].str = alias->str; 1213 aliases[j].str = alias->str;
1200 aliases[j].pmu = pmu->name; 1214 aliases[j].pmu = pmu->name;
1215 aliases[j].metric_expr = alias->metric_expr;
1216 aliases[j].metric_name = alias->metric_name;
1201 j++; 1217 j++;
1202 } 1218 }
1203 if (pmu->selectable && 1219 if (pmu->selectable &&
@@ -1232,8 +1248,14 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
1232 printf("%*s", 8, "["); 1248 printf("%*s", 8, "[");
1233 wordwrap(aliases[j].desc, 8, columns, 0); 1249 wordwrap(aliases[j].desc, 8, columns, 0);
1234 printf("]\n"); 1250 printf("]\n");
1235 if (verbose > 0) 1251 if (details_flag) {
1236 printf("%*s%s/%s/\n", 8, "", aliases[j].pmu, aliases[j].str); 1252 printf("%*s%s/%s/ ", 8, "", aliases[j].pmu, aliases[j].str);
1253 if (aliases[j].metric_name)
1254 printf(" MetricName: %s", aliases[j].metric_name);
1255 if (aliases[j].metric_expr)
1256 printf(" MetricExpr: %s", aliases[j].metric_expr);
1257 putchar('\n');
1258 }
1237 } else 1259 } else
1238 printf(" %-50s [Kernel PMU event]\n", aliases[j].name); 1260 printf(" %-50s [Kernel PMU event]\n", aliases[j].name);
1239 printed++; 1261 printed++;
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 00852ddc7741..ea7f450dc609 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -31,6 +31,8 @@ struct perf_pmu {
31 31
32struct perf_pmu_info { 32struct perf_pmu_info {
33 const char *unit; 33 const char *unit;
34 const char *metric_expr;
35 const char *metric_name;
34 double scale; 36 double scale;
35 bool per_pkg; 37 bool per_pkg;
36 bool snapshot; 38 bool snapshot;
@@ -50,6 +52,8 @@ struct perf_pmu_alias {
50 double scale; 52 double scale;
51 bool per_pkg; 53 bool per_pkg;
52 bool snapshot; 54 bool snapshot;
55 char *metric_expr;
56 char *metric_name;
53}; 57};
54 58
55struct perf_pmu *perf_pmu__find(const char *name); 59struct perf_pmu *perf_pmu__find(const char *name);
@@ -76,7 +80,7 @@ int perf_pmu__format_parse(char *dir, struct list_head *head);
76struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); 80struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
77 81
78void print_pmu_events(const char *event_glob, bool name_only, bool quiet, 82void print_pmu_events(const char *event_glob, bool name_only, bool quiet,
79 bool long_desc); 83 bool long_desc, bool details_flag);
80bool pmu_have_event(const char *pname, const char *name); 84bool pmu_have_event(const char *pname, const char *name);
81 85
82int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, 86int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
diff --git a/tools/perf/util/print_binary.c b/tools/perf/util/print_binary.c
new file mode 100644
index 000000000000..e908177b9976
--- /dev/null
+++ b/tools/perf/util/print_binary.c
@@ -0,0 +1,55 @@
1#include "print_binary.h"
2#include <linux/log2.h>
3#include "sane_ctype.h"
4
5void print_binary(unsigned char *data, size_t len,
6 size_t bytes_per_line, print_binary_t printer,
7 void *extra)
8{
9 size_t i, j, mask;
10
11 if (!printer)
12 return;
13
14 bytes_per_line = roundup_pow_of_two(bytes_per_line);
15 mask = bytes_per_line - 1;
16
17 printer(BINARY_PRINT_DATA_BEGIN, 0, extra);
18 for (i = 0; i < len; i++) {
19 if ((i & mask) == 0) {
20 printer(BINARY_PRINT_LINE_BEGIN, -1, extra);
21 printer(BINARY_PRINT_ADDR, i, extra);
22 }
23
24 printer(BINARY_PRINT_NUM_DATA, data[i], extra);
25
26 if (((i & mask) == mask) || i == len - 1) {
27 for (j = 0; j < mask-(i & mask); j++)
28 printer(BINARY_PRINT_NUM_PAD, -1, extra);
29
30 printer(BINARY_PRINT_SEP, i, extra);
31 for (j = i & ~mask; j <= i; j++)
32 printer(BINARY_PRINT_CHAR_DATA, data[j], extra);
33 for (j = 0; j < mask-(i & mask); j++)
34 printer(BINARY_PRINT_CHAR_PAD, i, extra);
35 printer(BINARY_PRINT_LINE_END, -1, extra);
36 }
37 }
38 printer(BINARY_PRINT_DATA_END, -1, extra);
39}
40
41int is_printable_array(char *p, unsigned int len)
42{
43 unsigned int i;
44
45 if (!p || !len || p[len - 1] != 0)
46 return 0;
47
48 len--;
49
50 for (i = 0; i < len; i++) {
51 if (!isprint(p[i]) && !isspace(p[i]))
52 return 0;
53 }
54 return 1;
55}
diff --git a/tools/perf/util/print_binary.h b/tools/perf/util/print_binary.h
new file mode 100644
index 000000000000..da0427263d2d
--- /dev/null
+++ b/tools/perf/util/print_binary.h
@@ -0,0 +1,28 @@
1#ifndef PERF_PRINT_BINARY_H
2#define PERF_PRINT_BINARY_H
3
4#include <stddef.h>
5
6enum binary_printer_ops {
7 BINARY_PRINT_DATA_BEGIN,
8 BINARY_PRINT_LINE_BEGIN,
9 BINARY_PRINT_ADDR,
10 BINARY_PRINT_NUM_DATA,
11 BINARY_PRINT_NUM_PAD,
12 BINARY_PRINT_SEP,
13 BINARY_PRINT_CHAR_DATA,
14 BINARY_PRINT_CHAR_PAD,
15 BINARY_PRINT_LINE_END,
16 BINARY_PRINT_DATA_END,
17};
18
19typedef void (*print_binary_t)(enum binary_printer_ops op,
20 unsigned int val, void *extra);
21
22void print_binary(unsigned char *data, size_t len,
23 size_t bytes_per_line, print_binary_t printer,
24 void *extra);
25
26int is_printable_array(char *p, unsigned int len);
27
28#endif /* PERF_PRINT_BINARY_H */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 28fb62c32678..84e7e698411e 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -19,6 +19,7 @@
19 * 19 *
20 */ 20 */
21 21
22#include <inttypes.h>
22#include <sys/utsname.h> 23#include <sys/utsname.h>
23#include <sys/types.h> 24#include <sys/types.h>
24#include <sys/stat.h> 25#include <sys/stat.h>
@@ -35,6 +36,7 @@
35#include "util.h" 36#include "util.h"
36#include "event.h" 37#include "event.h"
37#include "strlist.h" 38#include "strlist.h"
39#include "strfilter.h"
38#include "debug.h" 40#include "debug.h"
39#include "cache.h" 41#include "cache.h"
40#include "color.h" 42#include "color.h"
@@ -46,8 +48,10 @@
46#include "probe-finder.h" 48#include "probe-finder.h"
47#include "probe-file.h" 49#include "probe-file.h"
48#include "session.h" 50#include "session.h"
51#include "string2.h"
52
53#include "sane_ctype.h"
49 54
50#define MAX_CMDLEN 256
51#define PERFPROBE_GROUP "probe" 55#define PERFPROBE_GROUP "probe"
52 56
53bool probe_event_dry_run; /* Dry run flag */ 57bool probe_event_dry_run; /* Dry run flag */
@@ -757,7 +761,9 @@ post_process_kernel_probe_trace_events(struct probe_trace_event *tevs,
757 } 761 }
758 762
759 for (i = 0; i < ntevs; i++) { 763 for (i = 0; i < ntevs; i++) {
760 if (!tevs[i].point.address || tevs[i].point.retprobe) 764 if (!tevs[i].point.address)
765 continue;
766 if (tevs[i].point.retprobe && !kretprobe_offset_is_supported())
761 continue; 767 continue;
762 /* If we found a wrong one, mark it by NULL symbol */ 768 /* If we found a wrong one, mark it by NULL symbol */
763 if (kprobe_warn_out_range(tevs[i].point.symbol, 769 if (kprobe_warn_out_range(tevs[i].point.symbol,
@@ -1339,14 +1345,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
1339 if (!arg) 1345 if (!arg)
1340 return -EINVAL; 1346 return -EINVAL;
1341 1347
1342 /* 1348 if (is_sdt_event(arg)) {
1343 * If the probe point starts with '%',
1344 * or starts with "sdt_" and has a ':' but no '=',
1345 * then it should be a SDT/cached probe point.
1346 */
1347 if (arg[0] == '%' ||
1348 (!strncmp(arg, "sdt_", 4) &&
1349 !!strchr(arg, ':') && !strchr(arg, '='))) {
1350 pev->sdt = true; 1349 pev->sdt = true;
1351 if (arg[0] == '%') 1350 if (arg[0] == '%')
1352 arg++; 1351 arg++;
@@ -1528,11 +1527,6 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
1528 return -EINVAL; 1527 return -EINVAL;
1529 } 1528 }
1530 1529
1531 if (pp->retprobe && !pp->function) {
1532 semantic_error("Return probe requires an entry function.\n");
1533 return -EINVAL;
1534 }
1535
1536 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) { 1530 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
1537 semantic_error("Offset/Line/Lazy pattern can't be used with " 1531 semantic_error("Offset/Line/Lazy pattern can't be used with "
1538 "return probe.\n"); 1532 "return probe.\n");
@@ -2841,7 +2835,8 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2841 } 2835 }
2842 2836
2843 /* Note that the symbols in the kmodule are not relocated */ 2837 /* Note that the symbols in the kmodule are not relocated */
2844 if (!pev->uprobes && !pp->retprobe && !pev->target) { 2838 if (!pev->uprobes && !pev->target &&
2839 (!pp->retprobe || kretprobe_offset_is_supported())) {
2845 reloc_sym = kernel_get_ref_reloc_sym(); 2840 reloc_sym = kernel_get_ref_reloc_sym();
2846 if (!reloc_sym) { 2841 if (!reloc_sym) {
2847 pr_warning("Relocated base symbol is not found!\n"); 2842 pr_warning("Relocated base symbol is not found!\n");
@@ -3057,7 +3052,7 @@ concat_probe_trace_events(struct probe_trace_event **tevs, int *ntevs,
3057 struct probe_trace_event *new_tevs; 3052 struct probe_trace_event *new_tevs;
3058 int ret = 0; 3053 int ret = 0;
3059 3054
3060 if (ntevs == 0) { 3055 if (*ntevs == 0) {
3061 *tevs = *tevs2; 3056 *tevs = *tevs2;
3062 *ntevs = ntevs2; 3057 *ntevs = ntevs2;
3063 *tevs2 = NULL; 3058 *tevs2 = NULL;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 5d4e94061402..373842656fb6 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -3,8 +3,6 @@
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5#include "intlist.h" 5#include "intlist.h"
6#include "strlist.h"
7#include "strfilter.h"
8 6
9/* Probe related configurations */ 7/* Probe related configurations */
10struct probe_conf { 8struct probe_conf {
@@ -107,6 +105,8 @@ struct line_range {
107 struct intlist *line_list; /* Visible lines */ 105 struct intlist *line_list; /* Visible lines */
108}; 106};
109 107
108struct strlist;
109
110/* List of variables */ 110/* List of variables */
111struct variable_list { 111struct variable_list {
112 struct probe_trace_point point; /* Actual probepoint */ 112 struct probe_trace_point point; /* Actual probepoint */
@@ -153,6 +153,9 @@ int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs);
153int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs); 153int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs);
154int show_probe_trace_events(struct perf_probe_event *pevs, int npevs); 154int show_probe_trace_events(struct perf_probe_event *pevs, int npevs);
155void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs); 155void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs);
156
157struct strfilter;
158
156int del_perf_probe_events(struct strfilter *filter); 159int del_perf_probe_events(struct strfilter *filter);
157 160
158int show_perf_probe_event(const char *group, const char *event, 161int show_perf_probe_event(const char *group, const char *event,
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 436b64731f65..d679389e627c 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -14,10 +14,15 @@
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 * 15 *
16 */ 16 */
17#include <errno.h>
18#include <sys/stat.h>
19#include <sys/types.h>
17#include <sys/uio.h> 20#include <sys/uio.h>
21#include <unistd.h>
18#include "util.h" 22#include "util.h"
19#include "event.h" 23#include "event.h"
20#include "strlist.h" 24#include "strlist.h"
25#include "strfilter.h"
21#include "debug.h" 26#include "debug.h"
22#include "cache.h" 27#include "cache.h"
23#include "color.h" 28#include "color.h"
@@ -27,8 +32,11 @@
27#include "probe-event.h" 32#include "probe-event.h"
28#include "probe-file.h" 33#include "probe-file.h"
29#include "session.h" 34#include "session.h"
35#include "perf_regs.h"
36#include "string2.h"
30 37
31#define MAX_CMDLEN 256 38/* 4096 - 2 ('\n' + '\0') */
39#define MAX_CMDLEN 4094
32 40
33static void print_open_warning(int err, bool uprobe) 41static void print_open_warning(int err, bool uprobe)
34{ 42{
@@ -70,7 +78,7 @@ static void print_both_open_warning(int kerr, int uerr)
70 } 78 }
71} 79}
72 80
73static int open_probe_events(const char *trace_file, bool readwrite) 81int open_trace_file(const char *trace_file, bool readwrite)
74{ 82{
75 char buf[PATH_MAX]; 83 char buf[PATH_MAX];
76 int ret; 84 int ret;
@@ -92,12 +100,12 @@ static int open_probe_events(const char *trace_file, bool readwrite)
92 100
93static int open_kprobe_events(bool readwrite) 101static int open_kprobe_events(bool readwrite)
94{ 102{
95 return open_probe_events("kprobe_events", readwrite); 103 return open_trace_file("kprobe_events", readwrite);
96} 104}
97 105
98static int open_uprobe_events(bool readwrite) 106static int open_uprobe_events(bool readwrite)
99{ 107{
100 return open_probe_events("uprobe_events", readwrite); 108 return open_trace_file("uprobe_events", readwrite);
101} 109}
102 110
103int probe_file__open(int flag) 111int probe_file__open(int flag)
@@ -687,6 +695,110 @@ static unsigned long long sdt_note__get_addr(struct sdt_note *note)
687 : (unsigned long long)note->addr.a64[0]; 695 : (unsigned long long)note->addr.a64[0];
688} 696}
689 697
698static const char * const type_to_suffix[] = {
699 ":s64", "", "", "", ":s32", "", ":s16", ":s8",
700 "", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
701};
702
703/*
704 * Isolate the string number and convert it into a decimal value;
705 * this will be an index to get suffix of the uprobe name (defining
706 * the type)
707 */
708static int sdt_arg_parse_size(char *n_ptr, const char **suffix)
709{
710 long type_idx;
711
712 type_idx = strtol(n_ptr, NULL, 10);
713 if (type_idx < -8 || type_idx > 8) {
714 pr_debug4("Failed to get a valid sdt type\n");
715 return -1;
716 }
717
718 *suffix = type_to_suffix[type_idx + 8];
719 return 0;
720}
721
722static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
723{
724 char *op, *desc = strdup(arg), *new_op = NULL;
725 const char *suffix = "";
726 int ret = -1;
727
728 if (desc == NULL) {
729 pr_debug4("Allocation error\n");
730 return ret;
731 }
732
733 /*
734 * Argument is in N@OP format. N is size of the argument and OP is
735 * the actual assembly operand. N can be omitted; in that case
736 * argument is just OP(without @).
737 */
738 op = strchr(desc, '@');
739 if (op) {
740 op[0] = '\0';
741 op++;
742
743 if (sdt_arg_parse_size(desc, &suffix))
744 goto error;
745 } else {
746 op = desc;
747 }
748
749 ret = arch_sdt_arg_parse_op(op, &new_op);
750
751 if (ret < 0)
752 goto error;
753
754 if (ret == SDT_ARG_VALID) {
755 ret = strbuf_addf(buf, " arg%d=%s%s", i + 1, new_op, suffix);
756 if (ret < 0)
757 goto error;
758 }
759
760 ret = 0;
761error:
762 free(desc);
763 free(new_op);
764 return ret;
765}
766
767static char *synthesize_sdt_probe_command(struct sdt_note *note,
768 const char *pathname,
769 const char *sdtgrp)
770{
771 struct strbuf buf;
772 char *ret = NULL, **args;
773 int i, args_count;
774
775 if (strbuf_init(&buf, 32) < 0)
776 return NULL;
777
778 if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
779 sdtgrp, note->name, pathname,
780 sdt_note__get_addr(note)) < 0)
781 goto error;
782
783 if (!note->args)
784 goto out;
785
786 if (note->args) {
787 args = argv_split(note->args, &args_count);
788
789 for (i = 0; i < args_count; ++i) {
790 if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
791 goto error;
792 }
793 }
794
795out:
796 ret = strbuf_detach(&buf, NULL);
797error:
798 strbuf_release(&buf);
799 return ret;
800}
801
690int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname) 802int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
691{ 803{
692 struct probe_cache_entry *entry = NULL; 804 struct probe_cache_entry *entry = NULL;
@@ -723,11 +835,12 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
723 entry->pev.group = strdup(sdtgrp); 835 entry->pev.group = strdup(sdtgrp);
724 list_add_tail(&entry->node, &pcache->entries); 836 list_add_tail(&entry->node, &pcache->entries);
725 } 837 }
726 ret = asprintf(&buf, "p:%s/%s %s:0x%llx", 838 buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
727 sdtgrp, note->name, pathname, 839 if (!buf) {
728 sdt_note__get_addr(note)); 840 ret = -ENOMEM;
729 if (ret < 0)
730 break; 841 break;
842 }
843
731 strlist__add(entry->tevlist, buf); 844 strlist__add(entry->tevlist, buf);
732 free(buf); 845 free(buf);
733 entry = NULL; 846 entry = NULL;
@@ -877,59 +990,72 @@ int probe_cache__show_all_caches(struct strfilter *filter)
877 return 0; 990 return 0;
878} 991}
879 992
993enum ftrace_readme {
994 FTRACE_README_PROBE_TYPE_X = 0,
995 FTRACE_README_KRETPROBE_OFFSET,
996 FTRACE_README_END,
997};
998
880static struct { 999static struct {
881 const char *pattern; 1000 const char *pattern;
882 bool avail; 1001 bool avail;
883 bool checked; 1002} ftrace_readme_table[] = {
884} probe_type_table[] = { 1003#define DEFINE_TYPE(idx, pat) \
885#define DEFINE_TYPE(idx, pat, def_avail) \ 1004 [idx] = {.pattern = pat, .avail = false}
886 [idx] = {.pattern = pat, .avail = (def_avail)} 1005 DEFINE_TYPE(FTRACE_README_PROBE_TYPE_X, "*type: * x8/16/32/64,*"),
887 DEFINE_TYPE(PROBE_TYPE_U, "* u8/16/32/64,*", true), 1006 DEFINE_TYPE(FTRACE_README_KRETPROBE_OFFSET, "*place (kretprobe): *"),
888 DEFINE_TYPE(PROBE_TYPE_S, "* s8/16/32/64,*", true),
889 DEFINE_TYPE(PROBE_TYPE_X, "* x8/16/32/64,*", false),
890 DEFINE_TYPE(PROBE_TYPE_STRING, "* string,*", true),
891 DEFINE_TYPE(PROBE_TYPE_BITFIELD,
892 "* b<bit-width>@<bit-offset>/<container-size>", true),
893}; 1007};
894 1008
895bool probe_type_is_available(enum probe_type type) 1009static bool scan_ftrace_readme(enum ftrace_readme type)
896{ 1010{
1011 int fd;
897 FILE *fp; 1012 FILE *fp;
898 char *buf = NULL; 1013 char *buf = NULL;
899 size_t len = 0; 1014 size_t len = 0;
900 bool target_line = false; 1015 bool ret = false;
901 bool ret = probe_type_table[type].avail; 1016 static bool scanned = false;
902 1017
903 if (type >= PROBE_TYPE_END) 1018 if (scanned)
904 return false; 1019 goto result;
905 /* We don't have to check the type which supported by default */
906 if (ret || probe_type_table[type].checked)
907 return ret;
908 1020
909 if (asprintf(&buf, "%s/README", tracing_path) < 0) 1021 fd = open_trace_file("README", false);
1022 if (fd < 0)
910 return ret; 1023 return ret;
911 1024
912 fp = fopen(buf, "r"); 1025 fp = fdopen(fd, "r");
913 if (!fp) 1026 if (!fp) {
914 goto end; 1027 close(fd);
915 1028 return ret;
916 zfree(&buf);
917 while (getline(&buf, &len, fp) > 0 && !ret) {
918 if (!target_line) {
919 target_line = !!strstr(buf, " type: ");
920 if (!target_line)
921 continue;
922 } else if (strstr(buf, "\t ") != buf)
923 break;
924 ret = strglobmatch(buf, probe_type_table[type].pattern);
925 } 1029 }
926 /* Cache the result */ 1030
927 probe_type_table[type].checked = true; 1031 while (getline(&buf, &len, fp) > 0)
928 probe_type_table[type].avail = ret; 1032 for (enum ftrace_readme i = 0; i < FTRACE_README_END; i++)
1033 if (!ftrace_readme_table[i].avail)
1034 ftrace_readme_table[i].avail =
1035 strglobmatch(buf, ftrace_readme_table[i].pattern);
1036 scanned = true;
929 1037
930 fclose(fp); 1038 fclose(fp);
931end:
932 free(buf); 1039 free(buf);
933 1040
934 return ret; 1041result:
1042 if (type >= FTRACE_README_END)
1043 return false;
1044
1045 return ftrace_readme_table[type].avail;
1046}
1047
1048bool probe_type_is_available(enum probe_type type)
1049{
1050 if (type >= PROBE_TYPE_END)
1051 return false;
1052 else if (type == PROBE_TYPE_X)
1053 return scan_ftrace_readme(FTRACE_README_PROBE_TYPE_X);
1054
1055 return true;
1056}
1057
1058bool kretprobe_offset_is_supported(void)
1059{
1060 return scan_ftrace_readme(FTRACE_README_KRETPROBE_OFFSET);
935} 1061}
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index eba44c3e9dca..5ecc9d3925db 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -1,10 +1,11 @@
1#ifndef __PROBE_FILE_H 1#ifndef __PROBE_FILE_H
2#define __PROBE_FILE_H 2#define __PROBE_FILE_H
3 3
4#include "strlist.h"
5#include "strfilter.h"
6#include "probe-event.h" 4#include "probe-event.h"
7 5
6struct strlist;
7struct strfilter;
8
8/* Cache of probe definitions */ 9/* Cache of probe definitions */
9struct probe_cache_entry { 10struct probe_cache_entry {
10 struct list_head node; 11 struct list_head node;
@@ -35,11 +36,13 @@ enum probe_type {
35 36
36/* probe-file.c depends on libelf */ 37/* probe-file.c depends on libelf */
37#ifdef HAVE_LIBELF_SUPPORT 38#ifdef HAVE_LIBELF_SUPPORT
39int open_trace_file(const char *trace_file, bool readwrite);
38int probe_file__open(int flag); 40int probe_file__open(int flag);
39int probe_file__open_both(int *kfd, int *ufd, int flag); 41int probe_file__open_both(int *kfd, int *ufd, int flag);
40struct strlist *probe_file__get_namelist(int fd); 42struct strlist *probe_file__get_namelist(int fd);
41struct strlist *probe_file__get_rawlist(int fd); 43struct strlist *probe_file__get_rawlist(int fd);
42int probe_file__add_event(int fd, struct probe_trace_event *tev); 44int probe_file__add_event(int fd, struct probe_trace_event *tev);
45
43int probe_file__del_events(int fd, struct strfilter *filter); 46int probe_file__del_events(int fd, struct strfilter *filter);
44int probe_file__get_events(int fd, struct strfilter *filter, 47int probe_file__get_events(int fd, struct strfilter *filter,
45 struct strlist *plist); 48 struct strlist *plist);
@@ -64,6 +67,7 @@ struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache,
64 const char *group, const char *event); 67 const char *group, const char *event);
65int probe_cache__show_all_caches(struct strfilter *filter); 68int probe_cache__show_all_caches(struct strfilter *filter);
66bool probe_type_is_available(enum probe_type type); 69bool probe_type_is_available(enum probe_type type);
70bool kretprobe_offset_is_supported(void);
67#else /* ! HAVE_LIBELF_SUPPORT */ 71#else /* ! HAVE_LIBELF_SUPPORT */
68static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused) 72static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused)
69{ 73{
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 57cd268d4275..a5731de0e5eb 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -19,6 +19,7 @@
19 * 19 *
20 */ 20 */
21 21
22#include <inttypes.h>
22#include <sys/utsname.h> 23#include <sys/utsname.h>
23#include <sys/types.h> 24#include <sys/types.h>
24#include <sys/stat.h> 25#include <sys/stat.h>
@@ -37,9 +38,11 @@
37#include "debug.h" 38#include "debug.h"
38#include "intlist.h" 39#include "intlist.h"
39#include "util.h" 40#include "util.h"
41#include "strlist.h"
40#include "symbol.h" 42#include "symbol.h"
41#include "probe-finder.h" 43#include "probe-finder.h"
42#include "probe-file.h" 44#include "probe-file.h"
45#include "string2.h"
43 46
44/* Kprobe tracer basic type is up to u64 */ 47/* Kprobe tracer basic type is up to u64 */
45#define MAX_BASIC_TYPE_BITS 64 48#define MAX_BASIC_TYPE_BITS 64
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 2956c5198652..27f061551012 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -2,9 +2,9 @@
2#define _PROBE_FINDER_H 2#define _PROBE_FINDER_H
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5#include "util.h"
6#include "intlist.h" 5#include "intlist.h"
7#include "probe-event.h" 6#include "probe-event.h"
7#include "sane_ctype.h"
8 8
9#define MAX_PROBE_BUFFER 1024 9#define MAX_PROBE_BUFFER 1024
10#define MAX_PROBES 128 10#define MAX_PROBES 128
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 0546a4304347..9f3b0d9754a8 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -21,8 +21,10 @@ util/cgroup.c
21util/parse-branch-options.c 21util/parse-branch-options.c
22util/rblist.c 22util/rblist.c
23util/counts.c 23util/counts.c
24util/print_binary.c
24util/strlist.c 25util/strlist.c
25util/trace-event.c 26util/trace-event.c
26../lib/rbtree.c 27../lib/rbtree.c
27util/string.c 28util/string.c
28util/symbol_fprintf.c 29util/symbol_fprintf.c
30util/units.c
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index a5fbc012e3df..c129e99114ae 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -4,12 +4,26 @@
4#include <poll.h> 4#include <poll.h>
5#include <linux/err.h> 5#include <linux/err.h>
6#include "evlist.h" 6#include "evlist.h"
7#include "callchain.h"
7#include "evsel.h" 8#include "evsel.h"
8#include "event.h" 9#include "event.h"
9#include "cpumap.h" 10#include "cpumap.h"
11#include "print_binary.h"
10#include "thread_map.h" 12#include "thread_map.h"
11 13
12/* 14/*
15 * Provide these two so that we don't have to link against callchain.c and
16 * start dragging hist.c, etc.
17 */
18struct callchain_param callchain_param;
19
20int parse_callchain_record(const char *arg __maybe_unused,
21 struct callchain_param *param __maybe_unused)
22{
23 return 0;
24}
25
26/*
13 * Support debug printing even though util/debug.c is not linked. That means 27 * Support debug printing even though util/debug.c is not linked. That means
14 * implementing 'verbose' and 'eprintf'. 28 * implementing 'verbose' and 'eprintf'.
15 */ 29 */
diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c
index 293534c1a474..1ba8920151d8 100644
--- a/tools/perf/util/quote.c
+++ b/tools/perf/util/quote.c
@@ -1,3 +1,4 @@
1#include <errno.h>
1#include <stdlib.h> 2#include <stdlib.h>
2#include "strbuf.h" 3#include "strbuf.h"
3#include "quote.h" 4#include "quote.h"
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index 98bf584853ea..d91bdf5a1aa4 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -2,6 +2,7 @@
2#include "evsel.h" 2#include "evsel.h"
3#include "cpumap.h" 3#include "cpumap.h"
4#include "parse-events.h" 4#include "parse-events.h"
5#include <errno.h>
5#include <api/fs/fs.h> 6#include <api/fs/fs.h>
6#include "util.h" 7#include "util.h"
7#include "cloexec.h" 8#include "cloexec.h"
diff --git a/tools/perf/util/sane_ctype.h b/tools/perf/util/sane_ctype.h
new file mode 100644
index 000000000000..4308c22c22ad
--- /dev/null
+++ b/tools/perf/util/sane_ctype.h
@@ -0,0 +1,51 @@
1#ifndef _PERF_SANE_CTYPE_H
2#define _PERF_SANE_CTYPE_H
3
4extern const char *graph_line;
5extern const char *graph_dotted_line;
6extern const char *spaces;
7extern const char *dots;
8
9/* Sane ctype - no locale, and works with signed chars */
10#undef isascii
11#undef isspace
12#undef isdigit
13#undef isxdigit
14#undef isalpha
15#undef isprint
16#undef isalnum
17#undef islower
18#undef isupper
19#undef tolower
20#undef toupper
21
22extern unsigned char sane_ctype[256];
23#define GIT_SPACE 0x01
24#define GIT_DIGIT 0x02
25#define GIT_ALPHA 0x04
26#define GIT_GLOB_SPECIAL 0x08
27#define GIT_REGEX_SPECIAL 0x10
28#define GIT_PRINT_EXTRA 0x20
29#define GIT_PRINT 0x3E
30#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
31#define isascii(x) (((x) & ~0x7f) == 0)
32#define isspace(x) sane_istest(x,GIT_SPACE)
33#define isdigit(x) sane_istest(x,GIT_DIGIT)
34#define isxdigit(x) \
35 (sane_istest(toupper(x), GIT_ALPHA | GIT_DIGIT) && toupper(x) < 'G')
36#define isalpha(x) sane_istest(x,GIT_ALPHA)
37#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
38#define isprint(x) sane_istest(x,GIT_PRINT)
39#define islower(x) (sane_istest(x,GIT_ALPHA) && (x & 0x20))
40#define isupper(x) (sane_istest(x,GIT_ALPHA) && !(x & 0x20))
41#define tolower(x) sane_case((unsigned char)(x), 0x20)
42#define toupper(x) sane_case((unsigned char)(x), 0)
43
44static inline int sane_case(int x, int high)
45{
46 if (sane_istest(x, GIT_ALPHA))
47 x = (x & ~0x20) | high;
48 return x;
49}
50
51#endif /* _PERF_SANE_CTYPE_H */
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index dff043a29589..7b79c413486b 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -19,6 +19,7 @@
19 * 19 *
20 */ 20 */
21 21
22#include <inttypes.h>
22#include <stdio.h> 23#include <stdio.h>
23#include <stdlib.h> 24#include <stdlib.h>
24#include <string.h> 25#include <string.h>
@@ -27,7 +28,9 @@
27#include <linux/bitmap.h> 28#include <linux/bitmap.h>
28#include <linux/time64.h> 29#include <linux/time64.h>
29 30
30#include "../util.h" 31#include <stdbool.h>
32/* perl needs the following define, right after including stdbool.h */
33#define HAS_BOOL
31#include <EXTERN.h> 34#include <EXTERN.h>
32#include <perl.h> 35#include <perl.h>
33 36
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 783326cfbaa6..9d92af7d0718 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -21,6 +21,7 @@
21 21
22#include <Python.h> 22#include <Python.h>
23 23
24#include <inttypes.h>
24#include <stdio.h> 25#include <stdio.h>
25#include <stdlib.h> 26#include <stdlib.h>
26#include <string.h> 27#include <string.h>
@@ -45,6 +46,7 @@
45#include "../call-path.h" 46#include "../call-path.h"
46#include "thread_map.h" 47#include "thread_map.h"
47#include "cpumap.h" 48#include "cpumap.h"
49#include "print_binary.h"
48#include "stat.h" 50#include "stat.h"
49 51
50PyMODINIT_FUNC initperf_trace_context(void); 52PyMODINIT_FUNC initperf_trace_context(void);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 1dd617d116b5..7dc1096264c5 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1,5 +1,8 @@
1#include <errno.h>
2#include <inttypes.h>
1#include <linux/kernel.h> 3#include <linux/kernel.h>
2#include <traceevent/event-parse.h> 4#include <traceevent/event-parse.h>
5#include <api/fs/fs.h>
3 6
4#include <byteswap.h> 7#include <byteswap.h>
5#include <unistd.h> 8#include <unistd.h>
@@ -8,6 +11,7 @@
8 11
9#include "evlist.h" 12#include "evlist.h"
10#include "evsel.h" 13#include "evsel.h"
14#include "memswap.h"
11#include "session.h" 15#include "session.h"
12#include "tool.h" 16#include "tool.h"
13#include "sort.h" 17#include "sort.h"
@@ -16,6 +20,7 @@
16#include "perf_regs.h" 20#include "perf_regs.h"
17#include "asm/bug.h" 21#include "asm/bug.h"
18#include "auxtrace.h" 22#include "auxtrace.h"
23#include "thread.h"
19#include "thread-stack.h" 24#include "thread-stack.h"
20#include "stat.h" 25#include "stat.h"
21 26
@@ -139,8 +144,14 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
139 if (perf_session__open(session) < 0) 144 if (perf_session__open(session) < 0)
140 goto out_close; 145 goto out_close;
141 146
142 perf_session__set_id_hdr_size(session); 147 /*
143 perf_session__set_comm_exec(session); 148 * set session attributes that are present in perf.data
149 * but not in pipe-mode.
150 */
151 if (!file->is_pipe) {
152 perf_session__set_id_hdr_size(session);
153 perf_session__set_comm_exec(session);
154 }
144 } 155 }
145 } else { 156 } else {
146 session->machines.host.env = &perf_env; 157 session->machines.host.env = &perf_env;
@@ -155,7 +166,11 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
155 pr_warning("Cannot read kernel map\n"); 166 pr_warning("Cannot read kernel map\n");
156 } 167 }
157 168
158 if (tool && tool->ordering_requires_timestamps && 169 /*
170 * In pipe-mode, evlist is empty until PERF_RECORD_HEADER_ATTR is
171 * processed, so perf_evlist__sample_id_all is not meaningful here.
172 */
173 if ((!file || !file->is_pipe) && tool && tool->ordering_requires_timestamps &&
159 tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) { 174 tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) {
160 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 175 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
161 tool->ordered_events = false; 176 tool->ordered_events = false;
@@ -1239,6 +1254,8 @@ static int machines__deliver_event(struct machines *machines,
1239 return tool->mmap2(tool, event, sample, machine); 1254 return tool->mmap2(tool, event, sample, machine);
1240 case PERF_RECORD_COMM: 1255 case PERF_RECORD_COMM:
1241 return tool->comm(tool, event, sample, machine); 1256 return tool->comm(tool, event, sample, machine);
1257 case PERF_RECORD_NAMESPACES:
1258 return tool->namespaces(tool, event, sample, machine);
1242 case PERF_RECORD_FORK: 1259 case PERF_RECORD_FORK:
1243 return tool->fork(tool, event, sample, machine); 1260 return tool->fork(tool, event, sample, machine);
1244 case PERF_RECORD_EXIT: 1261 case PERF_RECORD_EXIT:
@@ -1258,9 +1275,12 @@ static int machines__deliver_event(struct machines *machines,
1258 case PERF_RECORD_UNTHROTTLE: 1275 case PERF_RECORD_UNTHROTTLE:
1259 return tool->unthrottle(tool, event, sample, machine); 1276 return tool->unthrottle(tool, event, sample, machine);
1260 case PERF_RECORD_AUX: 1277 case PERF_RECORD_AUX:
1261 if (tool->aux == perf_event__process_aux && 1278 if (tool->aux == perf_event__process_aux) {
1262 (event->aux.flags & PERF_AUX_FLAG_TRUNCATED)) 1279 if (event->aux.flags & PERF_AUX_FLAG_TRUNCATED)
1263 evlist->stats.total_aux_lost += 1; 1280 evlist->stats.total_aux_lost += 1;
1281 if (event->aux.flags & PERF_AUX_FLAG_PARTIAL)
1282 evlist->stats.total_aux_partial += 1;
1283 }
1264 return tool->aux(tool, event, sample, machine); 1284 return tool->aux(tool, event, sample, machine);
1265 case PERF_RECORD_ITRACE_START: 1285 case PERF_RECORD_ITRACE_START:
1266 return tool->itrace_start(tool, event, sample, machine); 1286 return tool->itrace_start(tool, event, sample, machine);
@@ -1494,6 +1514,11 @@ int perf_session__register_idle_thread(struct perf_session *session)
1494 err = -1; 1514 err = -1;
1495 } 1515 }
1496 1516
1517 if (thread == NULL || thread__set_namespaces(thread, 0, NULL)) {
1518 pr_err("problem inserting idle task.\n");
1519 err = -1;
1520 }
1521
1497 /* machine__findnew_thread() got the thread, so put it */ 1522 /* machine__findnew_thread() got the thread, so put it */
1498 thread__put(thread); 1523 thread__put(thread);
1499 return err; 1524 return err;
@@ -1548,6 +1573,23 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
1548 stats->nr_events[PERF_RECORD_AUX]); 1573 stats->nr_events[PERF_RECORD_AUX]);
1549 } 1574 }
1550 1575
1576 if (session->tool->aux == perf_event__process_aux &&
1577 stats->total_aux_partial != 0) {
1578 bool vmm_exclusive = false;
1579
1580 (void)sysfs__read_bool("module/kvm_intel/parameters/vmm_exclusive",
1581 &vmm_exclusive);
1582
1583 ui__warning("AUX data had gaps in it %" PRIu64 " times out of %u!\n\n"
1584 "Are you running a KVM guest in the background?%s\n\n",
1585 stats->total_aux_partial,
1586 stats->nr_events[PERF_RECORD_AUX],
1587 vmm_exclusive ?
1588 "\nReloading kvm_intel module with vmm_exclusive=0\n"
1589 "will reduce the gaps to only guest's timeslices." :
1590 "");
1591 }
1592
1551 if (stats->nr_unknown_events != 0) { 1593 if (stats->nr_unknown_events != 0) {
1552 ui__warning("Found %u unknown events!\n\n" 1594 ui__warning("Found %u unknown events!\n\n"
1553 "Is this an older tool processing a perf.data " 1595 "Is this an older tool processing a perf.data "
@@ -1628,6 +1670,7 @@ static int __perf_session__process_pipe_events(struct perf_session *session)
1628 buf = malloc(cur_size); 1670 buf = malloc(cur_size);
1629 if (!buf) 1671 if (!buf)
1630 return -errno; 1672 return -errno;
1673 ordered_events__set_copy_on_queue(oe, true);
1631more: 1674more:
1632 event = buf; 1675 event = buf;
1633 err = readn(fd, event, sizeof(struct perf_event_header)); 1676 err = readn(fd, event, sizeof(struct perf_event_header));
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 4bd758553450..47b5e7dbcb18 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -5,14 +5,14 @@
5#include "event.h" 5#include "event.h"
6#include "header.h" 6#include "header.h"
7#include "machine.h" 7#include "machine.h"
8#include "symbol.h"
9#include "thread.h"
10#include "data.h" 8#include "data.h"
11#include "ordered-events.h" 9#include "ordered-events.h"
10#include <linux/kernel.h>
12#include <linux/rbtree.h> 11#include <linux/rbtree.h>
13#include <linux/perf_event.h> 12#include <linux/perf_event.h>
14 13
15struct ip_callchain; 14struct ip_callchain;
15struct symbol;
16struct thread; 16struct thread;
17 17
18struct auxtrace; 18struct auxtrace;
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 0ff622288d24..5762ae4e9e91 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1,12 +1,18 @@
1#include <errno.h>
2#include <inttypes.h>
3#include <regex.h>
1#include <sys/mman.h> 4#include <sys/mman.h>
2#include "sort.h" 5#include "sort.h"
3#include "hist.h" 6#include "hist.h"
4#include "comm.h" 7#include "comm.h"
5#include "symbol.h" 8#include "symbol.h"
9#include "thread.h"
6#include "evsel.h" 10#include "evsel.h"
7#include "evlist.h" 11#include "evlist.h"
12#include "strlist.h"
8#include <traceevent/event-parse.h> 13#include <traceevent/event-parse.h>
9#include "mem-events.h" 14#include "mem-events.h"
15#include <linux/kernel.h>
10 16
11regex_t parent_regex; 17regex_t parent_regex;
12const char default_parent_pattern[] = "^sys_|^do_page_fault"; 18const char default_parent_pattern[] = "^sys_|^do_page_fault";
@@ -323,7 +329,7 @@ char *hist_entry__get_srcline(struct hist_entry *he)
323 return SRCLINE_UNKNOWN; 329 return SRCLINE_UNKNOWN;
324 330
325 return get_srcline(map->dso, map__rip_2objdump(map, he->ip), 331 return get_srcline(map->dso, map__rip_2objdump(map, he->ip),
326 he->ms.sym, true); 332 he->ms.sym, true, true);
327} 333}
328 334
329static int64_t 335static int64_t
@@ -366,7 +372,8 @@ sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
366 left->branch_info->srcline_from = get_srcline(map->dso, 372 left->branch_info->srcline_from = get_srcline(map->dso,
367 map__rip_2objdump(map, 373 map__rip_2objdump(map,
368 left->branch_info->from.al_addr), 374 left->branch_info->from.al_addr),
369 left->branch_info->from.sym, true); 375 left->branch_info->from.sym,
376 true, true);
370 } 377 }
371 if (!right->branch_info->srcline_from) { 378 if (!right->branch_info->srcline_from) {
372 struct map *map = right->branch_info->from.map; 379 struct map *map = right->branch_info->from.map;
@@ -376,7 +383,8 @@ sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
376 right->branch_info->srcline_from = get_srcline(map->dso, 383 right->branch_info->srcline_from = get_srcline(map->dso,
377 map__rip_2objdump(map, 384 map__rip_2objdump(map,
378 right->branch_info->from.al_addr), 385 right->branch_info->from.al_addr),
379 right->branch_info->from.sym, true); 386 right->branch_info->from.sym,
387 true, true);
380 } 388 }
381 return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from); 389 return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from);
382} 390}
@@ -407,7 +415,8 @@ sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
407 left->branch_info->srcline_to = get_srcline(map->dso, 415 left->branch_info->srcline_to = get_srcline(map->dso,
408 map__rip_2objdump(map, 416 map__rip_2objdump(map,
409 left->branch_info->to.al_addr), 417 left->branch_info->to.al_addr),
410 left->branch_info->from.sym, true); 418 left->branch_info->from.sym,
419 true, true);
411 } 420 }
412 if (!right->branch_info->srcline_to) { 421 if (!right->branch_info->srcline_to) {
413 struct map *map = right->branch_info->to.map; 422 struct map *map = right->branch_info->to.map;
@@ -417,7 +426,8 @@ sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
417 right->branch_info->srcline_to = get_srcline(map->dso, 426 right->branch_info->srcline_to = get_srcline(map->dso,
418 map__rip_2objdump(map, 427 map__rip_2objdump(map,
419 right->branch_info->to.al_addr), 428 right->branch_info->to.al_addr),
420 right->branch_info->to.sym, true); 429 right->branch_info->to.sym,
430 true, true);
421 } 431 }
422 return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to); 432 return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to);
423} 433}
@@ -448,7 +458,7 @@ static char *hist_entry__get_srcfile(struct hist_entry *e)
448 return no_srcfile; 458 return no_srcfile;
449 459
450 sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip), 460 sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip),
451 e->ms.sym, false, true); 461 e->ms.sym, false, true, true);
452 if (!strcmp(sf, SRCLINE_UNKNOWN)) 462 if (!strcmp(sf, SRCLINE_UNKNOWN))
453 return no_srcfile; 463 return no_srcfile;
454 p = strchr(sf, ':'); 464 p = strchr(sf, ':');
@@ -536,6 +546,46 @@ struct sort_entry sort_cpu = {
536 .se_width_idx = HISTC_CPU, 546 .se_width_idx = HISTC_CPU,
537}; 547};
538 548
549/* --sort cgroup_id */
550
551static int64_t _sort__cgroup_dev_cmp(u64 left_dev, u64 right_dev)
552{
553 return (int64_t)(right_dev - left_dev);
554}
555
556static int64_t _sort__cgroup_inode_cmp(u64 left_ino, u64 right_ino)
557{
558 return (int64_t)(right_ino - left_ino);
559}
560
561static int64_t
562sort__cgroup_id_cmp(struct hist_entry *left, struct hist_entry *right)
563{
564 int64_t ret;
565
566 ret = _sort__cgroup_dev_cmp(right->cgroup_id.dev, left->cgroup_id.dev);
567 if (ret != 0)
568 return ret;
569
570 return _sort__cgroup_inode_cmp(right->cgroup_id.ino,
571 left->cgroup_id.ino);
572}
573
574static int hist_entry__cgroup_id_snprintf(struct hist_entry *he,
575 char *bf, size_t size,
576 unsigned int width __maybe_unused)
577{
578 return repsep_snprintf(bf, size, "%lu/0x%lx", he->cgroup_id.dev,
579 he->cgroup_id.ino);
580}
581
582struct sort_entry sort_cgroup_id = {
583 .se_header = "cgroup id (dev/inode)",
584 .se_cmp = sort__cgroup_id_cmp,
585 .se_snprintf = hist_entry__cgroup_id_snprintf,
586 .se_width_idx = HISTC_CGROUP_ID,
587};
588
539/* --sort socket */ 589/* --sort socket */
540 590
541static int64_t 591static int64_t
@@ -846,6 +896,9 @@ static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
846static int64_t 896static int64_t
847sort__cycles_cmp(struct hist_entry *left, struct hist_entry *right) 897sort__cycles_cmp(struct hist_entry *left, struct hist_entry *right)
848{ 898{
899 if (!left->branch_info || !right->branch_info)
900 return cmp_null(left->branch_info, right->branch_info);
901
849 return left->branch_info->flags.cycles - 902 return left->branch_info->flags.cycles -
850 right->branch_info->flags.cycles; 903 right->branch_info->flags.cycles;
851} 904}
@@ -853,6 +906,8 @@ sort__cycles_cmp(struct hist_entry *left, struct hist_entry *right)
853static int hist_entry__cycles_snprintf(struct hist_entry *he, char *bf, 906static int hist_entry__cycles_snprintf(struct hist_entry *he, char *bf,
854 size_t size, unsigned int width) 907 size_t size, unsigned int width)
855{ 908{
909 if (!he->branch_info)
910 return scnprintf(bf, size, "%-.*s", width, "N/A");
856 if (he->branch_info->flags.cycles == 0) 911 if (he->branch_info->flags.cycles == 0)
857 return repsep_snprintf(bf, size, "%-*s", width, "-"); 912 return repsep_snprintf(bf, size, "%-*s", width, "-");
858 return repsep_snprintf(bf, size, "%-*hd", width, 913 return repsep_snprintf(bf, size, "%-*hd", width,
@@ -1396,6 +1451,46 @@ struct sort_entry sort_transaction = {
1396 .se_width_idx = HISTC_TRANSACTION, 1451 .se_width_idx = HISTC_TRANSACTION,
1397}; 1452};
1398 1453
1454/* --sort symbol_size */
1455
1456static int64_t _sort__sym_size_cmp(struct symbol *sym_l, struct symbol *sym_r)
1457{
1458 int64_t size_l = sym_l != NULL ? symbol__size(sym_l) : 0;
1459 int64_t size_r = sym_r != NULL ? symbol__size(sym_r) : 0;
1460
1461 return size_l < size_r ? -1 :
1462 size_l == size_r ? 0 : 1;
1463}
1464
1465static int64_t
1466sort__sym_size_cmp(struct hist_entry *left, struct hist_entry *right)
1467{
1468 return _sort__sym_size_cmp(right->ms.sym, left->ms.sym);
1469}
1470
1471static int _hist_entry__sym_size_snprintf(struct symbol *sym, char *bf,
1472 size_t bf_size, unsigned int width)
1473{
1474 if (sym)
1475 return repsep_snprintf(bf, bf_size, "%*d", width, symbol__size(sym));
1476
1477 return repsep_snprintf(bf, bf_size, "%*s", width, "unknown");
1478}
1479
1480static int hist_entry__sym_size_snprintf(struct hist_entry *he, char *bf,
1481 size_t size, unsigned int width)
1482{
1483 return _hist_entry__sym_size_snprintf(he->ms.sym, bf, size, width);
1484}
1485
1486struct sort_entry sort_sym_size = {
1487 .se_header = "Symbol size",
1488 .se_cmp = sort__sym_size_cmp,
1489 .se_snprintf = hist_entry__sym_size_snprintf,
1490 .se_width_idx = HISTC_SYM_SIZE,
1491};
1492
1493
1399struct sort_dimension { 1494struct sort_dimension {
1400 const char *name; 1495 const char *name;
1401 struct sort_entry *entry; 1496 struct sort_entry *entry;
@@ -1418,6 +1513,8 @@ static struct sort_dimension common_sort_dimensions[] = {
1418 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), 1513 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
1419 DIM(SORT_TRANSACTION, "transaction", sort_transaction), 1514 DIM(SORT_TRANSACTION, "transaction", sort_transaction),
1420 DIM(SORT_TRACE, "trace", sort_trace), 1515 DIM(SORT_TRACE, "trace", sort_trace),
1516 DIM(SORT_SYM_SIZE, "symbol_size", sort_sym_size),
1517 DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id),
1421}; 1518};
1422 1519
1423#undef DIM 1520#undef DIM
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 796c847e2f00..b7c75597e18f 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -2,7 +2,7 @@
2#define __PERF_SORT_H 2#define __PERF_SORT_H
3#include "../builtin.h" 3#include "../builtin.h"
4 4
5#include "util.h" 5#include <regex.h>
6 6
7#include "color.h" 7#include "color.h"
8#include <linux/list.h> 8#include <linux/list.h>
@@ -11,7 +11,6 @@
11#include "symbol.h" 11#include "symbol.h"
12#include "string.h" 12#include "string.h"
13#include "callchain.h" 13#include "callchain.h"
14#include "strlist.h"
15#include "values.h" 14#include "values.h"
16 15
17#include "../perf.h" 16#include "../perf.h"
@@ -21,7 +20,9 @@
21#include <subcmd/parse-options.h> 20#include <subcmd/parse-options.h>
22#include "parse-events.h" 21#include "parse-events.h"
23#include "hist.h" 22#include "hist.h"
24#include "thread.h" 23#include "srcline.h"
24
25struct thread;
25 26
26extern regex_t parent_regex; 27extern regex_t parent_regex;
27extern const char *sort_order; 28extern const char *sort_order;
@@ -54,6 +55,11 @@ struct he_stat {
54 u32 nr_events; 55 u32 nr_events;
55}; 56};
56 57
58struct namespace_id {
59 u64 dev;
60 u64 ino;
61};
62
57struct hist_entry_diff { 63struct hist_entry_diff {
58 bool computed; 64 bool computed;
59 union { 65 union {
@@ -91,6 +97,7 @@ struct hist_entry {
91 struct map_symbol ms; 97 struct map_symbol ms;
92 struct thread *thread; 98 struct thread *thread;
93 struct comm *comm; 99 struct comm *comm;
100 struct namespace_id cgroup_id;
94 u64 ip; 101 u64 ip;
95 u64 transaction; 102 u64 transaction;
96 s32 socket; 103 s32 socket;
@@ -122,6 +129,7 @@ struct hist_entry {
122 }; 129 };
123 char *srcline; 130 char *srcline;
124 char *srcfile; 131 char *srcfile;
132 struct inline_node *inline_node;
125 struct symbol *parent; 133 struct symbol *parent;
126 struct branch_info *branch_info; 134 struct branch_info *branch_info;
127 struct hists *hists; 135 struct hists *hists;
@@ -211,6 +219,8 @@ enum sort_type {
211 SORT_GLOBAL_WEIGHT, 219 SORT_GLOBAL_WEIGHT,
212 SORT_TRANSACTION, 220 SORT_TRANSACTION,
213 SORT_TRACE, 221 SORT_TRACE,
222 SORT_SYM_SIZE,
223 SORT_CGROUP_ID,
214 224
215 /* branch stack specific sort keys */ 225 /* branch stack specific sort keys */
216 __SORT_BRANCH_STACK, 226 __SORT_BRANCH_STACK,
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index b4db3f48e3b0..df051a52393c 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -1,3 +1,4 @@
1#include <inttypes.h>
1#include <stdio.h> 2#include <stdio.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <string.h> 4#include <string.h>
@@ -7,11 +8,59 @@
7#include "util/dso.h" 8#include "util/dso.h"
8#include "util/util.h" 9#include "util/util.h"
9#include "util/debug.h" 10#include "util/debug.h"
11#include "util/callchain.h"
12#include "srcline.h"
10 13
11#include "symbol.h" 14#include "symbol.h"
12 15
13bool srcline_full_filename; 16bool srcline_full_filename;
14 17
18static const char *dso__name(struct dso *dso)
19{
20 const char *dso_name;
21
22 if (dso->symsrc_filename)
23 dso_name = dso->symsrc_filename;
24 else
25 dso_name = dso->long_name;
26
27 if (dso_name[0] == '[')
28 return NULL;
29
30 if (!strncmp(dso_name, "/tmp/perf-", 10))
31 return NULL;
32
33 return dso_name;
34}
35
36static int inline_list__append(char *filename, char *funcname, int line_nr,
37 struct inline_node *node, struct dso *dso)
38{
39 struct inline_list *ilist;
40 char *demangled;
41
42 ilist = zalloc(sizeof(*ilist));
43 if (ilist == NULL)
44 return -1;
45
46 ilist->filename = filename;
47 ilist->line_nr = line_nr;
48
49 if (dso != NULL) {
50 demangled = dso__demangle_sym(dso, 0, funcname);
51 if (demangled == NULL) {
52 ilist->funcname = funcname;
53 } else {
54 ilist->funcname = demangled;
55 free(funcname);
56 }
57 }
58
59 list_add_tail(&ilist->list, &node->val);
60
61 return 0;
62}
63
15#ifdef HAVE_LIBBFD_SUPPORT 64#ifdef HAVE_LIBBFD_SUPPORT
16 65
17/* 66/*
@@ -151,9 +200,17 @@ static void addr2line_cleanup(struct a2l_data *a2l)
151 200
152#define MAX_INLINE_NEST 1024 201#define MAX_INLINE_NEST 1024
153 202
203static void inline_list__reverse(struct inline_node *node)
204{
205 struct inline_list *ilist, *n;
206
207 list_for_each_entry_safe_reverse(ilist, n, &node->val, list)
208 list_move_tail(&ilist->list, &node->val);
209}
210
154static int addr2line(const char *dso_name, u64 addr, 211static int addr2line(const char *dso_name, u64 addr,
155 char **file, unsigned int *line, struct dso *dso, 212 char **file, unsigned int *line, struct dso *dso,
156 bool unwind_inlines) 213 bool unwind_inlines, struct inline_node *node)
157{ 214{
158 int ret = 0; 215 int ret = 0;
159 struct a2l_data *a2l = dso->a2l; 216 struct a2l_data *a2l = dso->a2l;
@@ -178,8 +235,21 @@ static int addr2line(const char *dso_name, u64 addr,
178 235
179 while (bfd_find_inliner_info(a2l->abfd, &a2l->filename, 236 while (bfd_find_inliner_info(a2l->abfd, &a2l->filename,
180 &a2l->funcname, &a2l->line) && 237 &a2l->funcname, &a2l->line) &&
181 cnt++ < MAX_INLINE_NEST) 238 cnt++ < MAX_INLINE_NEST) {
182 ; 239
240 if (node != NULL) {
241 if (inline_list__append(strdup(a2l->filename),
242 strdup(a2l->funcname),
243 a2l->line, node,
244 dso) != 0)
245 return 0;
246 }
247 }
248
249 if ((node != NULL) &&
250 (callchain_param.order != ORDER_CALLEE)) {
251 inline_list__reverse(node);
252 }
183 } 253 }
184 254
185 if (a2l->found && a2l->filename) { 255 if (a2l->found && a2l->filename) {
@@ -205,18 +275,68 @@ void dso__free_a2l(struct dso *dso)
205 dso->a2l = NULL; 275 dso->a2l = NULL;
206} 276}
207 277
278static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
279 struct dso *dso)
280{
281 char *file = NULL;
282 unsigned int line = 0;
283 struct inline_node *node;
284
285 node = zalloc(sizeof(*node));
286 if (node == NULL) {
287 perror("not enough memory for the inline node");
288 return NULL;
289 }
290
291 INIT_LIST_HEAD(&node->val);
292 node->addr = addr;
293
294 if (!addr2line(dso_name, addr, &file, &line, dso, TRUE, node))
295 goto out_free_inline_node;
296
297 if (list_empty(&node->val))
298 goto out_free_inline_node;
299
300 return node;
301
302out_free_inline_node:
303 inline_node__delete(node);
304 return NULL;
305}
306
208#else /* HAVE_LIBBFD_SUPPORT */ 307#else /* HAVE_LIBBFD_SUPPORT */
209 308
309static int filename_split(char *filename, unsigned int *line_nr)
310{
311 char *sep;
312
313 sep = strchr(filename, '\n');
314 if (sep)
315 *sep = '\0';
316
317 if (!strcmp(filename, "??:0"))
318 return 0;
319
320 sep = strchr(filename, ':');
321 if (sep) {
322 *sep++ = '\0';
323 *line_nr = strtoul(sep, NULL, 0);
324 return 1;
325 }
326
327 return 0;
328}
329
210static int addr2line(const char *dso_name, u64 addr, 330static int addr2line(const char *dso_name, u64 addr,
211 char **file, unsigned int *line_nr, 331 char **file, unsigned int *line_nr,
212 struct dso *dso __maybe_unused, 332 struct dso *dso __maybe_unused,
213 bool unwind_inlines __maybe_unused) 333 bool unwind_inlines __maybe_unused,
334 struct inline_node *node __maybe_unused)
214{ 335{
215 FILE *fp; 336 FILE *fp;
216 char cmd[PATH_MAX]; 337 char cmd[PATH_MAX];
217 char *filename = NULL; 338 char *filename = NULL;
218 size_t len; 339 size_t len;
219 char *sep;
220 int ret = 0; 340 int ret = 0;
221 341
222 scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64, 342 scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64,
@@ -233,23 +353,14 @@ static int addr2line(const char *dso_name, u64 addr,
233 goto out; 353 goto out;
234 } 354 }
235 355
236 sep = strchr(filename, '\n'); 356 ret = filename_split(filename, line_nr);
237 if (sep) 357 if (ret != 1) {
238 *sep = '\0';
239
240 if (!strcmp(filename, "??:0")) {
241 pr_debug("no debugging info in %s\n", dso_name);
242 free(filename); 358 free(filename);
243 goto out; 359 goto out;
244 } 360 }
245 361
246 sep = strchr(filename, ':'); 362 *file = filename;
247 if (sep) { 363
248 *sep++ = '\0';
249 *file = filename;
250 *line_nr = strtoul(sep, NULL, 0);
251 ret = 1;
252 }
253out: 364out:
254 pclose(fp); 365 pclose(fp);
255 return ret; 366 return ret;
@@ -259,6 +370,58 @@ void dso__free_a2l(struct dso *dso __maybe_unused)
259{ 370{
260} 371}
261 372
373static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
374 struct dso *dso __maybe_unused)
375{
376 FILE *fp;
377 char cmd[PATH_MAX];
378 struct inline_node *node;
379 char *filename = NULL;
380 size_t len;
381 unsigned int line_nr = 0;
382
383 scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i %016"PRIx64,
384 dso_name, addr);
385
386 fp = popen(cmd, "r");
387 if (fp == NULL) {
388 pr_err("popen failed for %s\n", dso_name);
389 return NULL;
390 }
391
392 node = zalloc(sizeof(*node));
393 if (node == NULL) {
394 perror("not enough memory for the inline node");
395 goto out;
396 }
397
398 INIT_LIST_HEAD(&node->val);
399 node->addr = addr;
400
401 while (getline(&filename, &len, fp) != -1) {
402 if (filename_split(filename, &line_nr) != 1) {
403 free(filename);
404 goto out;
405 }
406
407 if (inline_list__append(filename, NULL, line_nr, node,
408 NULL) != 0)
409 goto out;
410
411 filename = NULL;
412 }
413
414out:
415 pclose(fp);
416
417 if (list_empty(&node->val)) {
418 inline_node__delete(node);
419 return NULL;
420 }
421
422 return node;
423}
424
262#endif /* HAVE_LIBBFD_SUPPORT */ 425#endif /* HAVE_LIBBFD_SUPPORT */
263 426
264/* 427/*
@@ -268,7 +431,7 @@ void dso__free_a2l(struct dso *dso __maybe_unused)
268#define A2L_FAIL_LIMIT 123 431#define A2L_FAIL_LIMIT 123
269 432
270char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 433char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
271 bool show_sym, bool unwind_inlines) 434 bool show_sym, bool show_addr, bool unwind_inlines)
272{ 435{
273 char *file = NULL; 436 char *file = NULL;
274 unsigned line = 0; 437 unsigned line = 0;
@@ -278,18 +441,11 @@ char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
278 if (!dso->has_srcline) 441 if (!dso->has_srcline)
279 goto out; 442 goto out;
280 443
281 if (dso->symsrc_filename) 444 dso_name = dso__name(dso);
282 dso_name = dso->symsrc_filename; 445 if (dso_name == NULL)
283 else
284 dso_name = dso->long_name;
285
286 if (dso_name[0] == '[')
287 goto out;
288
289 if (!strncmp(dso_name, "/tmp/perf-", 10))
290 goto out; 446 goto out;
291 447
292 if (!addr2line(dso_name, addr, &file, &line, dso, unwind_inlines)) 448 if (!addr2line(dso_name, addr, &file, &line, dso, unwind_inlines, NULL))
293 goto out; 449 goto out;
294 450
295 if (asprintf(&srcline, "%s:%u", 451 if (asprintf(&srcline, "%s:%u",
@@ -309,6 +465,11 @@ out:
309 dso->has_srcline = 0; 465 dso->has_srcline = 0;
310 dso__free_a2l(dso); 466 dso__free_a2l(dso);
311 } 467 }
468
469 if (!show_addr)
470 return (show_sym && sym) ?
471 strndup(sym->name, sym->namelen) : NULL;
472
312 if (sym) { 473 if (sym) {
313 if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "", 474 if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "",
314 addr - sym->start) < 0) 475 addr - sym->start) < 0)
@@ -325,7 +486,32 @@ void free_srcline(char *srcline)
325} 486}
326 487
327char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 488char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
328 bool show_sym) 489 bool show_sym, bool show_addr)
490{
491 return __get_srcline(dso, addr, sym, show_sym, show_addr, false);
492}
493
494struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr)
329{ 495{
330 return __get_srcline(dso, addr, sym, show_sym, false); 496 const char *dso_name;
497
498 dso_name = dso__name(dso);
499 if (dso_name == NULL)
500 return NULL;
501
502 return addr2inlines(dso_name, addr, dso);
503}
504
505void inline_node__delete(struct inline_node *node)
506{
507 struct inline_list *ilist, *tmp;
508
509 list_for_each_entry_safe(ilist, tmp, &node->val, list) {
510 list_del_init(&ilist->list);
511 zfree(&ilist->filename);
512 zfree(&ilist->funcname);
513 free(ilist);
514 }
515
516 free(node);
331} 517}
diff --git a/tools/perf/util/srcline.h b/tools/perf/util/srcline.h
new file mode 100644
index 000000000000..7b52ba88676e
--- /dev/null
+++ b/tools/perf/util/srcline.h
@@ -0,0 +1,34 @@
1#ifndef PERF_SRCLINE_H
2#define PERF_SRCLINE_H
3
4#include <linux/list.h>
5#include <linux/types.h>
6
7struct dso;
8struct symbol;
9
10extern bool srcline_full_filename;
11char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
12 bool show_sym, bool show_addr);
13char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
14 bool show_sym, bool show_addr, bool unwind_inlines);
15void free_srcline(char *srcline);
16
17#define SRCLINE_UNKNOWN ((char *) "??:0")
18
19struct inline_list {
20 char *filename;
21 char *funcname;
22 unsigned int line_nr;
23 struct list_head list;
24};
25
26struct inline_node {
27 u64 addr;
28 struct list_head val;
29};
30
31struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr);
32void inline_node__delete(struct inline_node *node);
33
34#endif /* PERF_SRCLINE_H */
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 8a2bbd2a4d82..ac10cc675d39 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -3,6 +3,9 @@
3#include "stat.h" 3#include "stat.h"
4#include "color.h" 4#include "color.h"
5#include "pmu.h" 5#include "pmu.h"
6#include "rblist.h"
7#include "evlist.h"
8#include "expr.h"
6 9
7enum { 10enum {
8 CTX_BIT_USER = 1 << 0, 11 CTX_BIT_USER = 1 << 0,
@@ -41,13 +44,73 @@ static struct stats runtime_topdown_slots_issued[NUM_CTX][MAX_NR_CPUS];
41static struct stats runtime_topdown_slots_retired[NUM_CTX][MAX_NR_CPUS]; 44static struct stats runtime_topdown_slots_retired[NUM_CTX][MAX_NR_CPUS];
42static struct stats runtime_topdown_fetch_bubbles[NUM_CTX][MAX_NR_CPUS]; 45static struct stats runtime_topdown_fetch_bubbles[NUM_CTX][MAX_NR_CPUS];
43static struct stats runtime_topdown_recovery_bubbles[NUM_CTX][MAX_NR_CPUS]; 46static struct stats runtime_topdown_recovery_bubbles[NUM_CTX][MAX_NR_CPUS];
47static struct rblist runtime_saved_values;
44static bool have_frontend_stalled; 48static bool have_frontend_stalled;
45 49
46struct stats walltime_nsecs_stats; 50struct stats walltime_nsecs_stats;
47 51
52struct saved_value {
53 struct rb_node rb_node;
54 struct perf_evsel *evsel;
55 int cpu;
56 int ctx;
57 struct stats stats;
58};
59
60static int saved_value_cmp(struct rb_node *rb_node, const void *entry)
61{
62 struct saved_value *a = container_of(rb_node,
63 struct saved_value,
64 rb_node);
65 const struct saved_value *b = entry;
66
67 if (a->ctx != b->ctx)
68 return a->ctx - b->ctx;
69 if (a->cpu != b->cpu)
70 return a->cpu - b->cpu;
71 return a->evsel - b->evsel;
72}
73
74static struct rb_node *saved_value_new(struct rblist *rblist __maybe_unused,
75 const void *entry)
76{
77 struct saved_value *nd = malloc(sizeof(struct saved_value));
78
79 if (!nd)
80 return NULL;
81 memcpy(nd, entry, sizeof(struct saved_value));
82 return &nd->rb_node;
83}
84
85static struct saved_value *saved_value_lookup(struct perf_evsel *evsel,
86 int cpu, int ctx,
87 bool create)
88{
89 struct rb_node *nd;
90 struct saved_value dm = {
91 .cpu = cpu,
92 .ctx = ctx,
93 .evsel = evsel,
94 };
95 nd = rblist__find(&runtime_saved_values, &dm);
96 if (nd)
97 return container_of(nd, struct saved_value, rb_node);
98 if (create) {
99 rblist__add_node(&runtime_saved_values, &dm);
100 nd = rblist__find(&runtime_saved_values, &dm);
101 if (nd)
102 return container_of(nd, struct saved_value, rb_node);
103 }
104 return NULL;
105}
106
48void perf_stat__init_shadow_stats(void) 107void perf_stat__init_shadow_stats(void)
49{ 108{
50 have_frontend_stalled = pmu_have_event("cpu", "stalled-cycles-frontend"); 109 have_frontend_stalled = pmu_have_event("cpu", "stalled-cycles-frontend");
110 rblist__init(&runtime_saved_values);
111 runtime_saved_values.node_cmp = saved_value_cmp;
112 runtime_saved_values.node_new = saved_value_new;
113 /* No delete for now */
51} 114}
52 115
53static int evsel_context(struct perf_evsel *evsel) 116static int evsel_context(struct perf_evsel *evsel)
@@ -70,6 +133,8 @@ static int evsel_context(struct perf_evsel *evsel)
70 133
71void perf_stat__reset_shadow_stats(void) 134void perf_stat__reset_shadow_stats(void)
72{ 135{
136 struct rb_node *pos, *next;
137
73 memset(runtime_nsecs_stats, 0, sizeof(runtime_nsecs_stats)); 138 memset(runtime_nsecs_stats, 0, sizeof(runtime_nsecs_stats));
74 memset(runtime_cycles_stats, 0, sizeof(runtime_cycles_stats)); 139 memset(runtime_cycles_stats, 0, sizeof(runtime_cycles_stats));
75 memset(runtime_stalled_cycles_front_stats, 0, sizeof(runtime_stalled_cycles_front_stats)); 140 memset(runtime_stalled_cycles_front_stats, 0, sizeof(runtime_stalled_cycles_front_stats));
@@ -92,6 +157,15 @@ void perf_stat__reset_shadow_stats(void)
92 memset(runtime_topdown_slots_issued, 0, sizeof(runtime_topdown_slots_issued)); 157 memset(runtime_topdown_slots_issued, 0, sizeof(runtime_topdown_slots_issued));
93 memset(runtime_topdown_fetch_bubbles, 0, sizeof(runtime_topdown_fetch_bubbles)); 158 memset(runtime_topdown_fetch_bubbles, 0, sizeof(runtime_topdown_fetch_bubbles));
94 memset(runtime_topdown_recovery_bubbles, 0, sizeof(runtime_topdown_recovery_bubbles)); 159 memset(runtime_topdown_recovery_bubbles, 0, sizeof(runtime_topdown_recovery_bubbles));
160
161 next = rb_first(&runtime_saved_values.entries);
162 while (next) {
163 pos = next;
164 next = rb_next(pos);
165 memset(&container_of(pos, struct saved_value, rb_node)->stats,
166 0,
167 sizeof(struct stats));
168 }
95} 169}
96 170
97/* 171/*
@@ -143,6 +217,12 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,
143 update_stats(&runtime_dtlb_cache_stats[ctx][cpu], count[0]); 217 update_stats(&runtime_dtlb_cache_stats[ctx][cpu], count[0]);
144 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB)) 218 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB))
145 update_stats(&runtime_itlb_cache_stats[ctx][cpu], count[0]); 219 update_stats(&runtime_itlb_cache_stats[ctx][cpu], count[0]);
220
221 if (counter->collect_stat) {
222 struct saved_value *v = saved_value_lookup(counter, cpu, ctx,
223 true);
224 update_stats(&v->stats, count[0]);
225 }
146} 226}
147 227
148/* used for get_ratio_color() */ 228/* used for get_ratio_color() */
@@ -172,6 +252,95 @@ static const char *get_ratio_color(enum grc_type type, double ratio)
172 return color; 252 return color;
173} 253}
174 254
255static struct perf_evsel *perf_stat__find_event(struct perf_evlist *evsel_list,
256 const char *name)
257{
258 struct perf_evsel *c2;
259
260 evlist__for_each_entry (evsel_list, c2) {
261 if (!strcasecmp(c2->name, name))
262 return c2;
263 }
264 return NULL;
265}
266
267/* Mark MetricExpr target events and link events using them to them. */
268void perf_stat__collect_metric_expr(struct perf_evlist *evsel_list)
269{
270 struct perf_evsel *counter, *leader, **metric_events, *oc;
271 bool found;
272 const char **metric_names;
273 int i;
274 int num_metric_names;
275
276 evlist__for_each_entry(evsel_list, counter) {
277 bool invalid = false;
278
279 leader = counter->leader;
280 if (!counter->metric_expr)
281 continue;
282 metric_events = counter->metric_events;
283 if (!metric_events) {
284 if (expr__find_other(counter->metric_expr, counter->name,
285 &metric_names, &num_metric_names) < 0)
286 continue;
287
288 metric_events = calloc(sizeof(struct perf_evsel *),
289 num_metric_names + 1);
290 if (!metric_events)
291 return;
292 counter->metric_events = metric_events;
293 }
294
295 for (i = 0; i < num_metric_names; i++) {
296 found = false;
297 if (leader) {
298 /* Search in group */
299 for_each_group_member (oc, leader) {
300 if (!strcasecmp(oc->name, metric_names[i])) {
301 found = true;
302 break;
303 }
304 }
305 }
306 if (!found) {
307 /* Search ignoring groups */
308 oc = perf_stat__find_event(evsel_list, metric_names[i]);
309 }
310 if (!oc) {
311 /* Deduping one is good enough to handle duplicated PMUs. */
312 static char *printed;
313
314 /*
315 * Adding events automatically would be difficult, because
316 * it would risk creating groups that are not schedulable.
317 * perf stat doesn't understand all the scheduling constraints
318 * of events. So we ask the user instead to add the missing
319 * events.
320 */
321 if (!printed || strcasecmp(printed, metric_names[i])) {
322 fprintf(stderr,
323 "Add %s event to groups to get metric expression for %s\n",
324 metric_names[i],
325 counter->name);
326 printed = strdup(metric_names[i]);
327 }
328 invalid = true;
329 continue;
330 }
331 metric_events[i] = oc;
332 oc->collect_stat = true;
333 }
334 metric_events[i] = NULL;
335 free(metric_names);
336 if (invalid) {
337 free(metric_events);
338 counter->metric_events = NULL;
339 counter->metric_expr = NULL;
340 }
341 }
342}
343
175static void print_stalled_cycles_frontend(int cpu, 344static void print_stalled_cycles_frontend(int cpu,
176 struct perf_evsel *evsel, double avg, 345 struct perf_evsel *evsel, double avg,
177 struct perf_stat_output_ctx *out) 346 struct perf_stat_output_ctx *out)
@@ -614,6 +783,34 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
614 be_bound * 100.); 783 be_bound * 100.);
615 else 784 else
616 print_metric(ctxp, NULL, NULL, name, 0); 785 print_metric(ctxp, NULL, NULL, name, 0);
786 } else if (evsel->metric_expr) {
787 struct parse_ctx pctx;
788 int i;
789
790 expr__ctx_init(&pctx);
791 expr__add_id(&pctx, evsel->name, avg);
792 for (i = 0; evsel->metric_events[i]; i++) {
793 struct saved_value *v;
794
795 v = saved_value_lookup(evsel->metric_events[i], cpu, ctx, false);
796 if (!v)
797 break;
798 expr__add_id(&pctx, evsel->metric_events[i]->name,
799 avg_stats(&v->stats));
800 }
801 if (!evsel->metric_events[i]) {
802 const char *p = evsel->metric_expr;
803
804 if (expr__parse(&ratio, &pctx, &p) == 0)
805 print_metric(ctxp, NULL, "%8.1f",
806 evsel->metric_name ?
807 evsel->metric_name :
808 out->force_header ? evsel->name : "",
809 ratio);
810 else
811 print_metric(ctxp, NULL, NULL, "", 0);
812 } else
813 print_metric(ctxp, NULL, NULL, "", 0);
617 } else if (runtime_nsecs_stats[cpu].n != 0) { 814 } else if (runtime_nsecs_stats[cpu].n != 0) {
618 char unit = 'M'; 815 char unit = 'M';
619 char unit_buf[10]; 816 char unit_buf[10];
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 0d51334a9b46..c58174443dc1 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -1,3 +1,5 @@
1#include <errno.h>
2#include <inttypes.h>
1#include <math.h> 3#include <math.h>
2#include "stat.h" 4#include "stat.h"
3#include "evlist.h" 5#include "evlist.h"
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index c29bb94c48a4..0a65ae23f495 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -85,11 +85,13 @@ struct perf_stat_output_ctx {
85 void *ctx; 85 void *ctx;
86 print_metric_t print_metric; 86 print_metric_t print_metric;
87 new_line_t new_line; 87 new_line_t new_line;
88 bool force_header;
88}; 89};
89 90
90void perf_stat__print_shadow_stats(struct perf_evsel *evsel, 91void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
91 double avg, int cpu, 92 double avg, int cpu,
92 struct perf_stat_output_ctx *out); 93 struct perf_stat_output_ctx *out);
94void perf_stat__collect_metric_expr(struct perf_evlist *);
93 95
94int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw); 96int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw);
95void perf_evlist__free_stats(struct perf_evlist *evlist); 97void perf_evlist__free_stats(struct perf_evlist *evlist);
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index 817593908d47..aafe908b82b5 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -1,15 +1,7 @@
1#include "debug.h" 1#include "debug.h"
2#include "util.h" 2#include "util.h"
3#include <linux/kernel.h> 3#include <linux/kernel.h>
4 4#include <errno.h>
5int prefixcmp(const char *str, const char *prefix)
6{
7 for (; ; str++, prefix++)
8 if (!*prefix)
9 return 0;
10 else if (*str != *prefix)
11 return (unsigned char)*prefix - (unsigned char)*str;
12}
13 5
14/* 6/*
15 * Used as the default ->buf value, so that people can always assume 7 * Used as the default ->buf value, so that people can always assume
diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c
index efb53772e0ec..4dc0af669a30 100644
--- a/tools/perf/util/strfilter.c
+++ b/tools/perf/util/strfilter.c
@@ -1,7 +1,10 @@
1#include "util.h" 1#include "util.h"
2#include "string.h" 2#include "string2.h"
3#include "strfilter.h" 3#include "strfilter.h"
4 4
5#include <errno.h>
6#include "sane_ctype.h"
7
5/* Operators */ 8/* Operators */
6static const char *OP_and = "&"; /* Logical AND */ 9static const char *OP_and = "&"; /* Logical AND */
7static const char *OP_or = "|"; /* Logical OR */ 10static const char *OP_or = "|"; /* Logical OR */
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index bddca519dd58..cca53b693a48 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -1,5 +1,9 @@
1#include "util.h" 1#include "string2.h"
2#include "linux/string.h" 2#include <linux/kernel.h>
3#include <linux/string.h>
4#include <stdlib.h>
5
6#include "sane_ctype.h"
3 7
4#define K 1024LL 8#define K 1024LL
5/* 9/*
@@ -99,8 +103,10 @@ static int count_argc(const char *str)
99void argv_free(char **argv) 103void argv_free(char **argv)
100{ 104{
101 char **p; 105 char **p;
102 for (p = argv; *p; p++) 106 for (p = argv; *p; p++) {
103 zfree(p); 107 free(*p);
108 *p = NULL;
109 }
104 110
105 free(argv); 111 free(argv);
106} 112}
@@ -120,7 +126,7 @@ void argv_free(char **argv)
120char **argv_split(const char *str, int *argcp) 126char **argv_split(const char *str, int *argcp)
121{ 127{
122 int argc = count_argc(str); 128 int argc = count_argc(str);
123 char **argv = zalloc(sizeof(*argv) * (argc+1)); 129 char **argv = calloc(argc + 1, sizeof(*argv));
124 char **argvp; 130 char **argvp;
125 131
126 if (argv == NULL) 132 if (argv == NULL)
@@ -322,12 +328,8 @@ char *strxfrchar(char *s, char from, char to)
322 */ 328 */
323char *ltrim(char *s) 329char *ltrim(char *s)
324{ 330{
325 int len = strlen(s); 331 while (isspace(*s))
326
327 while (len && isspace(*s)) {
328 len--;
329 s++; 332 s++;
330 }
331 333
332 return s; 334 return s;
333} 335}
@@ -381,7 +383,7 @@ char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints
381 goto out_err_overflow; 383 goto out_err_overflow;
382 384
383 if (i > 0) 385 if (i > 0)
384 printed += snprintf(e + printed, size - printed, " %s ", or_and); 386 printed += scnprintf(e + printed, size - printed, " %s ", or_and);
385 printed += scnprintf(e + printed, size - printed, 387 printed += scnprintf(e + printed, size - printed,
386 "%s %s %d", var, eq_neq, ints[i]); 388 "%s %s %d", var, eq_neq, ints[i]);
387 } 389 }
diff --git a/tools/perf/util/string2.h b/tools/perf/util/string2.h
new file mode 100644
index 000000000000..2f619681bd6a
--- /dev/null
+++ b/tools/perf/util/string2.h
@@ -0,0 +1,42 @@
1#ifndef PERF_STRING_H
2#define PERF_STRING_H
3
4#include <linux/types.h>
5#include <stddef.h>
6#include <string.h>
7
8s64 perf_atoll(const char *str);
9char **argv_split(const char *str, int *argcp);
10void argv_free(char **argv);
11bool strglobmatch(const char *str, const char *pat);
12bool strglobmatch_nocase(const char *str, const char *pat);
13bool strlazymatch(const char *str, const char *pat);
14static inline bool strisglob(const char *str)
15{
16 return strpbrk(str, "*?[") != NULL;
17}
18int strtailcmp(const char *s1, const char *s2);
19char *strxfrchar(char *s, char from, char to);
20
21char *ltrim(char *s);
22char *rtrim(char *s);
23
24static inline char *trim(char *s)
25{
26 return ltrim(rtrim(s));
27}
28
29char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints);
30
31static inline char *asprintf_expr_in_ints(const char *var, size_t nints, int *ints)
32{
33 return asprintf_expr_inout_ints(var, true, nints, ints);
34}
35
36static inline char *asprintf_expr_not_in_ints(const char *var, size_t nints, int *ints)
37{
38 return asprintf_expr_inout_ints(var, false, nints, ints);
39}
40
41
42#endif /* PERF_STRING_H */
diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c
index 0d3dfcb919b4..9de5434bb49e 100644
--- a/tools/perf/util/strlist.c
+++ b/tools/perf/util/strlist.c
@@ -10,6 +10,7 @@
10#include <stdio.h> 10#include <stdio.h>
11#include <stdlib.h> 11#include <stdlib.h>
12#include <string.h> 12#include <string.h>
13#include <unistd.h>
13 14
14static 15static
15struct rb_node *strlist__node_new(struct rblist *rblist, const void *entry) 16struct rb_node *strlist__node_new(struct rblist *rblist, const void *entry)
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 4e59ddeb4eda..e7ee47f7377a 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -10,8 +10,9 @@
10#include "demangle-rust.h" 10#include "demangle-rust.h"
11#include "machine.h" 11#include "machine.h"
12#include "vdso.h" 12#include "vdso.h"
13#include <symbol/kallsyms.h>
14#include "debug.h" 13#include "debug.h"
14#include "sane_ctype.h"
15#include <symbol/kallsyms.h>
15 16
16#ifndef EM_AARCH64 17#ifndef EM_AARCH64
17#define EM_AARCH64 183 /* ARM 64 bit */ 18#define EM_AARCH64 183 /* ARM 64 bit */
@@ -390,6 +391,11 @@ out_elf_end:
390 return 0; 391 return 0;
391} 392}
392 393
394char *dso__demangle_sym(struct dso *dso, int kmodule, char *elf_name)
395{
396 return demangle_sym(dso, kmodule, elf_name);
397}
398
393/* 399/*
394 * Align offset to 4 bytes as needed for note name and descriptor data. 400 * Align offset to 4 bytes as needed for note name and descriptor data.
395 */ 401 */
@@ -1828,7 +1834,7 @@ void kcore_extract__delete(struct kcore_extract *kce)
1828static int populate_sdt_note(Elf **elf, const char *data, size_t len, 1834static int populate_sdt_note(Elf **elf, const char *data, size_t len,
1829 struct list_head *sdt_notes) 1835 struct list_head *sdt_notes)
1830{ 1836{
1831 const char *provider, *name; 1837 const char *provider, *name, *args;
1832 struct sdt_note *tmp = NULL; 1838 struct sdt_note *tmp = NULL;
1833 GElf_Ehdr ehdr; 1839 GElf_Ehdr ehdr;
1834 GElf_Addr base_off = 0; 1840 GElf_Addr base_off = 0;
@@ -1887,6 +1893,25 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
1887 goto out_free_prov; 1893 goto out_free_prov;
1888 } 1894 }
1889 1895
1896 args = memchr(name, '\0', data + len - name);
1897
1898 /*
1899 * There is no argument if:
1900 * - We reached the end of the note;
1901 * - There is not enough room to hold a potential string;
1902 * - The argument string is empty or just contains ':'.
1903 */
1904 if (args == NULL || data + len - args < 2 ||
1905 args[1] == ':' || args[1] == '\0')
1906 tmp->args = NULL;
1907 else {
1908 tmp->args = strdup(++args);
1909 if (!tmp->args) {
1910 ret = -ENOMEM;
1911 goto out_free_name;
1912 }
1913 }
1914
1890 if (gelf_getclass(*elf) == ELFCLASS32) { 1915 if (gelf_getclass(*elf) == ELFCLASS32) {
1891 memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr)); 1916 memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
1892 tmp->bit32 = true; 1917 tmp->bit32 = true;
@@ -1898,7 +1923,7 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
1898 if (!gelf_getehdr(*elf, &ehdr)) { 1923 if (!gelf_getehdr(*elf, &ehdr)) {
1899 pr_debug("%s : cannot get elf header.\n", __func__); 1924 pr_debug("%s : cannot get elf header.\n", __func__);
1900 ret = -EBADF; 1925 ret = -EBADF;
1901 goto out_free_name; 1926 goto out_free_args;
1902 } 1927 }
1903 1928
1904 /* Adjust the prelink effect : 1929 /* Adjust the prelink effect :
@@ -1923,6 +1948,8 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
1923 list_add_tail(&tmp->note_list, sdt_notes); 1948 list_add_tail(&tmp->note_list, sdt_notes);
1924 return 0; 1949 return 0;
1925 1950
1951out_free_args:
1952 free(tmp->args);
1926out_free_name: 1953out_free_name:
1927 free(tmp->name); 1954 free(tmp->name);
1928out_free_prov: 1955out_free_prov:
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index 11cdde980545..40bf5d4c0bfd 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -1,6 +1,7 @@
1#include "symbol.h" 1#include "symbol.h"
2#include "util.h" 2#include "util.h"
3 3
4#include <errno.h>
4#include <stdio.h> 5#include <stdio.h>
5#include <fcntl.h> 6#include <fcntl.h>
6#include <string.h> 7#include <string.h>
@@ -373,3 +374,10 @@ int kcore_copy(const char *from_dir __maybe_unused,
373void symbol__elf_init(void) 374void symbol__elf_init(void)
374{ 375{
375} 376}
377
378char *dso__demangle_sym(struct dso *dso __maybe_unused,
379 int kmodule __maybe_unused,
380 char *elf_name __maybe_unused)
381{
382 return NULL;
383}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 9b4d8ba22fed..8f2b068ff756 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -3,6 +3,7 @@
3#include <stdlib.h> 3#include <stdlib.h>
4#include <stdio.h> 4#include <stdio.h>
5#include <string.h> 5#include <string.h>
6#include <linux/kernel.h>
6#include <sys/types.h> 7#include <sys/types.h>
7#include <sys/stat.h> 8#include <sys/stat.h>
8#include <sys/param.h> 9#include <sys/param.h>
@@ -18,6 +19,8 @@
18#include "strlist.h" 19#include "strlist.h"
19#include "intlist.h" 20#include "intlist.h"
20#include "header.h" 21#include "header.h"
22#include "path.h"
23#include "sane_ctype.h"
21 24
22#include <elf.h> 25#include <elf.h>
23#include <limits.h> 26#include <limits.h>
@@ -87,6 +90,17 @@ static int prefix_underscores_count(const char *str)
87 return tail - str; 90 return tail - str;
88} 91}
89 92
93int __weak arch__compare_symbol_names(const char *namea, const char *nameb)
94{
95 return strcmp(namea, nameb);
96}
97
98int __weak arch__compare_symbol_names_n(const char *namea, const char *nameb,
99 unsigned int n)
100{
101 return strncmp(namea, nameb, n);
102}
103
90int __weak arch__choose_best_symbol(struct symbol *syma, 104int __weak arch__choose_best_symbol(struct symbol *syma,
91 struct symbol *symb __maybe_unused) 105 struct symbol *symb __maybe_unused)
92{ 106{
@@ -396,8 +410,26 @@ static void symbols__sort_by_name(struct rb_root *symbols,
396 } 410 }
397} 411}
398 412
413int symbol__match_symbol_name(const char *name, const char *str,
414 enum symbol_tag_include includes)
415{
416 const char *versioning;
417
418 if (includes == SYMBOL_TAG_INCLUDE__DEFAULT_ONLY &&
419 (versioning = strstr(name, "@@"))) {
420 int len = strlen(str);
421
422 if (len < versioning - name)
423 len = versioning - name;
424
425 return arch__compare_symbol_names_n(name, str, len);
426 } else
427 return arch__compare_symbol_names(name, str);
428}
429
399static struct symbol *symbols__find_by_name(struct rb_root *symbols, 430static struct symbol *symbols__find_by_name(struct rb_root *symbols,
400 const char *name) 431 const char *name,
432 enum symbol_tag_include includes)
401{ 433{
402 struct rb_node *n; 434 struct rb_node *n;
403 struct symbol_name_rb_node *s = NULL; 435 struct symbol_name_rb_node *s = NULL;
@@ -411,11 +443,11 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols,
411 int cmp; 443 int cmp;
412 444
413 s = rb_entry(n, struct symbol_name_rb_node, rb_node); 445 s = rb_entry(n, struct symbol_name_rb_node, rb_node);
414 cmp = arch__compare_symbol_names(name, s->sym.name); 446 cmp = symbol__match_symbol_name(s->sym.name, name, includes);
415 447
416 if (cmp < 0) 448 if (cmp > 0)
417 n = n->rb_left; 449 n = n->rb_left;
418 else if (cmp > 0) 450 else if (cmp < 0)
419 n = n->rb_right; 451 n = n->rb_right;
420 else 452 else
421 break; 453 break;
@@ -424,16 +456,17 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols,
424 if (n == NULL) 456 if (n == NULL)
425 return NULL; 457 return NULL;
426 458
427 /* return first symbol that has same name (if any) */ 459 if (includes != SYMBOL_TAG_INCLUDE__DEFAULT_ONLY)
428 for (n = rb_prev(n); n; n = rb_prev(n)) { 460 /* return first symbol that has same name (if any) */
429 struct symbol_name_rb_node *tmp; 461 for (n = rb_prev(n); n; n = rb_prev(n)) {
462 struct symbol_name_rb_node *tmp;
430 463
431 tmp = rb_entry(n, struct symbol_name_rb_node, rb_node); 464 tmp = rb_entry(n, struct symbol_name_rb_node, rb_node);
432 if (arch__compare_symbol_names(tmp->sym.name, s->sym.name)) 465 if (arch__compare_symbol_names(tmp->sym.name, s->sym.name))
433 break; 466 break;
434 467
435 s = tmp; 468 s = tmp;
436 } 469 }
437 470
438 return &s->sym; 471 return &s->sym;
439} 472}
@@ -463,7 +496,7 @@ void dso__insert_symbol(struct dso *dso, enum map_type type, struct symbol *sym)
463struct symbol *dso__find_symbol(struct dso *dso, 496struct symbol *dso__find_symbol(struct dso *dso,
464 enum map_type type, u64 addr) 497 enum map_type type, u64 addr)
465{ 498{
466 if (dso->last_find_result[type].addr != addr) { 499 if (dso->last_find_result[type].addr != addr || dso->last_find_result[type].symbol == NULL) {
467 dso->last_find_result[type].addr = addr; 500 dso->last_find_result[type].addr = addr;
468 dso->last_find_result[type].symbol = symbols__find(&dso->symbols[type], addr); 501 dso->last_find_result[type].symbol = symbols__find(&dso->symbols[type], addr);
469 } 502 }
@@ -500,7 +533,12 @@ struct symbol *symbol__next_by_name(struct symbol *sym)
500struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 533struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
501 const char *name) 534 const char *name)
502{ 535{
503 return symbols__find_by_name(&dso->symbol_names[type], name); 536 struct symbol *s = symbols__find_by_name(&dso->symbol_names[type], name,
537 SYMBOL_TAG_INCLUDE__NONE);
538 if (!s)
539 s = symbols__find_by_name(&dso->symbol_names[type], name,
540 SYMBOL_TAG_INCLUDE__DEFAULT_ONLY);
541 return s;
504} 542}
505 543
506void dso__sort_by_name(struct dso *dso, enum map_type type) 544void dso__sort_by_name(struct dso *dso, enum map_type type)
@@ -1072,8 +1110,9 @@ static int validate_kcore_addresses(const char *kallsyms_filename,
1072 if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) { 1110 if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) {
1073 u64 start; 1111 u64 start;
1074 1112
1075 start = kallsyms__get_function_start(kallsyms_filename, 1113 if (kallsyms__get_function_start(kallsyms_filename,
1076 kmap->ref_reloc_sym->name); 1114 kmap->ref_reloc_sym->name, &start))
1115 return -ENOENT;
1077 if (start != kmap->ref_reloc_sym->addr) 1116 if (start != kmap->ref_reloc_sym->addr)
1078 return -EINVAL; 1117 return -EINVAL;
1079 } 1118 }
@@ -1245,9 +1284,7 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
1245 if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name) 1284 if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name)
1246 return 0; 1285 return 0;
1247 1286
1248 addr = kallsyms__get_function_start(filename, 1287 if (kallsyms__get_function_start(filename, kmap->ref_reloc_sym->name, &addr))
1249 kmap->ref_reloc_sym->name);
1250 if (!addr)
1251 return -1; 1288 return -1;
1252 1289
1253 *delta = addr - kmap->ref_reloc_sym->addr; 1290 *delta = addr - kmap->ref_reloc_sym->addr;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 6c358b7ed336..41ebba9a2eb2 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -13,7 +13,7 @@
13#include <libgen.h> 13#include <libgen.h>
14#include "build-id.h" 14#include "build-id.h"
15#include "event.h" 15#include "event.h"
16#include "util.h" 16#include "path.h"
17 17
18#ifdef HAVE_LIBELF_SUPPORT 18#ifdef HAVE_LIBELF_SUPPORT
19#include <libelf.h> 19#include <libelf.h>
@@ -118,7 +118,8 @@ struct symbol_conf {
118 show_ref_callgraph, 118 show_ref_callgraph,
119 hide_unresolved, 119 hide_unresolved,
120 raw_trace, 120 raw_trace,
121 report_hierarchy; 121 report_hierarchy,
122 inline_name;
122 const char *vmlinux_name, 123 const char *vmlinux_name,
123 *kallsyms_name, 124 *kallsyms_name,
124 *source_prefix, 125 *source_prefix,
@@ -305,6 +306,8 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
305int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, 306int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss,
306 struct map *map); 307 struct map *map);
307 308
309char *dso__demangle_sym(struct dso *dso, int kmodule, char *elf_name);
310
308void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel); 311void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel);
309void symbols__insert(struct rb_root *symbols, struct symbol *sym); 312void symbols__insert(struct rb_root *symbols, struct symbol *sym);
310void symbols__fixup_duplicate(struct rb_root *symbols); 313void symbols__fixup_duplicate(struct rb_root *symbols);
@@ -345,12 +348,24 @@ void arch__sym_update(struct symbol *s, GElf_Sym *sym);
345#define SYMBOL_A 0 348#define SYMBOL_A 0
346#define SYMBOL_B 1 349#define SYMBOL_B 1
347 350
351int arch__compare_symbol_names(const char *namea, const char *nameb);
352int arch__compare_symbol_names_n(const char *namea, const char *nameb,
353 unsigned int n);
348int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb); 354int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
349 355
356enum symbol_tag_include {
357 SYMBOL_TAG_INCLUDE__NONE = 0,
358 SYMBOL_TAG_INCLUDE__DEFAULT_ONLY
359};
360
361int symbol__match_symbol_name(const char *namea, const char *nameb,
362 enum symbol_tag_include includes);
363
350/* structure containing an SDT note's info */ 364/* structure containing an SDT note's info */
351struct sdt_note { 365struct sdt_note {
352 char *name; /* name of the note*/ 366 char *name; /* name of the note*/
353 char *provider; /* provider name */ 367 char *provider; /* provider name */
368 char *args;
354 bool bit32; /* whether the location is 32 bits? */ 369 bool bit32; /* whether the location is 32 bits? */
355 union { /* location, base and semaphore addrs */ 370 union { /* location, base and semaphore addrs */
356 Elf64_Addr a64[3]; 371 Elf64_Addr a64[3];
diff --git a/tools/perf/util/term.c b/tools/perf/util/term.c
index 90b47d8aa19c..8f254a74d97d 100644
--- a/tools/perf/util/term.c
+++ b/tools/perf/util/term.c
@@ -1,4 +1,8 @@
1#include "util.h" 1#include "term.h"
2#include <stdlib.h>
3#include <termios.h>
4#include <unistd.h>
5#include <sys/ioctl.h>
2 6
3void get_term_dimensions(struct winsize *ws) 7void get_term_dimensions(struct winsize *ws)
4{ 8{
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
index d3301529f6a7..dd17d6a38d3a 100644
--- a/tools/perf/util/thread-stack.c
+++ b/tools/perf/util/thread-stack.c
@@ -15,6 +15,7 @@
15 15
16#include <linux/rbtree.h> 16#include <linux/rbtree.h>
17#include <linux/list.h> 17#include <linux/list.h>
18#include <errno.h>
18#include "thread.h" 19#include "thread.h"
19#include "event.h" 20#include "event.h"
20#include "machine.h" 21#include "machine.h"
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index f5af87f66663..378c418ca0c1 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -1,12 +1,15 @@
1#include "../perf.h" 1#include "../perf.h"
2#include <errno.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <stdio.h> 4#include <stdio.h>
4#include <string.h> 5#include <string.h>
6#include <linux/kernel.h>
5#include "session.h" 7#include "session.h"
6#include "thread.h" 8#include "thread.h"
7#include "thread-stack.h" 9#include "thread-stack.h"
8#include "util.h" 10#include "util.h"
9#include "debug.h" 11#include "debug.h"
12#include "namespaces.h"
10#include "comm.h" 13#include "comm.h"
11#include "unwind.h" 14#include "unwind.h"
12 15
@@ -40,6 +43,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
40 thread->tid = tid; 43 thread->tid = tid;
41 thread->ppid = -1; 44 thread->ppid = -1;
42 thread->cpu = -1; 45 thread->cpu = -1;
46 INIT_LIST_HEAD(&thread->namespaces_list);
43 INIT_LIST_HEAD(&thread->comm_list); 47 INIT_LIST_HEAD(&thread->comm_list);
44 48
45 comm_str = malloc(32); 49 comm_str = malloc(32);
@@ -53,7 +57,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
53 goto err_thread; 57 goto err_thread;
54 58
55 list_add(&comm->list, &thread->comm_list); 59 list_add(&comm->list, &thread->comm_list);
56 atomic_set(&thread->refcnt, 1); 60 refcount_set(&thread->refcnt, 1);
57 RB_CLEAR_NODE(&thread->rb_node); 61 RB_CLEAR_NODE(&thread->rb_node);
58 } 62 }
59 63
@@ -66,7 +70,8 @@ err_thread:
66 70
67void thread__delete(struct thread *thread) 71void thread__delete(struct thread *thread)
68{ 72{
69 struct comm *comm, *tmp; 73 struct namespaces *namespaces, *tmp_namespaces;
74 struct comm *comm, *tmp_comm;
70 75
71 BUG_ON(!RB_EMPTY_NODE(&thread->rb_node)); 76 BUG_ON(!RB_EMPTY_NODE(&thread->rb_node));
72 77
@@ -76,7 +81,12 @@ void thread__delete(struct thread *thread)
76 map_groups__put(thread->mg); 81 map_groups__put(thread->mg);
77 thread->mg = NULL; 82 thread->mg = NULL;
78 } 83 }
79 list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) { 84 list_for_each_entry_safe(namespaces, tmp_namespaces,
85 &thread->namespaces_list, list) {
86 list_del(&namespaces->list);
87 namespaces__free(namespaces);
88 }
89 list_for_each_entry_safe(comm, tmp_comm, &thread->comm_list, list) {
80 list_del(&comm->list); 90 list_del(&comm->list);
81 comm__free(comm); 91 comm__free(comm);
82 } 92 }
@@ -88,13 +98,13 @@ void thread__delete(struct thread *thread)
88struct thread *thread__get(struct thread *thread) 98struct thread *thread__get(struct thread *thread)
89{ 99{
90 if (thread) 100 if (thread)
91 atomic_inc(&thread->refcnt); 101 refcount_inc(&thread->refcnt);
92 return thread; 102 return thread;
93} 103}
94 104
95void thread__put(struct thread *thread) 105void thread__put(struct thread *thread)
96{ 106{
97 if (thread && atomic_dec_and_test(&thread->refcnt)) { 107 if (thread && refcount_dec_and_test(&thread->refcnt)) {
98 /* 108 /*
99 * Remove it from the dead_threads list, as last reference 109 * Remove it from the dead_threads list, as last reference
100 * is gone. 110 * is gone.
@@ -104,6 +114,38 @@ void thread__put(struct thread *thread)
104 } 114 }
105} 115}
106 116
117struct namespaces *thread__namespaces(const struct thread *thread)
118{
119 if (list_empty(&thread->namespaces_list))
120 return NULL;
121
122 return list_first_entry(&thread->namespaces_list, struct namespaces, list);
123}
124
125int thread__set_namespaces(struct thread *thread, u64 timestamp,
126 struct namespaces_event *event)
127{
128 struct namespaces *new, *curr = thread__namespaces(thread);
129
130 new = namespaces__new(event);
131 if (!new)
132 return -ENOMEM;
133
134 list_add(&new->list, &thread->namespaces_list);
135
136 if (timestamp && curr) {
137 /*
138 * setns syscall must have changed few or all the namespaces
139 * of this thread. Update end time for the namespaces
140 * previously used.
141 */
142 curr = list_next_entry(new, list);
143 curr->end_time = timestamp;
144 }
145
146 return 0;
147}
148
107struct comm *thread__comm(const struct thread *thread) 149struct comm *thread__comm(const struct thread *thread)
108{ 150{
109 if (list_empty(&thread->comm_list)) 151 if (list_empty(&thread->comm_list))
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 99263cb6e6b6..4eb849e9098f 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -1,7 +1,7 @@
1#ifndef __PERF_THREAD_H 1#ifndef __PERF_THREAD_H
2#define __PERF_THREAD_H 2#define __PERF_THREAD_H
3 3
4#include <linux/atomic.h> 4#include <linux/refcount.h>
5#include <linux/rbtree.h> 5#include <linux/rbtree.h>
6#include <linux/list.h> 6#include <linux/list.h>
7#include <unistd.h> 7#include <unistd.h>
@@ -23,11 +23,12 @@ struct thread {
23 pid_t tid; 23 pid_t tid;
24 pid_t ppid; 24 pid_t ppid;
25 int cpu; 25 int cpu;
26 atomic_t refcnt; 26 refcount_t refcnt;
27 char shortname[3]; 27 char shortname[3];
28 bool comm_set; 28 bool comm_set;
29 int comm_len; 29 int comm_len;
30 bool dead; /* if set thread has exited */ 30 bool dead; /* if set thread has exited */
31 struct list_head namespaces_list;
31 struct list_head comm_list; 32 struct list_head comm_list;
32 u64 db_id; 33 u64 db_id;
33 34
@@ -40,6 +41,7 @@ struct thread {
40}; 41};
41 42
42struct machine; 43struct machine;
44struct namespaces;
43struct comm; 45struct comm;
44 46
45struct thread *thread__new(pid_t pid, pid_t tid); 47struct thread *thread__new(pid_t pid, pid_t tid);
@@ -62,6 +64,10 @@ static inline void thread__exited(struct thread *thread)
62 thread->dead = true; 64 thread->dead = true;
63} 65}
64 66
67struct namespaces *thread__namespaces(const struct thread *thread);
68int thread__set_namespaces(struct thread *thread, u64 timestamp,
69 struct namespaces_event *event);
70
65int __thread__set_comm(struct thread *thread, const char *comm, u64 timestamp, 71int __thread__set_comm(struct thread *thread, const char *comm, u64 timestamp,
66 bool exec); 72 bool exec);
67static inline int thread__set_comm(struct thread *thread, const char *comm, 73static inline int thread__set_comm(struct thread *thread, const char *comm,
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 7c3fcc538a70..63ead7b06324 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -1,4 +1,5 @@
1#include <dirent.h> 1#include <dirent.h>
2#include <errno.h>
2#include <limits.h> 3#include <limits.h>
3#include <stdbool.h> 4#include <stdbool.h>
4#include <stdlib.h> 5#include <stdlib.h>
@@ -6,6 +7,7 @@
6#include <sys/types.h> 7#include <sys/types.h>
7#include <sys/stat.h> 8#include <sys/stat.h>
8#include <unistd.h> 9#include <unistd.h>
10#include "string2.h"
9#include "strlist.h" 11#include "strlist.h"
10#include <string.h> 12#include <string.h>
11#include <api/fs/fs.h> 13#include <api/fs/fs.h>
@@ -66,7 +68,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
66 for (i = 0; i < items; i++) 68 for (i = 0; i < items; i++)
67 thread_map__set_pid(threads, i, atoi(namelist[i]->d_name)); 69 thread_map__set_pid(threads, i, atoi(namelist[i]->d_name));
68 threads->nr = items; 70 threads->nr = items;
69 atomic_set(&threads->refcnt, 1); 71 refcount_set(&threads->refcnt, 1);
70 } 72 }
71 73
72 for (i=0; i<items; i++) 74 for (i=0; i<items; i++)
@@ -83,7 +85,7 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)
83 if (threads != NULL) { 85 if (threads != NULL) {
84 thread_map__set_pid(threads, 0, tid); 86 thread_map__set_pid(threads, 0, tid);
85 threads->nr = 1; 87 threads->nr = 1;
86 atomic_set(&threads->refcnt, 1); 88 refcount_set(&threads->refcnt, 1);
87 } 89 }
88 90
89 return threads; 91 return threads;
@@ -105,7 +107,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
105 goto out_free_threads; 107 goto out_free_threads;
106 108
107 threads->nr = 0; 109 threads->nr = 0;
108 atomic_set(&threads->refcnt, 1); 110 refcount_set(&threads->refcnt, 1);
109 111
110 while ((dirent = readdir(proc)) != NULL) { 112 while ((dirent = readdir(proc)) != NULL) {
111 char *end; 113 char *end;
@@ -235,7 +237,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
235out: 237out:
236 strlist__delete(slist); 238 strlist__delete(slist);
237 if (threads) 239 if (threads)
238 atomic_set(&threads->refcnt, 1); 240 refcount_set(&threads->refcnt, 1);
239 return threads; 241 return threads;
240 242
241out_free_namelist: 243out_free_namelist:
@@ -255,7 +257,7 @@ struct thread_map *thread_map__new_dummy(void)
255 if (threads != NULL) { 257 if (threads != NULL) {
256 thread_map__set_pid(threads, 0, -1); 258 thread_map__set_pid(threads, 0, -1);
257 threads->nr = 1; 259 threads->nr = 1;
258 atomic_set(&threads->refcnt, 1); 260 refcount_set(&threads->refcnt, 1);
259 } 261 }
260 return threads; 262 return threads;
261} 263}
@@ -300,7 +302,7 @@ struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
300 } 302 }
301out: 303out:
302 if (threads) 304 if (threads)
303 atomic_set(&threads->refcnt, 1); 305 refcount_set(&threads->refcnt, 1);
304 return threads; 306 return threads;
305 307
306out_free_threads: 308out_free_threads:
@@ -326,7 +328,7 @@ static void thread_map__delete(struct thread_map *threads)
326 if (threads) { 328 if (threads) {
327 int i; 329 int i;
328 330
329 WARN_ONCE(atomic_read(&threads->refcnt) != 0, 331 WARN_ONCE(refcount_read(&threads->refcnt) != 0,
330 "thread map refcnt unbalanced\n"); 332 "thread map refcnt unbalanced\n");
331 for (i = 0; i < threads->nr; i++) 333 for (i = 0; i < threads->nr; i++)
332 free(thread_map__comm(threads, i)); 334 free(thread_map__comm(threads, i));
@@ -337,13 +339,13 @@ static void thread_map__delete(struct thread_map *threads)
337struct thread_map *thread_map__get(struct thread_map *map) 339struct thread_map *thread_map__get(struct thread_map *map)
338{ 340{
339 if (map) 341 if (map)
340 atomic_inc(&map->refcnt); 342 refcount_inc(&map->refcnt);
341 return map; 343 return map;
342} 344}
343 345
344void thread_map__put(struct thread_map *map) 346void thread_map__put(struct thread_map *map)
345{ 347{
346 if (map && atomic_dec_and_test(&map->refcnt)) 348 if (map && refcount_dec_and_test(&map->refcnt))
347 thread_map__delete(map); 349 thread_map__delete(map);
348} 350}
349 351
@@ -423,7 +425,7 @@ static void thread_map__copy_event(struct thread_map *threads,
423 threads->map[i].comm = strndup(event->entries[i].comm, 16); 425 threads->map[i].comm = strndup(event->entries[i].comm, 16);
424 } 426 }
425 427
426 atomic_set(&threads->refcnt, 1); 428 refcount_set(&threads->refcnt, 1);
427} 429}
428 430
429struct thread_map *thread_map__new_event(struct thread_map_event *event) 431struct thread_map *thread_map__new_event(struct thread_map_event *event)
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index ea0ef08c6303..bd34d7a0b9fa 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -3,7 +3,7 @@
3 3
4#include <sys/types.h> 4#include <sys/types.h>
5#include <stdio.h> 5#include <stdio.h>
6#include <linux/atomic.h> 6#include <linux/refcount.h>
7 7
8struct thread_map_data { 8struct thread_map_data {
9 pid_t pid; 9 pid_t pid;
@@ -11,7 +11,7 @@ struct thread_map_data {
11}; 11};
12 12
13struct thread_map { 13struct thread_map {
14 atomic_t refcnt; 14 refcount_t refcnt;
15 int nr; 15 int nr;
16 struct thread_map_data map[]; 16 struct thread_map_data map[];
17}; 17};
diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c
index d1b21c72206d..5b5d0214debd 100644
--- a/tools/perf/util/time-utils.c
+++ b/tools/perf/util/time-utils.c
@@ -117,3 +117,28 @@ bool perf_time__skip_sample(struct perf_time_interval *ptime, u64 timestamp)
117 117
118 return false; 118 return false;
119} 119}
120
121int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz)
122{
123 u64 sec = timestamp / NSEC_PER_SEC;
124 u64 usec = (timestamp % NSEC_PER_SEC) / NSEC_PER_USEC;
125
126 return scnprintf(buf, sz, "%"PRIu64".%06"PRIu64, sec, usec);
127}
128
129int fetch_current_timestamp(char *buf, size_t sz)
130{
131 struct timeval tv;
132 struct tm tm;
133 char dt[32];
134
135 if (gettimeofday(&tv, NULL) || !localtime_r(&tv.tv_sec, &tm))
136 return -1;
137
138 if (!strftime(dt, sizeof(dt), "%Y%m%d%H%M%S", &tm))
139 return -1;
140
141 scnprintf(buf, sz, "%s%02u", dt, (unsigned)tv.tv_usec / 10000);
142
143 return 0;
144}
diff --git a/tools/perf/util/time-utils.h b/tools/perf/util/time-utils.h
index c1f197c4af6c..8656be08513b 100644
--- a/tools/perf/util/time-utils.h
+++ b/tools/perf/util/time-utils.h
@@ -1,6 +1,9 @@
1#ifndef _TIME_UTILS_H_ 1#ifndef _TIME_UTILS_H_
2#define _TIME_UTILS_H_ 2#define _TIME_UTILS_H_
3 3
4#include <stddef.h>
5#include <linux/types.h>
6
4struct perf_time_interval { 7struct perf_time_interval {
5 u64 start, end; 8 u64 start, end;
6}; 9};
@@ -11,4 +14,8 @@ int perf_time__parse_str(struct perf_time_interval *ptime, const char *ostr);
11 14
12bool perf_time__skip_sample(struct perf_time_interval *ptime, u64 timestamp); 15bool perf_time__skip_sample(struct perf_time_interval *ptime, u64 timestamp);
13 16
17int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz);
18
19int fetch_current_timestamp(char *buf, size_t sz);
20
14#endif 21#endif
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index ac2590a3de2d..829471a1c6d7 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -40,6 +40,7 @@ struct perf_tool {
40 event_op mmap, 40 event_op mmap,
41 mmap2, 41 mmap2,
42 comm, 42 comm,
43 namespaces,
43 fork, 44 fork,
44 exit, 45 exit,
45 lost, 46 lost,
@@ -66,6 +67,7 @@ struct perf_tool {
66 event_op3 auxtrace; 67 event_op3 auxtrace;
67 bool ordered_events; 68 bool ordered_events;
68 bool ordering_requires_timestamps; 69 bool ordering_requires_timestamps;
70 bool namespace_events;
69}; 71};
70 72
71#endif /* __PERF_TOOL_H */ 73#endif /* __PERF_TOOL_H */
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index b2940c88734a..9bdfb78a9a35 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -5,7 +5,7 @@
5#include <linux/types.h> 5#include <linux/types.h>
6#include <stddef.h> 6#include <stddef.h>
7#include <stdbool.h> 7#include <stdbool.h>
8#include <termios.h> 8#include <sys/ioctl.h>
9 9
10struct perf_evlist; 10struct perf_evlist;
11struct perf_evsel; 11struct perf_evsel;
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index de0078e21408..746bbee645d9 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -21,13 +21,14 @@
21#include <stdio.h> 21#include <stdio.h>
22#include <stdlib.h> 22#include <stdlib.h>
23#include <string.h> 23#include <string.h>
24#include <ctype.h>
25#include <errno.h> 24#include <errno.h>
26 25
27#include "../perf.h" 26#include "../perf.h"
28#include "util.h" 27#include "util.h"
29#include "trace-event.h" 28#include "trace-event.h"
30 29
30#include "sane_ctype.h"
31
31static int get_common_field(struct scripting_context *context, 32static int get_common_field(struct scripting_context *context,
32 int *offset, int *size, const char *type) 33 int *offset, int *size, const char *type)
33{ 34{
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 27420159bf69..8a9a677f7576 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -192,7 +192,7 @@ static int read_ftrace_printk(struct pevent *pevent)
192 if (!size) 192 if (!size)
193 return 0; 193 return 0;
194 194
195 buf = malloc(size); 195 buf = malloc(size + 1);
196 if (buf == NULL) 196 if (buf == NULL)
197 return -1; 197 return -1;
198 198
@@ -201,6 +201,8 @@ static int read_ftrace_printk(struct pevent *pevent)
201 return -1; 201 return -1;
202 } 202 }
203 203
204 buf[size] = '\0';
205
204 parse_ftrace_printk(pevent, buf, size); 206 parse_ftrace_printk(pevent, buf, size);
205 207
206 free(buf); 208 free(buf);
diff --git a/tools/perf/util/units.c b/tools/perf/util/units.c
new file mode 100644
index 000000000000..4767ec2c5ef6
--- /dev/null
+++ b/tools/perf/util/units.c
@@ -0,0 +1,68 @@
1#include "units.h"
2#include <inttypes.h>
3#include <limits.h>
4#include <stdlib.h>
5#include <string.h>
6#include <linux/kernel.h>
7#include <linux/time64.h>
8
9unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
10{
11 struct parse_tag *i = tags;
12
13 while (i->tag) {
14 char *s = strchr(str, i->tag);
15
16 if (s) {
17 unsigned long int value;
18 char *endptr;
19
20 value = strtoul(str, &endptr, 10);
21 if (s != endptr)
22 break;
23
24 if (value > ULONG_MAX / i->mult)
25 break;
26 value *= i->mult;
27 return value;
28 }
29 i++;
30 }
31
32 return (unsigned long) -1;
33}
34
35unsigned long convert_unit(unsigned long value, char *unit)
36{
37 *unit = ' ';
38
39 if (value > 1000) {
40 value /= 1000;
41 *unit = 'K';
42 }
43
44 if (value > 1000) {
45 value /= 1000;
46 *unit = 'M';
47 }
48
49 if (value > 1000) {
50 value /= 1000;
51 *unit = 'G';
52 }
53
54 return value;
55}
56
57int unit_number__scnprintf(char *buf, size_t size, u64 n)
58{
59 char unit[4] = "BKMG";
60 int i = 0;
61
62 while (((n / 1024) > 1) && (i < 3)) {
63 n /= 1024;
64 i++;
65 }
66
67 return scnprintf(buf, size, "%" PRIu64 "%c", n, unit[i]);
68}
diff --git a/tools/perf/util/units.h b/tools/perf/util/units.h
new file mode 100644
index 000000000000..f02c87317150
--- /dev/null
+++ b/tools/perf/util/units.h
@@ -0,0 +1,17 @@
1#ifndef PERF_UNIT_H
2#define PERF_UNIT_H
3
4#include <stddef.h>
5#include <linux/types.h>
6
7struct parse_tag {
8 char tag;
9 int mult;
10};
11
12unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
13
14unsigned long convert_unit(unsigned long value, char *unit);
15int unit_number__scnprintf(char *buf, size_t size, u64 n);
16
17#endif /* PERF_UNIT_H */
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index 783a53fb7a4e..f90e11a555b2 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -12,6 +12,7 @@
12#include "event.h" 12#include "event.h"
13#include "perf_regs.h" 13#include "perf_regs.h"
14#include "callchain.h" 14#include "callchain.h"
15#include "util.h"
15 16
16static char *debuginfo_path; 17static char *debuginfo_path;
17 18
diff --git a/tools/perf/util/unwind-libdw.h b/tools/perf/util/unwind-libdw.h
index 58328669ed16..4a2b269a7b3b 100644
--- a/tools/perf/util/unwind-libdw.h
+++ b/tools/perf/util/unwind-libdw.h
@@ -2,10 +2,12 @@
2#define __PERF_UNWIND_LIBDW_H 2#define __PERF_UNWIND_LIBDW_H
3 3
4#include <elfutils/libdwfl.h> 4#include <elfutils/libdwfl.h>
5#include "event.h"
6#include "thread.h"
7#include "unwind.h" 5#include "unwind.h"
8 6
7struct machine;
8struct perf_sample;
9struct thread;
10
9bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg); 11bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg);
10 12
11struct unwind_info { 13struct unwind_info {
diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
index bfb9b7987692..f8455bed6e65 100644
--- a/tools/perf/util/unwind-libunwind-local.c
+++ b/tools/perf/util/unwind-libunwind-local.c
@@ -16,8 +16,10 @@
16 */ 16 */
17 17
18#include <elf.h> 18#include <elf.h>
19#include <errno.h>
19#include <gelf.h> 20#include <gelf.h>
20#include <fcntl.h> 21#include <fcntl.h>
22#include <inttypes.h>
21#include <string.h> 23#include <string.h>
22#include <unistd.h> 24#include <unistd.h>
23#include <sys/mman.h> 25#include <sys/mman.h>
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index 61fb1e90ff51..bfbdcc6198c9 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -1,10 +1,13 @@
1#ifndef __UNWIND_H 1#ifndef __UNWIND_H
2#define __UNWIND_H 2#define __UNWIND_H
3 3
4#include <linux/compiler.h>
4#include <linux/types.h> 5#include <linux/types.h>
5#include "event.h" 6
6#include "symbol.h" 7struct map;
7#include "thread.h" 8struct perf_sample;
9struct symbol;
10struct thread;
8 11
9struct unwind_entry { 12struct unwind_entry {
10 struct map *map; 13 struct map *map;
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index d8b45cea54d0..28c9f335006c 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -3,38 +3,22 @@
3#include "debug.h" 3#include "debug.h"
4#include <api/fs/fs.h> 4#include <api/fs/fs.h>
5#include <sys/mman.h> 5#include <sys/mman.h>
6#include <sys/stat.h>
6#include <sys/utsname.h> 7#include <sys/utsname.h>
7#ifdef HAVE_BACKTRACE_SUPPORT 8#include <dirent.h>
8#include <execinfo.h> 9#include <inttypes.h>
9#endif 10#include <signal.h>
10#include <stdio.h> 11#include <stdio.h>
11#include <stdlib.h> 12#include <stdlib.h>
12#include <string.h> 13#include <string.h>
13#include <errno.h> 14#include <errno.h>
14#include <limits.h> 15#include <limits.h>
15#include <byteswap.h>
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/log2.h> 17#include <linux/log2.h>
18#include <linux/time64.h> 18#include <linux/time64.h>
19#include <unistd.h> 19#include <unistd.h>
20#include "callchain.h"
21#include "strlist.h" 20#include "strlist.h"
22 21
23#define CALLCHAIN_PARAM_DEFAULT \
24 .mode = CHAIN_GRAPH_ABS, \
25 .min_percent = 0.5, \
26 .order = ORDER_CALLEE, \
27 .key = CCKEY_FUNCTION, \
28 .value = CCVAL_PERCENT, \
29
30struct callchain_param callchain_param = {
31 CALLCHAIN_PARAM_DEFAULT
32};
33
34struct callchain_param callchain_param_default = {
35 CALLCHAIN_PARAM_DEFAULT
36};
37
38/* 22/*
39 * XXX We need to find a better place for these things... 23 * XXX We need to find a better place for these things...
40 */ 24 */
@@ -269,28 +253,6 @@ int copyfile(const char *from, const char *to)
269 return copyfile_mode(from, to, 0755); 253 return copyfile_mode(from, to, 0755);
270} 254}
271 255
272unsigned long convert_unit(unsigned long value, char *unit)
273{
274 *unit = ' ';
275
276 if (value > 1000) {
277 value /= 1000;
278 *unit = 'K';
279 }
280
281 if (value > 1000) {
282 value /= 1000;
283 *unit = 'M';
284 }
285
286 if (value > 1000) {
287 value /= 1000;
288 *unit = 'G';
289 }
290
291 return value;
292}
293
294static ssize_t ion(bool is_read, int fd, void *buf, size_t n) 256static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
295{ 257{
296 void *buf_start = buf; 258 void *buf_start = buf;
@@ -372,171 +334,6 @@ int hex2u64(const char *ptr, u64 *long_val)
372 return p - ptr; 334 return p - ptr;
373} 335}
374 336
375/* Obtain a backtrace and print it to stdout. */
376#ifdef HAVE_BACKTRACE_SUPPORT
377void dump_stack(void)
378{
379 void *array[16];
380 size_t size = backtrace(array, ARRAY_SIZE(array));
381 char **strings = backtrace_symbols(array, size);
382 size_t i;
383
384 printf("Obtained %zd stack frames.\n", size);
385
386 for (i = 0; i < size; i++)
387 printf("%s\n", strings[i]);
388
389 free(strings);
390}
391#else
392void dump_stack(void) {}
393#endif
394
395void sighandler_dump_stack(int sig)
396{
397 psignal(sig, "perf");
398 dump_stack();
399 signal(sig, SIG_DFL);
400 raise(sig);
401}
402
403int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz)
404{
405 u64 sec = timestamp / NSEC_PER_SEC;
406 u64 usec = (timestamp % NSEC_PER_SEC) / NSEC_PER_USEC;
407
408 return scnprintf(buf, sz, "%"PRIu64".%06"PRIu64, sec, usec);
409}
410
411unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
412{
413 struct parse_tag *i = tags;
414
415 while (i->tag) {
416 char *s;
417
418 s = strchr(str, i->tag);
419 if (s) {
420 unsigned long int value;
421 char *endptr;
422
423 value = strtoul(str, &endptr, 10);
424 if (s != endptr)
425 break;
426
427 if (value > ULONG_MAX / i->mult)
428 break;
429 value *= i->mult;
430 return value;
431 }
432 i++;
433 }
434
435 return (unsigned long) -1;
436}
437
438int get_stack_size(const char *str, unsigned long *_size)
439{
440 char *endptr;
441 unsigned long size;
442 unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
443
444 size = strtoul(str, &endptr, 0);
445
446 do {
447 if (*endptr)
448 break;
449
450 size = round_up(size, sizeof(u64));
451 if (!size || size > max_size)
452 break;
453
454 *_size = size;
455 return 0;
456
457 } while (0);
458
459 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
460 max_size, str);
461 return -1;
462}
463
464int parse_callchain_record(const char *arg, struct callchain_param *param)
465{
466 char *tok, *name, *saveptr = NULL;
467 char *buf;
468 int ret = -1;
469
470 /* We need buffer that we know we can write to. */
471 buf = malloc(strlen(arg) + 1);
472 if (!buf)
473 return -ENOMEM;
474
475 strcpy(buf, arg);
476
477 tok = strtok_r((char *)buf, ",", &saveptr);
478 name = tok ? : (char *)buf;
479
480 do {
481 /* Framepointer style */
482 if (!strncmp(name, "fp", sizeof("fp"))) {
483 if (!strtok_r(NULL, ",", &saveptr)) {
484 param->record_mode = CALLCHAIN_FP;
485 ret = 0;
486 } else
487 pr_err("callchain: No more arguments "
488 "needed for --call-graph fp\n");
489 break;
490
491 /* Dwarf style */
492 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
493 const unsigned long default_stack_dump_size = 8192;
494
495 ret = 0;
496 param->record_mode = CALLCHAIN_DWARF;
497 param->dump_size = default_stack_dump_size;
498
499 tok = strtok_r(NULL, ",", &saveptr);
500 if (tok) {
501 unsigned long size = 0;
502
503 ret = get_stack_size(tok, &size);
504 param->dump_size = size;
505 }
506 } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
507 if (!strtok_r(NULL, ",", &saveptr)) {
508 param->record_mode = CALLCHAIN_LBR;
509 ret = 0;
510 } else
511 pr_err("callchain: No more arguments "
512 "needed for --call-graph lbr\n");
513 break;
514 } else {
515 pr_err("callchain: Unknown --call-graph option "
516 "value: %s\n", arg);
517 break;
518 }
519
520 } while (0);
521
522 free(buf);
523 return ret;
524}
525
526const char *get_filename_for_perf_kvm(void)
527{
528 const char *filename;
529
530 if (perf_host && !perf_guest)
531 filename = strdup("perf.data.host");
532 else if (!perf_host && perf_guest)
533 filename = strdup("perf.data.guest");
534 else
535 filename = strdup("perf.data.kvm");
536
537 return filename;
538}
539
540int perf_event_paranoid(void) 337int perf_event_paranoid(void)
541{ 338{
542 int value; 339 int value;
@@ -547,27 +344,6 @@ int perf_event_paranoid(void)
547 return value; 344 return value;
548} 345}
549 346
550void mem_bswap_32(void *src, int byte_size)
551{
552 u32 *m = src;
553 while (byte_size > 0) {
554 *m = bswap_32(*m);
555 byte_size -= sizeof(u32);
556 ++m;
557 }
558}
559
560void mem_bswap_64(void *src, int byte_size)
561{
562 u64 *m = src;
563
564 while (byte_size > 0) {
565 *m = bswap_64(*m);
566 byte_size -= sizeof(u64);
567 ++m;
568 }
569}
570
571bool find_process(const char *name) 347bool find_process(const char *name)
572{ 348{
573 size_t len = strlen(name); 349 size_t len = strlen(name);
@@ -696,7 +472,8 @@ const char *perf_tip(const char *dirpath)
696 472
697 tips = strlist__new("tips.txt", &conf); 473 tips = strlist__new("tips.txt", &conf);
698 if (tips == NULL) 474 if (tips == NULL)
699 return errno == ENOENT ? NULL : "Tip: get more memory! ;-p"; 475 return errno == ENOENT ? NULL :
476 "Tip: check path of tips.txt or get more memory! ;-p";
700 477
701 if (strlist__nr_entries(tips) == 0) 478 if (strlist__nr_entries(tips) == 0)
702 goto out; 479 goto out;
@@ -710,95 +487,3 @@ out:
710 487
711 return tip; 488 return tip;
712} 489}
713
714bool is_regular_file(const char *file)
715{
716 struct stat st;
717
718 if (stat(file, &st))
719 return false;
720
721 return S_ISREG(st.st_mode);
722}
723
724int fetch_current_timestamp(char *buf, size_t sz)
725{
726 struct timeval tv;
727 struct tm tm;
728 char dt[32];
729
730 if (gettimeofday(&tv, NULL) || !localtime_r(&tv.tv_sec, &tm))
731 return -1;
732
733 if (!strftime(dt, sizeof(dt), "%Y%m%d%H%M%S", &tm))
734 return -1;
735
736 scnprintf(buf, sz, "%s%02u", dt, (unsigned)tv.tv_usec / 10000);
737
738 return 0;
739}
740
741void print_binary(unsigned char *data, size_t len,
742 size_t bytes_per_line, print_binary_t printer,
743 void *extra)
744{
745 size_t i, j, mask;
746
747 if (!printer)
748 return;
749
750 bytes_per_line = roundup_pow_of_two(bytes_per_line);
751 mask = bytes_per_line - 1;
752
753 printer(BINARY_PRINT_DATA_BEGIN, 0, extra);
754 for (i = 0; i < len; i++) {
755 if ((i & mask) == 0) {
756 printer(BINARY_PRINT_LINE_BEGIN, -1, extra);
757 printer(BINARY_PRINT_ADDR, i, extra);
758 }
759
760 printer(BINARY_PRINT_NUM_DATA, data[i], extra);
761
762 if (((i & mask) == mask) || i == len - 1) {
763 for (j = 0; j < mask-(i & mask); j++)
764 printer(BINARY_PRINT_NUM_PAD, -1, extra);
765
766 printer(BINARY_PRINT_SEP, i, extra);
767 for (j = i & ~mask; j <= i; j++)
768 printer(BINARY_PRINT_CHAR_DATA, data[j], extra);
769 for (j = 0; j < mask-(i & mask); j++)
770 printer(BINARY_PRINT_CHAR_PAD, i, extra);
771 printer(BINARY_PRINT_LINE_END, -1, extra);
772 }
773 }
774 printer(BINARY_PRINT_DATA_END, -1, extra);
775}
776
777int is_printable_array(char *p, unsigned int len)
778{
779 unsigned int i;
780
781 if (!p || !len || p[len - 1] != 0)
782 return 0;
783
784 len--;
785
786 for (i = 0; i < len; i++) {
787 if (!isprint(p[i]) && !isspace(p[i]))
788 return 0;
789 }
790 return 1;
791}
792
793int unit_number__scnprintf(char *buf, size_t size, u64 n)
794{
795 char unit[4] = "BKMG";
796 int i = 0;
797
798 while (((n / 1024) > 1) && (i < 3)) {
799 n /= 1024;
800 i++;
801 }
802
803 return scnprintf(buf, size, "%" PRIu64 "%c", n, unit[i]);
804}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index c74708da8571..5dfb9bb6482d 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -1,125 +1,17 @@
1#ifndef GIT_COMPAT_UTIL_H 1#ifndef GIT_COMPAT_UTIL_H
2#define GIT_COMPAT_UTIL_H 2#define GIT_COMPAT_UTIL_H
3 3
4#ifndef FLEX_ARRAY
5/*
6 * See if our compiler is known to support flexible array members.
7 */
8#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
9# define FLEX_ARRAY /* empty */
10#elif defined(__GNUC__)
11# if (__GNUC__ >= 3)
12# define FLEX_ARRAY /* empty */
13# else
14# define FLEX_ARRAY 0 /* older GNU extension */
15# endif
16#endif
17
18/*
19 * Otherwise, default to safer but a bit wasteful traditional style
20 */
21#ifndef FLEX_ARRAY
22# define FLEX_ARRAY 1
23#endif
24#endif
25
26#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
27
28#ifdef __GNUC__
29#define TYPEOF(x) (__typeof__(x))
30#else
31#define TYPEOF(x)
32#endif
33
34#define MSB(x, bits) ((x) & TYPEOF(x)(~0ULL << (sizeof(x) * 8 - (bits))))
35#define HAS_MULTI_BITS(i) ((i) & ((i) - 1)) /* checks if an integer has more than 1 bit set */
36
37/* Approximation of the length of the decimal representation of this type. */
38#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
39
40#define _ALL_SOURCE 1 4#define _ALL_SOURCE 1
41#define _BSD_SOURCE 1 5#define _BSD_SOURCE 1
42/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */ 6/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */
43#define _DEFAULT_SOURCE 1 7#define _DEFAULT_SOURCE 1
44#define HAS_BOOL
45 8
46#include <unistd.h>
47#include <stdio.h>
48#include <sys/stat.h>
49#include <sys/statfs.h>
50#include <fcntl.h> 9#include <fcntl.h>
51#include <stdbool.h> 10#include <stdbool.h>
52#include <stddef.h> 11#include <stddef.h>
53#include <stdlib.h> 12#include <stdlib.h>
54#include <stdarg.h> 13#include <stdarg.h>
55#include <string.h>
56#include <term.h>
57#include <errno.h>
58#include <limits.h>
59#include <sys/param.h>
60#include <sys/types.h>
61#include <dirent.h>
62#include <sys/time.h>
63#include <time.h>
64#include <signal.h>
65#include <fnmatch.h>
66#include <assert.h>
67#include <regex.h>
68#include <utime.h>
69#include <sys/wait.h>
70#include <poll.h>
71#include <sys/socket.h>
72#include <sys/ioctl.h>
73#include <inttypes.h>
74#include <linux/kernel.h>
75#include <linux/types.h> 14#include <linux/types.h>
76#include <sys/ttydefaults.h>
77#include <api/fs/tracing_path.h>
78#include <termios.h>
79#include <linux/bitops.h>
80#include <termios.h>
81#include "strlist.h"
82
83extern const char *graph_line;
84extern const char *graph_dotted_line;
85extern const char *spaces;
86extern const char *dots;
87extern char buildid_dir[];
88
89/* On most systems <limits.h> would have given us this, but
90 * not on some systems (e.g. GNU/Hurd).
91 */
92#ifndef PATH_MAX
93#define PATH_MAX 4096
94#endif
95
96#ifndef PRIuMAX
97#define PRIuMAX "llu"
98#endif
99
100#ifndef PRIu32
101#define PRIu32 "u"
102#endif
103
104#ifndef PRIx32
105#define PRIx32 "x"
106#endif
107
108#ifndef PATH_SEP
109#define PATH_SEP ':'
110#endif
111
112#ifndef STRIP_EXTENSION
113#define STRIP_EXTENSION ""
114#endif
115
116#ifndef has_dos_drive_prefix
117#define has_dos_drive_prefix(path) 0
118#endif
119
120#ifndef is_dir_sep
121#define is_dir_sep(c) ((c) == '/')
122#endif
123 15
124#ifdef __GNUC__ 16#ifdef __GNUC__
125#define NORETURN __attribute__((__noreturn__)) 17#define NORETURN __attribute__((__noreturn__))
@@ -130,8 +22,6 @@ extern char buildid_dir[];
130#endif 22#endif
131#endif 23#endif
132 24
133#define PERF_GTK_DSO "libperf-gtk.so"
134
135/* General helper functions */ 25/* General helper functions */
136void usage(const char *err) NORETURN; 26void usage(const char *err) NORETURN;
137void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2))); 27void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
@@ -140,25 +30,6 @@ void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
140 30
141void set_warning_routine(void (*routine)(const char *err, va_list params)); 31void set_warning_routine(void (*routine)(const char *err, va_list params));
142 32
143int prefixcmp(const char *str, const char *prefix);
144void set_buildid_dir(const char *dir);
145
146#ifdef __GLIBC_PREREQ
147#if __GLIBC_PREREQ(2, 1)
148#define HAVE_STRCHRNUL
149#endif
150#endif
151
152#ifndef HAVE_STRCHRNUL
153#define strchrnul gitstrchrnul
154static inline char *gitstrchrnul(const char *s, int c)
155{
156 while (*s && *s != c)
157 s++;
158 return (char *)s;
159}
160#endif
161
162static inline void *zalloc(size_t size) 33static inline void *zalloc(size_t size)
163{ 34{
164 return calloc(1, size); 35 return calloc(1, size);
@@ -166,47 +37,8 @@ static inline void *zalloc(size_t size)
166 37
167#define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) 38#define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
168 39
169/* Sane ctype - no locale, and works with signed chars */ 40struct dirent;
170#undef isascii 41struct strlist;
171#undef isspace
172#undef isdigit
173#undef isxdigit
174#undef isalpha
175#undef isprint
176#undef isalnum
177#undef islower
178#undef isupper
179#undef tolower
180#undef toupper
181
182extern unsigned char sane_ctype[256];
183#define GIT_SPACE 0x01
184#define GIT_DIGIT 0x02
185#define GIT_ALPHA 0x04
186#define GIT_GLOB_SPECIAL 0x08
187#define GIT_REGEX_SPECIAL 0x10
188#define GIT_PRINT_EXTRA 0x20
189#define GIT_PRINT 0x3E
190#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
191#define isascii(x) (((x) & ~0x7f) == 0)
192#define isspace(x) sane_istest(x,GIT_SPACE)
193#define isdigit(x) sane_istest(x,GIT_DIGIT)
194#define isxdigit(x) \
195 (sane_istest(toupper(x), GIT_ALPHA | GIT_DIGIT) && toupper(x) < 'G')
196#define isalpha(x) sane_istest(x,GIT_ALPHA)
197#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
198#define isprint(x) sane_istest(x,GIT_PRINT)
199#define islower(x) (sane_istest(x,GIT_ALPHA) && (x & 0x20))
200#define isupper(x) (sane_istest(x,GIT_ALPHA) && !(x & 0x20))
201#define tolower(x) sane_case((unsigned char)(x), 0x20)
202#define toupper(x) sane_case((unsigned char)(x), 0)
203
204static inline int sane_case(int x, int high)
205{
206 if (sane_istest(x, GIT_ALPHA))
207 x = (x & ~0x20) | high;
208 return x;
209}
210 42
211int mkdir_p(char *path, mode_t mode); 43int mkdir_p(char *path, mode_t mode);
212int rm_rf(const char *path); 44int rm_rf(const char *path);
@@ -216,112 +48,17 @@ int copyfile(const char *from, const char *to);
216int copyfile_mode(const char *from, const char *to, mode_t mode); 48int copyfile_mode(const char *from, const char *to, mode_t mode);
217int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size); 49int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size);
218 50
219s64 perf_atoll(const char *str);
220char **argv_split(const char *str, int *argcp);
221void argv_free(char **argv);
222bool strglobmatch(const char *str, const char *pat);
223bool strglobmatch_nocase(const char *str, const char *pat);
224bool strlazymatch(const char *str, const char *pat);
225static inline bool strisglob(const char *str)
226{
227 return strpbrk(str, "*?[") != NULL;
228}
229int strtailcmp(const char *s1, const char *s2);
230char *strxfrchar(char *s, char from, char to);
231unsigned long convert_unit(unsigned long value, char *unit);
232ssize_t readn(int fd, void *buf, size_t n); 51ssize_t readn(int fd, void *buf, size_t n);
233ssize_t writen(int fd, void *buf, size_t n); 52ssize_t writen(int fd, void *buf, size_t n);
234 53
235struct perf_event_attr;
236
237void event_attr_init(struct perf_event_attr *attr);
238
239#define _STR(x) #x
240#define STR(x) _STR(x)
241
242size_t hex_width(u64 v); 54size_t hex_width(u64 v);
243int hex2u64(const char *ptr, u64 *val); 55int hex2u64(const char *ptr, u64 *val);
244 56
245char *ltrim(char *s);
246char *rtrim(char *s);
247
248static inline char *trim(char *s)
249{
250 return ltrim(rtrim(s));
251}
252
253void dump_stack(void);
254void sighandler_dump_stack(int sig);
255
256extern unsigned int page_size; 57extern unsigned int page_size;
257extern int cacheline_size; 58extern int cacheline_size;
258extern int sysctl_perf_event_max_stack;
259extern int sysctl_perf_event_max_contexts_per_stack;
260
261struct parse_tag {
262 char tag;
263 int mult;
264};
265
266unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
267
268#define SRCLINE_UNKNOWN ((char *) "??:0")
269
270static inline int path__join(char *bf, size_t size,
271 const char *path1, const char *path2)
272{
273 return scnprintf(bf, size, "%s%s%s", path1, path1[0] ? "/" : "", path2);
274}
275
276static inline int path__join3(char *bf, size_t size,
277 const char *path1, const char *path2,
278 const char *path3)
279{
280 return scnprintf(bf, size, "%s%s%s%s%s",
281 path1, path1[0] ? "/" : "",
282 path2, path2[0] ? "/" : "", path3);
283}
284
285struct dso;
286struct symbol;
287 59
288extern bool srcline_full_filename;
289char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
290 bool show_sym);
291char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
292 bool show_sym, bool unwind_inlines);
293void free_srcline(char *srcline);
294
295int perf_event_paranoid(void);
296
297void mem_bswap_64(void *src, int byte_size);
298void mem_bswap_32(void *src, int byte_size);
299
300const char *get_filename_for_perf_kvm(void);
301bool find_process(const char *name); 60bool find_process(const char *name);
302 61
303#ifdef HAVE_ZLIB_SUPPORT
304int gzip_decompress_to_file(const char *input, int output_fd);
305#endif
306
307#ifdef HAVE_LZMA_SUPPORT
308int lzma_decompress_to_file(const char *input, int output_fd);
309#endif
310
311char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints);
312
313static inline char *asprintf_expr_in_ints(const char *var, size_t nints, int *ints)
314{
315 return asprintf_expr_inout_ints(var, true, nints, ints);
316}
317
318static inline char *asprintf_expr_not_in_ints(const char *var, size_t nints, int *ints)
319{
320 return asprintf_expr_inout_ints(var, false, nints, ints);
321}
322
323int get_stack_size(const char *str, unsigned long *_size);
324
325int fetch_kernel_version(unsigned int *puint, 62int fetch_kernel_version(unsigned int *puint,
326 char *str, size_t str_sz); 63 char *str, size_t str_sz);
327#define KVER_VERSION(x) (((x) >> 16) & 0xff) 64#define KVER_VERSION(x) (((x) >> 16) & 0xff)
@@ -331,37 +68,9 @@ int fetch_kernel_version(unsigned int *puint,
331#define KVER_PARAM(x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x) 68#define KVER_PARAM(x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x)
332 69
333const char *perf_tip(const char *dirpath); 70const char *perf_tip(const char *dirpath);
334bool is_regular_file(const char *file);
335int fetch_current_timestamp(char *buf, size_t sz);
336 71
337enum binary_printer_ops { 72#ifndef HAVE_SCHED_GETCPU_SUPPORT
338 BINARY_PRINT_DATA_BEGIN, 73int sched_getcpu(void);
339 BINARY_PRINT_LINE_BEGIN,
340 BINARY_PRINT_ADDR,
341 BINARY_PRINT_NUM_DATA,
342 BINARY_PRINT_NUM_PAD,
343 BINARY_PRINT_SEP,
344 BINARY_PRINT_CHAR_DATA,
345 BINARY_PRINT_CHAR_PAD,
346 BINARY_PRINT_LINE_END,
347 BINARY_PRINT_DATA_END,
348};
349
350typedef void (*print_binary_t)(enum binary_printer_ops,
351 unsigned int val,
352 void *extra);
353
354void print_binary(unsigned char *data, size_t len,
355 size_t bytes_per_line, print_binary_t printer,
356 void *extra);
357
358#if !defined(__GLIBC__) && !defined(__ANDROID__)
359extern int sched_getcpu(void);
360#endif 74#endif
361 75
362int is_printable_array(char *p, unsigned int len);
363
364int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz);
365
366int unit_number__scnprintf(char *buf, size_t size, u64 n);
367#endif /* GIT_COMPAT_UTIL_H */ 76#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c
index 5074be4ed467..5de2e15e2eda 100644
--- a/tools/perf/util/values.c
+++ b/tools/perf/util/values.c
@@ -1,4 +1,7 @@
1#include <inttypes.h>
2#include <stdio.h>
1#include <stdlib.h> 3#include <stdlib.h>
4#include <errno.h>
2 5
3#include "util.h" 6#include "util.h"
4#include "values.h" 7#include "values.h"
@@ -108,24 +111,45 @@ static int perf_read_values__findnew_thread(struct perf_read_values *values,
108 return i; 111 return i;
109} 112}
110 113
111static void perf_read_values__enlarge_counters(struct perf_read_values *values) 114static int perf_read_values__enlarge_counters(struct perf_read_values *values)
112{ 115{
113 int i; 116 char **countername;
117 int i, counters_max = values->counters_max * 2;
118 u64 *counterrawid = realloc(values->counterrawid, counters_max * sizeof(*values->counterrawid));
119
120 if (!counterrawid) {
121 pr_debug("failed to enlarge read_values rawid array");
122 goto out_enomem;
123 }
114 124
115 values->counters_max *= 2; 125 countername = realloc(values->countername, counters_max * sizeof(*values->countername));
116 values->counterrawid = realloc(values->counterrawid, 126 if (!countername) {
117 values->counters_max * sizeof(*values->counterrawid)); 127 pr_debug("failed to enlarge read_values rawid array");
118 values->countername = realloc(values->countername, 128 goto out_free_rawid;
119 values->counters_max * sizeof(*values->countername)); 129 }
120 if (!values->counterrawid || !values->countername)
121 die("failed to enlarge read_values counters arrays");
122 130
123 for (i = 0; i < values->threads; i++) { 131 for (i = 0; i < values->threads; i++) {
124 values->value[i] = realloc(values->value[i], 132 u64 *value = realloc(values->value[i], counters_max * sizeof(**values->value));
125 values->counters_max * sizeof(**values->value)); 133
126 if (!values->value[i]) 134 if (value) {
127 die("failed to enlarge read_values counters arrays"); 135 pr_debug("failed to enlarge read_values ->values array");
136 goto out_free_name;
137 }
138
139 values->value[i] = value;
128 } 140 }
141
142 values->counters_max = counters_max;
143 values->counterrawid = counterrawid;
144 values->countername = countername;
145
146 return 0;
147out_free_name:
148 free(countername);
149out_free_rawid:
150 free(counterrawid);
151out_enomem:
152 return -ENOMEM;
129} 153}
130 154
131static int perf_read_values__findnew_counter(struct perf_read_values *values, 155static int perf_read_values__findnew_counter(struct perf_read_values *values,
@@ -137,8 +161,11 @@ static int perf_read_values__findnew_counter(struct perf_read_values *values,
137 if (values->counterrawid[i] == rawid) 161 if (values->counterrawid[i] == rawid)
138 return i; 162 return i;
139 163
140 if (values->counters == values->counters_max) 164 if (values->counters == values->counters_max) {
141 perf_read_values__enlarge_counters(values); 165 i = perf_read_values__enlarge_counters(values);
166 if (i)
167 return i;
168 }
142 169
143 i = values->counters++; 170 i = values->counters++;
144 values->counterrawid[i] = rawid; 171 values->counterrawid[i] = rawid;
@@ -172,8 +199,10 @@ static void perf_read_values__display_pretty(FILE *fp,
172 int *counterwidth; 199 int *counterwidth;
173 200
174 counterwidth = malloc(values->counters * sizeof(*counterwidth)); 201 counterwidth = malloc(values->counters * sizeof(*counterwidth));
175 if (!counterwidth) 202 if (!counterwidth) {
176 die("failed to allocate counterwidth array"); 203 fprintf(fp, "INTERNAL ERROR: Failed to allocate counterwidth array\n");
204 return;
205 }
177 tidwidth = 3; 206 tidwidth = 3;
178 pidwidth = 3; 207 pidwidth = 3;
179 for (j = 0; j < values->counters; j++) 208 for (j = 0; j < values->counters; j++)
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c
index 7bdcad484225..d3c39eec89a8 100644
--- a/tools/perf/util/vdso.c
+++ b/tools/perf/util/vdso.c
@@ -1,4 +1,4 @@
1 1#include <errno.h>
2#include <unistd.h> 2#include <unistd.h>
3#include <stdio.h> 3#include <stdio.h>
4#include <string.h> 4#include <string.h>
diff --git a/tools/perf/util/xyarray.c b/tools/perf/util/xyarray.c
index c10ba41ef3f6..7251fdbabced 100644
--- a/tools/perf/util/xyarray.c
+++ b/tools/perf/util/xyarray.c
@@ -1,5 +1,7 @@
1#include "xyarray.h" 1#include "xyarray.h"
2#include "util.h" 2#include "util.h"
3#include <stdlib.h>
4#include <string.h>
3 5
4struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size) 6struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)
5{ 7{
diff --git a/tools/perf/util/zlib.c b/tools/perf/util/zlib.c
index 495a449fc25c..1329d843eb7b 100644
--- a/tools/perf/util/zlib.c
+++ b/tools/perf/util/zlib.c
@@ -4,6 +4,7 @@
4#include <sys/mman.h> 4#include <sys/mman.h>
5#include <zlib.h> 5#include <zlib.h>
6 6
7#include "util/compress.h"
7#include "util/util.h" 8#include "util/util.h"
8#include "util/debug.h" 9#include "util/debug.h"
9 10
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 621578aa12d6..fc74db62fef4 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -43,6 +43,15 @@ ifneq ($(CC), clang)
43EXTRA_WARNINGS += -Wstrict-aliasing=3 43EXTRA_WARNINGS += -Wstrict-aliasing=3
44endif 44endif
45 45
46# Hack to avoid type-punned warnings on old systems such as RHEL5:
47# We should be changing CFLAGS and checking gcc version, but this
48# will do for now and keep the above -Wstrict-aliasing=3 in place
49# in newer systems.
50# Needed for the __raw_cmpxchg in tools/arch/x86/include/asm/cmpxchg.h
51ifneq ($(filter 3.%,$(MAKE_VERSION)),) # make-3
52EXTRA_WARNINGS += -fno-strict-aliasing
53endif
54
46ifneq ($(findstring $(MAKEFLAGS), w),w) 55ifneq ($(findstring $(MAKEFLAGS), w),w)
47PRINT_DIR = --no-print-directory 56PRINT_DIR = --no-print-directory
48else 57else