aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/trace/events-msr.txt37
-rw-r--r--Documentation/trace/postprocess/decode_msr.py37
-rw-r--r--arch/x86/include/asm/atomic.h1
-rw-r--r--arch/x86/include/asm/atomic64_32.h1
-rw-r--r--arch/x86/include/asm/intel_pt.h10
-rw-r--r--arch/x86/include/asm/msr-trace.h57
-rw-r--r--arch/x86/include/asm/msr.h31
-rw-r--r--arch/x86/include/asm/uaccess.h9
-rw-r--r--arch/x86/kernel/cpu/perf_event.c36
-rw-r--r--arch/x86/kernel/cpu/perf_event.h21
-rw-r--r--arch/x86/kernel/cpu/perf_event_amd.c2
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c115
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_ds.c39
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_lbr.c42
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_pt.c9
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_rapl.c25
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore.c17
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore.h3
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore_snb.c2
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c635
-rw-r--r--arch/x86/kernel/crash.c11
-rw-r--r--arch/x86/lib/msr.c26
-rw-r--r--include/linux/tracepoint-defs.h27
-rw-r--r--include/linux/tracepoint.h16
-rw-r--r--include/uapi/linux/perf_event.h6
-rw-r--r--kernel/events/core.c286
-rw-r--r--lib/atomic64_test.c4
-rw-r--r--tools/Makefile2
-rw-r--r--tools/build/Makefile2
-rw-r--r--tools/build/Makefile.feature44
-rw-r--r--tools/build/Makefile.include2
-rw-r--r--tools/build/feature/Makefile93
-rw-r--r--tools/include/linux/bitmap.h (renamed from tools/perf/util/include/linux/bitmap.h)2
-rw-r--r--tools/include/linux/string.h15
-rw-r--r--tools/lib/bitmap.c (renamed from tools/perf/util/bitmap.c)0
-rw-r--r--tools/lib/bpf/Makefile14
-rw-r--r--tools/lib/bpf/bpf.c14
-rw-r--r--tools/lib/bpf/bpf.h2
-rw-r--r--tools/lib/bpf/libbpf.c412
-rw-r--r--tools/lib/bpf/libbpf.h88
-rw-r--r--tools/lib/find_bit.c84
-rw-r--r--tools/lib/string.c89
-rw-r--r--tools/lib/subcmd/Build7
-rw-r--r--tools/lib/subcmd/Makefile48
-rw-r--r--tools/lib/subcmd/exec-cmd.c209
-rw-r--r--tools/lib/subcmd/exec-cmd.h16
-rw-r--r--tools/lib/subcmd/help.c (renamed from tools/perf/util/help.c)179
-rw-r--r--tools/lib/subcmd/help.h (renamed from tools/perf/util/help.h)13
-rw-r--r--tools/lib/subcmd/pager.c (renamed from tools/perf/util/pager.c)23
-rw-r--r--tools/lib/subcmd/pager.h9
-rw-r--r--tools/lib/subcmd/parse-options.c (renamed from tools/perf/util/parse-options.c)250
-rw-r--r--tools/lib/subcmd/parse-options.h (renamed from tools/perf/util/parse-options.h)26
-rw-r--r--tools/lib/subcmd/run-command.c (renamed from tools/perf/util/run-command.c)24
-rw-r--r--tools/lib/subcmd/run-command.h (renamed from tools/perf/util/run-command.h)12
-rw-r--r--tools/lib/subcmd/sigchain.c (renamed from tools/perf/util/sigchain.c)3
-rw-r--r--tools/lib/subcmd/sigchain.h (renamed from tools/perf/util/sigchain.h)6
-rw-r--r--tools/lib/subcmd/subcmd-config.c11
-rw-r--r--tools/lib/subcmd/subcmd-config.h14
-rw-r--r--tools/lib/subcmd/subcmd-util.h91
-rw-r--r--tools/lib/traceevent/event-parse.c134
-rw-r--r--tools/lib/traceevent/event-parse.h4
-rw-r--r--tools/lib/util/find_next_bit.c89
-rw-r--r--tools/perf/Build8
-rw-r--r--tools/perf/Documentation/perf-config.txt103
-rw-r--r--tools/perf/Documentation/perf-evlist.txt3
-rw-r--r--tools/perf/Documentation/perf-record.txt24
-rw-r--r--tools/perf/Documentation/perf-report.txt41
-rw-r--r--tools/perf/Documentation/perf-stat.txt34
-rw-r--r--tools/perf/Documentation/perf-top.txt3
-rw-r--r--tools/perf/Documentation/tips.txt14
-rw-r--r--tools/perf/MANIFEST7
-rw-r--r--tools/perf/Makefile.perf44
-rw-r--r--tools/perf/arch/x86/include/arch-tests.h8
-rw-r--r--tools/perf/arch/x86/tests/insn-x86.c2
-rw-r--r--tools/perf/arch/x86/tests/intel-cqm.c4
-rw-r--r--tools/perf/arch/x86/tests/perf-time-to-tsc.c3
-rw-r--r--tools/perf/arch/x86/tests/rdpmc.c2
-rw-r--r--tools/perf/arch/x86/util/Build1
-rw-r--r--tools/perf/arch/x86/util/intel-bts.c4
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c6
-rw-r--r--tools/perf/bench/futex-hash.c2
-rw-r--r--tools/perf/bench/futex-lock-pi.c2
-rw-r--r--tools/perf/bench/futex-requeue.c2
-rw-r--r--tools/perf/bench/futex-wake-parallel.c2
-rw-r--r--tools/perf/bench/futex-wake.c2
-rw-r--r--tools/perf/bench/mem-functions.c2
-rw-r--r--tools/perf/bench/numa.c2
-rw-r--r--tools/perf/bench/sched-messaging.c2
-rw-r--r--tools/perf/bench/sched-pipe.c2
-rw-r--r--tools/perf/builtin-annotate.c44
-rw-r--r--tools/perf/builtin-bench.c2
-rw-r--r--tools/perf/builtin-buildid-cache.c2
-rw-r--r--tools/perf/builtin-buildid-list.c2
-rw-r--r--tools/perf/builtin-config.c66
-rw-r--r--tools/perf/builtin-data.c2
-rw-r--r--tools/perf/builtin-diff.c15
-rw-r--r--tools/perf/builtin-evlist.c13
-rw-r--r--tools/perf/builtin-help.c10
-rw-r--r--tools/perf/builtin-inject.c2
-rw-r--r--tools/perf/builtin-kmem.c2
-rw-r--r--tools/perf/builtin-kvm.c5
-rw-r--r--tools/perf/builtin-list.c2
-rw-r--r--tools/perf/builtin-lock.c2
-rw-r--r--tools/perf/builtin-mem.c2
-rw-r--r--tools/perf/builtin-probe.c17
-rw-r--r--tools/perf/builtin-record.c48
-rw-r--r--tools/perf/builtin-report.c52
-rw-r--r--tools/perf/builtin-sched.c2
-rw-r--r--tools/perf/builtin-script.c245
-rw-r--r--tools/perf/builtin-stat.c679
-rw-r--r--tools/perf/builtin-timechart.c2
-rw-r--r--tools/perf/builtin-top.c75
-rw-r--r--tools/perf/builtin-trace.c4
-rw-r--r--tools/perf/builtin-version.c10
-rw-r--r--tools/perf/builtin.h1
-rw-r--r--tools/perf/command-list.txt3
-rw-r--r--tools/perf/config/Makefile24
-rw-r--r--tools/perf/config/utilities.mak19
-rw-r--r--tools/perf/perf.c24
-rw-r--r--tools/perf/scripts/python/stat-cpi.py77
-rw-r--r--tools/perf/tests/.gitignore1
-rw-r--r--tools/perf/tests/Build16
-rw-r--r--tools/perf/tests/attr.c6
-rw-r--r--tools/perf/tests/bp_signal.c2
-rw-r--r--tools/perf/tests/bp_signal_overflow.c2
-rw-r--r--tools/perf/tests/bpf-script-test-prologue.c35
-rw-r--r--tools/perf/tests/bpf.c93
-rw-r--r--tools/perf/tests/builtin-test.c141
-rw-r--r--tools/perf/tests/code-reading.c16
-rw-r--r--tools/perf/tests/cpumap.c88
-rw-r--r--tools/perf/tests/dso-data.c6
-rw-r--r--tools/perf/tests/dwarf-unwind.c37
-rw-r--r--tools/perf/tests/event_update.c117
-rw-r--r--tools/perf/tests/evsel-roundtrip-name.c5
-rw-r--r--tools/perf/tests/evsel-tp-sched.c2
-rw-r--r--tools/perf/tests/fdarray.c4
-rw-r--r--tools/perf/tests/hists_common.c6
-rw-r--r--tools/perf/tests/hists_cumulate.c10
-rw-r--r--tools/perf/tests/hists_filter.c4
-rw-r--r--tools/perf/tests/hists_link.c10
-rw-r--r--tools/perf/tests/hists_output.c12
-rw-r--r--tools/perf/tests/keep-tracking.c5
-rw-r--r--tools/perf/tests/kmod-path.c2
-rw-r--r--tools/perf/tests/llvm.c75
-rw-r--r--tools/perf/tests/llvm.h2
-rw-r--r--tools/perf/tests/make3
-rw-r--r--tools/perf/tests/mmap-basic.c2
-rw-r--r--tools/perf/tests/mmap-thread-lookup.c8
-rw-r--r--tools/perf/tests/openat-syscall-all-cpus.c2
-rw-r--r--tools/perf/tests/openat-syscall-tp-fields.c2
-rw-r--r--tools/perf/tests/openat-syscall.c2
-rw-r--r--tools/perf/tests/parse-events.c2
-rw-r--r--tools/perf/tests/parse-no-sample-id-all.c2
-rw-r--r--tools/perf/tests/perf-record.c8
-rw-r--r--tools/perf/tests/pmu.c2
-rw-r--r--tools/perf/tests/python-use.c3
-rw-r--r--tools/perf/tests/sample-parsing.c2
-rw-r--r--tools/perf/tests/stat.c111
-rw-r--r--tools/perf/tests/sw-clock.c2
-rw-r--r--tools/perf/tests/switch-tracking.c8
-rw-r--r--tools/perf/tests/task-exit.c2
-rw-r--r--tools/perf/tests/tests.h95
-rw-r--r--tools/perf/tests/thread-map.c45
-rw-r--r--tools/perf/tests/thread-mg-share.c2
-rw-r--r--tools/perf/tests/topology.c2
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c2
-rw-r--r--tools/perf/ui/browser.c2
-rw-r--r--tools/perf/ui/browsers/hists.c327
-rw-r--r--tools/perf/ui/gtk/hists.c152
-rw-r--r--tools/perf/ui/hist.c14
-rw-r--r--tools/perf/ui/stdio/hist.c100
-rw-r--r--tools/perf/util/Build28
-rw-r--r--tools/perf/util/annotate.c23
-rw-r--r--tools/perf/util/auxtrace.c2
-rw-r--r--tools/perf/util/bpf-loader.c433
-rw-r--r--tools/perf/util/bpf-loader.h4
-rw-r--r--tools/perf/util/bpf-prologue.c455
-rw-r--r--tools/perf/util/bpf-prologue.h34
-rw-r--r--tools/perf/util/cache.h14
-rw-r--r--tools/perf/util/callchain.c164
-rw-r--r--tools/perf/util/callchain.h30
-rw-r--r--tools/perf/util/cgroup.c2
-rw-r--r--tools/perf/util/color.c2
-rw-r--r--tools/perf/util/config.c2
-rw-r--r--tools/perf/util/cpumap.c51
-rw-r--r--tools/perf/util/cpumap.h1
-rw-r--r--tools/perf/util/data-convert-bt.c2
-rw-r--r--tools/perf/util/dso.c2
-rw-r--r--tools/perf/util/env.c9
-rw-r--r--tools/perf/util/environment.c8
-rw-r--r--tools/perf/util/event.c308
-rw-r--r--tools/perf/util/event.h150
-rw-r--r--tools/perf/util/evlist.c112
-rw-r--r--tools/perf/util/evlist.h10
-rw-r--r--tools/perf/util/evsel.c53
-rw-r--r--tools/perf/util/evsel.h4
-rw-r--r--tools/perf/util/exec_cmd.c148
-rw-r--r--tools/perf/util/exec_cmd.h12
-rwxr-xr-xtools/perf/util/generate-cmdlist.sh15
-rw-r--r--tools/perf/util/header.c207
-rw-r--r--tools/perf/util/header.h17
-rw-r--r--tools/perf/util/help-unknown-cmd.c103
-rw-r--r--tools/perf/util/help-unknown-cmd.h0
-rw-r--r--tools/perf/util/hist.c118
-rw-r--r--tools/perf/util/hist.h24
-rw-r--r--tools/perf/util/include/linux/string.h3
-rw-r--r--tools/perf/util/intel-pt.c4
-rw-r--r--tools/perf/util/machine.c74
-rw-r--r--tools/perf/util/map.c7
-rw-r--r--tools/perf/util/parse-branch-options.c2
-rw-r--r--tools/perf/util/parse-events.c4
-rw-r--r--tools/perf/util/parse-regs-options.c2
-rw-r--r--tools/perf/util/path.c18
-rw-r--r--tools/perf/util/pmu.c1
-rw-r--r--tools/perf/util/probe-event.c7
-rw-r--r--tools/perf/util/probe-finder.c6
-rw-r--r--tools/perf/util/python-ext-sources2
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c115
-rw-r--r--tools/perf/util/session.c200
-rw-r--r--tools/perf/util/session.h2
-rw-r--r--tools/perf/util/sort.c601
-rw-r--r--tools/perf/util/sort.h14
-rw-r--r--tools/perf/util/stat.c62
-rw-r--r--tools/perf/util/stat.h10
-rw-r--r--tools/perf/util/string.c16
-rw-r--r--tools/perf/util/symbol-elf.c9
-rw-r--r--tools/perf/util/symbol.c66
-rw-r--r--tools/perf/util/symbol.h4
-rw-r--r--tools/perf/util/term.c35
-rw-r--r--tools/perf/util/term.h10
-rw-r--r--tools/perf/util/thread.c10
-rw-r--r--tools/perf/util/thread_map.c28
-rw-r--r--tools/perf/util/thread_map.h3
-rw-r--r--tools/perf/util/tool.h8
-rw-r--r--tools/perf/util/trace-event.h4
-rw-r--r--tools/perf/util/unwind-libdw.c63
-rw-r--r--tools/perf/util/unwind-libdw.h2
-rw-r--r--tools/perf/util/unwind-libunwind.c80
-rw-r--r--tools/perf/util/util.c67
-rw-r--r--tools/perf/util/util.h20
240 files changed, 9147 insertions, 1876 deletions
diff --git a/Documentation/trace/events-msr.txt b/Documentation/trace/events-msr.txt
new file mode 100644
index 000000000000..78c383bf06aa
--- /dev/null
+++ b/Documentation/trace/events-msr.txt
@@ -0,0 +1,37 @@
1
2The x86 kernel supports tracing most MSR (Model Specific Register) accesses.
3To see the definition of the MSRs on Intel systems please see the SDM
4at http://www.intel.com/sdm (Volume 3)
5
6Available trace points:
7
8/sys/kernel/debug/tracing/events/msr/
9
10Trace MSR reads
11
12read_msr
13
14msr: MSR number
15val: Value written
16failed: 1 if the access failed, otherwise 0
17
18
19Trace MSR writes
20
21write_msr
22
23msr: MSR number
24val: Value written
25failed: 1 if the access failed, otherwise 0
26
27
28Trace RDPMC in kernel
29
30rdpmc
31
32The trace data can be post processed with the postprocess/decode_msr.py script
33
34cat /sys/kernel/debug/tracing/trace | decode_msr.py /usr/src/linux/include/asm/msr-index.h
35
36to add symbolic MSR names.
37
diff --git a/Documentation/trace/postprocess/decode_msr.py b/Documentation/trace/postprocess/decode_msr.py
new file mode 100644
index 000000000000..0ab40e0db580
--- /dev/null
+++ b/Documentation/trace/postprocess/decode_msr.py
@@ -0,0 +1,37 @@
1#!/usr/bin/python
2# add symbolic names to read_msr / write_msr in trace
3# decode_msr msr-index.h < trace
4import sys
5import re
6
7msrs = dict()
8
9with open(sys.argv[1] if len(sys.argv) > 1 else "msr-index.h", "r") as f:
10 for j in f:
11 m = re.match(r'#define (MSR_\w+)\s+(0x[0-9a-fA-F]+)', j)
12 if m:
13 msrs[int(m.group(2), 16)] = m.group(1)
14
15extra_ranges = (
16 ( "MSR_LASTBRANCH_%d_FROM_IP", 0x680, 0x69F ),
17 ( "MSR_LASTBRANCH_%d_TO_IP", 0x6C0, 0x6DF ),
18 ( "LBR_INFO_%d", 0xdc0, 0xddf ),
19)
20
21for j in sys.stdin:
22 m = re.search(r'(read|write)_msr:\s+([0-9a-f]+)', j)
23 if m:
24 r = None
25 num = int(m.group(2), 16)
26 if num in msrs:
27 r = msrs[num]
28 else:
29 for er in extra_ranges:
30 if er[1] <= num <= er[2]:
31 r = er[0] % (num - er[1],)
32 break
33 if r:
34 j = j.replace(" " + m.group(2), " " + r + "(" + m.group(2) + ")")
35 print j,
36
37
diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h
index ae5fb83e6d91..3e8674288198 100644
--- a/arch/x86/include/asm/atomic.h
+++ b/arch/x86/include/asm/atomic.h
@@ -3,7 +3,6 @@
3 3
4#include <linux/compiler.h> 4#include <linux/compiler.h>
5#include <linux/types.h> 5#include <linux/types.h>
6#include <asm/processor.h>
7#include <asm/alternative.h> 6#include <asm/alternative.h>
8#include <asm/cmpxchg.h> 7#include <asm/cmpxchg.h>
9#include <asm/rmwcc.h> 8#include <asm/rmwcc.h>
diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h
index a11c30b77fb5..a984111135b1 100644
--- a/arch/x86/include/asm/atomic64_32.h
+++ b/arch/x86/include/asm/atomic64_32.h
@@ -3,7 +3,6 @@
3 3
4#include <linux/compiler.h> 4#include <linux/compiler.h>
5#include <linux/types.h> 5#include <linux/types.h>
6#include <asm/processor.h>
7//#include <asm/cmpxchg.h> 6//#include <asm/cmpxchg.h>
8 7
9/* An 64bit atomic type */ 8/* An 64bit atomic type */
diff --git a/arch/x86/include/asm/intel_pt.h b/arch/x86/include/asm/intel_pt.h
new file mode 100644
index 000000000000..e1a411786bf5
--- /dev/null
+++ b/arch/x86/include/asm/intel_pt.h
@@ -0,0 +1,10 @@
1#ifndef _ASM_X86_INTEL_PT_H
2#define _ASM_X86_INTEL_PT_H
3
4#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_INTEL)
5void cpu_emergency_stop_pt(void);
6#else
7static inline void cpu_emergency_stop_pt(void) {}
8#endif
9
10#endif /* _ASM_X86_INTEL_PT_H */
diff --git a/arch/x86/include/asm/msr-trace.h b/arch/x86/include/asm/msr-trace.h
new file mode 100644
index 000000000000..7567225747d8
--- /dev/null
+++ b/arch/x86/include/asm/msr-trace.h
@@ -0,0 +1,57 @@
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM msr
3
4#undef TRACE_INCLUDE_FILE
5#define TRACE_INCLUDE_FILE msr-trace
6
7#undef TRACE_INCLUDE_PATH
8#define TRACE_INCLUDE_PATH asm/
9
10#if !defined(_TRACE_MSR_H) || defined(TRACE_HEADER_MULTI_READ)
11#define _TRACE_MSR_H
12
13#include <linux/tracepoint.h>
14
15/*
16 * Tracing for x86 model specific registers. Directly maps to the
17 * RDMSR/WRMSR instructions.
18 */
19
20DECLARE_EVENT_CLASS(msr_trace_class,
21 TP_PROTO(unsigned msr, u64 val, int failed),
22 TP_ARGS(msr, val, failed),
23 TP_STRUCT__entry(
24 __field( unsigned, msr )
25 __field( u64, val )
26 __field( int, failed )
27 ),
28 TP_fast_assign(
29 __entry->msr = msr;
30 __entry->val = val;
31 __entry->failed = failed;
32 ),
33 TP_printk("%x, value %llx%s",
34 __entry->msr,
35 __entry->val,
36 __entry->failed ? " #GP" : "")
37);
38
39DEFINE_EVENT(msr_trace_class, read_msr,
40 TP_PROTO(unsigned msr, u64 val, int failed),
41 TP_ARGS(msr, val, failed)
42);
43
44DEFINE_EVENT(msr_trace_class, write_msr,
45 TP_PROTO(unsigned msr, u64 val, int failed),
46 TP_ARGS(msr, val, failed)
47);
48
49DEFINE_EVENT(msr_trace_class, rdpmc,
50 TP_PROTO(unsigned msr, u64 val, int failed),
51 TP_ARGS(msr, val, failed)
52);
53
54#endif /* _TRACE_MSR_H */
55
56/* This part must be outside protection */
57#include <trace/define_trace.h>
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index 77d8b284e4a7..fedd6e6d1e43 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -57,11 +57,34 @@ static inline unsigned long long native_read_tscp(unsigned int *aux)
57#define EAX_EDX_RET(val, low, high) "=A" (val) 57#define EAX_EDX_RET(val, low, high) "=A" (val)
58#endif 58#endif
59 59
60#ifdef CONFIG_TRACEPOINTS
61/*
62 * Be very careful with includes. This header is prone to include loops.
63 */
64#include <asm/atomic.h>
65#include <linux/tracepoint-defs.h>
66
67extern struct tracepoint __tracepoint_read_msr;
68extern struct tracepoint __tracepoint_write_msr;
69extern struct tracepoint __tracepoint_rdpmc;
70#define msr_tracepoint_active(t) static_key_false(&(t).key)
71extern void do_trace_write_msr(unsigned msr, u64 val, int failed);
72extern void do_trace_read_msr(unsigned msr, u64 val, int failed);
73extern void do_trace_rdpmc(unsigned msr, u64 val, int failed);
74#else
75#define msr_tracepoint_active(t) false
76static inline void do_trace_write_msr(unsigned msr, u64 val, int failed) {}
77static inline void do_trace_read_msr(unsigned msr, u64 val, int failed) {}
78static inline void do_trace_rdpmc(unsigned msr, u64 val, int failed) {}
79#endif
80
60static inline unsigned long long native_read_msr(unsigned int msr) 81static inline unsigned long long native_read_msr(unsigned int msr)
61{ 82{
62 DECLARE_ARGS(val, low, high); 83 DECLARE_ARGS(val, low, high);
63 84
64 asm volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr)); 85 asm volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr));
86 if (msr_tracepoint_active(__tracepoint_read_msr))
87 do_trace_read_msr(msr, EAX_EDX_VAL(val, low, high), 0);
65 return EAX_EDX_VAL(val, low, high); 88 return EAX_EDX_VAL(val, low, high);
66} 89}
67 90
@@ -78,6 +101,8 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr,
78 _ASM_EXTABLE(2b, 3b) 101 _ASM_EXTABLE(2b, 3b)
79 : [err] "=r" (*err), EAX_EDX_RET(val, low, high) 102 : [err] "=r" (*err), EAX_EDX_RET(val, low, high)
80 : "c" (msr), [fault] "i" (-EIO)); 103 : "c" (msr), [fault] "i" (-EIO));
104 if (msr_tracepoint_active(__tracepoint_read_msr))
105 do_trace_read_msr(msr, EAX_EDX_VAL(val, low, high), *err);
81 return EAX_EDX_VAL(val, low, high); 106 return EAX_EDX_VAL(val, low, high);
82} 107}
83 108
@@ -85,6 +110,8 @@ static inline void native_write_msr(unsigned int msr,
85 unsigned low, unsigned high) 110 unsigned low, unsigned high)
86{ 111{
87 asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory"); 112 asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory");
113 if (msr_tracepoint_active(__tracepoint_read_msr))
114 do_trace_write_msr(msr, ((u64)high << 32 | low), 0);
88} 115}
89 116
90/* Can be uninlined because referenced by paravirt */ 117/* Can be uninlined because referenced by paravirt */
@@ -102,6 +129,8 @@ notrace static inline int native_write_msr_safe(unsigned int msr,
102 : "c" (msr), "0" (low), "d" (high), 129 : "c" (msr), "0" (low), "d" (high),
103 [fault] "i" (-EIO) 130 [fault] "i" (-EIO)
104 : "memory"); 131 : "memory");
132 if (msr_tracepoint_active(__tracepoint_read_msr))
133 do_trace_write_msr(msr, ((u64)high << 32 | low), err);
105 return err; 134 return err;
106} 135}
107 136
@@ -160,6 +189,8 @@ static inline unsigned long long native_read_pmc(int counter)
160 DECLARE_ARGS(val, low, high); 189 DECLARE_ARGS(val, low, high);
161 190
162 asm volatile("rdpmc" : EAX_EDX_RET(val, low, high) : "c" (counter)); 191 asm volatile("rdpmc" : EAX_EDX_RET(val, low, high) : "c" (counter));
192 if (msr_tracepoint_active(__tracepoint_rdpmc))
193 do_trace_rdpmc(counter, EAX_EDX_VAL(val, low, high), 0);
163 return EAX_EDX_VAL(val, low, high); 194 return EAX_EDX_VAL(val, low, high);
164} 195}
165 196
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 09b1b0ab94b7..660458af425d 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -745,5 +745,14 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
745#undef __copy_from_user_overflow 745#undef __copy_from_user_overflow
746#undef __copy_to_user_overflow 746#undef __copy_to_user_overflow
747 747
748/*
749 * We rely on the nested NMI work to allow atomic faults from the NMI path; the
750 * nested NMI paths are careful to preserve CR2.
751 *
752 * Caller must use pagefault_enable/disable, or run in interrupt context,
753 * and also do a uaccess_ok() check
754 */
755#define __copy_from_user_nmi __copy_from_user_inatomic
756
748#endif /* _ASM_X86_UACCESS_H */ 757#endif /* _ASM_X86_UACCESS_H */
749 758
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 2bf79d7c97df..1b443db2db50 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -482,6 +482,9 @@ int x86_pmu_hw_config(struct perf_event *event)
482 /* Support for IP fixup */ 482 /* Support for IP fixup */
483 if (x86_pmu.lbr_nr || x86_pmu.intel_cap.pebs_format >= 2) 483 if (x86_pmu.lbr_nr || x86_pmu.intel_cap.pebs_format >= 2)
484 precise++; 484 precise++;
485
486 if (x86_pmu.pebs_prec_dist)
487 precise++;
485 } 488 }
486 489
487 if (event->attr.precise_ip > precise) 490 if (event->attr.precise_ip > precise)
@@ -1531,6 +1534,7 @@ static void __init filter_events(struct attribute **attrs)
1531{ 1534{
1532 struct device_attribute *d; 1535 struct device_attribute *d;
1533 struct perf_pmu_events_attr *pmu_attr; 1536 struct perf_pmu_events_attr *pmu_attr;
1537 int offset = 0;
1534 int i, j; 1538 int i, j;
1535 1539
1536 for (i = 0; attrs[i]; i++) { 1540 for (i = 0; attrs[i]; i++) {
@@ -1539,7 +1543,7 @@ static void __init filter_events(struct attribute **attrs)
1539 /* str trumps id */ 1543 /* str trumps id */
1540 if (pmu_attr->event_str) 1544 if (pmu_attr->event_str)
1541 continue; 1545 continue;
1542 if (x86_pmu.event_map(i)) 1546 if (x86_pmu.event_map(i + offset))
1543 continue; 1547 continue;
1544 1548
1545 for (j = i; attrs[j]; j++) 1549 for (j = i; attrs[j]; j++)
@@ -1547,6 +1551,14 @@ static void __init filter_events(struct attribute **attrs)
1547 1551
1548 /* Check the shifted attr. */ 1552 /* Check the shifted attr. */
1549 i--; 1553 i--;
1554
1555 /*
1556 * event_map() is index based, the attrs array is organized
1557 * by increasing event index. If we shift the events, then
1558 * we need to compensate for the event_map(), otherwise
1559 * we are looking up the wrong event in the map
1560 */
1561 offset++;
1550 } 1562 }
1551} 1563}
1552 1564
@@ -2250,12 +2262,19 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
2250 ss_base = get_segment_base(regs->ss); 2262 ss_base = get_segment_base(regs->ss);
2251 2263
2252 fp = compat_ptr(ss_base + regs->bp); 2264 fp = compat_ptr(ss_base + regs->bp);
2265 pagefault_disable();
2253 while (entry->nr < PERF_MAX_STACK_DEPTH) { 2266 while (entry->nr < PERF_MAX_STACK_DEPTH) {
2254 unsigned long bytes; 2267 unsigned long bytes;
2255 frame.next_frame = 0; 2268 frame.next_frame = 0;
2256 frame.return_address = 0; 2269 frame.return_address = 0;
2257 2270
2258 bytes = copy_from_user_nmi(&frame, fp, sizeof(frame)); 2271 if (!access_ok(VERIFY_READ, fp, 8))
2272 break;
2273
2274 bytes = __copy_from_user_nmi(&frame.next_frame, fp, 4);
2275 if (bytes != 0)
2276 break;
2277 bytes = __copy_from_user_nmi(&frame.return_address, fp+4, 4);
2259 if (bytes != 0) 2278 if (bytes != 0)
2260 break; 2279 break;
2261 2280
@@ -2265,6 +2284,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
2265 perf_callchain_store(entry, cs_base + frame.return_address); 2284 perf_callchain_store(entry, cs_base + frame.return_address);
2266 fp = compat_ptr(ss_base + frame.next_frame); 2285 fp = compat_ptr(ss_base + frame.next_frame);
2267 } 2286 }
2287 pagefault_enable();
2268 return 1; 2288 return 1;
2269} 2289}
2270#else 2290#else
@@ -2302,12 +2322,19 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
2302 if (perf_callchain_user32(regs, entry)) 2322 if (perf_callchain_user32(regs, entry))
2303 return; 2323 return;
2304 2324
2325 pagefault_disable();
2305 while (entry->nr < PERF_MAX_STACK_DEPTH) { 2326 while (entry->nr < PERF_MAX_STACK_DEPTH) {
2306 unsigned long bytes; 2327 unsigned long bytes;
2307 frame.next_frame = NULL; 2328 frame.next_frame = NULL;
2308 frame.return_address = 0; 2329 frame.return_address = 0;
2309 2330
2310 bytes = copy_from_user_nmi(&frame, fp, sizeof(frame)); 2331 if (!access_ok(VERIFY_READ, fp, 16))
2332 break;
2333
2334 bytes = __copy_from_user_nmi(&frame.next_frame, fp, 8);
2335 if (bytes != 0)
2336 break;
2337 bytes = __copy_from_user_nmi(&frame.return_address, fp+8, 8);
2311 if (bytes != 0) 2338 if (bytes != 0)
2312 break; 2339 break;
2313 2340
@@ -2315,8 +2342,9 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
2315 break; 2342 break;
2316 2343
2317 perf_callchain_store(entry, frame.return_address); 2344 perf_callchain_store(entry, frame.return_address);
2318 fp = frame.next_frame; 2345 fp = (void __user *)frame.next_frame;
2319 } 2346 }
2347 pagefault_enable();
2320} 2348}
2321 2349
2322/* 2350/*
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index d0e35ebb2adb..7bb61e32fb29 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -14,17 +14,7 @@
14 14
15#include <linux/perf_event.h> 15#include <linux/perf_event.h>
16 16
17#if 0 17/* To enable MSR tracing please use the generic trace points. */
18#undef wrmsrl
19#define wrmsrl(msr, val) \
20do { \
21 unsigned int _msr = (msr); \
22 u64 _val = (val); \
23 trace_printk("wrmsrl(%x, %Lx)\n", (unsigned int)(_msr), \
24 (unsigned long long)(_val)); \
25 native_write_msr((_msr), (u32)(_val), (u32)(_val >> 32)); \
26} while (0)
27#endif
28 18
29/* 19/*
30 * | NHM/WSM | SNB | 20 * | NHM/WSM | SNB |
@@ -318,6 +308,10 @@ struct cpu_hw_events {
318#define INTEL_UEVENT_CONSTRAINT(c, n) \ 308#define INTEL_UEVENT_CONSTRAINT(c, n) \
319 EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK) 309 EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK)
320 310
311/* Constraint on specific umask bit only + event */
312#define INTEL_UBIT_EVENT_CONSTRAINT(c, n) \
313 EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT|(c))
314
321/* Like UEVENT_CONSTRAINT, but match flags too */ 315/* Like UEVENT_CONSTRAINT, but match flags too */
322#define INTEL_FLAGS_UEVENT_CONSTRAINT(c, n) \ 316#define INTEL_FLAGS_UEVENT_CONSTRAINT(c, n) \
323 EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS) 317 EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS)
@@ -589,7 +583,8 @@ struct x86_pmu {
589 bts_active :1, 583 bts_active :1,
590 pebs :1, 584 pebs :1,
591 pebs_active :1, 585 pebs_active :1,
592 pebs_broken :1; 586 pebs_broken :1,
587 pebs_prec_dist :1;
593 int pebs_record_size; 588 int pebs_record_size;
594 void (*drain_pebs)(struct pt_regs *regs); 589 void (*drain_pebs)(struct pt_regs *regs);
595 struct event_constraint *pebs_constraints; 590 struct event_constraint *pebs_constraints;
@@ -907,6 +902,8 @@ void intel_pmu_lbr_init_hsw(void);
907 902
908void intel_pmu_lbr_init_skl(void); 903void intel_pmu_lbr_init_skl(void);
909 904
905void intel_pmu_lbr_init_knl(void);
906
910int intel_pmu_setup_lbr_filter(struct perf_event *event); 907int intel_pmu_setup_lbr_filter(struct perf_event *event);
911 908
912void intel_pt_interrupt(void); 909void intel_pt_interrupt(void);
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
index 1cee5d2d7ece..05e76bf65781 100644
--- a/arch/x86/kernel/cpu/perf_event_amd.c
+++ b/arch/x86/kernel/cpu/perf_event_amd.c
@@ -18,7 +18,7 @@ static __initconst const u64 amd_hw_cache_event_ids
18 [ C(RESULT_MISS) ] = 0x0141, /* Data Cache Misses */ 18 [ C(RESULT_MISS) ] = 0x0141, /* Data Cache Misses */
19 }, 19 },
20 [ C(OP_WRITE) ] = { 20 [ C(OP_WRITE) ] = {
21 [ C(RESULT_ACCESS) ] = 0x0142, /* Data Cache Refills :system */ 21 [ C(RESULT_ACCESS) ] = 0,
22 [ C(RESULT_MISS) ] = 0, 22 [ C(RESULT_MISS) ] = 0,
23 }, 23 },
24 [ C(OP_PREFETCH) ] = { 24 [ C(OP_PREFETCH) ] = {
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index e2a430021e46..a667078a5180 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -185,6 +185,14 @@ struct event_constraint intel_skl_event_constraints[] = {
185 EVENT_CONSTRAINT_END 185 EVENT_CONSTRAINT_END
186}; 186};
187 187
188static struct extra_reg intel_knl_extra_regs[] __read_mostly = {
189 INTEL_UEVENT_EXTRA_REG(0x01b7,
190 MSR_OFFCORE_RSP_0, 0x7f9ffbffffull, RSP_0),
191 INTEL_UEVENT_EXTRA_REG(0x02b7,
192 MSR_OFFCORE_RSP_1, 0x3f9ffbffffull, RSP_1),
193 EVENT_EXTRA_END
194};
195
188static struct extra_reg intel_snb_extra_regs[] __read_mostly = { 196static struct extra_reg intel_snb_extra_regs[] __read_mostly = {
189 /* must define OFFCORE_RSP_X first, see intel_fixup_er() */ 197 /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
190 INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x3f807f8fffull, RSP_0), 198 INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x3f807f8fffull, RSP_0),
@@ -255,7 +263,7 @@ struct event_constraint intel_bdw_event_constraints[] = {
255 FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ 263 FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
256 FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */ 264 FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
257 INTEL_UEVENT_CONSTRAINT(0x148, 0x4), /* L1D_PEND_MISS.PENDING */ 265 INTEL_UEVENT_CONSTRAINT(0x148, 0x4), /* L1D_PEND_MISS.PENDING */
258 INTEL_UEVENT_CONSTRAINT(0x8a3, 0x4), /* CYCLE_ACTIVITY.CYCLES_L1D_MISS */ 266 INTEL_UBIT_EVENT_CONSTRAINT(0x8a3, 0x4), /* CYCLE_ACTIVITY.CYCLES_L1D_MISS */
259 EVENT_CONSTRAINT_END 267 EVENT_CONSTRAINT_END
260}; 268};
261 269
@@ -1457,6 +1465,42 @@ static __initconst const u64 slm_hw_cache_event_ids
1457 }, 1465 },
1458}; 1466};
1459 1467
1468#define KNL_OT_L2_HITE BIT_ULL(19) /* Other Tile L2 Hit */
1469#define KNL_OT_L2_HITF BIT_ULL(20) /* Other Tile L2 Hit */
1470#define KNL_MCDRAM_LOCAL BIT_ULL(21)
1471#define KNL_MCDRAM_FAR BIT_ULL(22)
1472#define KNL_DDR_LOCAL BIT_ULL(23)
1473#define KNL_DDR_FAR BIT_ULL(24)
1474#define KNL_DRAM_ANY (KNL_MCDRAM_LOCAL | KNL_MCDRAM_FAR | \
1475 KNL_DDR_LOCAL | KNL_DDR_FAR)
1476#define KNL_L2_READ SLM_DMND_READ
1477#define KNL_L2_WRITE SLM_DMND_WRITE
1478#define KNL_L2_PREFETCH SLM_DMND_PREFETCH
1479#define KNL_L2_ACCESS SLM_LLC_ACCESS
1480#define KNL_L2_MISS (KNL_OT_L2_HITE | KNL_OT_L2_HITF | \
1481 KNL_DRAM_ANY | SNB_SNP_ANY | \
1482 SNB_NON_DRAM)
1483
1484static __initconst const u64 knl_hw_cache_extra_regs
1485 [PERF_COUNT_HW_CACHE_MAX]
1486 [PERF_COUNT_HW_CACHE_OP_MAX]
1487 [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
1488 [C(LL)] = {
1489 [C(OP_READ)] = {
1490 [C(RESULT_ACCESS)] = KNL_L2_READ | KNL_L2_ACCESS,
1491 [C(RESULT_MISS)] = 0,
1492 },
1493 [C(OP_WRITE)] = {
1494 [C(RESULT_ACCESS)] = KNL_L2_WRITE | KNL_L2_ACCESS,
1495 [C(RESULT_MISS)] = KNL_L2_WRITE | KNL_L2_MISS,
1496 },
1497 [C(OP_PREFETCH)] = {
1498 [C(RESULT_ACCESS)] = KNL_L2_PREFETCH | KNL_L2_ACCESS,
1499 [C(RESULT_MISS)] = KNL_L2_PREFETCH | KNL_L2_MISS,
1500 },
1501 },
1502};
1503
1460/* 1504/*
1461 * Use from PMIs where the LBRs are already disabled. 1505 * Use from PMIs where the LBRs are already disabled.
1462 */ 1506 */
@@ -2475,6 +2519,44 @@ static void intel_pebs_aliases_snb(struct perf_event *event)
2475 } 2519 }
2476} 2520}
2477 2521
2522static void intel_pebs_aliases_precdist(struct perf_event *event)
2523{
2524 if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) {
2525 /*
2526 * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P
2527 * (0x003c) so that we can use it with PEBS.
2528 *
2529 * The regular CPU_CLK_UNHALTED.THREAD_P event (0x003c) isn't
2530 * PEBS capable. However we can use INST_RETIRED.PREC_DIST
2531 * (0x01c0), which is a PEBS capable event, to get the same
2532 * count.
2533 *
2534 * The PREC_DIST event has special support to minimize sample
2535 * shadowing effects. One drawback is that it can be
2536 * only programmed on counter 1, but that seems like an
2537 * acceptable trade off.
2538 */
2539 u64 alt_config = X86_CONFIG(.event=0xc0, .umask=0x01, .inv=1, .cmask=16);
2540
2541 alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK);
2542 event->hw.config = alt_config;
2543 }
2544}
2545
2546static void intel_pebs_aliases_ivb(struct perf_event *event)
2547{
2548 if (event->attr.precise_ip < 3)
2549 return intel_pebs_aliases_snb(event);
2550 return intel_pebs_aliases_precdist(event);
2551}
2552
2553static void intel_pebs_aliases_skl(struct perf_event *event)
2554{
2555 if (event->attr.precise_ip < 3)
2556 return intel_pebs_aliases_core2(event);
2557 return intel_pebs_aliases_precdist(event);
2558}
2559
2478static unsigned long intel_pmu_free_running_flags(struct perf_event *event) 2560static unsigned long intel_pmu_free_running_flags(struct perf_event *event)
2479{ 2561{
2480 unsigned long flags = x86_pmu.free_running_flags; 2562 unsigned long flags = x86_pmu.free_running_flags;
@@ -3332,6 +3414,7 @@ __init int intel_pmu_init(void)
3332 3414
3333 x86_pmu.event_constraints = intel_gen_event_constraints; 3415 x86_pmu.event_constraints = intel_gen_event_constraints;
3334 x86_pmu.pebs_constraints = intel_atom_pebs_event_constraints; 3416 x86_pmu.pebs_constraints = intel_atom_pebs_event_constraints;
3417 x86_pmu.pebs_aliases = intel_pebs_aliases_core2;
3335 pr_cont("Atom events, "); 3418 pr_cont("Atom events, ");
3336 break; 3419 break;
3337 3420
@@ -3431,7 +3514,8 @@ __init int intel_pmu_init(void)
3431 3514
3432 x86_pmu.event_constraints = intel_ivb_event_constraints; 3515 x86_pmu.event_constraints = intel_ivb_event_constraints;
3433 x86_pmu.pebs_constraints = intel_ivb_pebs_event_constraints; 3516 x86_pmu.pebs_constraints = intel_ivb_pebs_event_constraints;
3434 x86_pmu.pebs_aliases = intel_pebs_aliases_snb; 3517 x86_pmu.pebs_aliases = intel_pebs_aliases_ivb;
3518 x86_pmu.pebs_prec_dist = true;
3435 if (boot_cpu_data.x86_model == 62) 3519 if (boot_cpu_data.x86_model == 62)
3436 x86_pmu.extra_regs = intel_snbep_extra_regs; 3520 x86_pmu.extra_regs = intel_snbep_extra_regs;
3437 else 3521 else
@@ -3464,7 +3548,8 @@ __init int intel_pmu_init(void)
3464 x86_pmu.event_constraints = intel_hsw_event_constraints; 3548 x86_pmu.event_constraints = intel_hsw_event_constraints;
3465 x86_pmu.pebs_constraints = intel_hsw_pebs_event_constraints; 3549 x86_pmu.pebs_constraints = intel_hsw_pebs_event_constraints;
3466 x86_pmu.extra_regs = intel_snbep_extra_regs; 3550 x86_pmu.extra_regs = intel_snbep_extra_regs;
3467 x86_pmu.pebs_aliases = intel_pebs_aliases_snb; 3551 x86_pmu.pebs_aliases = intel_pebs_aliases_ivb;
3552 x86_pmu.pebs_prec_dist = true;
3468 /* all extra regs are per-cpu when HT is on */ 3553 /* all extra regs are per-cpu when HT is on */
3469 x86_pmu.flags |= PMU_FL_HAS_RSP_1; 3554 x86_pmu.flags |= PMU_FL_HAS_RSP_1;
3470 x86_pmu.flags |= PMU_FL_NO_HT_SHARING; 3555 x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
@@ -3499,7 +3584,8 @@ __init int intel_pmu_init(void)
3499 x86_pmu.event_constraints = intel_bdw_event_constraints; 3584 x86_pmu.event_constraints = intel_bdw_event_constraints;
3500 x86_pmu.pebs_constraints = intel_hsw_pebs_event_constraints; 3585 x86_pmu.pebs_constraints = intel_hsw_pebs_event_constraints;
3501 x86_pmu.extra_regs = intel_snbep_extra_regs; 3586 x86_pmu.extra_regs = intel_snbep_extra_regs;
3502 x86_pmu.pebs_aliases = intel_pebs_aliases_snb; 3587 x86_pmu.pebs_aliases = intel_pebs_aliases_ivb;
3588 x86_pmu.pebs_prec_dist = true;
3503 /* all extra regs are per-cpu when HT is on */ 3589 /* all extra regs are per-cpu when HT is on */
3504 x86_pmu.flags |= PMU_FL_HAS_RSP_1; 3590 x86_pmu.flags |= PMU_FL_HAS_RSP_1;
3505 x86_pmu.flags |= PMU_FL_NO_HT_SHARING; 3591 x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
@@ -3511,6 +3597,24 @@ __init int intel_pmu_init(void)
3511 pr_cont("Broadwell events, "); 3597 pr_cont("Broadwell events, ");
3512 break; 3598 break;
3513 3599
3600 case 87: /* Knights Landing Xeon Phi */
3601 memcpy(hw_cache_event_ids,
3602 slm_hw_cache_event_ids, sizeof(hw_cache_event_ids));
3603 memcpy(hw_cache_extra_regs,
3604 knl_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
3605 intel_pmu_lbr_init_knl();
3606
3607 x86_pmu.event_constraints = intel_slm_event_constraints;
3608 x86_pmu.pebs_constraints = intel_slm_pebs_event_constraints;
3609 x86_pmu.extra_regs = intel_knl_extra_regs;
3610
3611 /* all extra regs are per-cpu when HT is on */
3612 x86_pmu.flags |= PMU_FL_HAS_RSP_1;
3613 x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
3614
3615 pr_cont("Knights Landing events, ");
3616 break;
3617
3514 case 78: /* 14nm Skylake Mobile */ 3618 case 78: /* 14nm Skylake Mobile */
3515 case 94: /* 14nm Skylake Desktop */ 3619 case 94: /* 14nm Skylake Desktop */
3516 x86_pmu.late_ack = true; 3620 x86_pmu.late_ack = true;
@@ -3521,7 +3625,8 @@ __init int intel_pmu_init(void)
3521 x86_pmu.event_constraints = intel_skl_event_constraints; 3625 x86_pmu.event_constraints = intel_skl_event_constraints;
3522 x86_pmu.pebs_constraints = intel_skl_pebs_event_constraints; 3626 x86_pmu.pebs_constraints = intel_skl_pebs_event_constraints;
3523 x86_pmu.extra_regs = intel_skl_extra_regs; 3627 x86_pmu.extra_regs = intel_skl_extra_regs;
3524 x86_pmu.pebs_aliases = intel_pebs_aliases_snb; 3628 x86_pmu.pebs_aliases = intel_pebs_aliases_skl;
3629 x86_pmu.pebs_prec_dist = true;
3525 /* all extra regs are per-cpu when HT is on */ 3630 /* all extra regs are per-cpu when HT is on */
3526 x86_pmu.flags |= PMU_FL_HAS_RSP_1; 3631 x86_pmu.flags |= PMU_FL_HAS_RSP_1;
3527 x86_pmu.flags |= PMU_FL_NO_HT_SHARING; 3632 x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index 5db1c7755548..10602f0a438f 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -620,6 +620,8 @@ struct event_constraint intel_atom_pebs_event_constraints[] = {
620 INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED.* */ 620 INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED.* */
621 /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */ 621 /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */
622 INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x01), 622 INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x01),
623 /* Allow all events as PEBS with no flags */
624 INTEL_ALL_EVENT_CONSTRAINT(0, 0x1),
623 EVENT_CONSTRAINT_END 625 EVENT_CONSTRAINT_END
624}; 626};
625 627
@@ -686,6 +688,8 @@ struct event_constraint intel_ivb_pebs_event_constraints[] = {
686 INTEL_PST_CONSTRAINT(0x02cd, 0x8), /* MEM_TRANS_RETIRED.PRECISE_STORES */ 688 INTEL_PST_CONSTRAINT(0x02cd, 0x8), /* MEM_TRANS_RETIRED.PRECISE_STORES */
687 /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */ 689 /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
688 INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf), 690 INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
691 /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */
692 INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2),
689 INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOP_RETIRED.* */ 693 INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOP_RETIRED.* */
690 INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ 694 INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */
691 INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ 695 INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
@@ -700,6 +704,8 @@ struct event_constraint intel_hsw_pebs_event_constraints[] = {
700 INTEL_PLD_CONSTRAINT(0x01cd, 0xf), /* MEM_TRANS_RETIRED.* */ 704 INTEL_PLD_CONSTRAINT(0x01cd, 0xf), /* MEM_TRANS_RETIRED.* */
701 /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */ 705 /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
702 INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf), 706 INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
707 /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */
708 INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2),
703 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(0x01c2, 0xf), /* UOPS_RETIRED.ALL */ 709 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
704 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x11d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_LOADS */ 710 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x11d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_LOADS */
705 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x21d0, 0xf), /* MEM_UOPS_RETIRED.LOCK_LOADS */ 711 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x21d0, 0xf), /* MEM_UOPS_RETIRED.LOCK_LOADS */
@@ -718,9 +724,10 @@ struct event_constraint intel_hsw_pebs_event_constraints[] = {
718 724
719struct event_constraint intel_skl_pebs_event_constraints[] = { 725struct event_constraint intel_skl_pebs_event_constraints[] = {
720 INTEL_FLAGS_UEVENT_CONSTRAINT(0x1c0, 0x2), /* INST_RETIRED.PREC_DIST */ 726 INTEL_FLAGS_UEVENT_CONSTRAINT(0x1c0, 0x2), /* INST_RETIRED.PREC_DIST */
721 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(0x01c2, 0xf), /* UOPS_RETIRED.ALL */ 727 /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */
722 /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */ 728 INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2),
723 INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf), 729 /* INST_RETIRED.TOTAL_CYCLES_PS (inv=1, cmask=16) (cycles:p). */
730 INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x0f),
724 INTEL_PLD_CONSTRAINT(0x1cd, 0xf), /* MEM_TRANS_RETIRED.* */ 731 INTEL_PLD_CONSTRAINT(0x1cd, 0xf), /* MEM_TRANS_RETIRED.* */
725 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x11d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_LOADS */ 732 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x11d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_LOADS */
726 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x12d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_STORES */ 733 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x12d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_STORES */
@@ -1101,6 +1108,13 @@ get_next_pebs_record_by_bit(void *base, void *top, int bit)
1101 void *at; 1108 void *at;
1102 u64 pebs_status; 1109 u64 pebs_status;
1103 1110
1111 /*
1112 * fmt0 does not have a status bitfield (does not use
1113 * perf_record_nhm format)
1114 */
1115 if (x86_pmu.intel_cap.pebs_format < 1)
1116 return base;
1117
1104 if (base == NULL) 1118 if (base == NULL)
1105 return NULL; 1119 return NULL;
1106 1120
@@ -1186,7 +1200,7 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
1186 if (!event->attr.precise_ip) 1200 if (!event->attr.precise_ip)
1187 return; 1201 return;
1188 1202
1189 n = (top - at) / x86_pmu.pebs_record_size; 1203 n = top - at;
1190 if (n <= 0) 1204 if (n <= 0)
1191 return; 1205 return;
1192 1206
@@ -1230,12 +1244,21 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
1230 pebs_status = p->status & cpuc->pebs_enabled; 1244 pebs_status = p->status & cpuc->pebs_enabled;
1231 pebs_status &= (1ULL << x86_pmu.max_pebs_events) - 1; 1245 pebs_status &= (1ULL << x86_pmu.max_pebs_events) - 1;
1232 1246
1247 /*
1248 * On some CPUs the PEBS status can be zero when PEBS is
1249 * racing with clearing of GLOBAL_STATUS.
1250 *
1251 * Normally we would drop that record, but in the
1252 * case when there is only a single active PEBS event
1253 * we can assume it's for that event.
1254 */
1255 if (!pebs_status && cpuc->pebs_enabled &&
1256 !(cpuc->pebs_enabled & (cpuc->pebs_enabled-1)))
1257 pebs_status = cpuc->pebs_enabled;
1258
1233 bit = find_first_bit((unsigned long *)&pebs_status, 1259 bit = find_first_bit((unsigned long *)&pebs_status,
1234 x86_pmu.max_pebs_events); 1260 x86_pmu.max_pebs_events);
1235 if (WARN(bit >= x86_pmu.max_pebs_events, 1261 if (bit >= x86_pmu.max_pebs_events)
1236 "PEBS record without PEBS event! status=%Lx pebs_enabled=%Lx active_mask=%Lx",
1237 (unsigned long long)p->status, (unsigned long long)cpuc->pebs_enabled,
1238 *(unsigned long long *)cpuc->active_mask))
1239 continue; 1262 continue;
1240 1263
1241 /* 1264 /*
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
index 659f01e165d5..653f88d25987 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
@@ -42,6 +42,13 @@ static enum {
42#define LBR_FAR_BIT 8 /* do not capture far branches */ 42#define LBR_FAR_BIT 8 /* do not capture far branches */
43#define LBR_CALL_STACK_BIT 9 /* enable call stack */ 43#define LBR_CALL_STACK_BIT 9 /* enable call stack */
44 44
45/*
46 * Following bit only exists in Linux; we mask it out before writing it to
47 * the actual MSR. But it helps the constraint perf code to understand
48 * that this is a separate configuration.
49 */
50#define LBR_NO_INFO_BIT 63 /* don't read LBR_INFO. */
51
45#define LBR_KERNEL (1 << LBR_KERNEL_BIT) 52#define LBR_KERNEL (1 << LBR_KERNEL_BIT)
46#define LBR_USER (1 << LBR_USER_BIT) 53#define LBR_USER (1 << LBR_USER_BIT)
47#define LBR_JCC (1 << LBR_JCC_BIT) 54#define LBR_JCC (1 << LBR_JCC_BIT)
@@ -52,6 +59,7 @@ static enum {
52#define LBR_IND_JMP (1 << LBR_IND_JMP_BIT) 59#define LBR_IND_JMP (1 << LBR_IND_JMP_BIT)
53#define LBR_FAR (1 << LBR_FAR_BIT) 60#define LBR_FAR (1 << LBR_FAR_BIT)
54#define LBR_CALL_STACK (1 << LBR_CALL_STACK_BIT) 61#define LBR_CALL_STACK (1 << LBR_CALL_STACK_BIT)
62#define LBR_NO_INFO (1ULL << LBR_NO_INFO_BIT)
55 63
56#define LBR_PLM (LBR_KERNEL | LBR_USER) 64#define LBR_PLM (LBR_KERNEL | LBR_USER)
57 65
@@ -152,8 +160,8 @@ static void __intel_pmu_lbr_enable(bool pmi)
152 * did not change. 160 * did not change.
153 */ 161 */
154 if (cpuc->lbr_sel) 162 if (cpuc->lbr_sel)
155 lbr_select = cpuc->lbr_sel->config; 163 lbr_select = cpuc->lbr_sel->config & x86_pmu.lbr_sel_mask;
156 if (!pmi) 164 if (!pmi && cpuc->lbr_sel)
157 wrmsrl(MSR_LBR_SELECT, lbr_select); 165 wrmsrl(MSR_LBR_SELECT, lbr_select);
158 166
159 rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); 167 rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
@@ -422,6 +430,7 @@ static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc)
422 */ 430 */
423static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) 431static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
424{ 432{
433 bool need_info = false;
425 unsigned long mask = x86_pmu.lbr_nr - 1; 434 unsigned long mask = x86_pmu.lbr_nr - 1;
426 int lbr_format = x86_pmu.intel_cap.lbr_format; 435 int lbr_format = x86_pmu.intel_cap.lbr_format;
427 u64 tos = intel_pmu_lbr_tos(); 436 u64 tos = intel_pmu_lbr_tos();
@@ -429,8 +438,11 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
429 int out = 0; 438 int out = 0;
430 int num = x86_pmu.lbr_nr; 439 int num = x86_pmu.lbr_nr;
431 440
432 if (cpuc->lbr_sel->config & LBR_CALL_STACK) 441 if (cpuc->lbr_sel) {
433 num = tos; 442 need_info = !(cpuc->lbr_sel->config & LBR_NO_INFO);
443 if (cpuc->lbr_sel->config & LBR_CALL_STACK)
444 num = tos;
445 }
434 446
435 for (i = 0; i < num; i++) { 447 for (i = 0; i < num; i++) {
436 unsigned long lbr_idx = (tos - i) & mask; 448 unsigned long lbr_idx = (tos - i) & mask;
@@ -442,7 +454,7 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
442 rdmsrl(x86_pmu.lbr_from + lbr_idx, from); 454 rdmsrl(x86_pmu.lbr_from + lbr_idx, from);
443 rdmsrl(x86_pmu.lbr_to + lbr_idx, to); 455 rdmsrl(x86_pmu.lbr_to + lbr_idx, to);
444 456
445 if (lbr_format == LBR_FORMAT_INFO) { 457 if (lbr_format == LBR_FORMAT_INFO && need_info) {
446 u64 info; 458 u64 info;
447 459
448 rdmsrl(MSR_LBR_INFO_0 + lbr_idx, info); 460 rdmsrl(MSR_LBR_INFO_0 + lbr_idx, info);
@@ -590,6 +602,7 @@ static int intel_pmu_setup_hw_lbr_filter(struct perf_event *event)
590 if (v != LBR_IGN) 602 if (v != LBR_IGN)
591 mask |= v; 603 mask |= v;
592 } 604 }
605
593 reg = &event->hw.branch_reg; 606 reg = &event->hw.branch_reg;
594 reg->idx = EXTRA_REG_LBR; 607 reg->idx = EXTRA_REG_LBR;
595 608
@@ -600,6 +613,11 @@ static int intel_pmu_setup_hw_lbr_filter(struct perf_event *event)
600 */ 613 */
601 reg->config = mask ^ x86_pmu.lbr_sel_mask; 614 reg->config = mask ^ x86_pmu.lbr_sel_mask;
602 615
616 if ((br_type & PERF_SAMPLE_BRANCH_NO_CYCLES) &&
617 (br_type & PERF_SAMPLE_BRANCH_NO_FLAGS) &&
618 (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO))
619 reg->config |= LBR_NO_INFO;
620
603 return 0; 621 return 0;
604} 622}
605 623
@@ -1028,3 +1046,17 @@ void __init intel_pmu_lbr_init_atom(void)
1028 */ 1046 */
1029 pr_cont("8-deep LBR, "); 1047 pr_cont("8-deep LBR, ");
1030} 1048}
1049
1050/* Knights Landing */
1051void intel_pmu_lbr_init_knl(void)
1052{
1053 x86_pmu.lbr_nr = 8;
1054 x86_pmu.lbr_tos = MSR_LBR_TOS;
1055 x86_pmu.lbr_from = MSR_LBR_NHM_FROM;
1056 x86_pmu.lbr_to = MSR_LBR_NHM_TO;
1057
1058 x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
1059 x86_pmu.lbr_sel_map = snb_lbr_sel_map;
1060
1061 pr_cont("8-deep LBR, ");
1062}
diff --git a/arch/x86/kernel/cpu/perf_event_intel_pt.c b/arch/x86/kernel/cpu/perf_event_intel_pt.c
index 868e1194337f..c0bbd1033b7c 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_pt.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_pt.c
@@ -27,6 +27,7 @@
27#include <asm/perf_event.h> 27#include <asm/perf_event.h>
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 31
31#include "perf_event.h" 32#include "perf_event.h"
32#include "intel_pt.h" 33#include "intel_pt.h"
@@ -1122,6 +1123,14 @@ static int pt_event_init(struct perf_event *event)
1122 return 0; 1123 return 0;
1123} 1124}
1124 1125
1126void cpu_emergency_stop_pt(void)
1127{
1128 struct pt *pt = this_cpu_ptr(&pt_ctx);
1129
1130 if (pt->handle.event)
1131 pt_event_stop(pt->handle.event, PERF_EF_UPDATE);
1132}
1133
1125static __init int pt_init(void) 1134static __init int pt_init(void)
1126{ 1135{
1127 int ret, cpu, prior_warn = 0; 1136 int ret, cpu, prior_warn = 0;
diff --git a/arch/x86/kernel/cpu/perf_event_intel_rapl.c b/arch/x86/kernel/cpu/perf_event_intel_rapl.c
index ed446bdcbf31..24a351ad628d 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_rapl.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_rapl.c
@@ -63,7 +63,7 @@
63#define INTEL_RAPL_PP1 0x4 /* pseudo-encoding */ 63#define INTEL_RAPL_PP1 0x4 /* pseudo-encoding */
64 64
65#define NR_RAPL_DOMAINS 0x4 65#define NR_RAPL_DOMAINS 0x4
66static const char *rapl_domain_names[NR_RAPL_DOMAINS] __initconst = { 66static const char *const rapl_domain_names[NR_RAPL_DOMAINS] __initconst = {
67 "pp0-core", 67 "pp0-core",
68 "package", 68 "package",
69 "dram", 69 "dram",
@@ -109,11 +109,11 @@ static struct kobj_attribute format_attr_##_var = \
109 109
110#define RAPL_CNTR_WIDTH 32 /* 32-bit rapl counters */ 110#define RAPL_CNTR_WIDTH 32 /* 32-bit rapl counters */
111 111
112#define RAPL_EVENT_ATTR_STR(_name, v, str) \ 112#define RAPL_EVENT_ATTR_STR(_name, v, str) \
113static struct perf_pmu_events_attr event_attr_##v = { \ 113static struct perf_pmu_events_attr event_attr_##v = { \
114 .attr = __ATTR(_name, 0444, rapl_sysfs_show, NULL), \ 114 .attr = __ATTR(_name, 0444, perf_event_sysfs_show, NULL), \
115 .id = 0, \ 115 .id = 0, \
116 .event_str = str, \ 116 .event_str = str, \
117}; 117};
118 118
119struct rapl_pmu { 119struct rapl_pmu {
@@ -405,19 +405,6 @@ static struct attribute_group rapl_pmu_attr_group = {
405 .attrs = rapl_pmu_attrs, 405 .attrs = rapl_pmu_attrs,
406}; 406};
407 407
408static ssize_t rapl_sysfs_show(struct device *dev,
409 struct device_attribute *attr,
410 char *page)
411{
412 struct perf_pmu_events_attr *pmu_attr = \
413 container_of(attr, struct perf_pmu_events_attr, attr);
414
415 if (pmu_attr->event_str)
416 return sprintf(page, "%s", pmu_attr->event_str);
417
418 return 0;
419}
420
421RAPL_EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01"); 408RAPL_EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01");
422RAPL_EVENT_ATTR_STR(energy-pkg , rapl_pkg, "event=0x02"); 409RAPL_EVENT_ATTR_STR(energy-pkg , rapl_pkg, "event=0x02");
423RAPL_EVENT_ATTR_STR(energy-ram , rapl_ram, "event=0x03"); 410RAPL_EVENT_ATTR_STR(energy-ram , rapl_ram, "event=0x03");
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
index 61215a69b03d..f97f8075bf04 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
@@ -884,6 +884,15 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id
884 * each box has a different function id. 884 * each box has a different function id.
885 */ 885 */
886 pmu = &type->pmus[UNCORE_PCI_DEV_IDX(id->driver_data)]; 886 pmu = &type->pmus[UNCORE_PCI_DEV_IDX(id->driver_data)];
887 /* Knights Landing uses a common PCI device ID for multiple instances of
888 * an uncore PMU device type. There is only one entry per device type in
889 * the knl_uncore_pci_ids table inspite of multiple devices present for
890 * some device types. Hence PCI device idx would be 0 for all devices.
891 * So increment pmu pointer to point to an unused array element.
892 */
893 if (boot_cpu_data.x86_model == 87)
894 while (pmu->func_id >= 0)
895 pmu++;
887 if (pmu->func_id < 0) 896 if (pmu->func_id < 0)
888 pmu->func_id = pdev->devfn; 897 pmu->func_id = pdev->devfn;
889 else 898 else
@@ -966,6 +975,7 @@ static int __init uncore_pci_init(void)
966 case 63: /* Haswell-EP */ 975 case 63: /* Haswell-EP */
967 ret = hswep_uncore_pci_init(); 976 ret = hswep_uncore_pci_init();
968 break; 977 break;
978 case 79: /* BDX-EP */
969 case 86: /* BDX-DE */ 979 case 86: /* BDX-DE */
970 ret = bdx_uncore_pci_init(); 980 ret = bdx_uncore_pci_init();
971 break; 981 break;
@@ -982,6 +992,9 @@ static int __init uncore_pci_init(void)
982 case 61: /* Broadwell */ 992 case 61: /* Broadwell */
983 ret = bdw_uncore_pci_init(); 993 ret = bdw_uncore_pci_init();
984 break; 994 break;
995 case 87: /* Knights Landing */
996 ret = knl_uncore_pci_init();
997 break;
985 default: 998 default:
986 return 0; 999 return 0;
987 } 1000 }
@@ -1287,9 +1300,13 @@ static int __init uncore_cpu_init(void)
1287 case 63: /* Haswell-EP */ 1300 case 63: /* Haswell-EP */
1288 hswep_uncore_cpu_init(); 1301 hswep_uncore_cpu_init();
1289 break; 1302 break;
1303 case 79: /* BDX-EP */
1290 case 86: /* BDX-DE */ 1304 case 86: /* BDX-DE */
1291 bdx_uncore_cpu_init(); 1305 bdx_uncore_cpu_init();
1292 break; 1306 break;
1307 case 87: /* Knights Landing */
1308 knl_uncore_cpu_init();
1309 break;
1293 default: 1310 default:
1294 return 0; 1311 return 0;
1295 } 1312 }
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
index 2f0a4a98e16b..07aa2d6bd710 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
@@ -338,6 +338,7 @@ int hsw_uncore_pci_init(void);
338int bdw_uncore_pci_init(void); 338int bdw_uncore_pci_init(void);
339void snb_uncore_cpu_init(void); 339void snb_uncore_cpu_init(void);
340void nhm_uncore_cpu_init(void); 340void nhm_uncore_cpu_init(void);
341int snb_pci2phy_map_init(int devid);
341 342
342/* perf_event_intel_uncore_snbep.c */ 343/* perf_event_intel_uncore_snbep.c */
343int snbep_uncore_pci_init(void); 344int snbep_uncore_pci_init(void);
@@ -348,6 +349,8 @@ int hswep_uncore_pci_init(void);
348void hswep_uncore_cpu_init(void); 349void hswep_uncore_cpu_init(void);
349int bdx_uncore_pci_init(void); 350int bdx_uncore_pci_init(void);
350void bdx_uncore_cpu_init(void); 351void bdx_uncore_cpu_init(void);
352int knl_uncore_pci_init(void);
353void knl_uncore_cpu_init(void);
351 354
352/* perf_event_intel_uncore_nhmex.c */ 355/* perf_event_intel_uncore_nhmex.c */
353void nhmex_uncore_cpu_init(void); 356void nhmex_uncore_cpu_init(void);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore_snb.c b/arch/x86/kernel/cpu/perf_event_intel_uncore_snb.c
index 845256158a10..0b934820fafd 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore_snb.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore_snb.c
@@ -417,7 +417,7 @@ static void snb_uncore_imc_event_del(struct perf_event *event, int flags)
417 } 417 }
418} 418}
419 419
420static int snb_pci2phy_map_init(int devid) 420int snb_pci2phy_map_init(int devid)
421{ 421{
422 struct pci_dev *dev = NULL; 422 struct pci_dev *dev = NULL;
423 struct pci2phy_map *map; 423 struct pci2phy_map *map;
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c b/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c
index f0f4fcba252e..33acb884ccf1 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c
@@ -209,31 +209,98 @@
209#define HSWEP_PCU_MSR_PMON_BOX_CTL 0x710 209#define HSWEP_PCU_MSR_PMON_BOX_CTL 0x710
210#define HSWEP_PCU_MSR_PMON_BOX_FILTER 0x715 210#define HSWEP_PCU_MSR_PMON_BOX_FILTER 0x715
211 211
212/* KNL Ubox */
213#define KNL_U_MSR_PMON_RAW_EVENT_MASK \
214 (SNBEP_U_MSR_PMON_RAW_EVENT_MASK | \
215 SNBEP_CBO_PMON_CTL_TID_EN)
216/* KNL CHA */
217#define KNL_CHA_MSR_OFFSET 0xc
218#define KNL_CHA_MSR_PMON_CTL_QOR (1 << 16)
219#define KNL_CHA_MSR_PMON_RAW_EVENT_MASK \
220 (SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK | \
221 KNL_CHA_MSR_PMON_CTL_QOR)
222#define KNL_CHA_MSR_PMON_BOX_FILTER_TID 0x1ff
223#define KNL_CHA_MSR_PMON_BOX_FILTER_STATE (7 << 18)
224#define KNL_CHA_MSR_PMON_BOX_FILTER_OP (0xfffffe2aULL << 32)
225
226/* KNL EDC/MC UCLK */
227#define KNL_UCLK_MSR_PMON_CTR0_LOW 0x400
228#define KNL_UCLK_MSR_PMON_CTL0 0x420
229#define KNL_UCLK_MSR_PMON_BOX_CTL 0x430
230#define KNL_UCLK_MSR_PMON_UCLK_FIXED_LOW 0x44c
231#define KNL_UCLK_MSR_PMON_UCLK_FIXED_CTL 0x454
232#define KNL_PMON_FIXED_CTL_EN 0x1
233
234/* KNL EDC */
235#define KNL_EDC0_ECLK_MSR_PMON_CTR0_LOW 0xa00
236#define KNL_EDC0_ECLK_MSR_PMON_CTL0 0xa20
237#define KNL_EDC0_ECLK_MSR_PMON_BOX_CTL 0xa30
238#define KNL_EDC0_ECLK_MSR_PMON_ECLK_FIXED_LOW 0xa3c
239#define KNL_EDC0_ECLK_MSR_PMON_ECLK_FIXED_CTL 0xa44
240
241/* KNL MC */
242#define KNL_MC0_CH0_MSR_PMON_CTR0_LOW 0xb00
243#define KNL_MC0_CH0_MSR_PMON_CTL0 0xb20
244#define KNL_MC0_CH0_MSR_PMON_BOX_CTL 0xb30
245#define KNL_MC0_CH0_MSR_PMON_FIXED_LOW 0xb3c
246#define KNL_MC0_CH0_MSR_PMON_FIXED_CTL 0xb44
247
248/* KNL IRP */
249#define KNL_IRP_PCI_PMON_BOX_CTL 0xf0
250#define KNL_IRP_PCI_PMON_RAW_EVENT_MASK (SNBEP_PMON_RAW_EVENT_MASK | \
251 KNL_CHA_MSR_PMON_CTL_QOR)
252/* KNL PCU */
253#define KNL_PCU_PMON_CTL_EV_SEL_MASK 0x0000007f
254#define KNL_PCU_PMON_CTL_USE_OCC_CTR (1 << 7)
255#define KNL_PCU_MSR_PMON_CTL_TRESH_MASK 0x3f000000
256#define KNL_PCU_MSR_PMON_RAW_EVENT_MASK \
257 (KNL_PCU_PMON_CTL_EV_SEL_MASK | \
258 KNL_PCU_PMON_CTL_USE_OCC_CTR | \
259 SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \
260 SNBEP_PMON_CTL_EDGE_DET | \
261 SNBEP_CBO_PMON_CTL_TID_EN | \
262 SNBEP_PMON_CTL_EV_SEL_EXT | \
263 SNBEP_PMON_CTL_INVERT | \
264 KNL_PCU_MSR_PMON_CTL_TRESH_MASK | \
265 SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \
266 SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET)
212 267
213DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7"); 268DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7");
269DEFINE_UNCORE_FORMAT_ATTR(event2, event, "config:0-6");
214DEFINE_UNCORE_FORMAT_ATTR(event_ext, event, "config:0-7,21"); 270DEFINE_UNCORE_FORMAT_ATTR(event_ext, event, "config:0-7,21");
271DEFINE_UNCORE_FORMAT_ATTR(use_occ_ctr, use_occ_ctr, "config:7");
215DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15"); 272DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15");
273DEFINE_UNCORE_FORMAT_ATTR(qor, qor, "config:16");
216DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18"); 274DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18");
217DEFINE_UNCORE_FORMAT_ATTR(tid_en, tid_en, "config:19"); 275DEFINE_UNCORE_FORMAT_ATTR(tid_en, tid_en, "config:19");
218DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23"); 276DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23");
219DEFINE_UNCORE_FORMAT_ATTR(thresh8, thresh, "config:24-31"); 277DEFINE_UNCORE_FORMAT_ATTR(thresh8, thresh, "config:24-31");
278DEFINE_UNCORE_FORMAT_ATTR(thresh6, thresh, "config:24-29");
220DEFINE_UNCORE_FORMAT_ATTR(thresh5, thresh, "config:24-28"); 279DEFINE_UNCORE_FORMAT_ATTR(thresh5, thresh, "config:24-28");
221DEFINE_UNCORE_FORMAT_ATTR(occ_sel, occ_sel, "config:14-15"); 280DEFINE_UNCORE_FORMAT_ATTR(occ_sel, occ_sel, "config:14-15");
222DEFINE_UNCORE_FORMAT_ATTR(occ_invert, occ_invert, "config:30"); 281DEFINE_UNCORE_FORMAT_ATTR(occ_invert, occ_invert, "config:30");
223DEFINE_UNCORE_FORMAT_ATTR(occ_edge, occ_edge, "config:14-51"); 282DEFINE_UNCORE_FORMAT_ATTR(occ_edge, occ_edge, "config:14-51");
283DEFINE_UNCORE_FORMAT_ATTR(occ_edge_det, occ_edge_det, "config:31");
224DEFINE_UNCORE_FORMAT_ATTR(filter_tid, filter_tid, "config1:0-4"); 284DEFINE_UNCORE_FORMAT_ATTR(filter_tid, filter_tid, "config1:0-4");
225DEFINE_UNCORE_FORMAT_ATTR(filter_tid2, filter_tid, "config1:0"); 285DEFINE_UNCORE_FORMAT_ATTR(filter_tid2, filter_tid, "config1:0");
226DEFINE_UNCORE_FORMAT_ATTR(filter_tid3, filter_tid, "config1:0-5"); 286DEFINE_UNCORE_FORMAT_ATTR(filter_tid3, filter_tid, "config1:0-5");
287DEFINE_UNCORE_FORMAT_ATTR(filter_tid4, filter_tid, "config1:0-8");
227DEFINE_UNCORE_FORMAT_ATTR(filter_cid, filter_cid, "config1:5"); 288DEFINE_UNCORE_FORMAT_ATTR(filter_cid, filter_cid, "config1:5");
228DEFINE_UNCORE_FORMAT_ATTR(filter_link, filter_link, "config1:5-8"); 289DEFINE_UNCORE_FORMAT_ATTR(filter_link, filter_link, "config1:5-8");
229DEFINE_UNCORE_FORMAT_ATTR(filter_link2, filter_link, "config1:6-8"); 290DEFINE_UNCORE_FORMAT_ATTR(filter_link2, filter_link, "config1:6-8");
291DEFINE_UNCORE_FORMAT_ATTR(filter_link3, filter_link, "config1:12");
230DEFINE_UNCORE_FORMAT_ATTR(filter_nid, filter_nid, "config1:10-17"); 292DEFINE_UNCORE_FORMAT_ATTR(filter_nid, filter_nid, "config1:10-17");
231DEFINE_UNCORE_FORMAT_ATTR(filter_nid2, filter_nid, "config1:32-47"); 293DEFINE_UNCORE_FORMAT_ATTR(filter_nid2, filter_nid, "config1:32-47");
232DEFINE_UNCORE_FORMAT_ATTR(filter_state, filter_state, "config1:18-22"); 294DEFINE_UNCORE_FORMAT_ATTR(filter_state, filter_state, "config1:18-22");
233DEFINE_UNCORE_FORMAT_ATTR(filter_state2, filter_state, "config1:17-22"); 295DEFINE_UNCORE_FORMAT_ATTR(filter_state2, filter_state, "config1:17-22");
234DEFINE_UNCORE_FORMAT_ATTR(filter_state3, filter_state, "config1:17-23"); 296DEFINE_UNCORE_FORMAT_ATTR(filter_state3, filter_state, "config1:17-23");
297DEFINE_UNCORE_FORMAT_ATTR(filter_state4, filter_state, "config1:18-20");
298DEFINE_UNCORE_FORMAT_ATTR(filter_local, filter_local, "config1:33");
299DEFINE_UNCORE_FORMAT_ATTR(filter_all_op, filter_all_op, "config1:35");
300DEFINE_UNCORE_FORMAT_ATTR(filter_nnm, filter_nnm, "config1:37");
235DEFINE_UNCORE_FORMAT_ATTR(filter_opc, filter_opc, "config1:23-31"); 301DEFINE_UNCORE_FORMAT_ATTR(filter_opc, filter_opc, "config1:23-31");
236DEFINE_UNCORE_FORMAT_ATTR(filter_opc2, filter_opc, "config1:52-60"); 302DEFINE_UNCORE_FORMAT_ATTR(filter_opc2, filter_opc, "config1:52-60");
303DEFINE_UNCORE_FORMAT_ATTR(filter_opc3, filter_opc, "config1:41-60");
237DEFINE_UNCORE_FORMAT_ATTR(filter_nc, filter_nc, "config1:62"); 304DEFINE_UNCORE_FORMAT_ATTR(filter_nc, filter_nc, "config1:62");
238DEFINE_UNCORE_FORMAT_ATTR(filter_c6, filter_c6, "config1:61"); 305DEFINE_UNCORE_FORMAT_ATTR(filter_c6, filter_c6, "config1:61");
239DEFINE_UNCORE_FORMAT_ATTR(filter_isoc, filter_isoc, "config1:63"); 306DEFINE_UNCORE_FORMAT_ATTR(filter_isoc, filter_isoc, "config1:63");
@@ -315,8 +382,9 @@ static u64 snbep_uncore_pci_read_counter(struct intel_uncore_box *box, struct pe
315static void snbep_uncore_pci_init_box(struct intel_uncore_box *box) 382static void snbep_uncore_pci_init_box(struct intel_uncore_box *box)
316{ 383{
317 struct pci_dev *pdev = box->pci_dev; 384 struct pci_dev *pdev = box->pci_dev;
385 int box_ctl = uncore_pci_box_ctl(box);
318 386
319 pci_write_config_dword(pdev, SNBEP_PCI_PMON_BOX_CTL, SNBEP_PMON_BOX_CTL_INT); 387 pci_write_config_dword(pdev, box_ctl, SNBEP_PMON_BOX_CTL_INT);
320} 388}
321 389
322static void snbep_uncore_msr_disable_box(struct intel_uncore_box *box) 390static void snbep_uncore_msr_disable_box(struct intel_uncore_box *box)
@@ -1728,6 +1796,419 @@ int ivbep_uncore_pci_init(void)
1728} 1796}
1729/* end of IvyTown uncore support */ 1797/* end of IvyTown uncore support */
1730 1798
1799/* KNL uncore support */
1800static struct attribute *knl_uncore_ubox_formats_attr[] = {
1801 &format_attr_event.attr,
1802 &format_attr_umask.attr,
1803 &format_attr_edge.attr,
1804 &format_attr_tid_en.attr,
1805 &format_attr_inv.attr,
1806 &format_attr_thresh5.attr,
1807 NULL,
1808};
1809
1810static struct attribute_group knl_uncore_ubox_format_group = {
1811 .name = "format",
1812 .attrs = knl_uncore_ubox_formats_attr,
1813};
1814
1815static struct intel_uncore_type knl_uncore_ubox = {
1816 .name = "ubox",
1817 .num_counters = 2,
1818 .num_boxes = 1,
1819 .perf_ctr_bits = 48,
1820 .fixed_ctr_bits = 48,
1821 .perf_ctr = HSWEP_U_MSR_PMON_CTR0,
1822 .event_ctl = HSWEP_U_MSR_PMON_CTL0,
1823 .event_mask = KNL_U_MSR_PMON_RAW_EVENT_MASK,
1824 .fixed_ctr = HSWEP_U_MSR_PMON_UCLK_FIXED_CTR,
1825 .fixed_ctl = HSWEP_U_MSR_PMON_UCLK_FIXED_CTL,
1826 .ops = &snbep_uncore_msr_ops,
1827 .format_group = &knl_uncore_ubox_format_group,
1828};
1829
1830static struct attribute *knl_uncore_cha_formats_attr[] = {
1831 &format_attr_event.attr,
1832 &format_attr_umask.attr,
1833 &format_attr_qor.attr,
1834 &format_attr_edge.attr,
1835 &format_attr_tid_en.attr,
1836 &format_attr_inv.attr,
1837 &format_attr_thresh8.attr,
1838 &format_attr_filter_tid4.attr,
1839 &format_attr_filter_link3.attr,
1840 &format_attr_filter_state4.attr,
1841 &format_attr_filter_local.attr,
1842 &format_attr_filter_all_op.attr,
1843 &format_attr_filter_nnm.attr,
1844 &format_attr_filter_opc3.attr,
1845 &format_attr_filter_nc.attr,
1846 &format_attr_filter_isoc.attr,
1847 NULL,
1848};
1849
1850static struct attribute_group knl_uncore_cha_format_group = {
1851 .name = "format",
1852 .attrs = knl_uncore_cha_formats_attr,
1853};
1854
1855static struct event_constraint knl_uncore_cha_constraints[] = {
1856 UNCORE_EVENT_CONSTRAINT(0x11, 0x1),
1857 UNCORE_EVENT_CONSTRAINT(0x1f, 0x1),
1858 UNCORE_EVENT_CONSTRAINT(0x36, 0x1),
1859 EVENT_CONSTRAINT_END
1860};
1861
1862static struct extra_reg knl_uncore_cha_extra_regs[] = {
1863 SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
1864 SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
1865 SNBEP_CBO_EVENT_EXTRA_REG(0x3d, 0xff, 0x2),
1866 SNBEP_CBO_EVENT_EXTRA_REG(0x35, 0xff, 0x4),
1867 SNBEP_CBO_EVENT_EXTRA_REG(0x36, 0xff, 0x4),
1868 EVENT_EXTRA_END
1869};
1870
1871static u64 knl_cha_filter_mask(int fields)
1872{
1873 u64 mask = 0;
1874
1875 if (fields & 0x1)
1876 mask |= KNL_CHA_MSR_PMON_BOX_FILTER_TID;
1877 if (fields & 0x2)
1878 mask |= KNL_CHA_MSR_PMON_BOX_FILTER_STATE;
1879 if (fields & 0x4)
1880 mask |= KNL_CHA_MSR_PMON_BOX_FILTER_OP;
1881 return mask;
1882}
1883
1884static struct event_constraint *
1885knl_cha_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
1886{
1887 return __snbep_cbox_get_constraint(box, event, knl_cha_filter_mask);
1888}
1889
1890static int knl_cha_hw_config(struct intel_uncore_box *box,
1891 struct perf_event *event)
1892{
1893 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
1894 struct extra_reg *er;
1895 int idx = 0;
1896
1897 for (er = knl_uncore_cha_extra_regs; er->msr; er++) {
1898 if (er->event != (event->hw.config & er->config_mask))
1899 continue;
1900 idx |= er->idx;
1901 }
1902
1903 if (idx) {
1904 reg1->reg = HSWEP_C0_MSR_PMON_BOX_FILTER0 +
1905 KNL_CHA_MSR_OFFSET * box->pmu->pmu_idx;
1906 reg1->config = event->attr.config1 & knl_cha_filter_mask(idx);
1907 reg1->idx = idx;
1908 }
1909 return 0;
1910}
1911
1912static void hswep_cbox_enable_event(struct intel_uncore_box *box,
1913 struct perf_event *event);
1914
1915static struct intel_uncore_ops knl_uncore_cha_ops = {
1916 .init_box = snbep_uncore_msr_init_box,
1917 .disable_box = snbep_uncore_msr_disable_box,
1918 .enable_box = snbep_uncore_msr_enable_box,
1919 .disable_event = snbep_uncore_msr_disable_event,
1920 .enable_event = hswep_cbox_enable_event,
1921 .read_counter = uncore_msr_read_counter,
1922 .hw_config = knl_cha_hw_config,
1923 .get_constraint = knl_cha_get_constraint,
1924 .put_constraint = snbep_cbox_put_constraint,
1925};
1926
1927static struct intel_uncore_type knl_uncore_cha = {
1928 .name = "cha",
1929 .num_counters = 4,
1930 .num_boxes = 38,
1931 .perf_ctr_bits = 48,
1932 .event_ctl = HSWEP_C0_MSR_PMON_CTL0,
1933 .perf_ctr = HSWEP_C0_MSR_PMON_CTR0,
1934 .event_mask = KNL_CHA_MSR_PMON_RAW_EVENT_MASK,
1935 .box_ctl = HSWEP_C0_MSR_PMON_BOX_CTL,
1936 .msr_offset = KNL_CHA_MSR_OFFSET,
1937 .num_shared_regs = 1,
1938 .constraints = knl_uncore_cha_constraints,
1939 .ops = &knl_uncore_cha_ops,
1940 .format_group = &knl_uncore_cha_format_group,
1941};
1942
1943static struct attribute *knl_uncore_pcu_formats_attr[] = {
1944 &format_attr_event2.attr,
1945 &format_attr_use_occ_ctr.attr,
1946 &format_attr_occ_sel.attr,
1947 &format_attr_edge.attr,
1948 &format_attr_tid_en.attr,
1949 &format_attr_inv.attr,
1950 &format_attr_thresh6.attr,
1951 &format_attr_occ_invert.attr,
1952 &format_attr_occ_edge_det.attr,
1953 NULL,
1954};
1955
1956static struct attribute_group knl_uncore_pcu_format_group = {
1957 .name = "format",
1958 .attrs = knl_uncore_pcu_formats_attr,
1959};
1960
1961static struct intel_uncore_type knl_uncore_pcu = {
1962 .name = "pcu",
1963 .num_counters = 4,
1964 .num_boxes = 1,
1965 .perf_ctr_bits = 48,
1966 .perf_ctr = HSWEP_PCU_MSR_PMON_CTR0,
1967 .event_ctl = HSWEP_PCU_MSR_PMON_CTL0,
1968 .event_mask = KNL_PCU_MSR_PMON_RAW_EVENT_MASK,
1969 .box_ctl = HSWEP_PCU_MSR_PMON_BOX_CTL,
1970 .ops = &snbep_uncore_msr_ops,
1971 .format_group = &knl_uncore_pcu_format_group,
1972};
1973
1974static struct intel_uncore_type *knl_msr_uncores[] = {
1975 &knl_uncore_ubox,
1976 &knl_uncore_cha,
1977 &knl_uncore_pcu,
1978 NULL,
1979};
1980
1981void knl_uncore_cpu_init(void)
1982{
1983 uncore_msr_uncores = knl_msr_uncores;
1984}
1985
1986static void knl_uncore_imc_enable_box(struct intel_uncore_box *box)
1987{
1988 struct pci_dev *pdev = box->pci_dev;
1989 int box_ctl = uncore_pci_box_ctl(box);
1990
1991 pci_write_config_dword(pdev, box_ctl, 0);
1992}
1993
1994static void knl_uncore_imc_enable_event(struct intel_uncore_box *box,
1995 struct perf_event *event)
1996{
1997 struct pci_dev *pdev = box->pci_dev;
1998 struct hw_perf_event *hwc = &event->hw;
1999
2000 if ((event->attr.config & SNBEP_PMON_CTL_EV_SEL_MASK)
2001 == UNCORE_FIXED_EVENT)
2002 pci_write_config_dword(pdev, hwc->config_base,
2003 hwc->config | KNL_PMON_FIXED_CTL_EN);
2004 else
2005 pci_write_config_dword(pdev, hwc->config_base,
2006 hwc->config | SNBEP_PMON_CTL_EN);
2007}
2008
2009static struct intel_uncore_ops knl_uncore_imc_ops = {
2010 .init_box = snbep_uncore_pci_init_box,
2011 .disable_box = snbep_uncore_pci_disable_box,
2012 .enable_box = knl_uncore_imc_enable_box,
2013 .read_counter = snbep_uncore_pci_read_counter,
2014 .enable_event = knl_uncore_imc_enable_event,
2015 .disable_event = snbep_uncore_pci_disable_event,
2016};
2017
2018static struct intel_uncore_type knl_uncore_imc_uclk = {
2019 .name = "imc_uclk",
2020 .num_counters = 4,
2021 .num_boxes = 2,
2022 .perf_ctr_bits = 48,
2023 .fixed_ctr_bits = 48,
2024 .perf_ctr = KNL_UCLK_MSR_PMON_CTR0_LOW,
2025 .event_ctl = KNL_UCLK_MSR_PMON_CTL0,
2026 .event_mask = SNBEP_PMON_RAW_EVENT_MASK,
2027 .fixed_ctr = KNL_UCLK_MSR_PMON_UCLK_FIXED_LOW,
2028 .fixed_ctl = KNL_UCLK_MSR_PMON_UCLK_FIXED_CTL,
2029 .box_ctl = KNL_UCLK_MSR_PMON_BOX_CTL,
2030 .ops = &knl_uncore_imc_ops,
2031 .format_group = &snbep_uncore_format_group,
2032};
2033
2034static struct intel_uncore_type knl_uncore_imc_dclk = {
2035 .name = "imc",
2036 .num_counters = 4,
2037 .num_boxes = 6,
2038 .perf_ctr_bits = 48,
2039 .fixed_ctr_bits = 48,
2040 .perf_ctr = KNL_MC0_CH0_MSR_PMON_CTR0_LOW,
2041 .event_ctl = KNL_MC0_CH0_MSR_PMON_CTL0,
2042 .event_mask = SNBEP_PMON_RAW_EVENT_MASK,
2043 .fixed_ctr = KNL_MC0_CH0_MSR_PMON_FIXED_LOW,
2044 .fixed_ctl = KNL_MC0_CH0_MSR_PMON_FIXED_CTL,
2045 .box_ctl = KNL_MC0_CH0_MSR_PMON_BOX_CTL,
2046 .ops = &knl_uncore_imc_ops,
2047 .format_group = &snbep_uncore_format_group,
2048};
2049
2050static struct intel_uncore_type knl_uncore_edc_uclk = {
2051 .name = "edc_uclk",
2052 .num_counters = 4,
2053 .num_boxes = 8,
2054 .perf_ctr_bits = 48,
2055 .fixed_ctr_bits = 48,
2056 .perf_ctr = KNL_UCLK_MSR_PMON_CTR0_LOW,
2057 .event_ctl = KNL_UCLK_MSR_PMON_CTL0,
2058 .event_mask = SNBEP_PMON_RAW_EVENT_MASK,
2059 .fixed_ctr = KNL_UCLK_MSR_PMON_UCLK_FIXED_LOW,
2060 .fixed_ctl = KNL_UCLK_MSR_PMON_UCLK_FIXED_CTL,
2061 .box_ctl = KNL_UCLK_MSR_PMON_BOX_CTL,
2062 .ops = &knl_uncore_imc_ops,
2063 .format_group = &snbep_uncore_format_group,
2064};
2065
2066static struct intel_uncore_type knl_uncore_edc_eclk = {
2067 .name = "edc_eclk",
2068 .num_counters = 4,
2069 .num_boxes = 8,
2070 .perf_ctr_bits = 48,
2071 .fixed_ctr_bits = 48,
2072 .perf_ctr = KNL_EDC0_ECLK_MSR_PMON_CTR0_LOW,
2073 .event_ctl = KNL_EDC0_ECLK_MSR_PMON_CTL0,
2074 .event_mask = SNBEP_PMON_RAW_EVENT_MASK,
2075 .fixed_ctr = KNL_EDC0_ECLK_MSR_PMON_ECLK_FIXED_LOW,
2076 .fixed_ctl = KNL_EDC0_ECLK_MSR_PMON_ECLK_FIXED_CTL,
2077 .box_ctl = KNL_EDC0_ECLK_MSR_PMON_BOX_CTL,
2078 .ops = &knl_uncore_imc_ops,
2079 .format_group = &snbep_uncore_format_group,
2080};
2081
2082static struct event_constraint knl_uncore_m2pcie_constraints[] = {
2083 UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
2084 EVENT_CONSTRAINT_END
2085};
2086
2087static struct intel_uncore_type knl_uncore_m2pcie = {
2088 .name = "m2pcie",
2089 .num_counters = 4,
2090 .num_boxes = 1,
2091 .perf_ctr_bits = 48,
2092 .constraints = knl_uncore_m2pcie_constraints,
2093 SNBEP_UNCORE_PCI_COMMON_INIT(),
2094};
2095
2096static struct attribute *knl_uncore_irp_formats_attr[] = {
2097 &format_attr_event.attr,
2098 &format_attr_umask.attr,
2099 &format_attr_qor.attr,
2100 &format_attr_edge.attr,
2101 &format_attr_inv.attr,
2102 &format_attr_thresh8.attr,
2103 NULL,
2104};
2105
2106static struct attribute_group knl_uncore_irp_format_group = {
2107 .name = "format",
2108 .attrs = knl_uncore_irp_formats_attr,
2109};
2110
2111static struct intel_uncore_type knl_uncore_irp = {
2112 .name = "irp",
2113 .num_counters = 2,
2114 .num_boxes = 1,
2115 .perf_ctr_bits = 48,
2116 .perf_ctr = SNBEP_PCI_PMON_CTR0,
2117 .event_ctl = SNBEP_PCI_PMON_CTL0,
2118 .event_mask = KNL_IRP_PCI_PMON_RAW_EVENT_MASK,
2119 .box_ctl = KNL_IRP_PCI_PMON_BOX_CTL,
2120 .ops = &snbep_uncore_pci_ops,
2121 .format_group = &knl_uncore_irp_format_group,
2122};
2123
2124enum {
2125 KNL_PCI_UNCORE_MC_UCLK,
2126 KNL_PCI_UNCORE_MC_DCLK,
2127 KNL_PCI_UNCORE_EDC_UCLK,
2128 KNL_PCI_UNCORE_EDC_ECLK,
2129 KNL_PCI_UNCORE_M2PCIE,
2130 KNL_PCI_UNCORE_IRP,
2131};
2132
2133static struct intel_uncore_type *knl_pci_uncores[] = {
2134 [KNL_PCI_UNCORE_MC_UCLK] = &knl_uncore_imc_uclk,
2135 [KNL_PCI_UNCORE_MC_DCLK] = &knl_uncore_imc_dclk,
2136 [KNL_PCI_UNCORE_EDC_UCLK] = &knl_uncore_edc_uclk,
2137 [KNL_PCI_UNCORE_EDC_ECLK] = &knl_uncore_edc_eclk,
2138 [KNL_PCI_UNCORE_M2PCIE] = &knl_uncore_m2pcie,
2139 [KNL_PCI_UNCORE_IRP] = &knl_uncore_irp,
2140 NULL,
2141};
2142
2143/*
2144 * KNL uses a common PCI device ID for multiple instances of an Uncore PMU
2145 * device type. prior to KNL, each instance of a PMU device type had a unique
2146 * device ID.
2147 *
2148 * PCI Device ID Uncore PMU Devices
2149 * ----------------------------------
2150 * 0x7841 MC0 UClk, MC1 UClk
2151 * 0x7843 MC0 DClk CH 0, MC0 DClk CH 1, MC0 DClk CH 2,
2152 * MC1 DClk CH 0, MC1 DClk CH 1, MC1 DClk CH 2
2153 * 0x7833 EDC0 UClk, EDC1 UClk, EDC2 UClk, EDC3 UClk,
2154 * EDC4 UClk, EDC5 UClk, EDC6 UClk, EDC7 UClk
2155 * 0x7835 EDC0 EClk, EDC1 EClk, EDC2 EClk, EDC3 EClk,
2156 * EDC4 EClk, EDC5 EClk, EDC6 EClk, EDC7 EClk
2157 * 0x7817 M2PCIe
2158 * 0x7814 IRP
2159*/
2160
2161static const struct pci_device_id knl_uncore_pci_ids[] = {
2162 { /* MC UClk */
2163 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7841),
2164 .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_MC_UCLK, 0),
2165 },
2166 { /* MC DClk Channel */
2167 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7843),
2168 .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_MC_DCLK, 0),
2169 },
2170 { /* EDC UClk */
2171 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7833),
2172 .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_EDC_UCLK, 0),
2173 },
2174 { /* EDC EClk */
2175 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7835),
2176 .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_EDC_ECLK, 0),
2177 },
2178 { /* M2PCIe */
2179 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7817),
2180 .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_M2PCIE, 0),
2181 },
2182 { /* IRP */
2183 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7814),
2184 .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_IRP, 0),
2185 },
2186 { /* end: all zeroes */ }
2187};
2188
2189static struct pci_driver knl_uncore_pci_driver = {
2190 .name = "knl_uncore",
2191 .id_table = knl_uncore_pci_ids,
2192};
2193
2194int knl_uncore_pci_init(void)
2195{
2196 int ret;
2197
2198 /* All KNL PCI based PMON units are on the same PCI bus except IRP */
2199 ret = snb_pci2phy_map_init(0x7814); /* IRP */
2200 if (ret)
2201 return ret;
2202 ret = snb_pci2phy_map_init(0x7817); /* M2PCIe */
2203 if (ret)
2204 return ret;
2205 uncore_pci_uncores = knl_pci_uncores;
2206 uncore_pci_driver = &knl_uncore_pci_driver;
2207 return 0;
2208}
2209
2210/* end of KNL uncore support */
2211
1731/* Haswell-EP uncore support */ 2212/* Haswell-EP uncore support */
1732static struct attribute *hswep_uncore_ubox_formats_attr[] = { 2213static struct attribute *hswep_uncore_ubox_formats_attr[] = {
1733 &format_attr_event.attr, 2214 &format_attr_event.attr,
@@ -2338,7 +2819,7 @@ int hswep_uncore_pci_init(void)
2338} 2819}
2339/* end of Haswell-EP uncore support */ 2820/* end of Haswell-EP uncore support */
2340 2821
2341/* BDX-DE uncore support */ 2822/* BDX uncore support */
2342 2823
2343static struct intel_uncore_type bdx_uncore_ubox = { 2824static struct intel_uncore_type bdx_uncore_ubox = {
2344 .name = "ubox", 2825 .name = "ubox",
@@ -2360,13 +2841,14 @@ static struct event_constraint bdx_uncore_cbox_constraints[] = {
2360 UNCORE_EVENT_CONSTRAINT(0x09, 0x3), 2841 UNCORE_EVENT_CONSTRAINT(0x09, 0x3),
2361 UNCORE_EVENT_CONSTRAINT(0x11, 0x1), 2842 UNCORE_EVENT_CONSTRAINT(0x11, 0x1),
2362 UNCORE_EVENT_CONSTRAINT(0x36, 0x1), 2843 UNCORE_EVENT_CONSTRAINT(0x36, 0x1),
2844 UNCORE_EVENT_CONSTRAINT(0x3e, 0x1),
2363 EVENT_CONSTRAINT_END 2845 EVENT_CONSTRAINT_END
2364}; 2846};
2365 2847
2366static struct intel_uncore_type bdx_uncore_cbox = { 2848static struct intel_uncore_type bdx_uncore_cbox = {
2367 .name = "cbox", 2849 .name = "cbox",
2368 .num_counters = 4, 2850 .num_counters = 4,
2369 .num_boxes = 8, 2851 .num_boxes = 24,
2370 .perf_ctr_bits = 48, 2852 .perf_ctr_bits = 48,
2371 .event_ctl = HSWEP_C0_MSR_PMON_CTL0, 2853 .event_ctl = HSWEP_C0_MSR_PMON_CTL0,
2372 .perf_ctr = HSWEP_C0_MSR_PMON_CTR0, 2854 .perf_ctr = HSWEP_C0_MSR_PMON_CTR0,
@@ -2379,9 +2861,24 @@ static struct intel_uncore_type bdx_uncore_cbox = {
2379 .format_group = &hswep_uncore_cbox_format_group, 2861 .format_group = &hswep_uncore_cbox_format_group,
2380}; 2862};
2381 2863
2864static struct intel_uncore_type bdx_uncore_sbox = {
2865 .name = "sbox",
2866 .num_counters = 4,
2867 .num_boxes = 4,
2868 .perf_ctr_bits = 48,
2869 .event_ctl = HSWEP_S0_MSR_PMON_CTL0,
2870 .perf_ctr = HSWEP_S0_MSR_PMON_CTR0,
2871 .event_mask = HSWEP_S_MSR_PMON_RAW_EVENT_MASK,
2872 .box_ctl = HSWEP_S0_MSR_PMON_BOX_CTL,
2873 .msr_offset = HSWEP_SBOX_MSR_OFFSET,
2874 .ops = &hswep_uncore_sbox_msr_ops,
2875 .format_group = &hswep_uncore_sbox_format_group,
2876};
2877
2382static struct intel_uncore_type *bdx_msr_uncores[] = { 2878static struct intel_uncore_type *bdx_msr_uncores[] = {
2383 &bdx_uncore_ubox, 2879 &bdx_uncore_ubox,
2384 &bdx_uncore_cbox, 2880 &bdx_uncore_cbox,
2881 &bdx_uncore_sbox,
2385 &hswep_uncore_pcu, 2882 &hswep_uncore_pcu,
2386 NULL, 2883 NULL,
2387}; 2884};
@@ -2396,7 +2893,7 @@ void bdx_uncore_cpu_init(void)
2396static struct intel_uncore_type bdx_uncore_ha = { 2893static struct intel_uncore_type bdx_uncore_ha = {
2397 .name = "ha", 2894 .name = "ha",
2398 .num_counters = 4, 2895 .num_counters = 4,
2399 .num_boxes = 1, 2896 .num_boxes = 2,
2400 .perf_ctr_bits = 48, 2897 .perf_ctr_bits = 48,
2401 SNBEP_UNCORE_PCI_COMMON_INIT(), 2898 SNBEP_UNCORE_PCI_COMMON_INIT(),
2402}; 2899};
@@ -2404,7 +2901,7 @@ static struct intel_uncore_type bdx_uncore_ha = {
2404static struct intel_uncore_type bdx_uncore_imc = { 2901static struct intel_uncore_type bdx_uncore_imc = {
2405 .name = "imc", 2902 .name = "imc",
2406 .num_counters = 5, 2903 .num_counters = 5,
2407 .num_boxes = 2, 2904 .num_boxes = 8,
2408 .perf_ctr_bits = 48, 2905 .perf_ctr_bits = 48,
2409 .fixed_ctr_bits = 48, 2906 .fixed_ctr_bits = 48,
2410 .fixed_ctr = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR, 2907 .fixed_ctr = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
@@ -2424,6 +2921,19 @@ static struct intel_uncore_type bdx_uncore_irp = {
2424 .format_group = &snbep_uncore_format_group, 2921 .format_group = &snbep_uncore_format_group,
2425}; 2922};
2426 2923
2924static struct intel_uncore_type bdx_uncore_qpi = {
2925 .name = "qpi",
2926 .num_counters = 4,
2927 .num_boxes = 3,
2928 .perf_ctr_bits = 48,
2929 .perf_ctr = SNBEP_PCI_PMON_CTR0,
2930 .event_ctl = SNBEP_PCI_PMON_CTL0,
2931 .event_mask = SNBEP_QPI_PCI_PMON_RAW_EVENT_MASK,
2932 .box_ctl = SNBEP_PCI_PMON_BOX_CTL,
2933 .num_shared_regs = 1,
2934 .ops = &snbep_uncore_qpi_ops,
2935 .format_group = &snbep_uncore_qpi_format_group,
2936};
2427 2937
2428static struct event_constraint bdx_uncore_r2pcie_constraints[] = { 2938static struct event_constraint bdx_uncore_r2pcie_constraints[] = {
2429 UNCORE_EVENT_CONSTRAINT(0x10, 0x3), 2939 UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
@@ -2432,6 +2942,8 @@ static struct event_constraint bdx_uncore_r2pcie_constraints[] = {
2432 UNCORE_EVENT_CONSTRAINT(0x23, 0x1), 2942 UNCORE_EVENT_CONSTRAINT(0x23, 0x1),
2433 UNCORE_EVENT_CONSTRAINT(0x25, 0x1), 2943 UNCORE_EVENT_CONSTRAINT(0x25, 0x1),
2434 UNCORE_EVENT_CONSTRAINT(0x26, 0x3), 2944 UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
2945 UNCORE_EVENT_CONSTRAINT(0x28, 0x3),
2946 UNCORE_EVENT_CONSTRAINT(0x2c, 0x3),
2435 UNCORE_EVENT_CONSTRAINT(0x2d, 0x3), 2947 UNCORE_EVENT_CONSTRAINT(0x2d, 0x3),
2436 EVENT_CONSTRAINT_END 2948 EVENT_CONSTRAINT_END
2437}; 2949};
@@ -2445,18 +2957,65 @@ static struct intel_uncore_type bdx_uncore_r2pcie = {
2445 SNBEP_UNCORE_PCI_COMMON_INIT(), 2957 SNBEP_UNCORE_PCI_COMMON_INIT(),
2446}; 2958};
2447 2959
2960static struct event_constraint bdx_uncore_r3qpi_constraints[] = {
2961 UNCORE_EVENT_CONSTRAINT(0x01, 0x7),
2962 UNCORE_EVENT_CONSTRAINT(0x07, 0x7),
2963 UNCORE_EVENT_CONSTRAINT(0x08, 0x7),
2964 UNCORE_EVENT_CONSTRAINT(0x09, 0x7),
2965 UNCORE_EVENT_CONSTRAINT(0x0a, 0x7),
2966 UNCORE_EVENT_CONSTRAINT(0x0e, 0x7),
2967 UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
2968 UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
2969 UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
2970 UNCORE_EVENT_CONSTRAINT(0x14, 0x3),
2971 UNCORE_EVENT_CONSTRAINT(0x15, 0x3),
2972 UNCORE_EVENT_CONSTRAINT(0x1f, 0x3),
2973 UNCORE_EVENT_CONSTRAINT(0x20, 0x3),
2974 UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
2975 UNCORE_EVENT_CONSTRAINT(0x22, 0x3),
2976 UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
2977 UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
2978 UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
2979 UNCORE_EVENT_CONSTRAINT(0x28, 0x3),
2980 UNCORE_EVENT_CONSTRAINT(0x29, 0x3),
2981 UNCORE_EVENT_CONSTRAINT(0x2c, 0x3),
2982 UNCORE_EVENT_CONSTRAINT(0x2d, 0x3),
2983 UNCORE_EVENT_CONSTRAINT(0x2e, 0x3),
2984 UNCORE_EVENT_CONSTRAINT(0x2f, 0x3),
2985 UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
2986 UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
2987 UNCORE_EVENT_CONSTRAINT(0x36, 0x3),
2988 UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
2989 UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
2990 UNCORE_EVENT_CONSTRAINT(0x39, 0x3),
2991 EVENT_CONSTRAINT_END
2992};
2993
2994static struct intel_uncore_type bdx_uncore_r3qpi = {
2995 .name = "r3qpi",
2996 .num_counters = 3,
2997 .num_boxes = 3,
2998 .perf_ctr_bits = 48,
2999 .constraints = bdx_uncore_r3qpi_constraints,
3000 SNBEP_UNCORE_PCI_COMMON_INIT(),
3001};
3002
2448enum { 3003enum {
2449 BDX_PCI_UNCORE_HA, 3004 BDX_PCI_UNCORE_HA,
2450 BDX_PCI_UNCORE_IMC, 3005 BDX_PCI_UNCORE_IMC,
2451 BDX_PCI_UNCORE_IRP, 3006 BDX_PCI_UNCORE_IRP,
3007 BDX_PCI_UNCORE_QPI,
2452 BDX_PCI_UNCORE_R2PCIE, 3008 BDX_PCI_UNCORE_R2PCIE,
3009 BDX_PCI_UNCORE_R3QPI,
2453}; 3010};
2454 3011
2455static struct intel_uncore_type *bdx_pci_uncores[] = { 3012static struct intel_uncore_type *bdx_pci_uncores[] = {
2456 [BDX_PCI_UNCORE_HA] = &bdx_uncore_ha, 3013 [BDX_PCI_UNCORE_HA] = &bdx_uncore_ha,
2457 [BDX_PCI_UNCORE_IMC] = &bdx_uncore_imc, 3014 [BDX_PCI_UNCORE_IMC] = &bdx_uncore_imc,
2458 [BDX_PCI_UNCORE_IRP] = &bdx_uncore_irp, 3015 [BDX_PCI_UNCORE_IRP] = &bdx_uncore_irp,
3016 [BDX_PCI_UNCORE_QPI] = &bdx_uncore_qpi,
2459 [BDX_PCI_UNCORE_R2PCIE] = &bdx_uncore_r2pcie, 3017 [BDX_PCI_UNCORE_R2PCIE] = &bdx_uncore_r2pcie,
3018 [BDX_PCI_UNCORE_R3QPI] = &bdx_uncore_r3qpi,
2460 NULL, 3019 NULL,
2461}; 3020};
2462 3021
@@ -2465,6 +3024,10 @@ static const struct pci_device_id bdx_uncore_pci_ids[] = {
2465 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f30), 3024 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f30),
2466 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_HA, 0), 3025 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_HA, 0),
2467 }, 3026 },
3027 { /* Home Agent 1 */
3028 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f38),
3029 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_HA, 1),
3030 },
2468 { /* MC0 Channel 0 */ 3031 { /* MC0 Channel 0 */
2469 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fb0), 3032 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fb0),
2470 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 0), 3033 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 0),
@@ -2473,14 +3036,74 @@ static const struct pci_device_id bdx_uncore_pci_ids[] = {
2473 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fb1), 3036 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fb1),
2474 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 1), 3037 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 1),
2475 }, 3038 },
3039 { /* MC0 Channel 2 */
3040 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fb4),
3041 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 2),
3042 },
3043 { /* MC0 Channel 3 */
3044 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fb5),
3045 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 3),
3046 },
3047 { /* MC1 Channel 0 */
3048 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fd0),
3049 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 4),
3050 },
3051 { /* MC1 Channel 1 */
3052 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fd1),
3053 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 5),
3054 },
3055 { /* MC1 Channel 2 */
3056 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fd4),
3057 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 6),
3058 },
3059 { /* MC1 Channel 3 */
3060 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fd5),
3061 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 7),
3062 },
2476 { /* IRP */ 3063 { /* IRP */
2477 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f39), 3064 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f39),
2478 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IRP, 0), 3065 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IRP, 0),
2479 }, 3066 },
3067 { /* QPI0 Port 0 */
3068 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f32),
3069 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_QPI, 0),
3070 },
3071 { /* QPI0 Port 1 */
3072 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f33),
3073 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_QPI, 1),
3074 },
3075 { /* QPI1 Port 2 */
3076 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f3a),
3077 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_QPI, 2),
3078 },
2480 { /* R2PCIe */ 3079 { /* R2PCIe */
2481 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f34), 3080 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f34),
2482 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_R2PCIE, 0), 3081 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_R2PCIE, 0),
2483 }, 3082 },
3083 { /* R3QPI0 Link 0 */
3084 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f36),
3085 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_R3QPI, 0),
3086 },
3087 { /* R3QPI0 Link 1 */
3088 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f37),
3089 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_R3QPI, 1),
3090 },
3091 { /* R3QPI1 Link 2 */
3092 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f3e),
3093 .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_R3QPI, 2),
3094 },
3095 { /* QPI Port 0 filter */
3096 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f86),
3097 .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, 0),
3098 },
3099 { /* QPI Port 1 filter */
3100 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f96),
3101 .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, 1),
3102 },
3103 { /* QPI Port 2 filter */
3104 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f46),
3105 .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, 2),
3106 },
2484 { /* end: all zeroes */ } 3107 { /* end: all zeroes */ }
2485}; 3108};
2486 3109
@@ -2500,4 +3123,4 @@ int bdx_uncore_pci_init(void)
2500 return 0; 3123 return 0;
2501} 3124}
2502 3125
2503/* end of BDX-DE uncore support */ 3126/* end of BDX uncore support */
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index 2c1910f6717e..58f34319b29a 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -35,6 +35,7 @@
35#include <asm/cpu.h> 35#include <asm/cpu.h>
36#include <asm/reboot.h> 36#include <asm/reboot.h>
37#include <asm/virtext.h> 37#include <asm/virtext.h>
38#include <asm/intel_pt.h>
38 39
39/* Alignment required for elf header segment */ 40/* Alignment required for elf header segment */
40#define ELF_CORE_HEADER_ALIGN 4096 41#define ELF_CORE_HEADER_ALIGN 4096
@@ -125,6 +126,11 @@ static void kdump_nmi_callback(int cpu, struct pt_regs *regs)
125 cpu_emergency_vmxoff(); 126 cpu_emergency_vmxoff();
126 cpu_emergency_svm_disable(); 127 cpu_emergency_svm_disable();
127 128
129 /*
130 * Disable Intel PT to stop its logging
131 */
132 cpu_emergency_stop_pt();
133
128 disable_local_APIC(); 134 disable_local_APIC();
129} 135}
130 136
@@ -169,6 +175,11 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
169 cpu_emergency_vmxoff(); 175 cpu_emergency_vmxoff();
170 cpu_emergency_svm_disable(); 176 cpu_emergency_svm_disable();
171 177
178 /*
179 * Disable Intel PT to stop its logging
180 */
181 cpu_emergency_stop_pt();
182
172#ifdef CONFIG_X86_IO_APIC 183#ifdef CONFIG_X86_IO_APIC
173 /* Prevent crash_kexec() from deadlocking on ioapic_lock. */ 184 /* Prevent crash_kexec() from deadlocking on ioapic_lock. */
174 ioapic_zap_locks(); 185 ioapic_zap_locks();
diff --git a/arch/x86/lib/msr.c b/arch/x86/lib/msr.c
index 43623739c7cf..004c861b1648 100644
--- a/arch/x86/lib/msr.c
+++ b/arch/x86/lib/msr.c
@@ -1,6 +1,8 @@
1#include <linux/module.h> 1#include <linux/module.h>
2#include <linux/preempt.h> 2#include <linux/preempt.h>
3#include <asm/msr.h> 3#include <asm/msr.h>
4#define CREATE_TRACE_POINTS
5#include <asm/msr-trace.h>
4 6
5struct msr *msrs_alloc(void) 7struct msr *msrs_alloc(void)
6{ 8{
@@ -108,3 +110,27 @@ int msr_clear_bit(u32 msr, u8 bit)
108{ 110{
109 return __flip_bit(msr, bit, false); 111 return __flip_bit(msr, bit, false);
110} 112}
113
114#ifdef CONFIG_TRACEPOINTS
115void do_trace_write_msr(unsigned msr, u64 val, int failed)
116{
117 trace_write_msr(msr, val, failed);
118}
119EXPORT_SYMBOL(do_trace_write_msr);
120EXPORT_TRACEPOINT_SYMBOL(write_msr);
121
122void do_trace_read_msr(unsigned msr, u64 val, int failed)
123{
124 trace_read_msr(msr, val, failed);
125}
126EXPORT_SYMBOL(do_trace_read_msr);
127EXPORT_TRACEPOINT_SYMBOL(read_msr);
128
129void do_trace_rdpmc(unsigned counter, u64 val, int failed)
130{
131 trace_rdpmc(counter, val, failed);
132}
133EXPORT_SYMBOL(do_trace_rdpmc);
134EXPORT_TRACEPOINT_SYMBOL(rdpmc);
135
136#endif
diff --git a/include/linux/tracepoint-defs.h b/include/linux/tracepoint-defs.h
new file mode 100644
index 000000000000..e1ee97c713bf
--- /dev/null
+++ b/include/linux/tracepoint-defs.h
@@ -0,0 +1,27 @@
1#ifndef TRACEPOINT_DEFS_H
2#define TRACEPOINT_DEFS_H 1
3
4/*
5 * File can be included directly by headers who only want to access
6 * tracepoint->key to guard out of line trace calls. Otherwise
7 * linux/tracepoint.h should be used.
8 */
9
10#include <linux/atomic.h>
11#include <linux/static_key.h>
12
13struct tracepoint_func {
14 void *func;
15 void *data;
16 int prio;
17};
18
19struct tracepoint {
20 const char *name; /* Tracepoint name */
21 struct static_key key;
22 void (*regfunc)(void);
23 void (*unregfunc)(void);
24 struct tracepoint_func __rcu *funcs;
25};
26
27#endif
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 7834a8a8bf1e..78e8397a1800 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -17,26 +17,12 @@
17#include <linux/errno.h> 17#include <linux/errno.h>
18#include <linux/types.h> 18#include <linux/types.h>
19#include <linux/rcupdate.h> 19#include <linux/rcupdate.h>
20#include <linux/static_key.h> 20#include <linux/tracepoint-defs.h>
21 21
22struct module; 22struct module;
23struct tracepoint; 23struct tracepoint;
24struct notifier_block; 24struct notifier_block;
25 25
26struct tracepoint_func {
27 void *func;
28 void *data;
29 int prio;
30};
31
32struct tracepoint {
33 const char *name; /* Tracepoint name */
34 struct static_key key;
35 void (*regfunc)(void);
36 void (*unregfunc)(void);
37 struct tracepoint_func __rcu *funcs;
38};
39
40struct trace_enum_map { 26struct trace_enum_map {
41 const char *system; 27 const char *system;
42 const char *enum_string; 28 const char *enum_string;
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index d801bb0d9f6d..1afe9623c1a7 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -171,6 +171,9 @@ enum perf_branch_sample_type_shift {
171 PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT = 12, /* indirect jumps */ 171 PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT = 12, /* indirect jumps */
172 PERF_SAMPLE_BRANCH_CALL_SHIFT = 13, /* direct call */ 172 PERF_SAMPLE_BRANCH_CALL_SHIFT = 13, /* direct call */
173 173
174 PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT = 14, /* no flags */
175 PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 15, /* no cycles */
176
174 PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */ 177 PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */
175}; 178};
176 179
@@ -192,6 +195,9 @@ enum perf_branch_sample_type {
192 PERF_SAMPLE_BRANCH_IND_JUMP = 1U << PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT, 195 PERF_SAMPLE_BRANCH_IND_JUMP = 1U << PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT,
193 PERF_SAMPLE_BRANCH_CALL = 1U << PERF_SAMPLE_BRANCH_CALL_SHIFT, 196 PERF_SAMPLE_BRANCH_CALL = 1U << PERF_SAMPLE_BRANCH_CALL_SHIFT,
194 197
198 PERF_SAMPLE_BRANCH_NO_FLAGS = 1U << PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT,
199 PERF_SAMPLE_BRANCH_NO_CYCLES = 1U << PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT,
200
195 PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT, 201 PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT,
196}; 202};
197 203
diff --git a/kernel/events/core.c b/kernel/events/core.c
index cfc227ccfceb..bf8244190d0f 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -126,6 +126,37 @@ static int cpu_function_call(int cpu, remote_function_f func, void *info)
126 return data.ret; 126 return data.ret;
127} 127}
128 128
129static void event_function_call(struct perf_event *event,
130 int (*active)(void *),
131 void (*inactive)(void *),
132 void *data)
133{
134 struct perf_event_context *ctx = event->ctx;
135 struct task_struct *task = ctx->task;
136
137 if (!task) {
138 cpu_function_call(event->cpu, active, data);
139 return;
140 }
141
142again:
143 if (!task_function_call(task, active, data))
144 return;
145
146 raw_spin_lock_irq(&ctx->lock);
147 if (ctx->is_active) {
148 /*
149 * Reload the task pointer, it might have been changed by
150 * a concurrent perf_event_context_sched_out().
151 */
152 task = ctx->task;
153 raw_spin_unlock_irq(&ctx->lock);
154 goto again;
155 }
156 inactive(data);
157 raw_spin_unlock_irq(&ctx->lock);
158}
159
129#define EVENT_OWNER_KERNEL ((void *) -1) 160#define EVENT_OWNER_KERNEL ((void *) -1)
130 161
131static bool is_kernel_event(struct perf_event *event) 162static bool is_kernel_event(struct perf_event *event)
@@ -1629,6 +1660,17 @@ struct remove_event {
1629 bool detach_group; 1660 bool detach_group;
1630}; 1661};
1631 1662
1663static void ___perf_remove_from_context(void *info)
1664{
1665 struct remove_event *re = info;
1666 struct perf_event *event = re->event;
1667 struct perf_event_context *ctx = event->ctx;
1668
1669 if (re->detach_group)
1670 perf_group_detach(event);
1671 list_del_event(event, ctx);
1672}
1673
1632/* 1674/*
1633 * Cross CPU call to remove a performance event 1675 * Cross CPU call to remove a performance event
1634 * 1676 *
@@ -1656,7 +1698,6 @@ static int __perf_remove_from_context(void *info)
1656 return 0; 1698 return 0;
1657} 1699}
1658 1700
1659
1660/* 1701/*
1661 * Remove the event from a task's (or a CPU's) list of events. 1702 * Remove the event from a task's (or a CPU's) list of events.
1662 * 1703 *
@@ -1673,7 +1714,6 @@ static int __perf_remove_from_context(void *info)
1673static void perf_remove_from_context(struct perf_event *event, bool detach_group) 1714static void perf_remove_from_context(struct perf_event *event, bool detach_group)
1674{ 1715{
1675 struct perf_event_context *ctx = event->ctx; 1716 struct perf_event_context *ctx = event->ctx;
1676 struct task_struct *task = ctx->task;
1677 struct remove_event re = { 1717 struct remove_event re = {
1678 .event = event, 1718 .event = event,
1679 .detach_group = detach_group, 1719 .detach_group = detach_group,
@@ -1681,44 +1721,8 @@ static void perf_remove_from_context(struct perf_event *event, bool detach_group
1681 1721
1682 lockdep_assert_held(&ctx->mutex); 1722 lockdep_assert_held(&ctx->mutex);
1683 1723
1684 if (!task) { 1724 event_function_call(event, __perf_remove_from_context,
1685 /* 1725 ___perf_remove_from_context, &re);
1686 * Per cpu events are removed via an smp call. The removal can
1687 * fail if the CPU is currently offline, but in that case we
1688 * already called __perf_remove_from_context from
1689 * perf_event_exit_cpu.
1690 */
1691 cpu_function_call(event->cpu, __perf_remove_from_context, &re);
1692 return;
1693 }
1694
1695retry:
1696 if (!task_function_call(task, __perf_remove_from_context, &re))
1697 return;
1698
1699 raw_spin_lock_irq(&ctx->lock);
1700 /*
1701 * If we failed to find a running task, but find the context active now
1702 * that we've acquired the ctx->lock, retry.
1703 */
1704 if (ctx->is_active) {
1705 raw_spin_unlock_irq(&ctx->lock);
1706 /*
1707 * Reload the task pointer, it might have been changed by
1708 * a concurrent perf_event_context_sched_out().
1709 */
1710 task = ctx->task;
1711 goto retry;
1712 }
1713
1714 /*
1715 * Since the task isn't running, its safe to remove the event, us
1716 * holding the ctx->lock ensures the task won't get scheduled in.
1717 */
1718 if (detach_group)
1719 perf_group_detach(event);
1720 list_del_event(event, ctx);
1721 raw_spin_unlock_irq(&ctx->lock);
1722} 1726}
1723 1727
1724/* 1728/*
@@ -1762,6 +1766,20 @@ int __perf_event_disable(void *info)
1762 return 0; 1766 return 0;
1763} 1767}
1764 1768
1769void ___perf_event_disable(void *info)
1770{
1771 struct perf_event *event = info;
1772
1773 /*
1774 * Since we have the lock this context can't be scheduled
1775 * in, so we can change the state safely.
1776 */
1777 if (event->state == PERF_EVENT_STATE_INACTIVE) {
1778 update_group_times(event);
1779 event->state = PERF_EVENT_STATE_OFF;
1780 }
1781}
1782
1765/* 1783/*
1766 * Disable a event. 1784 * Disable a event.
1767 * 1785 *
@@ -1778,43 +1796,16 @@ int __perf_event_disable(void *info)
1778static void _perf_event_disable(struct perf_event *event) 1796static void _perf_event_disable(struct perf_event *event)
1779{ 1797{
1780 struct perf_event_context *ctx = event->ctx; 1798 struct perf_event_context *ctx = event->ctx;
1781 struct task_struct *task = ctx->task;
1782
1783 if (!task) {
1784 /*
1785 * Disable the event on the cpu that it's on
1786 */
1787 cpu_function_call(event->cpu, __perf_event_disable, event);
1788 return;
1789 }
1790
1791retry:
1792 if (!task_function_call(task, __perf_event_disable, event))
1793 return;
1794 1799
1795 raw_spin_lock_irq(&ctx->lock); 1800 raw_spin_lock_irq(&ctx->lock);
1796 /* 1801 if (event->state <= PERF_EVENT_STATE_OFF) {
1797 * If the event is still active, we need to retry the cross-call.
1798 */
1799 if (event->state == PERF_EVENT_STATE_ACTIVE) {
1800 raw_spin_unlock_irq(&ctx->lock); 1802 raw_spin_unlock_irq(&ctx->lock);
1801 /* 1803 return;
1802 * Reload the task pointer, it might have been changed by
1803 * a concurrent perf_event_context_sched_out().
1804 */
1805 task = ctx->task;
1806 goto retry;
1807 }
1808
1809 /*
1810 * Since we have the lock this context can't be scheduled
1811 * in, so we can change the state safely.
1812 */
1813 if (event->state == PERF_EVENT_STATE_INACTIVE) {
1814 update_group_times(event);
1815 event->state = PERF_EVENT_STATE_OFF;
1816 } 1804 }
1817 raw_spin_unlock_irq(&ctx->lock); 1805 raw_spin_unlock_irq(&ctx->lock);
1806
1807 event_function_call(event, __perf_event_disable,
1808 ___perf_event_disable, event);
1818} 1809}
1819 1810
1820/* 1811/*
@@ -2067,6 +2058,18 @@ static void perf_event_sched_in(struct perf_cpu_context *cpuctx,
2067 ctx_sched_in(ctx, cpuctx, EVENT_FLEXIBLE, task); 2058 ctx_sched_in(ctx, cpuctx, EVENT_FLEXIBLE, task);
2068} 2059}
2069 2060
2061static void ___perf_install_in_context(void *info)
2062{
2063 struct perf_event *event = info;
2064 struct perf_event_context *ctx = event->ctx;
2065
2066 /*
2067 * Since the task isn't running, its safe to add the event, us holding
2068 * the ctx->lock ensures the task won't get scheduled in.
2069 */
2070 add_event_to_ctx(event, ctx);
2071}
2072
2070/* 2073/*
2071 * Cross CPU call to install and enable a performance event 2074 * Cross CPU call to install and enable a performance event
2072 * 2075 *
@@ -2143,48 +2146,14 @@ perf_install_in_context(struct perf_event_context *ctx,
2143 struct perf_event *event, 2146 struct perf_event *event,
2144 int cpu) 2147 int cpu)
2145{ 2148{
2146 struct task_struct *task = ctx->task;
2147
2148 lockdep_assert_held(&ctx->mutex); 2149 lockdep_assert_held(&ctx->mutex);
2149 2150
2150 event->ctx = ctx; 2151 event->ctx = ctx;
2151 if (event->cpu != -1) 2152 if (event->cpu != -1)
2152 event->cpu = cpu; 2153 event->cpu = cpu;
2153 2154
2154 if (!task) { 2155 event_function_call(event, __perf_install_in_context,
2155 /* 2156 ___perf_install_in_context, event);
2156 * Per cpu events are installed via an smp call and
2157 * the install is always successful.
2158 */
2159 cpu_function_call(cpu, __perf_install_in_context, event);
2160 return;
2161 }
2162
2163retry:
2164 if (!task_function_call(task, __perf_install_in_context, event))
2165 return;
2166
2167 raw_spin_lock_irq(&ctx->lock);
2168 /*
2169 * If we failed to find a running task, but find the context active now
2170 * that we've acquired the ctx->lock, retry.
2171 */
2172 if (ctx->is_active) {
2173 raw_spin_unlock_irq(&ctx->lock);
2174 /*
2175 * Reload the task pointer, it might have been changed by
2176 * a concurrent perf_event_context_sched_out().
2177 */
2178 task = ctx->task;
2179 goto retry;
2180 }
2181
2182 /*
2183 * Since the task isn't running, its safe to add the event, us holding
2184 * the ctx->lock ensures the task won't get scheduled in.
2185 */
2186 add_event_to_ctx(event, ctx);
2187 raw_spin_unlock_irq(&ctx->lock);
2188} 2157}
2189 2158
2190/* 2159/*
@@ -2287,6 +2256,11 @@ unlock:
2287 return 0; 2256 return 0;
2288} 2257}
2289 2258
2259void ___perf_event_enable(void *info)
2260{
2261 __perf_event_mark_enabled((struct perf_event *)info);
2262}
2263
2290/* 2264/*
2291 * Enable a event. 2265 * Enable a event.
2292 * 2266 *
@@ -2299,58 +2273,26 @@ unlock:
2299static void _perf_event_enable(struct perf_event *event) 2273static void _perf_event_enable(struct perf_event *event)
2300{ 2274{
2301 struct perf_event_context *ctx = event->ctx; 2275 struct perf_event_context *ctx = event->ctx;
2302 struct task_struct *task = ctx->task;
2303 2276
2304 if (!task) { 2277 raw_spin_lock_irq(&ctx->lock);
2305 /* 2278 if (event->state >= PERF_EVENT_STATE_INACTIVE) {
2306 * Enable the event on the cpu that it's on 2279 raw_spin_unlock_irq(&ctx->lock);
2307 */
2308 cpu_function_call(event->cpu, __perf_event_enable, event);
2309 return; 2280 return;
2310 } 2281 }
2311 2282
2312 raw_spin_lock_irq(&ctx->lock);
2313 if (event->state >= PERF_EVENT_STATE_INACTIVE)
2314 goto out;
2315
2316 /* 2283 /*
2317 * If the event is in error state, clear that first. 2284 * If the event is in error state, clear that first.
2318 * That way, if we see the event in error state below, we 2285 *
2319 * know that it has gone back into error state, as distinct 2286 * That way, if we see the event in error state below, we know that it
2320 * from the task having been scheduled away before the 2287 * has gone back into error state, as distinct from the task having
2321 * cross-call arrived. 2288 * been scheduled away before the cross-call arrived.
2322 */ 2289 */
2323 if (event->state == PERF_EVENT_STATE_ERROR) 2290 if (event->state == PERF_EVENT_STATE_ERROR)
2324 event->state = PERF_EVENT_STATE_OFF; 2291 event->state = PERF_EVENT_STATE_OFF;
2325
2326retry:
2327 if (!ctx->is_active) {
2328 __perf_event_mark_enabled(event);
2329 goto out;
2330 }
2331
2332 raw_spin_unlock_irq(&ctx->lock); 2292 raw_spin_unlock_irq(&ctx->lock);
2333 2293
2334 if (!task_function_call(task, __perf_event_enable, event)) 2294 event_function_call(event, __perf_event_enable,
2335 return; 2295 ___perf_event_enable, event);
2336
2337 raw_spin_lock_irq(&ctx->lock);
2338
2339 /*
2340 * If the context is active and the event is still off,
2341 * we need to retry the cross-call.
2342 */
2343 if (ctx->is_active && event->state == PERF_EVENT_STATE_OFF) {
2344 /*
2345 * task could have been flipped by a concurrent
2346 * perf_event_context_sched_out()
2347 */
2348 task = ctx->task;
2349 goto retry;
2350 }
2351
2352out:
2353 raw_spin_unlock_irq(&ctx->lock);
2354} 2296}
2355 2297
2356/* 2298/*
@@ -4149,6 +4091,22 @@ struct period_event {
4149 u64 value; 4091 u64 value;
4150}; 4092};
4151 4093
4094static void ___perf_event_period(void *info)
4095{
4096 struct period_event *pe = info;
4097 struct perf_event *event = pe->event;
4098 u64 value = pe->value;
4099
4100 if (event->attr.freq) {
4101 event->attr.sample_freq = value;
4102 } else {
4103 event->attr.sample_period = value;
4104 event->hw.sample_period = value;
4105 }
4106
4107 local64_set(&event->hw.period_left, 0);
4108}
4109
4152static int __perf_event_period(void *info) 4110static int __perf_event_period(void *info)
4153{ 4111{
4154 struct period_event *pe = info; 4112 struct period_event *pe = info;
@@ -4185,8 +4143,6 @@ static int __perf_event_period(void *info)
4185static int perf_event_period(struct perf_event *event, u64 __user *arg) 4143static int perf_event_period(struct perf_event *event, u64 __user *arg)
4186{ 4144{
4187 struct period_event pe = { .event = event, }; 4145 struct period_event pe = { .event = event, };
4188 struct perf_event_context *ctx = event->ctx;
4189 struct task_struct *task;
4190 u64 value; 4146 u64 value;
4191 4147
4192 if (!is_sampling_event(event)) 4148 if (!is_sampling_event(event))
@@ -4201,34 +4157,10 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg)
4201 if (event->attr.freq && value > sysctl_perf_event_sample_rate) 4157 if (event->attr.freq && value > sysctl_perf_event_sample_rate)
4202 return -EINVAL; 4158 return -EINVAL;
4203 4159
4204 task = ctx->task;
4205 pe.value = value; 4160 pe.value = value;
4206 4161
4207 if (!task) { 4162 event_function_call(event, __perf_event_period,
4208 cpu_function_call(event->cpu, __perf_event_period, &pe); 4163 ___perf_event_period, &pe);
4209 return 0;
4210 }
4211
4212retry:
4213 if (!task_function_call(task, __perf_event_period, &pe))
4214 return 0;
4215
4216 raw_spin_lock_irq(&ctx->lock);
4217 if (ctx->is_active) {
4218 raw_spin_unlock_irq(&ctx->lock);
4219 task = ctx->task;
4220 goto retry;
4221 }
4222
4223 if (event->attr.freq) {
4224 event->attr.sample_freq = value;
4225 } else {
4226 event->attr.sample_period = value;
4227 event->hw.sample_period = value;
4228 }
4229
4230 local64_set(&event->hw.period_left, 0);
4231 raw_spin_unlock_irq(&ctx->lock);
4232 4164
4233 return 0; 4165 return 0;
4234} 4166}
diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c
index 18e422b259cf..d62de8bf022d 100644
--- a/lib/atomic64_test.c
+++ b/lib/atomic64_test.c
@@ -16,6 +16,10 @@
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/atomic.h> 17#include <linux/atomic.h>
18 18
19#ifdef CONFIG_X86
20#include <asm/processor.h> /* for boot_cpu_has below */
21#endif
22
19#define TEST(bit, op, c_op, val) \ 23#define TEST(bit, op, c_op, val) \
20do { \ 24do { \
21 atomic##bit##_set(&v, v0); \ 25 atomic##bit##_set(&v, v0); \
diff --git a/tools/Makefile b/tools/Makefile
index 7dc820a8c1f1..0ba0df3b516f 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -96,7 +96,7 @@ cgroup_install firewire_install hv_install lguest_install perf_install usb_insta
96 $(call descend,$(@:_install=),install) 96 $(call descend,$(@:_install=),install)
97 97
98selftests_install: 98selftests_install:
99 $(call descend,testing/$(@:_clean=),install) 99 $(call descend,testing/$(@:_install=),install)
100 100
101turbostat_install x86_energy_perf_policy_install: 101turbostat_install x86_energy_perf_policy_install:
102 $(call descend,power/x86/$(@:_install=),install) 102 $(call descend,power/x86/$(@:_install=),install)
diff --git a/tools/build/Makefile b/tools/build/Makefile
index a93036272d43..0d5a0e3a8fa9 100644
--- a/tools/build/Makefile
+++ b/tools/build/Makefile
@@ -25,7 +25,7 @@ export Q srctree CC LD
25MAKEFLAGS := --no-print-directory 25MAKEFLAGS := --no-print-directory
26build := -f $(srctree)/tools/build/Makefile.build dir=. obj 26build := -f $(srctree)/tools/build/Makefile.build dir=. obj
27 27
28all: fixdep 28all: $(OUTPUT)fixdep
29 29
30clean: 30clean:
31 $(call QUIET_CLEAN, fixdep) 31 $(call QUIET_CLEAN, fixdep)
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index 37ff4c9f92f1..02db3cdff20f 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -7,7 +7,7 @@ endif
7 7
8feature_check = $(eval $(feature_check_code)) 8feature_check = $(eval $(feature_check_code))
9define feature_check_code 9define feature_check_code
10 feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0) 10 feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) $(OUTPUT_FEATURES)test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
11endef 11endef
12 12
13feature_set = $(eval $(feature_set_code)) 13feature_set = $(eval $(feature_set_code))
@@ -101,7 +101,6 @@ ifeq ($(feature-all), 1)
101 # 101 #
102 $(foreach feat,$(FEATURE_TESTS),$(call feature_set,$(feat))) 102 $(foreach feat,$(FEATURE_TESTS),$(call feature_set,$(feat)))
103else 103else
104 $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C $(feature_dir) $(addsuffix .bin,$(FEATURE_TESTS)) >/dev/null 2>&1)
105 $(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat))) 104 $(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat)))
106endif 105endif
107 106
@@ -123,13 +122,31 @@ define feature_print_text_code
123 MSG = $(shell printf '...%30s: %s' $(1) $(2)) 122 MSG = $(shell printf '...%30s: %s' $(1) $(2))
124endef 123endef
125 124
125#
126# generates feature value assignment for name, like:
127# $(call feature_assign,dwarf) == feature-dwarf=1
128#
129feature_assign = feature-$(1)=$(feature-$(1))
130
126FEATURE_DUMP_FILENAME = $(OUTPUT)FEATURE-DUMP$(FEATURE_USER) 131FEATURE_DUMP_FILENAME = $(OUTPUT)FEATURE-DUMP$(FEATURE_USER)
127FEATURE_DUMP := $(foreach feat,$(FEATURE_DISPLAY),feature-$(feat)($(feature-$(feat)))) 132FEATURE_DUMP := $(shell touch $(FEATURE_DUMP_FILENAME); cat $(FEATURE_DUMP_FILENAME))
128FEATURE_DUMP_FILE := $(shell touch $(FEATURE_DUMP_FILENAME); cat $(FEATURE_DUMP_FILENAME))
129 133
130ifeq ($(dwarf-post-unwind),1) 134feature_dump_check = $(eval $(feature_dump_check_code))
131 FEATURE_DUMP += dwarf-post-unwind($(dwarf-post-unwind-text)) 135define feature_dump_check_code
132endif 136 ifeq ($(findstring $(1),$(FEATURE_DUMP)),)
137 $(2) := 1
138 endif
139endef
140
141#
142# First check if any test from FEATURE_DISPLAY
143# and set feature_display := 1 if it does
144$(foreach feat,$(FEATURE_DISPLAY),$(call feature_dump_check,$(call feature_assign,$(feat)),feature_display))
145
146#
147# Now also check if any other test changed,
148# so we force FEATURE-DUMP generation
149$(foreach feat,$(FEATURE_TESTS),$(call feature_dump_check,$(call feature_assign,$(feat)),feature_dump_changed))
133 150
134# The $(feature_display) controls the default detection message 151# The $(feature_display) controls the default detection message
135# output. It's set if: 152# output. It's set if:
@@ -138,13 +155,13 @@ endif
138# - one of the $(FEATURE_DISPLAY) is not detected 155# - one of the $(FEATURE_DISPLAY) is not detected
139# - VF is enabled 156# - VF is enabled
140 157
141ifneq ("$(FEATURE_DUMP)","$(FEATURE_DUMP_FILE)") 158ifeq ($(feature_dump_changed),1)
142 $(shell echo "$(FEATURE_DUMP)" > $(FEATURE_DUMP_FILENAME)) 159 $(shell rm -f $(FEATURE_DUMP_FILENAME))
143 feature_display := 1 160 $(foreach feat,$(FEATURE_TESTS),$(shell echo "$(call feature_assign,$(feat))" >> $(FEATURE_DUMP_FILENAME)))
144endif 161endif
145 162
146feature_display_check = $(eval $(feature_check_display_code)) 163feature_display_check = $(eval $(feature_check_display_code))
147define feature_display_check_code 164define feature_check_display_code
148 ifneq ($(feature-$(1)), 1) 165 ifneq ($(feature-$(1)), 1)
149 feature_display := 1 166 feature_display := 1
150 endif 167 endif
@@ -161,11 +178,6 @@ ifeq ($(feature_display),1)
161 $(info ) 178 $(info )
162 $(info Auto-detecting system features:) 179 $(info Auto-detecting system features:)
163 $(foreach feat,$(FEATURE_DISPLAY),$(call feature_print_status,$(feat),)) 180 $(foreach feat,$(FEATURE_DISPLAY),$(call feature_print_status,$(feat),))
164
165 ifeq ($(dwarf-post-unwind),1)
166 $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
167 endif
168
169 ifneq ($(feature_verbose),1) 181 ifneq ($(feature_verbose),1)
170 $(info ) 182 $(info )
171 endif 183 endif
diff --git a/tools/build/Makefile.include b/tools/build/Makefile.include
index 4e09ad617a60..be630bed66d2 100644
--- a/tools/build/Makefile.include
+++ b/tools/build/Makefile.include
@@ -4,7 +4,7 @@ ifdef CROSS_COMPILE
4fixdep: 4fixdep:
5else 5else
6fixdep: 6fixdep:
7 $(Q)$(MAKE) -C $(srctree)/tools/build fixdep 7 $(Q)$(MAKE) -C $(srctree)/tools/build CFLAGS= LDFLAGS= $(OUTPUT)fixdep
8endif 8endif
9 9
10.PHONY: fixdep 10.PHONY: fixdep
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index cea04ce9f35c..bf8f0352264d 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -1,4 +1,3 @@
1
2FILES= \ 1FILES= \
3 test-all.bin \ 2 test-all.bin \
4 test-backtrace.bin \ 3 test-backtrace.bin \
@@ -38,38 +37,40 @@ FILES= \
38 test-bpf.bin \ 37 test-bpf.bin \
39 test-get_cpuid.bin 38 test-get_cpuid.bin
40 39
40FILES := $(addprefix $(OUTPUT),$(FILES))
41
41CC := $(CROSS_COMPILE)gcc -MD 42CC := $(CROSS_COMPILE)gcc -MD
42PKG_CONFIG := $(CROSS_COMPILE)pkg-config 43PKG_CONFIG := $(CROSS_COMPILE)pkg-config
43 44
44all: $(FILES) 45all: $(FILES)
45 46
46__BUILD = $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS) 47__BUILD = $(CC) $(CFLAGS) -Wall -Werror -o $@ $(patsubst %.bin,%.c,$(@F)) $(LDFLAGS)
47 BUILD = $(__BUILD) > $(OUTPUT)$(@:.bin=.make.output) 2>&1 48 BUILD = $(__BUILD) > $(@:.bin=.make.output) 2>&1
48 49
49############################### 50###############################
50 51
51test-all.bin: 52$(OUTPUT)test-all.bin:
52 $(BUILD) -fstack-protector-all -O2 -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz -llzma 53 $(BUILD) -fstack-protector-all -O2 -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz -llzma
53 54
54test-hello.bin: 55$(OUTPUT)test-hello.bin:
55 $(BUILD) 56 $(BUILD)
56 57
57test-pthread-attr-setaffinity-np.bin: 58$(OUTPUT)test-pthread-attr-setaffinity-np.bin:
58 $(BUILD) -D_GNU_SOURCE -lpthread 59 $(BUILD) -D_GNU_SOURCE -lpthread
59 60
60test-stackprotector-all.bin: 61$(OUTPUT)test-stackprotector-all.bin:
61 $(BUILD) -fstack-protector-all 62 $(BUILD) -fstack-protector-all
62 63
63test-fortify-source.bin: 64$(OUTPUT)test-fortify-source.bin:
64 $(BUILD) -O2 -D_FORTIFY_SOURCE=2 65 $(BUILD) -O2 -D_FORTIFY_SOURCE=2
65 66
66test-bionic.bin: 67$(OUTPUT)test-bionic.bin:
67 $(BUILD) 68 $(BUILD)
68 69
69test-libelf.bin: 70$(OUTPUT)test-libelf.bin:
70 $(BUILD) -lelf 71 $(BUILD) -lelf
71 72
72test-glibc.bin: 73$(OUTPUT)test-glibc.bin:
73 $(BUILD) 74 $(BUILD)
74 75
75DWARFLIBS := -ldw 76DWARFLIBS := -ldw
@@ -77,37 +78,37 @@ ifeq ($(findstring -static,${LDFLAGS}),-static)
77DWARFLIBS += -lelf -lebl -lz -llzma -lbz2 78DWARFLIBS += -lelf -lebl -lz -llzma -lbz2
78endif 79endif
79 80
80test-dwarf.bin: 81$(OUTPUT)test-dwarf.bin:
81 $(BUILD) $(DWARFLIBS) 82 $(BUILD) $(DWARFLIBS)
82 83
83test-libelf-mmap.bin: 84$(OUTPUT)test-libelf-mmap.bin:
84 $(BUILD) -lelf 85 $(BUILD) -lelf
85 86
86test-libelf-getphdrnum.bin: 87$(OUTPUT)test-libelf-getphdrnum.bin:
87 $(BUILD) -lelf 88 $(BUILD) -lelf
88 89
89test-libnuma.bin: 90$(OUTPUT)test-libnuma.bin:
90 $(BUILD) -lnuma 91 $(BUILD) -lnuma
91 92
92test-numa_num_possible_cpus.bin: 93$(OUTPUT)test-numa_num_possible_cpus.bin:
93 $(BUILD) -lnuma 94 $(BUILD) -lnuma
94 95
95test-libunwind.bin: 96$(OUTPUT)test-libunwind.bin:
96 $(BUILD) -lelf 97 $(BUILD) -lelf
97 98
98test-libunwind-debug-frame.bin: 99$(OUTPUT)test-libunwind-debug-frame.bin:
99 $(BUILD) -lelf 100 $(BUILD) -lelf
100 101
101test-libaudit.bin: 102$(OUTPUT)test-libaudit.bin:
102 $(BUILD) -laudit 103 $(BUILD) -laudit
103 104
104test-libslang.bin: 105$(OUTPUT)test-libslang.bin:
105 $(BUILD) -I/usr/include/slang -lslang 106 $(BUILD) -I/usr/include/slang -lslang
106 107
107test-gtk2.bin: 108$(OUTPUT)test-gtk2.bin:
108 $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) 109 $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
109 110
110test-gtk2-infobar.bin: 111$(OUTPUT)test-gtk2-infobar.bin:
111 $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) 112 $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
112 113
113grep-libs = $(filter -l%,$(1)) 114grep-libs = $(filter -l%,$(1))
@@ -119,63 +120,63 @@ PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
119PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` 120PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
120FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) 121FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
121 122
122test-libperl.bin: 123$(OUTPUT)test-libperl.bin:
123 $(BUILD) $(FLAGS_PERL_EMBED) 124 $(BUILD) $(FLAGS_PERL_EMBED)
124 125
125test-libpython.bin: 126$(OUTPUT)test-libpython.bin:
126 $(BUILD) 127 $(BUILD)
127 128
128test-libpython-version.bin: 129$(OUTPUT)test-libpython-version.bin:
129 $(BUILD) 130 $(BUILD)
130 131
131test-libbfd.bin: 132$(OUTPUT)test-libbfd.bin:
132 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl 133 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
133 134
134test-liberty.bin: 135$(OUTPUT)test-liberty.bin:
135 $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty 136 $(CC) $(CFLAGS) -Wall -Werror -o $@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty
136 137
137test-liberty-z.bin: 138$(OUTPUT)test-liberty-z.bin:
138 $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty -lz 139 $(CC) $(CFLAGS) -Wall -Werror -o $@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty -lz
139 140
140test-cplus-demangle.bin: 141$(OUTPUT)test-cplus-demangle.bin:
141 $(BUILD) -liberty 142 $(BUILD) -liberty
142 143
143test-backtrace.bin: 144$(OUTPUT)test-backtrace.bin:
144 $(BUILD) 145 $(BUILD)
145 146
146test-timerfd.bin: 147$(OUTPUT)test-timerfd.bin:
147 $(BUILD) 148 $(BUILD)
148 149
149test-libdw-dwarf-unwind.bin: 150$(OUTPUT)test-libdw-dwarf-unwind.bin:
150 $(BUILD) # -ldw provided by $(FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind) 151 $(BUILD) # -ldw provided by $(FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind)
151 152
152test-libbabeltrace.bin: 153$(OUTPUT)test-libbabeltrace.bin:
153 $(BUILD) # -lbabeltrace provided by $(FEATURE_CHECK_LDFLAGS-libbabeltrace) 154 $(BUILD) # -lbabeltrace provided by $(FEATURE_CHECK_LDFLAGS-libbabeltrace)
154 155
155test-sync-compare-and-swap.bin: 156$(OUTPUT)test-sync-compare-and-swap.bin:
156 $(BUILD) 157 $(BUILD)
157 158
158test-compile-32.bin: 159$(OUTPUT)test-compile-32.bin:
159 $(CC) -m32 -o $(OUTPUT)$@ test-compile.c 160 $(CC) -m32 -o $@ test-compile.c
160 161
161test-compile-x32.bin: 162$(OUTPUT)test-compile-x32.bin:
162 $(CC) -mx32 -o $(OUTPUT)$@ test-compile.c 163 $(CC) -mx32 -o $@ test-compile.c
163 164
164test-zlib.bin: 165$(OUTPUT)test-zlib.bin:
165 $(BUILD) -lz 166 $(BUILD) -lz
166 167
167test-lzma.bin: 168$(OUTPUT)test-lzma.bin:
168 $(BUILD) -llzma 169 $(BUILD) -llzma
169 170
170test-get_cpuid.bin: 171$(OUTPUT)test-get_cpuid.bin:
171 $(BUILD) 172 $(BUILD)
172 173
173test-bpf.bin: 174$(OUTPUT)test-bpf.bin:
174 $(BUILD) 175 $(BUILD)
175 176
176-include *.d 177-include $(OUTPUT)*.d
177 178
178############################### 179###############################
179 180
180clean: 181clean:
181 rm -f $(FILES) *.d $(FILES:.bin=.make.output) 182 rm -f $(FILES) $(OUTPUT)*.d $(FILES:.bin=.make.output)
diff --git a/tools/perf/util/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 40bd21488032..28f5493da491 100644
--- a/tools/perf/util/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -11,6 +11,8 @@ int __bitmap_weight(const unsigned long *bitmap, int bits);
11void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1, 11void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
12 const unsigned long *bitmap2, int bits); 12 const unsigned long *bitmap2, int bits);
13 13
14#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
15
14#define BITMAP_LAST_WORD_MASK(nbits) \ 16#define BITMAP_LAST_WORD_MASK(nbits) \
15( \ 17( \
16 ((nbits) % BITS_PER_LONG) ? \ 18 ((nbits) % BITS_PER_LONG) ? \
diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h
new file mode 100644
index 000000000000..e26223f1f287
--- /dev/null
+++ b/tools/include/linux/string.h
@@ -0,0 +1,15 @@
1#ifndef _TOOLS_LINUX_STRING_H_
2#define _TOOLS_LINUX_STRING_H_
3
4
5#include <linux/types.h> /* for size_t */
6
7void *memdup(const void *src, size_t len);
8
9int strtobool(const char *s, bool *res);
10
11#ifndef __UCLIBC__
12extern size_t strlcpy(char *dest, const char *src, size_t size);
13#endif
14
15#endif /* _LINUX_STRING_H_ */
diff --git a/tools/perf/util/bitmap.c b/tools/lib/bitmap.c
index 0a1adc1111fd..0a1adc1111fd 100644
--- a/tools/perf/util/bitmap.c
+++ b/tools/lib/bitmap.c
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index a3caaf3eafbd..919b71780710 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -71,7 +71,21 @@ FEATURE_DISPLAY = libelf bpf
71INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/arch/$(ARCH)/include/uapi -I$(srctree)/include/uapi 71INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/arch/$(ARCH)/include/uapi -I$(srctree)/include/uapi
72FEATURE_CHECK_CFLAGS-bpf = $(INCLUDES) 72FEATURE_CHECK_CFLAGS-bpf = $(INCLUDES)
73 73
74check_feat := 1
75NON_CHECK_FEAT_TARGETS := clean TAGS tags cscope help
76ifdef MAKECMDGOALS
77ifeq ($(filter-out $(NON_CHECK_FEAT_TARGETS),$(MAKECMDGOALS)),)
78 check_feat := 0
79endif
80endif
81
82ifeq ($(check_feat),1)
83ifeq ($(FEATURES_DUMP),)
74include $(srctree)/tools/build/Makefile.feature 84include $(srctree)/tools/build/Makefile.feature
85else
86include $(FEATURES_DUMP)
87endif
88endif
75 89
76export prefix libdir src obj 90export prefix libdir src obj
77 91
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index a6331050ab79..5bdc6eab6852 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -83,3 +83,17 @@ int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns,
83 log_buf[0] = 0; 83 log_buf[0] = 0;
84 return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); 84 return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
85} 85}
86
87int bpf_map_update_elem(int fd, void *key, void *value,
88 u64 flags)
89{
90 union bpf_attr attr;
91
92 bzero(&attr, sizeof(attr));
93 attr.map_fd = fd;
94 attr.key = ptr_to_u64(key);
95 attr.value = ptr_to_u64(value);
96 attr.flags = flags;
97
98 return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
99}
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 854b7361b784..a76465541292 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -20,4 +20,6 @@ int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns,
20 u32 kern_version, char *log_buf, 20 u32 kern_version, char *log_buf,
21 size_t log_buf_sz); 21 size_t log_buf_sz);
22 22
23int bpf_map_update_elem(int fd, void *key, void *value,
24 u64 flags);
23#endif 25#endif
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index e176bad19bcb..8334a5a9d5d7 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -152,29 +152,36 @@ struct bpf_program {
152 } *reloc_desc; 152 } *reloc_desc;
153 int nr_reloc; 153 int nr_reloc;
154 154
155 int fd; 155 struct {
156 int nr;
157 int *fds;
158 } instances;
159 bpf_program_prep_t preprocessor;
156 160
157 struct bpf_object *obj; 161 struct bpf_object *obj;
158 void *priv; 162 void *priv;
159 bpf_program_clear_priv_t clear_priv; 163 bpf_program_clear_priv_t clear_priv;
160}; 164};
161 165
166struct bpf_map {
167 int fd;
168 char *name;
169 struct bpf_map_def def;
170 void *priv;
171 bpf_map_clear_priv_t clear_priv;
172};
173
162static LIST_HEAD(bpf_objects_list); 174static LIST_HEAD(bpf_objects_list);
163 175
164struct bpf_object { 176struct bpf_object {
165 char license[64]; 177 char license[64];
166 u32 kern_version; 178 u32 kern_version;
167 void *maps_buf;
168 size_t maps_buf_sz;
169 179
170 struct bpf_program *programs; 180 struct bpf_program *programs;
171 size_t nr_programs; 181 size_t nr_programs;
172 int *map_fds; 182 struct bpf_map *maps;
173 /* 183 size_t nr_maps;
174 * This field is required because maps_buf will be freed and 184
175 * maps_buf_sz will be set to 0 after loaded.
176 */
177 size_t nr_map_fds;
178 bool loaded; 185 bool loaded;
179 186
180 /* 187 /*
@@ -188,6 +195,7 @@ struct bpf_object {
188 Elf *elf; 195 Elf *elf;
189 GElf_Ehdr ehdr; 196 GElf_Ehdr ehdr;
190 Elf_Data *symbols; 197 Elf_Data *symbols;
198 size_t strtabidx;
191 struct { 199 struct {
192 GElf_Shdr shdr; 200 GElf_Shdr shdr;
193 Elf_Data *data; 201 Elf_Data *data;
@@ -206,10 +214,25 @@ struct bpf_object {
206 214
207static void bpf_program__unload(struct bpf_program *prog) 215static void bpf_program__unload(struct bpf_program *prog)
208{ 216{
217 int i;
218
209 if (!prog) 219 if (!prog)
210 return; 220 return;
211 221
212 zclose(prog->fd); 222 /*
223 * If the object is opened but the program was never loaded,
224 * it is possible that prog->instances.nr == -1.
225 */
226 if (prog->instances.nr > 0) {
227 for (i = 0; i < prog->instances.nr; i++)
228 zclose(prog->instances.fds[i]);
229 } else if (prog->instances.nr != -1) {
230 pr_warning("Internal error: instances.nr is %d\n",
231 prog->instances.nr);
232 }
233
234 prog->instances.nr = -1;
235 zfree(&prog->instances.fds);
213} 236}
214 237
215static void bpf_program__exit(struct bpf_program *prog) 238static void bpf_program__exit(struct bpf_program *prog)
@@ -260,7 +283,8 @@ bpf_program__init(void *data, size_t size, char *name, int idx,
260 memcpy(prog->insns, data, 283 memcpy(prog->insns, data,
261 prog->insns_cnt * sizeof(struct bpf_insn)); 284 prog->insns_cnt * sizeof(struct bpf_insn));
262 prog->idx = idx; 285 prog->idx = idx;
263 prog->fd = -1; 286 prog->instances.fds = NULL;
287 prog->instances.nr = -1;
264 288
265 return 0; 289 return 0;
266errout: 290errout:
@@ -469,21 +493,77 @@ static int
469bpf_object__init_maps(struct bpf_object *obj, void *data, 493bpf_object__init_maps(struct bpf_object *obj, void *data,
470 size_t size) 494 size_t size)
471{ 495{
472 if (size == 0) { 496 size_t nr_maps;
497 int i;
498
499 nr_maps = size / sizeof(struct bpf_map_def);
500 if (!data || !nr_maps) {
473 pr_debug("%s doesn't need map definition\n", 501 pr_debug("%s doesn't need map definition\n",
474 obj->path); 502 obj->path);
475 return 0; 503 return 0;
476 } 504 }
477 505
478 obj->maps_buf = malloc(size); 506 pr_debug("maps in %s: %zd bytes\n", obj->path, size);
479 if (!obj->maps_buf) { 507
480 pr_warning("malloc maps failed: %s\n", obj->path); 508 obj->maps = calloc(nr_maps, sizeof(obj->maps[0]));
509 if (!obj->maps) {
510 pr_warning("alloc maps for object failed\n");
481 return -ENOMEM; 511 return -ENOMEM;
482 } 512 }
513 obj->nr_maps = nr_maps;
483 514
484 obj->maps_buf_sz = size; 515 for (i = 0; i < nr_maps; i++) {
485 memcpy(obj->maps_buf, data, size); 516 struct bpf_map_def *def = &obj->maps[i].def;
486 pr_debug("maps in %s: %ld bytes\n", obj->path, (long)size); 517
518 /*
519 * fill all fd with -1 so won't close incorrect
520 * fd (fd=0 is stdin) when failure (zclose won't close
521 * negative fd)).
522 */
523 obj->maps[i].fd = -1;
524
525 /* Save map definition into obj->maps */
526 *def = ((struct bpf_map_def *)data)[i];
527 }
528 return 0;
529}
530
531static int
532bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
533{
534 int i;
535 Elf_Data *symbols = obj->efile.symbols;
536
537 if (!symbols || maps_shndx < 0)
538 return -EINVAL;
539
540 for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
541 GElf_Sym sym;
542 size_t map_idx;
543 const char *map_name;
544
545 if (!gelf_getsym(symbols, i, &sym))
546 continue;
547 if (sym.st_shndx != maps_shndx)
548 continue;
549
550 map_name = elf_strptr(obj->efile.elf,
551 obj->efile.strtabidx,
552 sym.st_name);
553 map_idx = sym.st_value / sizeof(struct bpf_map_def);
554 if (map_idx >= obj->nr_maps) {
555 pr_warning("index of map \"%s\" is buggy: %zu > %zu\n",
556 map_name, map_idx, obj->nr_maps);
557 continue;
558 }
559 obj->maps[map_idx].name = strdup(map_name);
560 if (!obj->maps[map_idx].name) {
561 pr_warning("failed to alloc map name\n");
562 return -ENOMEM;
563 }
564 pr_debug("map %zu is \"%s\"\n", map_idx,
565 obj->maps[map_idx].name);
566 }
487 return 0; 567 return 0;
488} 568}
489 569
@@ -492,7 +572,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
492 Elf *elf = obj->efile.elf; 572 Elf *elf = obj->efile.elf;
493 GElf_Ehdr *ep = &obj->efile.ehdr; 573 GElf_Ehdr *ep = &obj->efile.ehdr;
494 Elf_Scn *scn = NULL; 574 Elf_Scn *scn = NULL;
495 int idx = 0, err = 0; 575 int idx = 0, err = 0, maps_shndx = -1;
496 576
497 /* Elf is corrupted/truncated, avoid calling elf_strptr. */ 577 /* Elf is corrupted/truncated, avoid calling elf_strptr. */
498 if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) { 578 if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) {
@@ -542,16 +622,19 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
542 err = bpf_object__init_kversion(obj, 622 err = bpf_object__init_kversion(obj,
543 data->d_buf, 623 data->d_buf,
544 data->d_size); 624 data->d_size);
545 else if (strcmp(name, "maps") == 0) 625 else if (strcmp(name, "maps") == 0) {
546 err = bpf_object__init_maps(obj, data->d_buf, 626 err = bpf_object__init_maps(obj, data->d_buf,
547 data->d_size); 627 data->d_size);
548 else if (sh.sh_type == SHT_SYMTAB) { 628 maps_shndx = idx;
629 } else if (sh.sh_type == SHT_SYMTAB) {
549 if (obj->efile.symbols) { 630 if (obj->efile.symbols) {
550 pr_warning("bpf: multiple SYMTAB in %s\n", 631 pr_warning("bpf: multiple SYMTAB in %s\n",
551 obj->path); 632 obj->path);
552 err = -LIBBPF_ERRNO__FORMAT; 633 err = -LIBBPF_ERRNO__FORMAT;
553 } else 634 } else {
554 obj->efile.symbols = data; 635 obj->efile.symbols = data;
636 obj->efile.strtabidx = sh.sh_link;
637 }
555 } else if ((sh.sh_type == SHT_PROGBITS) && 638 } else if ((sh.sh_type == SHT_PROGBITS) &&
556 (sh.sh_flags & SHF_EXECINSTR) && 639 (sh.sh_flags & SHF_EXECINSTR) &&
557 (data->d_size > 0)) { 640 (data->d_size > 0)) {
@@ -586,6 +669,13 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
586 if (err) 669 if (err)
587 goto out; 670 goto out;
588 } 671 }
672
673 if (!obj->efile.strtabidx || obj->efile.strtabidx >= idx) {
674 pr_warning("Corrupted ELF file: index of strtab invalid\n");
675 return LIBBPF_ERRNO__FORMAT;
676 }
677 if (maps_shndx >= 0)
678 err = bpf_object__init_maps_name(obj, maps_shndx);
589out: 679out:
590 return err; 680 return err;
591} 681}
@@ -668,37 +758,15 @@ static int
668bpf_object__create_maps(struct bpf_object *obj) 758bpf_object__create_maps(struct bpf_object *obj)
669{ 759{
670 unsigned int i; 760 unsigned int i;
671 size_t nr_maps;
672 int *pfd;
673
674 nr_maps = obj->maps_buf_sz / sizeof(struct bpf_map_def);
675 if (!obj->maps_buf || !nr_maps) {
676 pr_debug("don't need create maps for %s\n",
677 obj->path);
678 return 0;
679 }
680
681 obj->map_fds = malloc(sizeof(int) * nr_maps);
682 if (!obj->map_fds) {
683 pr_warning("realloc perf_bpf_map_fds failed\n");
684 return -ENOMEM;
685 }
686 obj->nr_map_fds = nr_maps;
687 761
688 /* fill all fd with -1 */ 762 for (i = 0; i < obj->nr_maps; i++) {
689 memset(obj->map_fds, -1, sizeof(int) * nr_maps); 763 struct bpf_map_def *def = &obj->maps[i].def;
690 764 int *pfd = &obj->maps[i].fd;
691 pfd = obj->map_fds;
692 for (i = 0; i < nr_maps; i++) {
693 struct bpf_map_def def;
694 765
695 def = *(struct bpf_map_def *)(obj->maps_buf + 766 *pfd = bpf_create_map(def->type,
696 i * sizeof(struct bpf_map_def)); 767 def->key_size,
697 768 def->value_size,
698 *pfd = bpf_create_map(def.type, 769 def->max_entries);
699 def.key_size,
700 def.value_size,
701 def.max_entries);
702 if (*pfd < 0) { 770 if (*pfd < 0) {
703 size_t j; 771 size_t j;
704 int err = *pfd; 772 int err = *pfd;
@@ -706,22 +774,17 @@ bpf_object__create_maps(struct bpf_object *obj)
706 pr_warning("failed to create map: %s\n", 774 pr_warning("failed to create map: %s\n",
707 strerror(errno)); 775 strerror(errno));
708 for (j = 0; j < i; j++) 776 for (j = 0; j < i; j++)
709 zclose(obj->map_fds[j]); 777 zclose(obj->maps[j].fd);
710 obj->nr_map_fds = 0;
711 zfree(&obj->map_fds);
712 return err; 778 return err;
713 } 779 }
714 pr_debug("create map: fd=%d\n", *pfd); 780 pr_debug("create map: fd=%d\n", *pfd);
715 pfd++;
716 } 781 }
717 782
718 zfree(&obj->maps_buf);
719 obj->maps_buf_sz = 0;
720 return 0; 783 return 0;
721} 784}
722 785
723static int 786static int
724bpf_program__relocate(struct bpf_program *prog, int *map_fds) 787bpf_program__relocate(struct bpf_program *prog, struct bpf_object *obj)
725{ 788{
726 int i; 789 int i;
727 790
@@ -741,7 +804,7 @@ bpf_program__relocate(struct bpf_program *prog, int *map_fds)
741 return -LIBBPF_ERRNO__RELOC; 804 return -LIBBPF_ERRNO__RELOC;
742 } 805 }
743 insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD; 806 insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD;
744 insns[insn_idx].imm = map_fds[map_idx]; 807 insns[insn_idx].imm = obj->maps[map_idx].fd;
745 } 808 }
746 809
747 zfree(&prog->reloc_desc); 810 zfree(&prog->reloc_desc);
@@ -760,7 +823,7 @@ bpf_object__relocate(struct bpf_object *obj)
760 for (i = 0; i < obj->nr_programs; i++) { 823 for (i = 0; i < obj->nr_programs; i++) {
761 prog = &obj->programs[i]; 824 prog = &obj->programs[i];
762 825
763 err = bpf_program__relocate(prog, obj->map_fds); 826 err = bpf_program__relocate(prog, obj);
764 if (err) { 827 if (err) {
765 pr_warning("failed to relocate '%s'\n", 828 pr_warning("failed to relocate '%s'\n",
766 prog->section_name); 829 prog->section_name);
@@ -784,8 +847,7 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
784 Elf_Data *data = obj->efile.reloc[i].data; 847 Elf_Data *data = obj->efile.reloc[i].data;
785 int idx = shdr->sh_info; 848 int idx = shdr->sh_info;
786 struct bpf_program *prog; 849 struct bpf_program *prog;
787 size_t nr_maps = obj->maps_buf_sz / 850 size_t nr_maps = obj->nr_maps;
788 sizeof(struct bpf_map_def);
789 851
790 if (shdr->sh_type != SHT_REL) { 852 if (shdr->sh_type != SHT_REL) {
791 pr_warning("internal error at %d\n", __LINE__); 853 pr_warning("internal error at %d\n", __LINE__);
@@ -860,13 +922,73 @@ static int
860bpf_program__load(struct bpf_program *prog, 922bpf_program__load(struct bpf_program *prog,
861 char *license, u32 kern_version) 923 char *license, u32 kern_version)
862{ 924{
863 int err, fd; 925 int err = 0, fd, i;
864 926
865 err = load_program(prog->insns, prog->insns_cnt, 927 if (prog->instances.nr < 0 || !prog->instances.fds) {
866 license, kern_version, &fd); 928 if (prog->preprocessor) {
867 if (!err) 929 pr_warning("Internal error: can't load program '%s'\n",
868 prog->fd = fd; 930 prog->section_name);
931 return -LIBBPF_ERRNO__INTERNAL;
932 }
933
934 prog->instances.fds = malloc(sizeof(int));
935 if (!prog->instances.fds) {
936 pr_warning("Not enough memory for BPF fds\n");
937 return -ENOMEM;
938 }
939 prog->instances.nr = 1;
940 prog->instances.fds[0] = -1;
941 }
942
943 if (!prog->preprocessor) {
944 if (prog->instances.nr != 1) {
945 pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n",
946 prog->section_name, prog->instances.nr);
947 }
948 err = load_program(prog->insns, prog->insns_cnt,
949 license, kern_version, &fd);
950 if (!err)
951 prog->instances.fds[0] = fd;
952 goto out;
953 }
954
955 for (i = 0; i < prog->instances.nr; i++) {
956 struct bpf_prog_prep_result result;
957 bpf_program_prep_t preprocessor = prog->preprocessor;
958
959 bzero(&result, sizeof(result));
960 err = preprocessor(prog, i, prog->insns,
961 prog->insns_cnt, &result);
962 if (err) {
963 pr_warning("Preprocessing the %dth instance of program '%s' failed\n",
964 i, prog->section_name);
965 goto out;
966 }
967
968 if (!result.new_insn_ptr || !result.new_insn_cnt) {
969 pr_debug("Skip loading the %dth instance of program '%s'\n",
970 i, prog->section_name);
971 prog->instances.fds[i] = -1;
972 if (result.pfd)
973 *result.pfd = -1;
974 continue;
975 }
976
977 err = load_program(result.new_insn_ptr,
978 result.new_insn_cnt,
979 license, kern_version, &fd);
980
981 if (err) {
982 pr_warning("Loading the %dth instance of program '%s' failed\n",
983 i, prog->section_name);
984 goto out;
985 }
869 986
987 if (result.pfd)
988 *result.pfd = fd;
989 prog->instances.fds[i] = fd;
990 }
991out:
870 if (err) 992 if (err)
871 pr_warning("failed to load program '%s'\n", 993 pr_warning("failed to load program '%s'\n",
872 prog->section_name); 994 prog->section_name);
@@ -970,10 +1092,8 @@ int bpf_object__unload(struct bpf_object *obj)
970 if (!obj) 1092 if (!obj)
971 return -EINVAL; 1093 return -EINVAL;
972 1094
973 for (i = 0; i < obj->nr_map_fds; i++) 1095 for (i = 0; i < obj->nr_maps; i++)
974 zclose(obj->map_fds[i]); 1096 zclose(obj->maps[i].fd);
975 zfree(&obj->map_fds);
976 obj->nr_map_fds = 0;
977 1097
978 for (i = 0; i < obj->nr_programs; i++) 1098 for (i = 0; i < obj->nr_programs; i++)
979 bpf_program__unload(&obj->programs[i]); 1099 bpf_program__unload(&obj->programs[i]);
@@ -1016,7 +1136,16 @@ void bpf_object__close(struct bpf_object *obj)
1016 bpf_object__elf_finish(obj); 1136 bpf_object__elf_finish(obj);
1017 bpf_object__unload(obj); 1137 bpf_object__unload(obj);
1018 1138
1019 zfree(&obj->maps_buf); 1139 for (i = 0; i < obj->nr_maps; i++) {
1140 zfree(&obj->maps[i].name);
1141 if (obj->maps[i].clear_priv)
1142 obj->maps[i].clear_priv(&obj->maps[i],
1143 obj->maps[i].priv);
1144 obj->maps[i].priv = NULL;
1145 obj->maps[i].clear_priv = NULL;
1146 }
1147 zfree(&obj->maps);
1148 obj->nr_maps = 0;
1020 1149
1021 if (obj->programs && obj->nr_programs) { 1150 if (obj->programs && obj->nr_programs) {
1022 for (i = 0; i < obj->nr_programs; i++) 1151 for (i = 0; i < obj->nr_programs; i++)
@@ -1121,5 +1250,142 @@ const char *bpf_program__title(struct bpf_program *prog, bool needs_copy)
1121 1250
1122int bpf_program__fd(struct bpf_program *prog) 1251int bpf_program__fd(struct bpf_program *prog)
1123{ 1252{
1124 return prog->fd; 1253 return bpf_program__nth_fd(prog, 0);
1254}
1255
1256int bpf_program__set_prep(struct bpf_program *prog, int nr_instances,
1257 bpf_program_prep_t prep)
1258{
1259 int *instances_fds;
1260
1261 if (nr_instances <= 0 || !prep)
1262 return -EINVAL;
1263
1264 if (prog->instances.nr > 0 || prog->instances.fds) {
1265 pr_warning("Can't set pre-processor after loading\n");
1266 return -EINVAL;
1267 }
1268
1269 instances_fds = malloc(sizeof(int) * nr_instances);
1270 if (!instances_fds) {
1271 pr_warning("alloc memory failed for fds\n");
1272 return -ENOMEM;
1273 }
1274
1275 /* fill all fd with -1 */
1276 memset(instances_fds, -1, sizeof(int) * nr_instances);
1277
1278 prog->instances.nr = nr_instances;
1279 prog->instances.fds = instances_fds;
1280 prog->preprocessor = prep;
1281 return 0;
1282}
1283
1284int bpf_program__nth_fd(struct bpf_program *prog, int n)
1285{
1286 int fd;
1287
1288 if (n >= prog->instances.nr || n < 0) {
1289 pr_warning("Can't get the %dth fd from program %s: only %d instances\n",
1290 n, prog->section_name, prog->instances.nr);
1291 return -EINVAL;
1292 }
1293
1294 fd = prog->instances.fds[n];
1295 if (fd < 0) {
1296 pr_warning("%dth instance of program '%s' is invalid\n",
1297 n, prog->section_name);
1298 return -ENOENT;
1299 }
1300
1301 return fd;
1302}
1303
1304int bpf_map__get_fd(struct bpf_map *map)
1305{
1306 if (!map)
1307 return -EINVAL;
1308
1309 return map->fd;
1310}
1311
1312int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef)
1313{
1314 if (!map || !pdef)
1315 return -EINVAL;
1316
1317 *pdef = map->def;
1318 return 0;
1319}
1320
1321const char *bpf_map__get_name(struct bpf_map *map)
1322{
1323 if (!map)
1324 return NULL;
1325 return map->name;
1326}
1327
1328int bpf_map__set_private(struct bpf_map *map, void *priv,
1329 bpf_map_clear_priv_t clear_priv)
1330{
1331 if (!map)
1332 return -EINVAL;
1333
1334 if (map->priv) {
1335 if (map->clear_priv)
1336 map->clear_priv(map, map->priv);
1337 }
1338
1339 map->priv = priv;
1340 map->clear_priv = clear_priv;
1341 return 0;
1342}
1343
1344int bpf_map__get_private(struct bpf_map *map, void **ppriv)
1345{
1346 if (!map)
1347 return -EINVAL;
1348
1349 if (ppriv)
1350 *ppriv = map->priv;
1351 return 0;
1352}
1353
1354struct bpf_map *
1355bpf_map__next(struct bpf_map *prev, struct bpf_object *obj)
1356{
1357 size_t idx;
1358 struct bpf_map *s, *e;
1359
1360 if (!obj || !obj->maps)
1361 return NULL;
1362
1363 s = obj->maps;
1364 e = obj->maps + obj->nr_maps;
1365
1366 if (prev == NULL)
1367 return s;
1368
1369 if ((prev < s) || (prev >= e)) {
1370 pr_warning("error in %s: map handler doesn't belong to object\n",
1371 __func__);
1372 return NULL;
1373 }
1374
1375 idx = (prev - obj->maps) + 1;
1376 if (idx >= obj->nr_maps)
1377 return NULL;
1378 return &obj->maps[idx];
1379}
1380
1381struct bpf_map *
1382bpf_object__get_map_by_name(struct bpf_object *obj, const char *name)
1383{
1384 struct bpf_map *pos;
1385
1386 bpf_map__for_each(pos, obj) {
1387 if (pos->name && !strcmp(pos->name, name))
1388 return pos;
1389 }
1390 return NULL;
1125} 1391}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index c9a9aef2806c..a51594c7b518 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -88,6 +88,70 @@ const char *bpf_program__title(struct bpf_program *prog, bool needs_copy);
88 88
89int bpf_program__fd(struct bpf_program *prog); 89int bpf_program__fd(struct bpf_program *prog);
90 90
91struct bpf_insn;
92
93/*
94 * Libbpf allows callers to adjust BPF programs before being loaded
95 * into kernel. One program in an object file can be transform into
96 * multiple variants to be attached to different code.
97 *
98 * bpf_program_prep_t, bpf_program__set_prep and bpf_program__nth_fd
99 * are APIs for this propose.
100 *
101 * - bpf_program_prep_t:
102 * It defines 'preprocessor', which is a caller defined function
103 * passed to libbpf through bpf_program__set_prep(), and will be
104 * called before program is loaded. The processor should adjust
105 * the program one time for each instances according to the number
106 * passed to it.
107 *
108 * - bpf_program__set_prep:
109 * Attachs a preprocessor to a BPF program. The number of instances
110 * whould be created is also passed through this function.
111 *
112 * - bpf_program__nth_fd:
113 * After the program is loaded, get resuling fds from bpf program for
114 * each instances.
115 *
116 * If bpf_program__set_prep() is not used, the program whould be loaded
117 * without adjustment during bpf_object__load(). The program has only
118 * one instance. In this case bpf_program__fd(prog) is equal to
119 * bpf_program__nth_fd(prog, 0).
120 */
121
122struct bpf_prog_prep_result {
123 /*
124 * If not NULL, load new instruction array.
125 * If set to NULL, don't load this instance.
126 */
127 struct bpf_insn *new_insn_ptr;
128 int new_insn_cnt;
129
130 /* If not NULL, result fd is set to it */
131 int *pfd;
132};
133
134/*
135 * Parameters of bpf_program_prep_t:
136 * - prog: The bpf_program being loaded.
137 * - n: Index of instance being generated.
138 * - insns: BPF instructions array.
139 * - insns_cnt:Number of instructions in insns.
140 * - res: Output parameter, result of transformation.
141 *
142 * Return value:
143 * - Zero: pre-processing success.
144 * - Non-zero: pre-processing, stop loading.
145 */
146typedef int (*bpf_program_prep_t)(struct bpf_program *prog, int n,
147 struct bpf_insn *insns, int insns_cnt,
148 struct bpf_prog_prep_result *res);
149
150int bpf_program__set_prep(struct bpf_program *prog, int nr_instance,
151 bpf_program_prep_t prep);
152
153int bpf_program__nth_fd(struct bpf_program *prog, int n);
154
91/* 155/*
92 * We don't need __attribute__((packed)) now since it is 156 * We don't need __attribute__((packed)) now since it is
93 * unnecessary for 'bpf_map_def' because they are all aligned. 157 * unnecessary for 'bpf_map_def' because they are all aligned.
@@ -101,4 +165,28 @@ struct bpf_map_def {
101 unsigned int max_entries; 165 unsigned int max_entries;
102}; 166};
103 167
168/*
169 * There is another 'struct bpf_map' in include/linux/map.h. However,
170 * it is not a uapi header so no need to consider name clash.
171 */
172struct bpf_map;
173struct bpf_map *
174bpf_object__get_map_by_name(struct bpf_object *obj, const char *name);
175
176struct bpf_map *
177bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
178#define bpf_map__for_each(pos, obj) \
179 for ((pos) = bpf_map__next(NULL, (obj)); \
180 (pos) != NULL; \
181 (pos) = bpf_map__next((pos), (obj)))
182
183int bpf_map__get_fd(struct bpf_map *map);
184int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef);
185const char *bpf_map__get_name(struct bpf_map *map);
186
187typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
188int bpf_map__set_private(struct bpf_map *map, void *priv,
189 bpf_map_clear_priv_t clear_priv);
190int bpf_map__get_private(struct bpf_map *map, void **ppriv);
191
104#endif 192#endif
diff --git a/tools/lib/find_bit.c b/tools/lib/find_bit.c
new file mode 100644
index 000000000000..9122a9e80046
--- /dev/null
+++ b/tools/lib/find_bit.c
@@ -0,0 +1,84 @@
1/* bit search implementation
2 *
3 * Copied from lib/find_bit.c to tools/lib/find_bit.c
4 *
5 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
6 * Written by David Howells (dhowells@redhat.com)
7 *
8 * Copyright (C) 2008 IBM Corporation
9 * 'find_last_bit' is written by Rusty Russell <rusty@rustcorp.com.au>
10 * (Inspired by David Howell's find_next_bit implementation)
11 *
12 * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease
13 * size and improve performance, 2015.
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version
18 * 2 of the License, or (at your option) any later version.
19 */
20
21#include <linux/bitops.h>
22#include <linux/bitmap.h>
23#include <linux/kernel.h>
24
25#if !defined(find_next_bit)
26
27/*
28 * This is a common helper function for find_next_bit and
29 * find_next_zero_bit. The difference is the "invert" argument, which
30 * is XORed with each fetched word before searching it for one bits.
31 */
32static unsigned long _find_next_bit(const unsigned long *addr,
33 unsigned long nbits, unsigned long start, unsigned long invert)
34{
35 unsigned long tmp;
36
37 if (!nbits || start >= nbits)
38 return nbits;
39
40 tmp = addr[start / BITS_PER_LONG] ^ invert;
41
42 /* Handle 1st word. */
43 tmp &= BITMAP_FIRST_WORD_MASK(start);
44 start = round_down(start, BITS_PER_LONG);
45
46 while (!tmp) {
47 start += BITS_PER_LONG;
48 if (start >= nbits)
49 return nbits;
50
51 tmp = addr[start / BITS_PER_LONG] ^ invert;
52 }
53
54 return min(start + __ffs(tmp), nbits);
55}
56#endif
57
58#ifndef find_next_bit
59/*
60 * Find the next set bit in a memory region.
61 */
62unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
63 unsigned long offset)
64{
65 return _find_next_bit(addr, size, offset, 0UL);
66}
67#endif
68
69#ifndef find_first_bit
70/*
71 * Find the first set bit in a memory region.
72 */
73unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
74{
75 unsigned long idx;
76
77 for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
78 if (addr[idx])
79 return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size);
80 }
81
82 return size;
83}
84#endif
diff --git a/tools/lib/string.c b/tools/lib/string.c
new file mode 100644
index 000000000000..bd239bc1d557
--- /dev/null
+++ b/tools/lib/string.c
@@ -0,0 +1,89 @@
1/*
2 * linux/tools/lib/string.c
3 *
4 * Copied from linux/lib/string.c, where it is:
5 *
6 * Copyright (C) 1991, 1992 Linus Torvalds
7 *
8 * More specifically, the first copied function was strtobool, which
9 * was introduced by:
10 *
11 * d0f1fed29e6e ("Add a strtobool function matching semantics of existing in kernel equivalents")
12 * Author: Jonathan Cameron <jic23@cam.ac.uk>
13 */
14
15#include <stdlib.h>
16#include <string.h>
17#include <errno.h>
18#include <linux/string.h>
19#include <linux/compiler.h>
20
21/**
22 * memdup - duplicate region of memory
23 *
24 * @src: memory region to duplicate
25 * @len: memory region length
26 */
27void *memdup(const void *src, size_t len)
28{
29 void *p = malloc(len);
30
31 if (p)
32 memcpy(p, src, len);
33
34 return p;
35}
36
37/**
38 * strtobool - convert common user inputs into boolean values
39 * @s: input string
40 * @res: result
41 *
42 * This routine returns 0 iff the first character is one of 'Yy1Nn0'.
43 * Otherwise it will return -EINVAL. Value pointed to by res is
44 * updated upon finding a match.
45 */
46int strtobool(const char *s, bool *res)
47{
48 switch (s[0]) {
49 case 'y':
50 case 'Y':
51 case '1':
52 *res = true;
53 break;
54 case 'n':
55 case 'N':
56 case '0':
57 *res = false;
58 break;
59 default:
60 return -EINVAL;
61 }
62 return 0;
63}
64
65/**
66 * strlcpy - Copy a C-string into a sized buffer
67 * @dest: Where to copy the string to
68 * @src: Where to copy the string from
69 * @size: size of destination buffer
70 *
71 * Compatible with *BSD: the result is always a valid
72 * NUL-terminated string that fits in the buffer (unless,
73 * of course, the buffer size is zero). It does not pad
74 * out the result like strncpy() does.
75 *
76 * If libc has strlcpy() then that version will override this
77 * implementation:
78 */
79size_t __weak strlcpy(char *dest, const char *src, size_t size)
80{
81 size_t ret = strlen(src);
82
83 if (size) {
84 size_t len = (ret >= size) ? size - 1 : ret;
85 memcpy(dest, src, len);
86 dest[len] = '\0';
87 }
88 return ret;
89}
diff --git a/tools/lib/subcmd/Build b/tools/lib/subcmd/Build
new file mode 100644
index 000000000000..ee31288788c1
--- /dev/null
+++ b/tools/lib/subcmd/Build
@@ -0,0 +1,7 @@
1libsubcmd-y += exec-cmd.o
2libsubcmd-y += help.o
3libsubcmd-y += pager.o
4libsubcmd-y += parse-options.o
5libsubcmd-y += run-command.o
6libsubcmd-y += sigchain.o
7libsubcmd-y += subcmd-config.o
diff --git a/tools/lib/subcmd/Makefile b/tools/lib/subcmd/Makefile
new file mode 100644
index 000000000000..629cf8c14e68
--- /dev/null
+++ b/tools/lib/subcmd/Makefile
@@ -0,0 +1,48 @@
1include ../../scripts/Makefile.include
2include ../../perf/config/utilities.mak # QUIET_CLEAN
3
4ifeq ($(srctree),)
5srctree := $(patsubst %/,%,$(dir $(shell pwd)))
6srctree := $(patsubst %/,%,$(dir $(srctree)))
7srctree := $(patsubst %/,%,$(dir $(srctree)))
8#$(info Determined 'srctree' to be $(srctree))
9endif
10
11CC = $(CROSS_COMPILE)gcc
12AR = $(CROSS_COMPILE)ar
13RM = rm -f
14
15MAKEFLAGS += --no-print-directory
16
17LIBFILE = $(OUTPUT)libsubcmd.a
18
19CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
20CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
21CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
22
23CFLAGS += -I$(srctree)/tools/include/
24CFLAGS += -I$(srctree)/include/uapi
25CFLAGS += -I$(srctree)/include
26
27SUBCMD_IN := $(OUTPUT)libsubcmd-in.o
28
29all:
30
31export srctree OUTPUT CC LD CFLAGS V
32include $(srctree)/tools/build/Makefile.include
33
34all: fixdep $(LIBFILE)
35
36$(SUBCMD_IN): FORCE
37 @$(MAKE) $(build)=libsubcmd
38
39$(LIBFILE): $(SUBCMD_IN)
40 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(SUBCMD_IN)
41
42clean:
43 $(call QUIET_CLEAN, libsubcmd) $(RM) $(LIBFILE); \
44 find $(if $(OUTPUT),$(OUTPUT),.) -name \*.o -or -name \*.o.cmd -or -name \*.o.d | xargs $(RM)
45
46FORCE:
47
48.PHONY: clean FORCE
diff --git a/tools/lib/subcmd/exec-cmd.c b/tools/lib/subcmd/exec-cmd.c
new file mode 100644
index 000000000000..1ae833af1a4a
--- /dev/null
+++ b/tools/lib/subcmd/exec-cmd.c
@@ -0,0 +1,209 @@
1#include <linux/compiler.h>
2#include <linux/string.h>
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <unistd.h>
6#include <string.h>
7#include <stdlib.h>
8#include <stdio.h>
9#include "subcmd-util.h"
10#include "exec-cmd.h"
11#include "subcmd-config.h"
12
13#define MAX_ARGS 32
14#define PATH_MAX 4096
15
16static const char *argv_exec_path;
17static const char *argv0_path;
18
19void exec_cmd_init(const char *exec_name, const char *prefix,
20 const char *exec_path, const char *exec_path_env)
21{
22 subcmd_config.exec_name = exec_name;
23 subcmd_config.prefix = prefix;
24 subcmd_config.exec_path = exec_path;
25 subcmd_config.exec_path_env = exec_path_env;
26}
27
28#define is_dir_sep(c) ((c) == '/')
29
30static int is_absolute_path(const char *path)
31{
32 return path[0] == '/';
33}
34
35static const char *get_pwd_cwd(void)
36{
37 static char cwd[PATH_MAX + 1];
38 char *pwd;
39 struct stat cwd_stat, pwd_stat;
40 if (getcwd(cwd, PATH_MAX) == NULL)
41 return NULL;
42 pwd = getenv("PWD");
43 if (pwd && strcmp(pwd, cwd)) {
44 stat(cwd, &cwd_stat);
45 if (!stat(pwd, &pwd_stat) &&
46 pwd_stat.st_dev == cwd_stat.st_dev &&
47 pwd_stat.st_ino == cwd_stat.st_ino) {
48 strlcpy(cwd, pwd, PATH_MAX);
49 }
50 }
51 return cwd;
52}
53
54static const char *make_nonrelative_path(const char *path)
55{
56 static char buf[PATH_MAX + 1];
57
58 if (is_absolute_path(path)) {
59 if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
60 die("Too long path: %.*s", 60, path);
61 } else {
62 const char *cwd = get_pwd_cwd();
63 if (!cwd)
64 die("Cannot determine the current working directory");
65 if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX)
66 die("Too long path: %.*s", 60, path);
67 }
68 return buf;
69}
70
71char *system_path(const char *path)
72{
73 char *buf = NULL;
74
75 if (is_absolute_path(path))
76 return strdup(path);
77
78 astrcatf(&buf, "%s/%s", subcmd_config.prefix, path);
79
80 return buf;
81}
82
83const char *extract_argv0_path(const char *argv0)
84{
85 const char *slash;
86
87 if (!argv0 || !*argv0)
88 return NULL;
89 slash = argv0 + strlen(argv0);
90
91 while (argv0 <= slash && !is_dir_sep(*slash))
92 slash--;
93
94 if (slash >= argv0) {
95 argv0_path = strndup(argv0, slash - argv0);
96 return argv0_path ? slash + 1 : NULL;
97 }
98
99 return argv0;
100}
101
102void set_argv_exec_path(const char *exec_path)
103{
104 argv_exec_path = exec_path;
105 /*
106 * Propagate this setting to external programs.
107 */
108 setenv(subcmd_config.exec_path_env, exec_path, 1);
109}
110
111
112/* Returns the highest-priority location to look for subprograms. */
113char *get_argv_exec_path(void)
114{
115 char *env;
116
117 if (argv_exec_path)
118 return strdup(argv_exec_path);
119
120 env = getenv(subcmd_config.exec_path_env);
121 if (env && *env)
122 return strdup(env);
123
124 return system_path(subcmd_config.exec_path);
125}
126
127static void add_path(char **out, const char *path)
128{
129 if (path && *path) {
130 if (is_absolute_path(path))
131 astrcat(out, path);
132 else
133 astrcat(out, make_nonrelative_path(path));
134
135 astrcat(out, ":");
136 }
137}
138
139void setup_path(void)
140{
141 const char *old_path = getenv("PATH");
142 char *new_path = NULL;
143 char *tmp = get_argv_exec_path();
144
145 add_path(&new_path, tmp);
146 add_path(&new_path, argv0_path);
147 free(tmp);
148
149 if (old_path)
150 astrcat(&new_path, old_path);
151 else
152 astrcat(&new_path, "/usr/local/bin:/usr/bin:/bin");
153
154 setenv("PATH", new_path, 1);
155
156 free(new_path);
157}
158
159static const char **prepare_exec_cmd(const char **argv)
160{
161 int argc;
162 const char **nargv;
163
164 for (argc = 0; argv[argc]; argc++)
165 ; /* just counting */
166 nargv = malloc(sizeof(*nargv) * (argc + 2));
167
168 nargv[0] = subcmd_config.exec_name;
169 for (argc = 0; argv[argc]; argc++)
170 nargv[argc + 1] = argv[argc];
171 nargv[argc + 1] = NULL;
172 return nargv;
173}
174
175int execv_cmd(const char **argv) {
176 const char **nargv = prepare_exec_cmd(argv);
177
178 /* execvp() can only ever return if it fails */
179 execvp(subcmd_config.exec_name, (char **)nargv);
180
181 free(nargv);
182 return -1;
183}
184
185
186int execl_cmd(const char *cmd,...)
187{
188 int argc;
189 const char *argv[MAX_ARGS + 1];
190 const char *arg;
191 va_list param;
192
193 va_start(param, cmd);
194 argv[0] = cmd;
195 argc = 1;
196 while (argc < MAX_ARGS) {
197 arg = argv[argc++] = va_arg(param, char *);
198 if (!arg)
199 break;
200 }
201 va_end(param);
202 if (MAX_ARGS <= argc) {
203 fprintf(stderr, " Error: too many args to run %s\n", cmd);
204 return -1;
205 }
206
207 argv[argc] = NULL;
208 return execv_cmd(argv);
209}
diff --git a/tools/lib/subcmd/exec-cmd.h b/tools/lib/subcmd/exec-cmd.h
new file mode 100644
index 000000000000..5d08bda31d90
--- /dev/null
+++ b/tools/lib/subcmd/exec-cmd.h
@@ -0,0 +1,16 @@
1#ifndef __SUBCMD_EXEC_CMD_H
2#define __SUBCMD_EXEC_CMD_H
3
4extern void exec_cmd_init(const char *exec_name, const char *prefix,
5 const char *exec_path, const char *exec_path_env);
6
7extern void set_argv_exec_path(const char *exec_path);
8extern const char *extract_argv0_path(const char *path);
9extern void setup_path(void);
10extern int execv_cmd(const char **argv); /* NULL terminated */
11extern int execl_cmd(const char *cmd, ...);
12/* get_argv_exec_path and system_path return malloc'd string, caller must free it */
13extern char *get_argv_exec_path(void);
14extern char *system_path(const char *path);
15
16#endif /* __SUBCMD_EXEC_CMD_H */
diff --git a/tools/perf/util/help.c b/tools/lib/subcmd/help.c
index 86c37c472263..e228c3cb3716 100644
--- a/tools/perf/util/help.c
+++ b/tools/lib/subcmd/help.c
@@ -1,9 +1,15 @@
1#include "cache.h" 1#include <stdio.h>
2#include "../builtin.h" 2#include <stdlib.h>
3#include "exec_cmd.h" 3#include <string.h>
4#include "levenshtein.h"
5#include "help.h"
6#include <termios.h> 4#include <termios.h>
5#include <sys/ioctl.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <unistd.h>
9#include <dirent.h>
10#include "subcmd-util.h"
11#include "help.h"
12#include "exec-cmd.h"
7 13
8void add_cmdname(struct cmdnames *cmds, const char *name, size_t len) 14void add_cmdname(struct cmdnames *cmds, const char *name, size_t len)
9{ 15{
@@ -17,7 +23,7 @@ void add_cmdname(struct cmdnames *cmds, const char *name, size_t len)
17 cmds->names[cmds->cnt++] = ent; 23 cmds->names[cmds->cnt++] = ent;
18} 24}
19 25
20static void clean_cmdnames(struct cmdnames *cmds) 26void clean_cmdnames(struct cmdnames *cmds)
21{ 27{
22 unsigned int i; 28 unsigned int i;
23 29
@@ -28,14 +34,14 @@ static void clean_cmdnames(struct cmdnames *cmds)
28 cmds->alloc = 0; 34 cmds->alloc = 0;
29} 35}
30 36
31static int cmdname_compare(const void *a_, const void *b_) 37int cmdname_compare(const void *a_, const void *b_)
32{ 38{
33 struct cmdname *a = *(struct cmdname **)a_; 39 struct cmdname *a = *(struct cmdname **)a_;
34 struct cmdname *b = *(struct cmdname **)b_; 40 struct cmdname *b = *(struct cmdname **)b_;
35 return strcmp(a->name, b->name); 41 return strcmp(a->name, b->name);
36} 42}
37 43
38static void uniq(struct cmdnames *cmds) 44void uniq(struct cmdnames *cmds)
39{ 45{
40 unsigned int i, j; 46 unsigned int i, j;
41 47
@@ -71,6 +77,28 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
71 cmds->cnt = cj; 77 cmds->cnt = cj;
72} 78}
73 79
80static void get_term_dimensions(struct winsize *ws)
81{
82 char *s = getenv("LINES");
83
84 if (s != NULL) {
85 ws->ws_row = atoi(s);
86 s = getenv("COLUMNS");
87 if (s != NULL) {
88 ws->ws_col = atoi(s);
89 if (ws->ws_row && ws->ws_col)
90 return;
91 }
92 }
93#ifdef TIOCGWINSZ
94 if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
95 ws->ws_row && ws->ws_col)
96 return;
97#endif
98 ws->ws_row = 25;
99 ws->ws_col = 80;
100}
101
74static void pretty_print_string_list(struct cmdnames *cmds, int longest) 102static void pretty_print_string_list(struct cmdnames *cmds, int longest)
75{ 103{
76 int cols = 1, rows; 104 int cols = 1, rows;
@@ -114,6 +142,14 @@ static int is_executable(const char *name)
114 return st.st_mode & S_IXUSR; 142 return st.st_mode & S_IXUSR;
115} 143}
116 144
145static int has_extension(const char *filename, const char *ext)
146{
147 size_t len = strlen(filename);
148 size_t extlen = strlen(ext);
149
150 return len > extlen && !memcmp(filename + len - extlen, ext, extlen);
151}
152
117static void list_commands_in_dir(struct cmdnames *cmds, 153static void list_commands_in_dir(struct cmdnames *cmds,
118 const char *path, 154 const char *path,
119 const char *prefix) 155 const char *prefix)
@@ -121,8 +157,7 @@ static void list_commands_in_dir(struct cmdnames *cmds,
121 int prefix_len; 157 int prefix_len;
122 DIR *dir = opendir(path); 158 DIR *dir = opendir(path);
123 struct dirent *de; 159 struct dirent *de;
124 struct strbuf buf = STRBUF_INIT; 160 char *buf = NULL;
125 int len;
126 161
127 if (!dir) 162 if (!dir)
128 return; 163 return;
@@ -130,8 +165,7 @@ static void list_commands_in_dir(struct cmdnames *cmds,
130 prefix = "perf-"; 165 prefix = "perf-";
131 prefix_len = strlen(prefix); 166 prefix_len = strlen(prefix);
132 167
133 strbuf_addf(&buf, "%s/", path); 168 astrcatf(&buf, "%s/", path);
134 len = buf.len;
135 169
136 while ((de = readdir(dir)) != NULL) { 170 while ((de = readdir(dir)) != NULL) {
137 int entlen; 171 int entlen;
@@ -139,9 +173,8 @@ static void list_commands_in_dir(struct cmdnames *cmds,
139 if (prefixcmp(de->d_name, prefix)) 173 if (prefixcmp(de->d_name, prefix))
140 continue; 174 continue;
141 175
142 strbuf_setlen(&buf, len); 176 astrcat(&buf, de->d_name);
143 strbuf_addstr(&buf, de->d_name); 177 if (!is_executable(buf))
144 if (!is_executable(buf.buf))
145 continue; 178 continue;
146 179
147 entlen = strlen(de->d_name) - prefix_len; 180 entlen = strlen(de->d_name) - prefix_len;
@@ -151,7 +184,7 @@ static void list_commands_in_dir(struct cmdnames *cmds,
151 add_cmdname(cmds, de->d_name + prefix_len, entlen); 184 add_cmdname(cmds, de->d_name + prefix_len, entlen);
152 } 185 }
153 closedir(dir); 186 closedir(dir);
154 strbuf_release(&buf); 187 free(buf);
155} 188}
156 189
157void load_command_list(const char *prefix, 190void load_command_list(const char *prefix,
@@ -159,7 +192,7 @@ void load_command_list(const char *prefix,
159 struct cmdnames *other_cmds) 192 struct cmdnames *other_cmds)
160{ 193{
161 const char *env_path = getenv("PATH"); 194 const char *env_path = getenv("PATH");
162 const char *exec_path = perf_exec_path(); 195 char *exec_path = get_argv_exec_path();
163 196
164 if (exec_path) { 197 if (exec_path) {
165 list_commands_in_dir(main_cmds, exec_path, prefix); 198 list_commands_in_dir(main_cmds, exec_path, prefix);
@@ -172,7 +205,7 @@ void load_command_list(const char *prefix,
172 char *paths, *path, *colon; 205 char *paths, *path, *colon;
173 path = paths = strdup(env_path); 206 path = paths = strdup(env_path);
174 while (1) { 207 while (1) {
175 if ((colon = strchr(path, PATH_SEP))) 208 if ((colon = strchr(path, ':')))
176 *colon = 0; 209 *colon = 0;
177 if (!exec_path || strcmp(path, exec_path)) 210 if (!exec_path || strcmp(path, exec_path))
178 list_commands_in_dir(other_cmds, path, prefix); 211 list_commands_in_dir(other_cmds, path, prefix);
@@ -187,6 +220,7 @@ void load_command_list(const char *prefix,
187 sizeof(*other_cmds->names), cmdname_compare); 220 sizeof(*other_cmds->names), cmdname_compare);
188 uniq(other_cmds); 221 uniq(other_cmds);
189 } 222 }
223 free(exec_path);
190 exclude_cmds(other_cmds, main_cmds); 224 exclude_cmds(other_cmds, main_cmds);
191} 225}
192 226
@@ -203,13 +237,14 @@ void list_commands(const char *title, struct cmdnames *main_cmds,
203 longest = other_cmds->names[i]->len; 237 longest = other_cmds->names[i]->len;
204 238
205 if (main_cmds->cnt) { 239 if (main_cmds->cnt) {
206 const char *exec_path = perf_exec_path(); 240 char *exec_path = get_argv_exec_path();
207 printf("available %s in '%s'\n", title, exec_path); 241 printf("available %s in '%s'\n", title, exec_path);
208 printf("----------------"); 242 printf("----------------");
209 mput_char('-', strlen(title) + strlen(exec_path)); 243 mput_char('-', strlen(title) + strlen(exec_path));
210 putchar('\n'); 244 putchar('\n');
211 pretty_print_string_list(main_cmds, longest); 245 pretty_print_string_list(main_cmds, longest);
212 putchar('\n'); 246 putchar('\n');
247 free(exec_path);
213 } 248 }
214 249
215 if (other_cmds->cnt) { 250 if (other_cmds->cnt) {
@@ -231,109 +266,3 @@ int is_in_cmdlist(struct cmdnames *c, const char *s)
231 return 1; 266 return 1;
232 return 0; 267 return 0;
233} 268}
234
235static int autocorrect;
236static struct cmdnames aliases;
237
238static int perf_unknown_cmd_config(const char *var, const char *value, void *cb)
239{
240 if (!strcmp(var, "help.autocorrect"))
241 autocorrect = perf_config_int(var,value);
242 /* Also use aliases for command lookup */
243 if (!prefixcmp(var, "alias."))
244 add_cmdname(&aliases, var + 6, strlen(var + 6));
245
246 return perf_default_config(var, value, cb);
247}
248
249static int levenshtein_compare(const void *p1, const void *p2)
250{
251 const struct cmdname *const *c1 = p1, *const *c2 = p2;
252 const char *s1 = (*c1)->name, *s2 = (*c2)->name;
253 int l1 = (*c1)->len;
254 int l2 = (*c2)->len;
255 return l1 != l2 ? l1 - l2 : strcmp(s1, s2);
256}
257
258static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
259{
260 unsigned int i;
261
262 ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc);
263
264 for (i = 0; i < old->cnt; i++)
265 cmds->names[cmds->cnt++] = old->names[i];
266 zfree(&old->names);
267 old->cnt = 0;
268}
269
270const char *help_unknown_cmd(const char *cmd)
271{
272 unsigned int i, n = 0, best_similarity = 0;
273 struct cmdnames main_cmds, other_cmds;
274
275 memset(&main_cmds, 0, sizeof(main_cmds));
276 memset(&other_cmds, 0, sizeof(main_cmds));
277 memset(&aliases, 0, sizeof(aliases));
278
279 perf_config(perf_unknown_cmd_config, NULL);
280
281 load_command_list("perf-", &main_cmds, &other_cmds);
282
283 add_cmd_list(&main_cmds, &aliases);
284 add_cmd_list(&main_cmds, &other_cmds);
285 qsort(main_cmds.names, main_cmds.cnt,
286 sizeof(main_cmds.names), cmdname_compare);
287 uniq(&main_cmds);
288
289 if (main_cmds.cnt) {
290 /* This reuses cmdname->len for similarity index */
291 for (i = 0; i < main_cmds.cnt; ++i)
292 main_cmds.names[i]->len =
293 levenshtein(cmd, main_cmds.names[i]->name, 0, 2, 1, 4);
294
295 qsort(main_cmds.names, main_cmds.cnt,
296 sizeof(*main_cmds.names), levenshtein_compare);
297
298 best_similarity = main_cmds.names[0]->len;
299 n = 1;
300 while (n < main_cmds.cnt && best_similarity == main_cmds.names[n]->len)
301 ++n;
302 }
303
304 if (autocorrect && n == 1) {
305 const char *assumed = main_cmds.names[0]->name;
306
307 main_cmds.names[0] = NULL;
308 clean_cmdnames(&main_cmds);
309 fprintf(stderr, "WARNING: You called a perf program named '%s', "
310 "which does not exist.\n"
311 "Continuing under the assumption that you meant '%s'\n",
312 cmd, assumed);
313 if (autocorrect > 0) {
314 fprintf(stderr, "in %0.1f seconds automatically...\n",
315 (float)autocorrect/10.0);
316 poll(NULL, 0, autocorrect * 100);
317 }
318 return assumed;
319 }
320
321 fprintf(stderr, "perf: '%s' is not a perf-command. See 'perf --help'.\n", cmd);
322
323 if (main_cmds.cnt && best_similarity < 6) {
324 fprintf(stderr, "\nDid you mean %s?\n",
325 n < 2 ? "this": "one of these");
326
327 for (i = 0; i < n; i++)
328 fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
329 }
330
331 exit(1);
332}
333
334int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused,
335 const char *prefix __maybe_unused)
336{
337 printf("perf version %s\n", perf_version_string);
338 return 0;
339}
diff --git a/tools/perf/util/help.h b/tools/lib/subcmd/help.h
index 7f5c6dedd714..e145a020780c 100644
--- a/tools/perf/util/help.h
+++ b/tools/lib/subcmd/help.h
@@ -1,12 +1,14 @@
1#ifndef __PERF_HELP_H 1#ifndef __SUBCMD_HELP_H
2#define __PERF_HELP_H 2#define __SUBCMD_HELP_H
3
4#include <sys/types.h>
3 5
4struct cmdnames { 6struct cmdnames {
5 size_t alloc; 7 size_t alloc;
6 size_t cnt; 8 size_t cnt;
7 struct cmdname { 9 struct cmdname {
8 size_t len; /* also used for similarity index in help.c */ 10 size_t len; /* also used for similarity index in help.c */
9 char name[FLEX_ARRAY]; 11 char name[];
10 } **names; 12 } **names;
11}; 13};
12 14
@@ -20,10 +22,13 @@ void load_command_list(const char *prefix,
20 struct cmdnames *main_cmds, 22 struct cmdnames *main_cmds,
21 struct cmdnames *other_cmds); 23 struct cmdnames *other_cmds);
22void add_cmdname(struct cmdnames *cmds, const char *name, size_t len); 24void add_cmdname(struct cmdnames *cmds, const char *name, size_t len);
25void clean_cmdnames(struct cmdnames *cmds);
26int cmdname_compare(const void *a, const void *b);
27void uniq(struct cmdnames *cmds);
23/* Here we require that excludes is a sorted list. */ 28/* Here we require that excludes is a sorted list. */
24void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes); 29void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes);
25int is_in_cmdlist(struct cmdnames *c, const char *s); 30int is_in_cmdlist(struct cmdnames *c, const char *s);
26void list_commands(const char *title, struct cmdnames *main_cmds, 31void list_commands(const char *title, struct cmdnames *main_cmds,
27 struct cmdnames *other_cmds); 32 struct cmdnames *other_cmds);
28 33
29#endif /* __PERF_HELP_H */ 34#endif /* __SUBCMD_HELP_H */
diff --git a/tools/perf/util/pager.c b/tools/lib/subcmd/pager.c
index 53ef006a951c..d50f3b58606b 100644
--- a/tools/perf/util/pager.c
+++ b/tools/lib/subcmd/pager.c
@@ -1,6 +1,12 @@
1#include "cache.h" 1#include <sys/select.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include <string.h>
5#include <signal.h>
6#include "pager.h"
2#include "run-command.h" 7#include "run-command.h"
3#include "sigchain.h" 8#include "sigchain.h"
9#include "subcmd-config.h"
4 10
5/* 11/*
6 * This is split up from the rest of git so that we can do 12 * This is split up from the rest of git so that we can do
@@ -9,6 +15,11 @@
9 15
10static int spawned_pager; 16static int spawned_pager;
11 17
18void pager_init(const char *pager_env)
19{
20 subcmd_config.pager_env = pager_env;
21}
22
12static void pager_preexec(void) 23static void pager_preexec(void)
13{ 24{
14 /* 25 /*
@@ -46,7 +57,7 @@ static void wait_for_pager_signal(int signo)
46 57
47void setup_pager(void) 58void setup_pager(void)
48{ 59{
49 const char *pager = getenv("PERF_PAGER"); 60 const char *pager = getenv(subcmd_config.pager_env);
50 61
51 if (!isatty(1)) 62 if (!isatty(1))
52 return; 63 return;
@@ -85,11 +96,5 @@ void setup_pager(void)
85 96
86int pager_in_use(void) 97int pager_in_use(void)
87{ 98{
88 const char *env; 99 return spawned_pager;
89
90 if (spawned_pager)
91 return 1;
92
93 env = getenv("PERF_PAGER_IN_USE");
94 return env ? perf_config_bool("PERF_PAGER_IN_USE", env) : 0;
95} 100}
diff --git a/tools/lib/subcmd/pager.h b/tools/lib/subcmd/pager.h
new file mode 100644
index 000000000000..8b83714ecf73
--- /dev/null
+++ b/tools/lib/subcmd/pager.h
@@ -0,0 +1,9 @@
1#ifndef __SUBCMD_PAGER_H
2#define __SUBCMD_PAGER_H
3
4extern void pager_init(const char *pager_env);
5
6extern void setup_pager(void);
7extern int pager_in_use(void);
8
9#endif /* __SUBCMD_PAGER_H */
diff --git a/tools/perf/util/parse-options.c b/tools/lib/subcmd/parse-options.c
index 9fca09296eb3..981bb4481fd5 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/lib/subcmd/parse-options.c
@@ -1,37 +1,66 @@
1#include "util.h" 1#include <linux/compiler.h>
2#include <linux/types.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <stdint.h>
6#include <string.h>
7#include <ctype.h>
8#include "subcmd-util.h"
2#include "parse-options.h" 9#include "parse-options.h"
3#include "cache.h" 10#include "subcmd-config.h"
4#include "header.h" 11#include "pager.h"
5#include <linux/string.h>
6 12
7#define OPT_SHORT 1 13#define OPT_SHORT 1
8#define OPT_UNSET 2 14#define OPT_UNSET 2
9 15
10static struct strbuf error_buf = STRBUF_INIT; 16char *error_buf;
11 17
12static int opterror(const struct option *opt, const char *reason, int flags) 18static int opterror(const struct option *opt, const char *reason, int flags)
13{ 19{
14 if (flags & OPT_SHORT) 20 if (flags & OPT_SHORT)
15 return error("switch `%c' %s", opt->short_name, reason); 21 fprintf(stderr, " Error: switch `%c' %s", opt->short_name, reason);
16 if (flags & OPT_UNSET) 22 else if (flags & OPT_UNSET)
17 return error("option `no-%s' %s", opt->long_name, reason); 23 fprintf(stderr, " Error: option `no-%s' %s", opt->long_name, reason);
18 return error("option `%s' %s", opt->long_name, reason); 24 else
25 fprintf(stderr, " Error: option `%s' %s", opt->long_name, reason);
26
27 return -1;
28}
29
30static const char *skip_prefix(const char *str, const char *prefix)
31{
32 size_t len = strlen(prefix);
33 return strncmp(str, prefix, len) ? NULL : str + len;
34}
35
36static void optwarning(const struct option *opt, const char *reason, int flags)
37{
38 if (flags & OPT_SHORT)
39 fprintf(stderr, " Warning: switch `%c' %s", opt->short_name, reason);
40 else if (flags & OPT_UNSET)
41 fprintf(stderr, " Warning: option `no-%s' %s", opt->long_name, reason);
42 else
43 fprintf(stderr, " Warning: option `%s' %s", opt->long_name, reason);
19} 44}
20 45
21static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt, 46static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
22 int flags, const char **arg) 47 int flags, const char **arg)
23{ 48{
49 const char *res;
50
24 if (p->opt) { 51 if (p->opt) {
25 *arg = p->opt; 52 res = p->opt;
26 p->opt = NULL; 53 p->opt = NULL;
27 } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 || 54 } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 ||
28 **(p->argv + 1) == '-')) { 55 **(p->argv + 1) == '-')) {
29 *arg = (const char *)opt->defval; 56 res = (const char *)opt->defval;
30 } else if (p->argc > 1) { 57 } else if (p->argc > 1) {
31 p->argc--; 58 p->argc--;
32 *arg = *++p->argv; 59 res = *++p->argv;
33 } else 60 } else
34 return opterror(opt, "requires a value", flags); 61 return opterror(opt, "requires a value", flags);
62 if (arg)
63 *arg = res;
35 return 0; 64 return 0;
36} 65}
37 66
@@ -55,11 +84,11 @@ static int get_value(struct parse_opt_ctx_t *p,
55 84
56 if (((flags & OPT_SHORT) && p->excl_opt->short_name) || 85 if (((flags & OPT_SHORT) && p->excl_opt->short_name) ||
57 p->excl_opt->long_name == NULL) { 86 p->excl_opt->long_name == NULL) {
58 scnprintf(msg, sizeof(msg), "cannot be used with switch `%c'", 87 snprintf(msg, sizeof(msg), "cannot be used with switch `%c'",
59 p->excl_opt->short_name); 88 p->excl_opt->short_name);
60 } else { 89 } else {
61 scnprintf(msg, sizeof(msg), "cannot be used with %s", 90 snprintf(msg, sizeof(msg), "cannot be used with %s",
62 p->excl_opt->long_name); 91 p->excl_opt->long_name);
63 } 92 }
64 opterror(opt, msg, flags); 93 opterror(opt, msg, flags);
65 return -3; 94 return -3;
@@ -91,6 +120,64 @@ static int get_value(struct parse_opt_ctx_t *p,
91 } 120 }
92 } 121 }
93 122
123 if (opt->flags & PARSE_OPT_NOBUILD) {
124 char reason[128];
125 bool noarg = false;
126
127 err = snprintf(reason, sizeof(reason),
128 opt->flags & PARSE_OPT_CANSKIP ?
129 "is being ignored because %s " :
130 "is not available because %s",
131 opt->build_opt);
132 reason[sizeof(reason) - 1] = '\0';
133
134 if (err < 0)
135 strncpy(reason, opt->flags & PARSE_OPT_CANSKIP ?
136 "is being ignored" :
137 "is not available",
138 sizeof(reason));
139
140 if (!(opt->flags & PARSE_OPT_CANSKIP))
141 return opterror(opt, reason, flags);
142
143 err = 0;
144 if (unset)
145 noarg = true;
146 if (opt->flags & PARSE_OPT_NOARG)
147 noarg = true;
148 if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
149 noarg = true;
150
151 switch (opt->type) {
152 case OPTION_BOOLEAN:
153 case OPTION_INCR:
154 case OPTION_BIT:
155 case OPTION_SET_UINT:
156 case OPTION_SET_PTR:
157 case OPTION_END:
158 case OPTION_ARGUMENT:
159 case OPTION_GROUP:
160 noarg = true;
161 break;
162 case OPTION_CALLBACK:
163 case OPTION_STRING:
164 case OPTION_INTEGER:
165 case OPTION_UINTEGER:
166 case OPTION_LONG:
167 case OPTION_U64:
168 default:
169 break;
170 }
171
172 if (!noarg)
173 err = get_arg(p, opt, flags, NULL);
174 if (err)
175 return err;
176
177 optwarning(opt, reason, flags);
178 return 0;
179 }
180
94 switch (opt->type) { 181 switch (opt->type) {
95 case OPTION_BIT: 182 case OPTION_BIT:
96 if (unset) 183 if (unset)
@@ -327,14 +414,16 @@ match:
327 return get_value(p, options, flags); 414 return get_value(p, options, flags);
328 } 415 }
329 416
330 if (ambiguous_option) 417 if (ambiguous_option) {
331 return error("Ambiguous option: %s " 418 fprintf(stderr,
332 "(could be --%s%s or --%s%s)", 419 " Error: Ambiguous option: %s (could be --%s%s or --%s%s)",
333 arg, 420 arg,
334 (ambiguous_flags & OPT_UNSET) ? "no-" : "", 421 (ambiguous_flags & OPT_UNSET) ? "no-" : "",
335 ambiguous_option->long_name, 422 ambiguous_option->long_name,
336 (abbrev_flags & OPT_UNSET) ? "no-" : "", 423 (abbrev_flags & OPT_UNSET) ? "no-" : "",
337 abbrev_option->long_name); 424 abbrev_option->long_name);
425 return -1;
426 }
338 if (abbrev_option) 427 if (abbrev_option)
339 return get_value(p, abbrev_option, abbrev_flags); 428 return get_value(p, abbrev_option, abbrev_flags);
340 return -2; 429 return -2;
@@ -346,7 +435,7 @@ static void check_typos(const char *arg, const struct option *options)
346 return; 435 return;
347 436
348 if (!prefixcmp(arg, "no-")) { 437 if (!prefixcmp(arg, "no-")) {
349 error ("did you mean `--%s` (with two dashes ?)", arg); 438 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg);
350 exit(129); 439 exit(129);
351 } 440 }
352 441
@@ -354,14 +443,14 @@ static void check_typos(const char *arg, const struct option *options)
354 if (!options->long_name) 443 if (!options->long_name)
355 continue; 444 continue;
356 if (!prefixcmp(options->long_name, arg)) { 445 if (!prefixcmp(options->long_name, arg)) {
357 error ("did you mean `--%s` (with two dashes ?)", arg); 446 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg);
358 exit(129); 447 exit(129);
359 } 448 }
360 } 449 }
361} 450}
362 451
363void parse_options_start(struct parse_opt_ctx_t *ctx, 452static void parse_options_start(struct parse_opt_ctx_t *ctx,
364 int argc, const char **argv, int flags) 453 int argc, const char **argv, int flags)
365{ 454{
366 memset(ctx, 0, sizeof(*ctx)); 455 memset(ctx, 0, sizeof(*ctx));
367 ctx->argc = argc - 1; 456 ctx->argc = argc - 1;
@@ -378,9 +467,9 @@ static int usage_with_options_internal(const char * const *,
378 const struct option *, int, 467 const struct option *, int,
379 struct parse_opt_ctx_t *); 468 struct parse_opt_ctx_t *);
380 469
381int parse_options_step(struct parse_opt_ctx_t *ctx, 470static int parse_options_step(struct parse_opt_ctx_t *ctx,
382 const struct option *options, 471 const struct option *options,
383 const char * const usagestr[]) 472 const char * const usagestr[])
384{ 473{
385 int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP); 474 int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
386 int excl_short_opt = 1; 475 int excl_short_opt = 1;
@@ -489,7 +578,7 @@ exclusive:
489 return PARSE_OPT_HELP; 578 return PARSE_OPT_HELP;
490} 579}
491 580
492int parse_options_end(struct parse_opt_ctx_t *ctx) 581static int parse_options_end(struct parse_opt_ctx_t *ctx)
493{ 582{
494 memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out)); 583 memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out));
495 ctx->out[ctx->cpidx + ctx->argc] = NULL; 584 ctx->out[ctx->cpidx + ctx->argc] = NULL;
@@ -501,22 +590,20 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o
501{ 590{
502 struct parse_opt_ctx_t ctx; 591 struct parse_opt_ctx_t ctx;
503 592
504 perf_env__set_cmdline(&perf_env, argc, argv);
505
506 /* build usage string if it's not provided */ 593 /* build usage string if it's not provided */
507 if (subcommands && !usagestr[0]) { 594 if (subcommands && !usagestr[0]) {
508 struct strbuf buf = STRBUF_INIT; 595 char *buf = NULL;
596
597 astrcatf(&buf, "%s %s [<options>] {", subcmd_config.exec_name, argv[0]);
509 598
510 strbuf_addf(&buf, "perf %s [<options>] {", argv[0]);
511 for (int i = 0; subcommands[i]; i++) { 599 for (int i = 0; subcommands[i]; i++) {
512 if (i) 600 if (i)
513 strbuf_addstr(&buf, "|"); 601 astrcat(&buf, "|");
514 strbuf_addstr(&buf, subcommands[i]); 602 astrcat(&buf, subcommands[i]);
515 } 603 }
516 strbuf_addstr(&buf, "}"); 604 astrcat(&buf, "}");
517 605
518 usagestr[0] = strdup(buf.buf); 606 usagestr[0] = buf;
519 strbuf_release(&buf);
520 } 607 }
521 608
522 parse_options_start(&ctx, argc, argv, flags); 609 parse_options_start(&ctx, argc, argv, flags);
@@ -541,13 +628,11 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o
541 putchar('\n'); 628 putchar('\n');
542 exit(130); 629 exit(130);
543 default: /* PARSE_OPT_UNKNOWN */ 630 default: /* PARSE_OPT_UNKNOWN */
544 if (ctx.argv[0][1] == '-') { 631 if (ctx.argv[0][1] == '-')
545 strbuf_addf(&error_buf, "unknown option `%s'", 632 astrcatf(&error_buf, "unknown option `%s'",
546 ctx.argv[0] + 2); 633 ctx.argv[0] + 2);
547 } else { 634 else
548 strbuf_addf(&error_buf, "unknown switch `%c'", 635 astrcatf(&error_buf, "unknown switch `%c'", *ctx.opt);
549 *ctx.opt);
550 }
551 usage_with_options(usagestr, options); 636 usage_with_options(usagestr, options);
552 } 637 }
553 638
@@ -647,6 +732,10 @@ static void print_option_help(const struct option *opts, int full)
647 pad = USAGE_OPTS_WIDTH; 732 pad = USAGE_OPTS_WIDTH;
648 } 733 }
649 fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help); 734 fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
735 if (opts->flags & PARSE_OPT_NOBUILD)
736 fprintf(stderr, "%*s(not built-in because %s)\n",
737 USAGE_OPTS_WIDTH + USAGE_GAP, "",
738 opts->build_opt);
650} 739}
651 740
652static int option__cmp(const void *va, const void *vb) 741static int option__cmp(const void *va, const void *vb)
@@ -672,16 +761,18 @@ static int option__cmp(const void *va, const void *vb)
672 761
673static struct option *options__order(const struct option *opts) 762static struct option *options__order(const struct option *opts)
674{ 763{
675 int nr_opts = 0; 764 int nr_opts = 0, len;
676 const struct option *o = opts; 765 const struct option *o = opts;
677 struct option *ordered; 766 struct option *ordered;
678 767
679 for (o = opts; o->type != OPTION_END; o++) 768 for (o = opts; o->type != OPTION_END; o++)
680 ++nr_opts; 769 ++nr_opts;
681 770
682 ordered = memdup(opts, sizeof(*o) * (nr_opts + 1)); 771 len = sizeof(*o) * (nr_opts + 1);
683 if (ordered == NULL) 772 ordered = malloc(len);
773 if (!ordered)
684 goto out; 774 goto out;
775 memcpy(ordered, opts, len);
685 776
686 qsort(ordered, nr_opts, sizeof(*o), option__cmp); 777 qsort(ordered, nr_opts, sizeof(*o), option__cmp);
687out: 778out:
@@ -719,9 +810,9 @@ static bool option__in_argv(const struct option *opt, const struct parse_opt_ctx
719 return false; 810 return false;
720} 811}
721 812
722int usage_with_options_internal(const char * const *usagestr, 813static int usage_with_options_internal(const char * const *usagestr,
723 const struct option *opts, int full, 814 const struct option *opts, int full,
724 struct parse_opt_ctx_t *ctx) 815 struct parse_opt_ctx_t *ctx)
725{ 816{
726 struct option *ordered; 817 struct option *ordered;
727 818
@@ -730,9 +821,9 @@ int usage_with_options_internal(const char * const *usagestr,
730 821
731 setup_pager(); 822 setup_pager();
732 823
733 if (strbuf_avail(&error_buf)) { 824 if (error_buf) {
734 fprintf(stderr, " Error: %s\n", error_buf.buf); 825 fprintf(stderr, " Error: %s\n", error_buf);
735 strbuf_release(&error_buf); 826 zfree(&error_buf);
736 } 827 }
737 828
738 fprintf(stderr, "\n Usage: %s\n", *usagestr++); 829 fprintf(stderr, "\n Usage: %s\n", *usagestr++);
@@ -768,7 +859,6 @@ int usage_with_options_internal(const char * const *usagestr,
768void usage_with_options(const char * const *usagestr, 859void usage_with_options(const char * const *usagestr,
769 const struct option *opts) 860 const struct option *opts)
770{ 861{
771 exit_browser(false);
772 usage_with_options_internal(usagestr, opts, 0, NULL); 862 usage_with_options_internal(usagestr, opts, 0, NULL);
773 exit(129); 863 exit(129);
774} 864}
@@ -777,13 +867,15 @@ void usage_with_options_msg(const char * const *usagestr,
777 const struct option *opts, const char *fmt, ...) 867 const struct option *opts, const char *fmt, ...)
778{ 868{
779 va_list ap; 869 va_list ap;
780 870 char *tmp = error_buf;
781 exit_browser(false);
782 871
783 va_start(ap, fmt); 872 va_start(ap, fmt);
784 strbuf_addv(&error_buf, fmt, ap); 873 if (vasprintf(&error_buf, fmt, ap) == -1)
874 die("vasprintf failed");
785 va_end(ap); 875 va_end(ap);
786 876
877 free(tmp);
878
787 usage_with_options_internal(usagestr, opts, 0, NULL); 879 usage_with_options_internal(usagestr, opts, 0, NULL);
788 exit(129); 880 exit(129);
789} 881}
@@ -853,15 +945,39 @@ int parse_opt_verbosity_cb(const struct option *opt,
853 return 0; 945 return 0;
854} 946}
855 947
856void set_option_flag(struct option *opts, int shortopt, const char *longopt, 948static struct option *
857 int flag) 949find_option(struct option *opts, int shortopt, const char *longopt)
858{ 950{
859 for (; opts->type != OPTION_END; opts++) { 951 for (; opts->type != OPTION_END; opts++) {
860 if ((shortopt && opts->short_name == shortopt) || 952 if ((shortopt && opts->short_name == shortopt) ||
861 (opts->long_name && longopt && 953 (opts->long_name && longopt &&
862 !strcmp(opts->long_name, longopt))) { 954 !strcmp(opts->long_name, longopt)))
863 opts->flags |= flag; 955 return opts;
864 break;
865 }
866 } 956 }
957 return NULL;
958}
959
960void set_option_flag(struct option *opts, int shortopt, const char *longopt,
961 int flag)
962{
963 struct option *opt = find_option(opts, shortopt, longopt);
964
965 if (opt)
966 opt->flags |= flag;
967 return;
968}
969
970void set_option_nobuild(struct option *opts, int shortopt,
971 const char *longopt,
972 const char *build_opt,
973 bool can_skip)
974{
975 struct option *opt = find_option(opts, shortopt, longopt);
976
977 if (!opt)
978 return;
979
980 opt->flags |= PARSE_OPT_NOBUILD;
981 opt->flags |= can_skip ? PARSE_OPT_CANSKIP : 0;
982 opt->build_opt = build_opt;
867} 983}
diff --git a/tools/perf/util/parse-options.h b/tools/lib/subcmd/parse-options.h
index a8e407bc251e..13a2cc1d6140 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/lib/subcmd/parse-options.h
@@ -1,8 +1,8 @@
1#ifndef __PERF_PARSE_OPTIONS_H 1#ifndef __SUBCMD_PARSE_OPTIONS_H
2#define __PERF_PARSE_OPTIONS_H 2#define __SUBCMD_PARSE_OPTIONS_H
3 3
4#include <linux/kernel.h>
5#include <stdbool.h> 4#include <stdbool.h>
5#include <stdint.h>
6 6
7enum parse_opt_type { 7enum parse_opt_type {
8 /* special types */ 8 /* special types */
@@ -41,6 +41,8 @@ enum parse_opt_option_flags {
41 PARSE_OPT_DISABLED = 32, 41 PARSE_OPT_DISABLED = 32,
42 PARSE_OPT_EXCLUSIVE = 64, 42 PARSE_OPT_EXCLUSIVE = 64,
43 PARSE_OPT_NOEMPTY = 128, 43 PARSE_OPT_NOEMPTY = 128,
44 PARSE_OPT_NOBUILD = 256,
45 PARSE_OPT_CANSKIP = 512,
44}; 46};
45 47
46struct option; 48struct option;
@@ -96,6 +98,7 @@ struct option {
96 void *value; 98 void *value;
97 const char *argh; 99 const char *argh;
98 const char *help; 100 const char *help;
101 const char *build_opt;
99 102
100 int flags; 103 int flags;
101 parse_opt_cb *callback; 104 parse_opt_cb *callback;
@@ -149,6 +152,9 @@ struct option {
149/* parse_options() will filter out the processed options and leave the 152/* parse_options() will filter out the processed options and leave the
150 * non-option argments in argv[]. 153 * non-option argments in argv[].
151 * Returns the number of arguments left in argv[]. 154 * Returns the number of arguments left in argv[].
155 *
156 * NOTE: parse_options() and parse_options_subcommand() may call exit() in the
157 * case of an error (or for 'special' options like --list-cmds or --list-opts).
152 */ 158 */
153extern int parse_options(int argc, const char **argv, 159extern int parse_options(int argc, const char **argv,
154 const struct option *options, 160 const struct option *options,
@@ -195,15 +201,6 @@ extern int parse_options_usage(const char * const *usagestr,
195 const char *optstr, 201 const char *optstr,
196 bool short_opt); 202 bool short_opt);
197 203
198extern void parse_options_start(struct parse_opt_ctx_t *ctx,
199 int argc, const char **argv, int flags);
200
201extern int parse_options_step(struct parse_opt_ctx_t *ctx,
202 const struct option *options,
203 const char * const usagestr[]);
204
205extern int parse_options_end(struct parse_opt_ctx_t *ctx);
206
207 204
208/*----- some often used options -----*/ 205/*----- some often used options -----*/
209extern int parse_opt_abbrev_cb(const struct option *, const char *, int); 206extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
@@ -226,4 +223,7 @@ extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
226extern const char *parse_options_fix_filename(const char *prefix, const char *file); 223extern const char *parse_options_fix_filename(const char *prefix, const char *file);
227 224
228void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag); 225void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag);
229#endif /* __PERF_PARSE_OPTIONS_H */ 226void set_option_nobuild(struct option *opts, int shortopt, const char *longopt,
227 const char *build_opt, bool can_skip);
228
229#endif /* __SUBCMD_PARSE_OPTIONS_H */
diff --git a/tools/perf/util/run-command.c b/tools/lib/subcmd/run-command.c
index 34622b53e733..f4f6c9eb8e59 100644
--- a/tools/perf/util/run-command.c
+++ b/tools/lib/subcmd/run-command.c
@@ -1,7 +1,15 @@
1#include "cache.h" 1#include <unistd.h>
2#include <sys/types.h>
3#include <sys/stat.h>
4#include <fcntl.h>
5#include <string.h>
6#include <errno.h>
7#include <sys/wait.h>
8#include "subcmd-util.h"
2#include "run-command.h" 9#include "run-command.h"
3#include "exec_cmd.h" 10#include "exec-cmd.h"
4#include "debug.h" 11
12#define STRERR_BUFSIZE 128
5 13
6static inline void close_pair(int fd[2]) 14static inline void close_pair(int fd[2])
7{ 15{
@@ -112,8 +120,8 @@ int start_command(struct child_process *cmd)
112 } 120 }
113 if (cmd->preexec_cb) 121 if (cmd->preexec_cb)
114 cmd->preexec_cb(); 122 cmd->preexec_cb();
115 if (cmd->perf_cmd) { 123 if (cmd->exec_cmd) {
116 execv_perf_cmd(cmd->argv); 124 execv_cmd(cmd->argv);
117 } else { 125 } else {
118 execvp(cmd->argv[0], (char *const*) cmd->argv); 126 execvp(cmd->argv[0], (char *const*) cmd->argv);
119 } 127 }
@@ -164,8 +172,8 @@ static int wait_or_whine(pid_t pid)
164 if (waiting < 0) { 172 if (waiting < 0) {
165 if (errno == EINTR) 173 if (errno == EINTR)
166 continue; 174 continue;
167 error("waitpid failed (%s)", 175 fprintf(stderr, " Error: waitpid failed (%s)",
168 strerror_r(errno, sbuf, sizeof(sbuf))); 176 strerror_r(errno, sbuf, sizeof(sbuf)));
169 return -ERR_RUN_COMMAND_WAITPID; 177 return -ERR_RUN_COMMAND_WAITPID;
170 } 178 }
171 if (waiting != pid) 179 if (waiting != pid)
@@ -207,7 +215,7 @@ static void prepare_run_command_v_opt(struct child_process *cmd,
207 memset(cmd, 0, sizeof(*cmd)); 215 memset(cmd, 0, sizeof(*cmd));
208 cmd->argv = argv; 216 cmd->argv = argv;
209 cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0; 217 cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
210 cmd->perf_cmd = opt & RUN_PERF_CMD ? 1 : 0; 218 cmd->exec_cmd = opt & RUN_EXEC_CMD ? 1 : 0;
211 cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0; 219 cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
212} 220}
213 221
diff --git a/tools/perf/util/run-command.h b/tools/lib/subcmd/run-command.h
index 1ef264d5069c..fe2befea1e73 100644
--- a/tools/perf/util/run-command.h
+++ b/tools/lib/subcmd/run-command.h
@@ -1,5 +1,7 @@
1#ifndef __PERF_RUN_COMMAND_H 1#ifndef __SUBCMD_RUN_COMMAND_H
2#define __PERF_RUN_COMMAND_H 2#define __SUBCMD_RUN_COMMAND_H
3
4#include <unistd.h>
3 5
4enum { 6enum {
5 ERR_RUN_COMMAND_FORK = 10000, 7 ERR_RUN_COMMAND_FORK = 10000,
@@ -41,7 +43,7 @@ struct child_process {
41 unsigned no_stdin:1; 43 unsigned no_stdin:1;
42 unsigned no_stdout:1; 44 unsigned no_stdout:1;
43 unsigned no_stderr:1; 45 unsigned no_stderr:1;
44 unsigned perf_cmd:1; /* if this is to be perf sub-command */ 46 unsigned exec_cmd:1; /* if this is to be external sub-command */
45 unsigned stdout_to_stderr:1; 47 unsigned stdout_to_stderr:1;
46 void (*preexec_cb)(void); 48 void (*preexec_cb)(void);
47}; 49};
@@ -51,8 +53,8 @@ int finish_command(struct child_process *);
51int run_command(struct child_process *); 53int run_command(struct child_process *);
52 54
53#define RUN_COMMAND_NO_STDIN 1 55#define RUN_COMMAND_NO_STDIN 1
54#define RUN_PERF_CMD 2 /*If this is to be perf sub-command */ 56#define RUN_EXEC_CMD 2 /*If this is to be external sub-command */
55#define RUN_COMMAND_STDOUT_TO_STDERR 4 57#define RUN_COMMAND_STDOUT_TO_STDERR 4
56int run_command_v_opt(const char **argv, int opt); 58int run_command_v_opt(const char **argv, int opt);
57 59
58#endif /* __PERF_RUN_COMMAND_H */ 60#endif /* __SUBCMD_RUN_COMMAND_H */
diff --git a/tools/perf/util/sigchain.c b/tools/lib/subcmd/sigchain.c
index ba785e9b1841..3537c348a18e 100644
--- a/tools/perf/util/sigchain.c
+++ b/tools/lib/subcmd/sigchain.c
@@ -1,5 +1,6 @@
1#include <signal.h>
2#include "subcmd-util.h"
1#include "sigchain.h" 3#include "sigchain.h"
2#include "cache.h"
3 4
4#define SIGCHAIN_MAX_SIGNALS 32 5#define SIGCHAIN_MAX_SIGNALS 32
5 6
diff --git a/tools/perf/util/sigchain.h b/tools/lib/subcmd/sigchain.h
index 959d64eb5557..0c919f2874ca 100644
--- a/tools/perf/util/sigchain.h
+++ b/tools/lib/subcmd/sigchain.h
@@ -1,5 +1,5 @@
1#ifndef __PERF_SIGCHAIN_H 1#ifndef __SUBCMD_SIGCHAIN_H
2#define __PERF_SIGCHAIN_H 2#define __SUBCMD_SIGCHAIN_H
3 3
4typedef void (*sigchain_fun)(int); 4typedef void (*sigchain_fun)(int);
5 5
@@ -7,4 +7,4 @@ int sigchain_pop(int sig);
7 7
8void sigchain_push_common(sigchain_fun f); 8void sigchain_push_common(sigchain_fun f);
9 9
10#endif /* __PERF_SIGCHAIN_H */ 10#endif /* __SUBCMD_SIGCHAIN_H */
diff --git a/tools/lib/subcmd/subcmd-config.c b/tools/lib/subcmd/subcmd-config.c
new file mode 100644
index 000000000000..d017c728bd1b
--- /dev/null
+++ b/tools/lib/subcmd/subcmd-config.c
@@ -0,0 +1,11 @@
1#include "subcmd-config.h"
2
3#define UNDEFINED "SUBCMD_HAS_NOT_BEEN_INITIALIZED"
4
5struct subcmd_config subcmd_config = {
6 .exec_name = UNDEFINED,
7 .prefix = UNDEFINED,
8 .exec_path = UNDEFINED,
9 .exec_path_env = UNDEFINED,
10 .pager_env = UNDEFINED,
11};
diff --git a/tools/lib/subcmd/subcmd-config.h b/tools/lib/subcmd/subcmd-config.h
new file mode 100644
index 000000000000..cc8514030b5c
--- /dev/null
+++ b/tools/lib/subcmd/subcmd-config.h
@@ -0,0 +1,14 @@
1#ifndef __PERF_SUBCMD_CONFIG_H
2#define __PERF_SUBCMD_CONFIG_H
3
4struct subcmd_config {
5 const char *exec_name;
6 const char *prefix;
7 const char *exec_path;
8 const char *exec_path_env;
9 const char *pager_env;
10};
11
12extern struct subcmd_config subcmd_config;
13
14#endif /* __PERF_SUBCMD_CONFIG_H */
diff --git a/tools/lib/subcmd/subcmd-util.h b/tools/lib/subcmd/subcmd-util.h
new file mode 100644
index 000000000000..fc2e45d8aaf1
--- /dev/null
+++ b/tools/lib/subcmd/subcmd-util.h
@@ -0,0 +1,91 @@
1#ifndef __SUBCMD_UTIL_H
2#define __SUBCMD_UTIL_H
3
4#include <stdarg.h>
5#include <stdlib.h>
6#include <stdio.h>
7
8#define NORETURN __attribute__((__noreturn__))
9
10static inline void report(const char *prefix, const char *err, va_list params)
11{
12 char msg[1024];
13 vsnprintf(msg, sizeof(msg), err, params);
14 fprintf(stderr, " %s%s\n", prefix, msg);
15}
16
17static NORETURN inline void die(const char *err, ...)
18{
19 va_list params;
20
21 va_start(params, err);
22 report(" Fatal: ", err, params);
23 exit(128);
24 va_end(params);
25}
26
27#define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
28
29#define alloc_nr(x) (((x)+16)*3/2)
30
31/*
32 * Realloc the buffer pointed at by variable 'x' so that it can hold
33 * at least 'nr' entries; the number of entries currently allocated
34 * is 'alloc', using the standard growing factor alloc_nr() macro.
35 *
36 * DO NOT USE any expression with side-effect for 'x' or 'alloc'.
37 */
38#define ALLOC_GROW(x, nr, alloc) \
39 do { \
40 if ((nr) > alloc) { \
41 if (alloc_nr(alloc) < (nr)) \
42 alloc = (nr); \
43 else \
44 alloc = alloc_nr(alloc); \
45 x = xrealloc((x), alloc * sizeof(*(x))); \
46 } \
47 } while(0)
48
49static inline void *xrealloc(void *ptr, size_t size)
50{
51 void *ret = realloc(ptr, size);
52 if (!ret && !size)
53 ret = realloc(ptr, 1);
54 if (!ret) {
55 ret = realloc(ptr, size);
56 if (!ret && !size)
57 ret = realloc(ptr, 1);
58 if (!ret)
59 die("Out of memory, realloc failed");
60 }
61 return ret;
62}
63
64#define astrcatf(out, fmt, ...) \
65({ \
66 char *tmp = *(out); \
67 if (asprintf((out), "%s" fmt, tmp ?: "", ## __VA_ARGS__) == -1) \
68 die("asprintf failed"); \
69 free(tmp); \
70})
71
72static inline void astrcat(char **out, const char *add)
73{
74 char *tmp = *out;
75
76 if (asprintf(out, "%s%s", tmp ?: "", add) == -1)
77 die("asprintf failed");
78
79 free(tmp);
80}
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 */
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 2a912df6771b..ea69ce35e902 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -4735,73 +4735,80 @@ static int is_printable_array(char *p, unsigned int len)
4735 return 1; 4735 return 1;
4736} 4736}
4737 4737
4738static void print_event_fields(struct trace_seq *s, void *data, 4738void pevent_print_field(struct trace_seq *s, void *data,
4739 int size __maybe_unused, 4739 struct format_field *field)
4740 struct event_format *event)
4741{ 4740{
4742 struct format_field *field;
4743 unsigned long long val; 4741 unsigned long long val;
4744 unsigned int offset, len, i; 4742 unsigned int offset, len, i;
4745 4743 struct pevent *pevent = field->event->pevent;
4746 field = event->format.fields; 4744
4747 while (field) { 4745 if (field->flags & FIELD_IS_ARRAY) {
4748 trace_seq_printf(s, " %s=", field->name); 4746 offset = field->offset;
4749 if (field->flags & FIELD_IS_ARRAY) { 4747 len = field->size;
4750 offset = field->offset; 4748 if (field->flags & FIELD_IS_DYNAMIC) {
4751 len = field->size; 4749 val = pevent_read_number(pevent, data + offset, len);
4752 if (field->flags & FIELD_IS_DYNAMIC) { 4750 offset = val;
4753 val = pevent_read_number(event->pevent, data + offset, len); 4751 len = offset >> 16;
4754 offset = val; 4752 offset &= 0xffff;
4755 len = offset >> 16; 4753 }
4756 offset &= 0xffff; 4754 if (field->flags & FIELD_IS_STRING &&
4757 } 4755 is_printable_array(data + offset, len)) {
4758 if (field->flags & FIELD_IS_STRING && 4756 trace_seq_printf(s, "%s", (char *)data + offset);
4759 is_printable_array(data + offset, len)) {
4760 trace_seq_printf(s, "%s", (char *)data + offset);
4761 } else {
4762 trace_seq_puts(s, "ARRAY[");
4763 for (i = 0; i < len; i++) {
4764 if (i)
4765 trace_seq_puts(s, ", ");
4766 trace_seq_printf(s, "%02x",
4767 *((unsigned char *)data + offset + i));
4768 }
4769 trace_seq_putc(s, ']');
4770 field->flags &= ~FIELD_IS_STRING;
4771 }
4772 } else { 4757 } else {
4773 val = pevent_read_number(event->pevent, data + field->offset, 4758 trace_seq_puts(s, "ARRAY[");
4774 field->size); 4759 for (i = 0; i < len; i++) {
4775 if (field->flags & FIELD_IS_POINTER) { 4760 if (i)
4776 trace_seq_printf(s, "0x%llx", val); 4761 trace_seq_puts(s, ", ");
4777 } else if (field->flags & FIELD_IS_SIGNED) { 4762 trace_seq_printf(s, "%02x",
4778 switch (field->size) { 4763 *((unsigned char *)data + offset + i));
4779 case 4: 4764 }
4780 /* 4765 trace_seq_putc(s, ']');
4781 * If field is long then print it in hex. 4766 field->flags &= ~FIELD_IS_STRING;
4782 * A long usually stores pointers. 4767 }
4783 */ 4768 } else {
4784 if (field->flags & FIELD_IS_LONG) 4769 val = pevent_read_number(pevent, data + field->offset,
4785 trace_seq_printf(s, "0x%x", (int)val); 4770 field->size);
4786 else 4771 if (field->flags & FIELD_IS_POINTER) {
4787 trace_seq_printf(s, "%d", (int)val); 4772 trace_seq_printf(s, "0x%llx", val);
4788 break; 4773 } else if (field->flags & FIELD_IS_SIGNED) {
4789 case 2: 4774 switch (field->size) {
4790 trace_seq_printf(s, "%2d", (short)val); 4775 case 4:
4791 break; 4776 /*
4792 case 1: 4777 * If field is long then print it in hex.
4793 trace_seq_printf(s, "%1d", (char)val); 4778 * A long usually stores pointers.
4794 break; 4779 */
4795 default:
4796 trace_seq_printf(s, "%lld", val);
4797 }
4798 } else {
4799 if (field->flags & FIELD_IS_LONG) 4780 if (field->flags & FIELD_IS_LONG)
4800 trace_seq_printf(s, "0x%llx", val); 4781 trace_seq_printf(s, "0x%x", (int)val);
4801 else 4782 else
4802 trace_seq_printf(s, "%llu", val); 4783 trace_seq_printf(s, "%d", (int)val);
4784 break;
4785 case 2:
4786 trace_seq_printf(s, "%2d", (short)val);
4787 break;
4788 case 1:
4789 trace_seq_printf(s, "%1d", (char)val);
4790 break;
4791 default:
4792 trace_seq_printf(s, "%lld", val);
4803 } 4793 }
4794 } else {
4795 if (field->flags & FIELD_IS_LONG)
4796 trace_seq_printf(s, "0x%llx", val);
4797 else
4798 trace_seq_printf(s, "%llu", val);
4804 } 4799 }
4800 }
4801}
4802
4803void pevent_print_fields(struct trace_seq *s, void *data,
4804 int size __maybe_unused, struct event_format *event)
4805{
4806 struct format_field *field;
4807
4808 field = event->format.fields;
4809 while (field) {
4810 trace_seq_printf(s, " %s=", field->name);
4811 pevent_print_field(s, data, field);
4805 field = field->next; 4812 field = field->next;
4806 } 4813 }
4807} 4814}
@@ -4827,7 +4834,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
4827 4834
4828 if (event->flags & EVENT_FL_FAILED) { 4835 if (event->flags & EVENT_FL_FAILED) {
4829 trace_seq_printf(s, "[FAILED TO PARSE]"); 4836 trace_seq_printf(s, "[FAILED TO PARSE]");
4830 print_event_fields(s, data, size, event); 4837 pevent_print_fields(s, data, size, event);
4831 return; 4838 return;
4832 } 4839 }
4833 4840
@@ -4968,13 +4975,12 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
4968 sizeof(long) != 8) { 4975 sizeof(long) != 8) {
4969 char *p; 4976 char *p;
4970 4977
4971 ls = 2;
4972 /* make %l into %ll */ 4978 /* make %l into %ll */
4973 p = strchr(format, 'l'); 4979 if (ls == 1 && (p = strchr(format, 'l')))
4974 if (p)
4975 memmove(p+1, p, strlen(p)+1); 4980 memmove(p+1, p, strlen(p)+1);
4976 else if (strcmp(format, "%p") == 0) 4981 else if (strcmp(format, "%p") == 0)
4977 strcpy(format, "0x%llx"); 4982 strcpy(format, "0x%llx");
4983 ls = 2;
4978 } 4984 }
4979 switch (ls) { 4985 switch (ls) {
4980 case -2: 4986 case -2:
@@ -5302,7 +5308,7 @@ void pevent_event_info(struct trace_seq *s, struct event_format *event,
5302 int print_pretty = 1; 5308 int print_pretty = 1;
5303 5309
5304 if (event->pevent->print_raw || (event->flags & EVENT_FL_PRINTRAW)) 5310 if (event->pevent->print_raw || (event->flags & EVENT_FL_PRINTRAW))
5305 print_event_fields(s, record->data, record->size, event); 5311 pevent_print_fields(s, record->data, record->size, event);
5306 else { 5312 else {
5307 5313
5308 if (event->handler && !(event->flags & EVENT_FL_NOHANDLE)) 5314 if (event->handler && !(event->flags & EVENT_FL_NOHANDLE))
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 6fc83c7edbe9..706d9bc24066 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -705,6 +705,10 @@ struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *com
705 struct cmdline *next); 705 struct cmdline *next);
706int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline); 706int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline);
707 707
708void pevent_print_field(struct trace_seq *s, void *data,
709 struct format_field *field);
710void pevent_print_fields(struct trace_seq *s, void *data,
711 int size __maybe_unused, struct event_format *event);
708void pevent_event_info(struct trace_seq *s, struct event_format *event, 712void pevent_event_info(struct trace_seq *s, struct event_format *event,
709 struct pevent_record *record); 713 struct pevent_record *record);
710int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum, 714int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum,
diff --git a/tools/lib/util/find_next_bit.c b/tools/lib/util/find_next_bit.c
deleted file mode 100644
index 41b44f65a79e..000000000000
--- a/tools/lib/util/find_next_bit.c
+++ /dev/null
@@ -1,89 +0,0 @@
1/* find_next_bit.c: fallback find next bit implementation
2 *
3 * Copied from lib/find_next_bit.c to tools/lib/next_bit.c
4 *
5 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
6 * Written by David Howells (dhowells@redhat.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13
14#include <linux/bitops.h>
15#include <asm/types.h>
16#include <asm/byteorder.h>
17
18#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
19
20#ifndef find_next_bit
21/*
22 * Find the next set bit in a memory region.
23 */
24unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
25 unsigned long offset)
26{
27 const unsigned long *p = addr + BITOP_WORD(offset);
28 unsigned long result = offset & ~(BITS_PER_LONG-1);
29 unsigned long tmp;
30
31 if (offset >= size)
32 return size;
33 size -= result;
34 offset %= BITS_PER_LONG;
35 if (offset) {
36 tmp = *(p++);
37 tmp &= (~0UL << offset);
38 if (size < BITS_PER_LONG)
39 goto found_first;
40 if (tmp)
41 goto found_middle;
42 size -= BITS_PER_LONG;
43 result += BITS_PER_LONG;
44 }
45 while (size & ~(BITS_PER_LONG-1)) {
46 if ((tmp = *(p++)))
47 goto found_middle;
48 result += BITS_PER_LONG;
49 size -= BITS_PER_LONG;
50 }
51 if (!size)
52 return result;
53 tmp = *p;
54
55found_first:
56 tmp &= (~0UL >> (BITS_PER_LONG - size));
57 if (tmp == 0UL) /* Are any bits set? */
58 return result + size; /* Nope. */
59found_middle:
60 return result + __ffs(tmp);
61}
62#endif
63
64#ifndef find_first_bit
65/*
66 * Find the first set bit in a memory region.
67 */
68unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
69{
70 const unsigned long *p = addr;
71 unsigned long result = 0;
72 unsigned long tmp;
73
74 while (size & ~(BITS_PER_LONG-1)) {
75 if ((tmp = *(p++)))
76 goto found;
77 result += BITS_PER_LONG;
78 size -= BITS_PER_LONG;
79 }
80 if (!size)
81 return result;
82
83 tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
84 if (tmp == 0UL) /* Are any bits set? */
85 return result + size; /* Nope. */
86found:
87 return result + __ffs(tmp);
88}
89#endif
diff --git a/tools/perf/Build b/tools/perf/Build
index 72237455b400..6b67e6f4179f 100644
--- a/tools/perf/Build
+++ b/tools/perf/Build
@@ -1,5 +1,6 @@
1perf-y += builtin-bench.o 1perf-y += builtin-bench.o
2perf-y += builtin-annotate.o 2perf-y += builtin-annotate.o
3perf-y += builtin-config.o
3perf-y += builtin-diff.o 4perf-y += builtin-diff.o
4perf-y += builtin-evlist.o 5perf-y += builtin-evlist.o
5perf-y += builtin-help.o 6perf-y += builtin-help.o
@@ -19,6 +20,7 @@ perf-y += builtin-kvm.o
19perf-y += builtin-inject.o 20perf-y += builtin-inject.o
20perf-y += builtin-mem.o 21perf-y += builtin-mem.o
21perf-y += builtin-data.o 22perf-y += builtin-data.o
23perf-y += builtin-version.o
22 24
23perf-$(CONFIG_AUDIT) += builtin-trace.o 25perf-$(CONFIG_AUDIT) += builtin-trace.o
24perf-$(CONFIG_LIBELF) += builtin-probe.o 26perf-$(CONFIG_LIBELF) += builtin-probe.o
@@ -34,8 +36,12 @@ paths += -DPERF_MAN_PATH="BUILD_STR($(mandir_SQ))"
34 36
35CFLAGS_builtin-help.o += $(paths) 37CFLAGS_builtin-help.o += $(paths)
36CFLAGS_builtin-timechart.o += $(paths) 38CFLAGS_builtin-timechart.o += $(paths)
37CFLAGS_perf.o += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))" -include $(OUTPUT)PERF-VERSION-FILE 39CFLAGS_perf.o += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))" \
40 -DPERF_EXEC_PATH="BUILD_STR($(perfexecdir_SQ))" \
41 -DPREFIX="BUILD_STR($(prefix_SQ))" \
42 -include $(OUTPUT)PERF-VERSION-FILE
38CFLAGS_builtin-trace.o += -DSTRACE_GROUPS_DIR="BUILD_STR($(STRACE_GROUPS_DIR_SQ))" 43CFLAGS_builtin-trace.o += -DSTRACE_GROUPS_DIR="BUILD_STR($(STRACE_GROUPS_DIR_SQ))"
44CFLAGS_builtin-report.o += -DTIPDIR="BUILD_STR($(tipdir_SQ))"
39 45
40libperf-y += util/ 46libperf-y += util/
41libperf-y += arch/ 47libperf-y += arch/
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
new file mode 100644
index 000000000000..b9ca1e304158
--- /dev/null
+++ b/tools/perf/Documentation/perf-config.txt
@@ -0,0 +1,103 @@
1perf-config(1)
2==============
3
4NAME
5----
6perf-config - Get and set variables in a configuration file.
7
8SYNOPSIS
9--------
10[verse]
11'perf config' -l | --list
12
13DESCRIPTION
14-----------
15You can manage variables in a configuration file with this command.
16
17OPTIONS
18-------
19
20-l::
21--list::
22 Show current config variables, name and value, for all sections.
23
24CONFIGURATION FILE
25------------------
26
27The perf configuration file contains many variables to change various
28aspects of each of its tools, including output, disk usage, etc.
29The '$HOME/.perfconfig' file is used to store a per-user configuration.
30The file '$(sysconfdir)/perfconfig' can be used to
31store a system-wide default configuration.
32
33Syntax
34~~~~~~
35
36The file consist of sections. A section starts with its name
37surrounded by square brackets and continues till the next section
38begins. Each variable must be in a section, and have the form
39'name = value', for example:
40
41 [section]
42 name1 = value1
43 name2 = value2
44
45Section names are case sensitive and can contain any characters except
46newline (double quote `"` and backslash have to be escaped as `\"` and `\\`,
47respectively). Section headers can't span multiple lines.
48
49Example
50~~~~~~~
51
52Given a $HOME/.perfconfig like this:
53
54#
55# This is the config file, and
56# a '#' and ';' character indicates a comment
57#
58
59 [colors]
60 # Color variables
61 top = red, default
62 medium = green, default
63 normal = lightgray, default
64 selected = white, lightgray
65 code = blue, default
66 addr = magenta, default
67 root = white, blue
68
69 [tui]
70 # Defaults if linked with libslang
71 report = on
72 annotate = on
73 top = on
74
75 [buildid]
76 # Default, disable using /dev/null
77 dir = ~/.debug
78
79 [annotate]
80 # Defaults
81 hide_src_code = false
82 use_offset = true
83 jump_arrows = true
84 show_nr_jumps = false
85
86 [help]
87 # Format can be man, info, web or html
88 format = man
89 autocorrect = 0
90
91 [ui]
92 show-headers = true
93
94 [call-graph]
95 # fp (framepointer), dwarf
96 record-mode = fp
97 print-type = graph
98 order = caller
99 sort-key = function
100
101SEE ALSO
102--------
103linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-evlist.txt b/tools/perf/Documentation/perf-evlist.txt
index 1ceb3700ffbb..6f7200fb85cf 100644
--- a/tools/perf/Documentation/perf-evlist.txt
+++ b/tools/perf/Documentation/perf-evlist.txt
@@ -32,6 +32,9 @@ OPTIONS
32--group:: 32--group::
33 Show event group information. 33 Show event group information.
34 34
35--trace-fields::
36 Show tracepoint field names.
37
35SEE ALSO 38SEE ALSO
36-------- 39--------
37linkperf:perf-record[1], linkperf:perf-list[1], 40linkperf:perf-record[1], linkperf:perf-list[1],
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index e630a7d2c348..3a1a32f5479f 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -207,11 +207,23 @@ comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-
207In per-thread mode with inheritance mode on (default), samples are captured only when 207In per-thread mode with inheritance mode on (default), samples are captured only when
208the thread executes on the designated CPUs. Default is to monitor all CPUs. 208the thread executes on the designated CPUs. Default is to monitor all CPUs.
209 209
210-B::
211--no-buildid::
212Do not save the build ids of binaries in the perf.data files. This skips
213post processing after recording, which sometimes makes the final step in
214the recording process to take a long time, as it needs to process all
215events looking for mmap records. The downside is that it can misresolve
216symbols if the workload binaries used when recording get locally rebuilt
217or upgraded, because the only key available in this case is the
218pathname. You can also set the "record.build-id" config variable to
219'skip to have this behaviour permanently.
220
210-N:: 221-N::
211--no-buildid-cache:: 222--no-buildid-cache::
212Do not update the buildid cache. This saves some overhead in situations 223Do not update the buildid cache. This saves some overhead in situations
213where the information in the perf.data file (which includes buildids) 224where the information in the perf.data file (which includes buildids)
214is sufficient. 225is sufficient. You can also set the "record.build-id" config variable to
226'no-cache' to have the same effect.
215 227
216-G name,...:: 228-G name,...::
217--cgroup name,...:: 229--cgroup name,...::
@@ -314,11 +326,17 @@ This option sets the time out limit. The default value is 500 ms.
314Record context switch events i.e. events of type PERF_RECORD_SWITCH or 326Record context switch events i.e. events of type PERF_RECORD_SWITCH or
315PERF_RECORD_SWITCH_CPU_WIDE. 327PERF_RECORD_SWITCH_CPU_WIDE.
316 328
317--clang-path:: 329--clang-path=PATH::
318Path to clang binary to use for compiling BPF scriptlets. 330Path to clang binary to use for compiling BPF scriptlets.
331(enabled when BPF support is on)
319 332
320--clang-opt:: 333--clang-opt=OPTIONS::
321Options passed to clang when compiling BPF scriptlets. 334Options passed to clang when compiling BPF scriptlets.
335(enabled when BPF support is on)
336
337--vmlinux=PATH::
338Specify vmlinux path which has debuginfo.
339(enabled when BPF prologue is on)
322 340
323SEE ALSO 341SEE ALSO
324-------- 342--------
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 5ce8da1e1256..8a301f6afb37 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -117,6 +117,30 @@ OPTIONS
117 And default sort keys are changed to comm, dso_from, symbol_from, dso_to 117 And default sort keys are changed to comm, dso_from, symbol_from, dso_to
118 and symbol_to, see '--branch-stack'. 118 and symbol_to, see '--branch-stack'.
119 119
120 If the data file has tracepoint event(s), following (dynamic) sort keys
121 are also available:
122 trace, trace_fields, [<event>.]<field>[/raw]
123
124 - trace: pretty printed trace output in a single column
125 - trace_fields: fields in tracepoints in separate columns
126 - <field name>: optional event and field name for a specific field
127
128 The last form consists of event and field names. If event name is
129 omitted, it searches all events for matching field name. The matched
130 field will be shown only for the event has the field. The event name
131 supports substring match so user doesn't need to specify full subsystem
132 and event name everytime. For example, 'sched:sched_switch' event can
133 be shortened to 'switch' as long as it's not ambiguous. Also event can
134 be specified by its index (starting from 1) preceded by the '%'.
135 So '%1' is the first event, '%2' is the second, and so on.
136
137 The field name can have '/raw' suffix which disables pretty printing
138 and shows raw field value like hex numbers. The --raw-trace option
139 has the same effect for all dynamic sort keys.
140
141 The default sort keys are changed to 'trace' if all events in the data
142 file are tracepoint.
143
120-F:: 144-F::
121--fields=:: 145--fields=::
122 Specify output field - multiple keys can be specified in CSV format. 146 Specify output field - multiple keys can be specified in CSV format.
@@ -170,17 +194,18 @@ OPTIONS
170 Dump raw trace in ASCII. 194 Dump raw trace in ASCII.
171 195
172-g:: 196-g::
173--call-graph=<print_type,threshold[,print_limit],order,sort_key,branch>:: 197--call-graph=<print_type,threshold[,print_limit],order,sort_key[,branch],value>::
174 Display call chains using type, min percent threshold, print limit, 198 Display call chains using type, min percent threshold, print limit,
175 call order, sort key and branch. Note that ordering of parameters is not 199 call order, sort key, optional branch and value. Note that ordering of
176 fixed so any parement can be given in an arbitraty order. One exception 200 parameters is not fixed so any parement can be given in an arbitraty order.
177 is the print_limit which should be preceded by threshold. 201 One exception is the print_limit which should be preceded by threshold.
178 202
179 print_type can be either: 203 print_type can be either:
180 - flat: single column, linear exposure of call chains. 204 - flat: single column, linear exposure of call chains.
181 - graph: use a graph tree, displaying absolute overhead rates. (default) 205 - graph: use a graph tree, displaying absolute overhead rates. (default)
182 - fractal: like graph, but displays relative rates. Each branch of 206 - fractal: like graph, but displays relative rates. Each branch of
183 the tree is considered as a new profiled object. 207 the tree is considered as a new profiled object.
208 - folded: call chains are displayed in a line, separated by semicolons
184 - none: disable call chain display. 209 - none: disable call chain display.
185 210
186 threshold is a percentage value which specifies a minimum percent to be 211 threshold is a percentage value which specifies a minimum percent to be
@@ -204,6 +229,11 @@ OPTIONS
204 - branch: include last branch information in callgraph when available. 229 - branch: include last branch information in callgraph when available.
205 Usually more convenient to use --branch-history for this. 230 Usually more convenient to use --branch-history for this.
206 231
232 value can be:
233 - percent: diplay overhead percent (default)
234 - period: display event period
235 - count: display event count
236
207--children:: 237--children::
208 Accumulate callchain of children to parent entry so that then can 238 Accumulate callchain of children to parent entry so that then can
209 show up in the output. The output will have a new "Children" column 239 show up in the output. The output will have a new "Children" column
@@ -365,6 +395,9 @@ include::itrace.txt[]
365--socket-filter:: 395--socket-filter::
366 Only report the samples on the processor socket that match with this filter 396 Only report the samples on the processor socket that match with this filter
367 397
398--raw-trace::
399 When displaying traceevent output, do not use print fmt or plugins.
400
368include::callchain-overhead-calculation.txt[] 401include::callchain-overhead-calculation.txt[]
369 402
370SEE ALSO 403SEE ALSO
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 4e074a660826..52ef7a9d50aa 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -10,6 +10,8 @@ SYNOPSIS
10[verse] 10[verse]
11'perf stat' [-e <EVENT> | --event=EVENT] [-a] <command> 11'perf stat' [-e <EVENT> | --event=EVENT] [-a] <command>
12'perf stat' [-e <EVENT> | --event=EVENT] [-a] -- <command> [<options>] 12'perf stat' [-e <EVENT> | --event=EVENT] [-a] -- <command> [<options>]
13'perf stat' [-e <EVENT> | --event=EVENT] [-a] record [-o file] -- <command> [<options>]
14'perf stat' report [-i file]
13 15
14DESCRIPTION 16DESCRIPTION
15----------- 17-----------
@@ -22,6 +24,11 @@ OPTIONS
22<command>...:: 24<command>...::
23 Any command you can specify in a shell. 25 Any command you can specify in a shell.
24 26
27record::
28 See STAT RECORD.
29
30report::
31 See STAT REPORT.
25 32
26-e:: 33-e::
27--event=:: 34--event=::
@@ -159,6 +166,33 @@ filter out the startup phase of the program, which is often very different.
159 166
160Print statistics of transactional execution if supported. 167Print statistics of transactional execution if supported.
161 168
169STAT RECORD
170-----------
171Stores stat data into perf data file.
172
173-o file::
174--output file::
175Output file name.
176
177STAT REPORT
178-----------
179Reads and reports stat data from perf data file.
180
181-i file::
182--input file::
183Input file name.
184
185--per-socket::
186Aggregate counts per processor socket for system-wide mode measurements.
187
188--per-core::
189Aggregate counts per physical processor for system-wide mode measurements.
190
191-A::
192--no-aggr::
193Do not aggregate counts across all monitored CPUs.
194
195
162EXAMPLES 196EXAMPLES
163-------- 197--------
164 198
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 556cec09bf50..b0e60e17db38 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -230,6 +230,9 @@ Default is to monitor all CPUS.
230 The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k 230 The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k
231 Note that this feature may not be available on all processors. 231 Note that this feature may not be available on all processors.
232 232
233--raw-trace::
234 When displaying traceevent output, do not use print fmt or plugins.
235
233INTERACTIVE PROMPTING KEYS 236INTERACTIVE PROMPTING KEYS
234-------------------------- 237--------------------------
235 238
diff --git a/tools/perf/Documentation/tips.txt b/tools/perf/Documentation/tips.txt
new file mode 100644
index 000000000000..a1c10e360db5
--- /dev/null
+++ b/tools/perf/Documentation/tips.txt
@@ -0,0 +1,14 @@
1For a higher level overview, try: perf report --sort comm,dso
2Sample related events with: perf record -e '{cycles,instructions}:S'
3Compare performance results with: perf diff [<old file> <new file>]
4Boolean options have negative forms, e.g.: perf report --no-children
5Customize output of perf script with: perf script -F event,ip,sym
6Generate a script for your data: perf script -g <lang>
7Save output of perf stat using: perf stat record <target workload>
8Create an archive with symtabs to analyse on other machine: perf archive
9Search options using a keyword: perf report -h <keyword>
10Use parent filter to see specific call path: perf report -p <regex>
11List events using substring match: perf list <keyword>
12To see list of saved events and attributes: perf evlist -v
13Use --symfs <dir> if your symbol files are in non-standard locations
14To see callchains in a more compact form: perf report -g folded
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 39c38cb45b00..ddf922f93aa1 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -1,6 +1,7 @@
1tools/perf 1tools/perf
2tools/arch/alpha/include/asm/barrier.h 2tools/arch/alpha/include/asm/barrier.h
3tools/arch/arm/include/asm/barrier.h 3tools/arch/arm/include/asm/barrier.h
4tools/arch/arm64/include/asm/barrier.h
4tools/arch/ia64/include/asm/barrier.h 5tools/arch/ia64/include/asm/barrier.h
5tools/arch/mips/include/asm/barrier.h 6tools/arch/mips/include/asm/barrier.h
6tools/arch/powerpc/include/asm/barrier.h 7tools/arch/powerpc/include/asm/barrier.h
@@ -20,14 +21,17 @@ tools/lib/traceevent
20tools/lib/bpf 21tools/lib/bpf
21tools/lib/api 22tools/lib/api
22tools/lib/bpf 23tools/lib/bpf
24tools/lib/subcmd
23tools/lib/hweight.c 25tools/lib/hweight.c
24tools/lib/rbtree.c 26tools/lib/rbtree.c
27tools/lib/string.c
25tools/lib/symbol/kallsyms.c 28tools/lib/symbol/kallsyms.c
26tools/lib/symbol/kallsyms.h 29tools/lib/symbol/kallsyms.h
27tools/lib/util/find_next_bit.c 30tools/lib/find_bit.c
28tools/include/asm/atomic.h 31tools/include/asm/atomic.h
29tools/include/asm/barrier.h 32tools/include/asm/barrier.h
30tools/include/asm/bug.h 33tools/include/asm/bug.h
34tools/include/asm-generic/atomic-gcc.h
31tools/include/asm-generic/barrier.h 35tools/include/asm-generic/barrier.h
32tools/include/asm-generic/bitops/arch_hweight.h 36tools/include/asm-generic/bitops/arch_hweight.h
33tools/include/asm-generic/bitops/atomic.h 37tools/include/asm-generic/bitops/atomic.h
@@ -50,6 +54,7 @@ tools/include/linux/log2.h
50tools/include/linux/poison.h 54tools/include/linux/poison.h
51tools/include/linux/rbtree.h 55tools/include/linux/rbtree.h
52tools/include/linux/rbtree_augmented.h 56tools/include/linux/rbtree_augmented.h
57tools/include/linux/string.h
53tools/include/linux/types.h 58tools/include/linux/types.h
54tools/include/linux/err.h 59tools/include/linux/err.h
55include/asm-generic/bitops/arch_hweight.h 60include/asm-generic/bitops/arch_hweight.h
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 0d19d5447d6c..0a22407e1d7d 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -145,9 +145,10 @@ BISON = bison
145STRIP = strip 145STRIP = strip
146AWK = awk 146AWK = awk
147 147
148LIB_DIR = $(srctree)/tools/lib/api/ 148LIB_DIR = $(srctree)/tools/lib/api/
149TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/ 149TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
150BPF_DIR = $(srctree)/tools/lib/bpf/ 150BPF_DIR = $(srctree)/tools/lib/bpf/
151SUBCMD_DIR = $(srctree)/tools/lib/subcmd/
151 152
152# include config/Makefile by default and rule out 153# include config/Makefile by default and rule out
153# non-config cases 154# non-config cases
@@ -184,15 +185,17 @@ strip-libs = $(filter-out -l%,$(1))
184ifneq ($(OUTPUT),) 185ifneq ($(OUTPUT),)
185 TE_PATH=$(OUTPUT) 186 TE_PATH=$(OUTPUT)
186 BPF_PATH=$(OUTPUT) 187 BPF_PATH=$(OUTPUT)
188 SUBCMD_PATH=$(OUTPUT)
187ifneq ($(subdir),) 189ifneq ($(subdir),)
188 LIB_PATH=$(OUTPUT)/../lib/api/ 190 API_PATH=$(OUTPUT)/../lib/api/
189else 191else
190 LIB_PATH=$(OUTPUT) 192 API_PATH=$(OUTPUT)
191endif 193endif
192else 194else
193 TE_PATH=$(TRACE_EVENT_DIR) 195 TE_PATH=$(TRACE_EVENT_DIR)
194 LIB_PATH=$(LIB_DIR) 196 API_PATH=$(LIB_DIR)
195 BPF_PATH=$(BPF_DIR) 197 BPF_PATH=$(BPF_DIR)
198 SUBCMD_PATH=$(SUBCMD_DIR)
196endif 199endif
197 200
198LIBTRACEEVENT = $(TE_PATH)libtraceevent.a 201LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
@@ -201,11 +204,13 @@ export LIBTRACEEVENT
201LIBTRACEEVENT_DYNAMIC_LIST = $(TE_PATH)libtraceevent-dynamic-list 204LIBTRACEEVENT_DYNAMIC_LIST = $(TE_PATH)libtraceevent-dynamic-list
202LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS = -Xlinker --dynamic-list=$(LIBTRACEEVENT_DYNAMIC_LIST) 205LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS = -Xlinker --dynamic-list=$(LIBTRACEEVENT_DYNAMIC_LIST)
203 206
204LIBAPI = $(LIB_PATH)libapi.a 207LIBAPI = $(API_PATH)libapi.a
205export LIBAPI 208export LIBAPI
206 209
207LIBBPF = $(BPF_PATH)libbpf.a 210LIBBPF = $(BPF_PATH)libbpf.a
208 211
212LIBSUBCMD = $(SUBCMD_PATH)libsubcmd.a
213
209# python extension build directories 214# python extension build directories
210PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/ 215PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
211PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/ 216PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
@@ -257,7 +262,7 @@ export PERL_PATH
257 262
258LIB_FILE=$(OUTPUT)libperf.a 263LIB_FILE=$(OUTPUT)libperf.a
259 264
260PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT) 265PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT) $(LIBSUBCMD)
261ifndef NO_LIBBPF 266ifndef NO_LIBBPF
262 PERFLIBS += $(LIBBPF) 267 PERFLIBS += $(LIBBPF)
263endif 268endif
@@ -420,7 +425,7 @@ $(LIBTRACEEVENT)-clean:
420 $(call QUIET_CLEAN, libtraceevent) 425 $(call QUIET_CLEAN, libtraceevent)
421 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null 426 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null
422 427
423install-traceevent-plugins: $(LIBTRACEEVENT) 428install-traceevent-plugins: libtraceevent_plugins
424 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) install_plugins 429 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) install_plugins
425 430
426$(LIBAPI): fixdep FORCE 431$(LIBAPI): fixdep FORCE
@@ -431,12 +436,19 @@ $(LIBAPI)-clean:
431 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null 436 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
432 437
433$(LIBBPF): fixdep FORCE 438$(LIBBPF): fixdep FORCE
434 $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) $(OUTPUT)libbpf.a 439 $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) $(OUTPUT)libbpf.a FEATURES_DUMP=$(realpath $(OUTPUT)FEATURE-DUMP)
435 440
436$(LIBBPF)-clean: 441$(LIBBPF)-clean:
437 $(call QUIET_CLEAN, libbpf) 442 $(call QUIET_CLEAN, libbpf)
438 $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) clean >/dev/null 443 $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) clean >/dev/null
439 444
445$(LIBSUBCMD): fixdep FORCE
446 $(Q)$(MAKE) -C $(SUBCMD_DIR) O=$(OUTPUT) $(OUTPUT)libsubcmd.a
447
448$(LIBSUBCMD)-clean:
449 $(call QUIET_CLEAN, libsubcmd)
450 $(Q)$(MAKE) -C $(SUBCMD_DIR) O=$(OUTPUT) clean
451
440help: 452help:
441 @echo 'Perf make targets:' 453 @echo 'Perf make targets:'
442 @echo ' doc - make *all* documentation (see below)' 454 @echo ' doc - make *all* documentation (see below)'
@@ -476,7 +488,7 @@ INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
476$(DOC_TARGETS): 488$(DOC_TARGETS):
477 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all) 489 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)
478 490
479TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol ../include ../lib/bpf 491TAG_FOLDERS= . ../lib ../include
480TAG_FILES= ../../include/uapi/linux/perf_event.h 492TAG_FILES= ../../include/uapi/linux/perf_event.h
481 493
482TAGS: 494TAGS:
@@ -555,6 +567,9 @@ endif
555 $(call QUIET_INSTALL, perf_completion-script) \ 567 $(call QUIET_INSTALL, perf_completion-script) \
556 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \ 568 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \
557 $(INSTALL) perf-completion.sh '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf' 569 $(INSTALL) perf-completion.sh '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
570 $(call QUIET_INSTALL, perf-tip) \
571 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(tip_instdir_SQ)'; \
572 $(INSTALL) Documentation/tips.txt -t '$(DESTDIR_SQ)$(tip_instdir_SQ)'
558 573
559install-tests: all install-gtk 574install-tests: all install-gtk
560 $(call QUIET_INSTALL, tests) \ 575 $(call QUIET_INSTALL, tests) \
@@ -582,15 +597,16 @@ $(INSTALL_DOC_TARGETS):
582# 597#
583config-clean: 598config-clean:
584 $(call QUIET_CLEAN, config) 599 $(call QUIET_CLEAN, config)
585 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null 600 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ $(if $(OUTPUT),OUTPUT=$(OUTPUT)feature/,) clean >/dev/null
586 601
587clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean config-clean 602clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean
588 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS) 603 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
589 $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete 604 $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
590 $(Q)$(RM) $(OUTPUT).config-detected 605 $(Q)$(RM) $(OUTPUT).config-detected
591 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 606 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32
592 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \ 607 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \
593 $(OUTPUT)util/intel-pt-decoder/inat-tables.c 608 $(OUTPUT)util/intel-pt-decoder/inat-tables.c $(OUTPUT)fixdep \
609 $(OUTPUT)tests/llvm-src-{base,kbuild,prologue}.c
594 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 610 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
595 $(python-clean) 611 $(python-clean)
596 612
diff --git a/tools/perf/arch/x86/include/arch-tests.h b/tools/perf/arch/x86/include/arch-tests.h
index 7ed00f4b0908..b48de2f5813c 100644
--- a/tools/perf/arch/x86/include/arch-tests.h
+++ b/tools/perf/arch/x86/include/arch-tests.h
@@ -2,10 +2,10 @@
2#define ARCH_TESTS_H 2#define ARCH_TESTS_H
3 3
4/* Tests */ 4/* Tests */
5int test__rdpmc(void); 5int test__rdpmc(int subtest);
6int test__perf_time_to_tsc(void); 6int test__perf_time_to_tsc(int subtest);
7int test__insn_x86(void); 7int test__insn_x86(int subtest);
8int test__intel_cqm_count_nmi_context(void); 8int test__intel_cqm_count_nmi_context(int subtest);
9 9
10#ifdef HAVE_DWARF_UNWIND_SUPPORT 10#ifdef HAVE_DWARF_UNWIND_SUPPORT
11struct thread; 11struct thread;
diff --git a/tools/perf/arch/x86/tests/insn-x86.c b/tools/perf/arch/x86/tests/insn-x86.c
index b6115dfd28f0..08d9b2bc185c 100644
--- a/tools/perf/arch/x86/tests/insn-x86.c
+++ b/tools/perf/arch/x86/tests/insn-x86.c
@@ -171,7 +171,7 @@ static int test_data_set(struct test_data *dat_set, int x86_64)
171 * verbose (-v) option to see all the instructions and whether or not they 171 * verbose (-v) option to see all the instructions and whether or not they
172 * decoded successfuly. 172 * decoded successfuly.
173 */ 173 */
174int test__insn_x86(void) 174int test__insn_x86(int subtest __maybe_unused)
175{ 175{
176 int ret = 0; 176 int ret = 0;
177 177
diff --git a/tools/perf/arch/x86/tests/intel-cqm.c b/tools/perf/arch/x86/tests/intel-cqm.c
index d28c1b6a3b54..3e89ba825f6b 100644
--- a/tools/perf/arch/x86/tests/intel-cqm.c
+++ b/tools/perf/arch/x86/tests/intel-cqm.c
@@ -33,7 +33,7 @@ static pid_t spawn(void)
33 * the last read counter value to avoid triggering a WARN_ON_ONCE() in 33 * the last read counter value to avoid triggering a WARN_ON_ONCE() in
34 * smp_call_function_many() caused by sending IPIs from NMI context. 34 * smp_call_function_many() caused by sending IPIs from NMI context.
35 */ 35 */
36int test__intel_cqm_count_nmi_context(void) 36int test__intel_cqm_count_nmi_context(int subtest __maybe_unused)
37{ 37{
38 struct perf_evlist *evlist = NULL; 38 struct perf_evlist *evlist = NULL;
39 struct perf_evsel *evsel = NULL; 39 struct perf_evsel *evsel = NULL;
@@ -54,7 +54,7 @@ int test__intel_cqm_count_nmi_context(void)
54 54
55 ret = parse_events(evlist, "intel_cqm/llc_occupancy/", NULL); 55 ret = parse_events(evlist, "intel_cqm/llc_occupancy/", NULL);
56 if (ret) { 56 if (ret) {
57 pr_debug("parse_events failed\n"); 57 pr_debug("parse_events failed, is \"intel_cqm/llc_occupancy/\" available?\n");
58 err = TEST_SKIP; 58 err = TEST_SKIP;
59 goto out; 59 goto out;
60 } 60 }
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 658cd200af74..9d29ee283ac5 100644
--- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -35,13 +35,12 @@
35 * %0 is returned, otherwise %-1 is returned. If TSC conversion is not 35 * %0 is returned, otherwise %-1 is returned. If TSC conversion is not
36 * supported then then the test passes but " (not supported)" is printed. 36 * supported then then the test passes but " (not supported)" is printed.
37 */ 37 */
38int test__perf_time_to_tsc(void) 38int test__perf_time_to_tsc(int subtest __maybe_unused)
39{ 39{
40 struct record_opts opts = { 40 struct record_opts opts = {
41 .mmap_pages = UINT_MAX, 41 .mmap_pages = UINT_MAX,
42 .user_freq = UINT_MAX, 42 .user_freq = UINT_MAX,
43 .user_interval = ULLONG_MAX, 43 .user_interval = ULLONG_MAX,
44 .freq = 4000,
45 .target = { 44 .target = {
46 .uses_mmap = true, 45 .uses_mmap = true,
47 }, 46 },
diff --git a/tools/perf/arch/x86/tests/rdpmc.c b/tools/perf/arch/x86/tests/rdpmc.c
index e7688214c7cf..7bb0d13c235f 100644
--- a/tools/perf/arch/x86/tests/rdpmc.c
+++ b/tools/perf/arch/x86/tests/rdpmc.c
@@ -149,7 +149,7 @@ out_close:
149 return 0; 149 return 0;
150} 150}
151 151
152int test__rdpmc(void) 152int test__rdpmc(int subtest __maybe_unused)
153{ 153{
154 int status = 0; 154 int status = 0;
155 int wret = 0; 155 int wret = 0;
diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build
index ff63649fa9ac..465970370f3e 100644
--- a/tools/perf/arch/x86/util/Build
+++ b/tools/perf/arch/x86/util/Build
@@ -5,6 +5,7 @@ libperf-y += kvm-stat.o
5libperf-y += perf_regs.o 5libperf-y += perf_regs.o
6 6
7libperf-$(CONFIG_DWARF) += dwarf-regs.o 7libperf-$(CONFIG_DWARF) += dwarf-regs.o
8libperf-$(CONFIG_BPF_PROLOGUE) += dwarf-regs.o
8 9
9libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o 10libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
10libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o 11libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c
index 9b94ce520917..8d8150f1cf9b 100644
--- a/tools/perf/arch/x86/util/intel-bts.c
+++ b/tools/perf/arch/x86/util/intel-bts.c
@@ -327,7 +327,7 @@ static int intel_bts_snapshot_start(struct auxtrace_record *itr)
327 327
328 evlist__for_each(btsr->evlist, evsel) { 328 evlist__for_each(btsr->evlist, evsel) {
329 if (evsel->attr.type == btsr->intel_bts_pmu->type) 329 if (evsel->attr.type == btsr->intel_bts_pmu->type)
330 return perf_evlist__disable_event(btsr->evlist, evsel); 330 return perf_evsel__disable(evsel);
331 } 331 }
332 return -EINVAL; 332 return -EINVAL;
333} 333}
@@ -340,7 +340,7 @@ static int intel_bts_snapshot_finish(struct auxtrace_record *itr)
340 340
341 evlist__for_each(btsr->evlist, evsel) { 341 evlist__for_each(btsr->evlist, evsel) {
342 if (evsel->attr.type == btsr->intel_bts_pmu->type) 342 if (evsel->attr.type == btsr->intel_bts_pmu->type)
343 return perf_evlist__enable_event(btsr->evlist, evsel); 343 return perf_evsel__enable(evsel);
344 } 344 }
345 return -EINVAL; 345 return -EINVAL;
346} 346}
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index b02af064f0f9..f05daacc9e78 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -26,7 +26,7 @@
26#include "../../util/evlist.h" 26#include "../../util/evlist.h"
27#include "../../util/evsel.h" 27#include "../../util/evsel.h"
28#include "../../util/cpumap.h" 28#include "../../util/cpumap.h"
29#include "../../util/parse-options.h" 29#include <subcmd/parse-options.h>
30#include "../../util/parse-events.h" 30#include "../../util/parse-events.h"
31#include "../../util/pmu.h" 31#include "../../util/pmu.h"
32#include "../../util/debug.h" 32#include "../../util/debug.h"
@@ -725,7 +725,7 @@ static int intel_pt_snapshot_start(struct auxtrace_record *itr)
725 725
726 evlist__for_each(ptr->evlist, evsel) { 726 evlist__for_each(ptr->evlist, evsel) {
727 if (evsel->attr.type == ptr->intel_pt_pmu->type) 727 if (evsel->attr.type == ptr->intel_pt_pmu->type)
728 return perf_evlist__disable_event(ptr->evlist, evsel); 728 return perf_evsel__disable(evsel);
729 } 729 }
730 return -EINVAL; 730 return -EINVAL;
731} 731}
@@ -738,7 +738,7 @@ static int intel_pt_snapshot_finish(struct auxtrace_record *itr)
738 738
739 evlist__for_each(ptr->evlist, evsel) { 739 evlist__for_each(ptr->evlist, evsel) {
740 if (evsel->attr.type == ptr->intel_pt_pmu->type) 740 if (evsel->attr.type == ptr->intel_pt_pmu->type)
741 return perf_evlist__enable_event(ptr->evlist, evsel); 741 return perf_evsel__enable(evsel);
742 } 742 }
743 return -EINVAL; 743 return -EINVAL;
744} 744}
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index fc9bebd2cca0..0999ac536d86 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -11,7 +11,7 @@
11#include "../perf.h" 11#include "../perf.h"
12#include "../util/util.h" 12#include "../util/util.h"
13#include "../util/stat.h" 13#include "../util/stat.h"
14#include "../util/parse-options.h" 14#include <subcmd/parse-options.h>
15#include "../util/header.h" 15#include "../util/header.h"
16#include "bench.h" 16#include "bench.h"
17#include "futex.h" 17#include "futex.h"
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index bc6a16adbca8..6a18ce21f865 100644
--- a/tools/perf/bench/futex-lock-pi.c
+++ b/tools/perf/bench/futex-lock-pi.c
@@ -5,7 +5,7 @@
5#include "../perf.h" 5#include "../perf.h"
6#include "../util/util.h" 6#include "../util/util.h"
7#include "../util/stat.h" 7#include "../util/stat.h"
8#include "../util/parse-options.h" 8#include <subcmd/parse-options.h>
9#include "../util/header.h" 9#include "../util/header.h"
10#include "bench.h" 10#include "bench.h"
11#include "futex.h" 11#include "futex.h"
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index ad0d9b5342fb..718238683013 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -11,7 +11,7 @@
11#include "../perf.h" 11#include "../perf.h"
12#include "../util/util.h" 12#include "../util/util.h"
13#include "../util/stat.h" 13#include "../util/stat.h"
14#include "../util/parse-options.h" 14#include <subcmd/parse-options.h>
15#include "../util/header.h" 15#include "../util/header.h"
16#include "bench.h" 16#include "bench.h"
17#include "futex.h" 17#include "futex.h"
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index 6d8c9fa2a16c..91aaf2a1fa90 100644
--- a/tools/perf/bench/futex-wake-parallel.c
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -10,7 +10,7 @@
10#include "../perf.h" 10#include "../perf.h"
11#include "../util/util.h" 11#include "../util/util.h"
12#include "../util/stat.h" 12#include "../util/stat.h"
13#include "../util/parse-options.h" 13#include <subcmd/parse-options.h>
14#include "../util/header.h" 14#include "../util/header.h"
15#include "bench.h" 15#include "bench.h"
16#include "futex.h" 16#include "futex.h"
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index e5e41d3bdce7..f416bd705f66 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -11,7 +11,7 @@
11#include "../perf.h" 11#include "../perf.h"
12#include "../util/util.h" 12#include "../util/util.h"
13#include "../util/stat.h" 13#include "../util/stat.h"
14#include "../util/parse-options.h" 14#include <subcmd/parse-options.h>
15#include "../util/header.h" 15#include "../util/header.h"
16#include "bench.h" 16#include "bench.h"
17#include "futex.h" 17#include "futex.h"
diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c
index 9419b944220f..a91aa85d80ff 100644
--- a/tools/perf/bench/mem-functions.c
+++ b/tools/perf/bench/mem-functions.c
@@ -8,7 +8,7 @@
8 8
9#include "../perf.h" 9#include "../perf.h"
10#include "../util/util.h" 10#include "../util/util.h"
11#include "../util/parse-options.h" 11#include <subcmd/parse-options.h>
12#include "../util/header.h" 12#include "../util/header.h"
13#include "../util/cloexec.h" 13#include "../util/cloexec.h"
14#include "bench.h" 14#include "bench.h"
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 492df2752a2d..5049d6357a46 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -7,7 +7,7 @@
7#include "../perf.h" 7#include "../perf.h"
8#include "../builtin.h" 8#include "../builtin.h"
9#include "../util/util.h" 9#include "../util/util.h"
10#include "../util/parse-options.h" 10#include <subcmd/parse-options.h>
11#include "../util/cloexec.h" 11#include "../util/cloexec.h"
12 12
13#include "bench.h" 13#include "bench.h"
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
index d4ff1b539cfd..bfaf9503de8e 100644
--- a/tools/perf/bench/sched-messaging.c
+++ b/tools/perf/bench/sched-messaging.c
@@ -11,7 +11,7 @@
11 11
12#include "../perf.h" 12#include "../perf.h"
13#include "../util/util.h" 13#include "../util/util.h"
14#include "../util/parse-options.h" 14#include <subcmd/parse-options.h>
15#include "../builtin.h" 15#include "../builtin.h"
16#include "bench.h" 16#include "bench.h"
17 17
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index 005cc283790c..1dc2d13cc272 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -10,7 +10,7 @@
10 */ 10 */
11#include "../perf.h" 11#include "../perf.h"
12#include "../util/util.h" 12#include "../util/util.h"
13#include "../util/parse-options.h" 13#include <subcmd/parse-options.h>
14#include "../builtin.h" 14#include "../builtin.h"
15#include "bench.h" 15#include "bench.h"
16 16
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 2bf9b3fd9e61..cc5c1267c738 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -21,7 +21,7 @@
21#include "util/evsel.h" 21#include "util/evsel.h"
22#include "util/annotate.h" 22#include "util/annotate.h"
23#include "util/event.h" 23#include "util/event.h"
24#include "util/parse-options.h" 24#include <subcmd/parse-options.h>
25#include "util/parse-events.h" 25#include "util/parse-events.h"
26#include "util/thread.h" 26#include "util/thread.h"
27#include "util/sort.h" 27#include "util/sort.h"
@@ -47,7 +47,7 @@ struct perf_annotate {
47}; 47};
48 48
49static int perf_evsel__add_sample(struct perf_evsel *evsel, 49static int perf_evsel__add_sample(struct perf_evsel *evsel,
50 struct perf_sample *sample __maybe_unused, 50 struct perf_sample *sample,
51 struct addr_location *al, 51 struct addr_location *al,
52 struct perf_annotate *ann) 52 struct perf_annotate *ann)
53{ 53{
@@ -72,7 +72,10 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
72 return 0; 72 return 0;
73 } 73 }
74 74
75 he = __hists__add_entry(hists, al, NULL, NULL, NULL, 1, 1, 0, true); 75 sample->period = 1;
76 sample->weight = 1;
77
78 he = __hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
76 if (he == NULL) 79 if (he == NULL)
77 return -ENOMEM; 80 return -ENOMEM;
78 81
@@ -343,18 +346,19 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
343 return ret; 346 return ret;
344 347
345 argc = parse_options(argc, argv, options, annotate_usage, 0); 348 argc = parse_options(argc, argv, options, annotate_usage, 0);
349 if (argc) {
350 /*
351 * Special case: if there's an argument left then assume that
352 * it's a symbol filter:
353 */
354 if (argc > 1)
355 usage_with_options(annotate_usage, options);
346 356
347 if (annotate.use_stdio) 357 annotate.sym_hist_filter = argv[0];
348 use_browser = 0; 358 }
349 else if (annotate.use_tui)
350 use_browser = 1;
351 else if (annotate.use_gtk)
352 use_browser = 2;
353 359
354 file.path = input_name; 360 file.path = input_name;
355 361
356 setup_browser(true);
357
358 annotate.session = perf_session__new(&file, false, &annotate.tool); 362 annotate.session = perf_session__new(&file, false, &annotate.tool);
359 if (annotate.session == NULL) 363 if (annotate.session == NULL)
360 return -1; 364 return -1;
@@ -366,19 +370,17 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
366 if (ret < 0) 370 if (ret < 0)
367 goto out_delete; 371 goto out_delete;
368 372
369 if (setup_sorting() < 0) 373 if (setup_sorting(NULL) < 0)
370 usage_with_options(annotate_usage, options); 374 usage_with_options(annotate_usage, options);
371 375
372 if (argc) { 376 if (annotate.use_stdio)
373 /* 377 use_browser = 0;
374 * Special case: if there's an argument left then assume that 378 else if (annotate.use_tui)
375 * it's a symbol filter: 379 use_browser = 1;
376 */ 380 else if (annotate.use_gtk)
377 if (argc > 1) 381 use_browser = 2;
378 usage_with_options(annotate_usage, options);
379 382
380 annotate.sym_hist_filter = argv[0]; 383 setup_browser(true);
381 }
382 384
383 ret = __cmd_annotate(&annotate); 385 ret = __cmd_annotate(&annotate);
384 386
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index b17aed36ca16..a1cddc6bbf0f 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -16,7 +16,7 @@
16 */ 16 */
17#include "perf.h" 17#include "perf.h"
18#include "util/util.h" 18#include "util/util.h"
19#include "util/parse-options.h" 19#include <subcmd/parse-options.h>
20#include "builtin.h" 20#include "builtin.h"
21#include "bench/bench.h" 21#include "bench/bench.h"
22 22
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 7b8450cd33c2..d93bff7fc0e4 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -16,7 +16,7 @@
16#include "util/cache.h" 16#include "util/cache.h"
17#include "util/debug.h" 17#include "util/debug.h"
18#include "util/header.h" 18#include "util/header.h"
19#include "util/parse-options.h" 19#include <subcmd/parse-options.h>
20#include "util/strlist.h" 20#include "util/strlist.h"
21#include "util/build-id.h" 21#include "util/build-id.h"
22#include "util/session.h" 22#include "util/session.h"
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 6419f57b0850..5e914ee79eb3 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -12,7 +12,7 @@
12#include "util/build-id.h" 12#include "util/build-id.h"
13#include "util/cache.h" 13#include "util/cache.h"
14#include "util/debug.h" 14#include "util/debug.h"
15#include "util/parse-options.h" 15#include <subcmd/parse-options.h>
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"
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
new file mode 100644
index 000000000000..f04e804a9fad
--- /dev/null
+++ b/tools/perf/builtin-config.c
@@ -0,0 +1,66 @@
1/*
2 * builtin-config.c
3 *
4 * Copyright (C) 2015, Taeung Song <treeze.taeung@gmail.com>
5 *
6 */
7#include "builtin.h"
8
9#include "perf.h"
10
11#include "util/cache.h"
12#include <subcmd/parse-options.h>
13#include "util/util.h"
14#include "util/debug.h"
15
16static const char * const config_usage[] = {
17 "perf config [options]",
18 NULL
19};
20
21enum actions {
22 ACTION_LIST = 1
23} actions;
24
25static struct option config_options[] = {
26 OPT_SET_UINT('l', "list", &actions,
27 "show current config variables", ACTION_LIST),
28 OPT_END()
29};
30
31static int show_config(const char *key, const char *value,
32 void *cb __maybe_unused)
33{
34 if (value)
35 printf("%s=%s\n", key, value);
36 else
37 printf("%s\n", key);
38
39 return 0;
40}
41
42int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
43{
44 int ret = 0;
45
46 argc = parse_options(argc, argv, config_options, config_usage,
47 PARSE_OPT_STOP_AT_NON_OPTION);
48
49 switch (actions) {
50 case ACTION_LIST:
51 if (argc) {
52 pr_err("Error: takes no arguments\n");
53 parse_options_usage(config_usage, config_options, "l", 1);
54 } else {
55 ret = perf_config(show_config, NULL);
56 if (ret < 0)
57 pr_err("Nothing configured, "
58 "please check your ~/.perfconfig file\n");
59 }
60 break;
61 default:
62 usage_with_options(config_usage, config_options);
63 }
64
65 return ret;
66}
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c
index d6525bc54d13..b97bc1518b44 100644
--- a/tools/perf/builtin-data.c
+++ b/tools/perf/builtin-data.c
@@ -2,7 +2,7 @@
2#include "builtin.h" 2#include "builtin.h"
3#include "perf.h" 3#include "perf.h"
4#include "debug.h" 4#include "debug.h"
5#include "parse-options.h" 5#include <subcmd/parse-options.h>
6#include "data-convert-bt.h" 6#include "data-convert-bt.h"
7 7
8typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix); 8typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix);
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 0b180a885ba3..36ccc2b8827f 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -311,11 +311,11 @@ static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair,
311} 311}
312 312
313static int hists__add_entry(struct hists *hists, 313static int hists__add_entry(struct hists *hists,
314 struct addr_location *al, u64 period, 314 struct addr_location *al,
315 u64 weight, u64 transaction) 315 struct perf_sample *sample)
316{ 316{
317 if (__hists__add_entry(hists, al, NULL, NULL, NULL, period, weight, 317 if (__hists__add_entry(hists, al, NULL, NULL, NULL,
318 transaction, true) != NULL) 318 sample, true) != NULL)
319 return 0; 319 return 0;
320 return -ENOMEM; 320 return -ENOMEM;
321} 321}
@@ -336,8 +336,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
336 return -1; 336 return -1;
337 } 337 }
338 338
339 if (hists__add_entry(hists, &al, sample->period, 339 if (hists__add_entry(hists, &al, sample)) {
340 sample->weight, sample->transaction)) {
341 pr_warning("problem incrementing symbol period, skipping event\n"); 340 pr_warning("problem incrementing symbol period, skipping event\n");
342 goto out_put; 341 goto out_put;
343 } 342 }
@@ -1208,7 +1207,7 @@ static int ui_init(void)
1208 BUG_ON(1); 1207 BUG_ON(1);
1209 } 1208 }
1210 1209
1211 list_add(&fmt->sort_list, &perf_hpp__sort_list); 1210 perf_hpp__register_sort_field(fmt);
1212 return 0; 1211 return 0;
1213} 1212}
1214 1213
@@ -1280,7 +1279,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
1280 1279
1281 sort__mode = SORT_MODE__DIFF; 1280 sort__mode = SORT_MODE__DIFF;
1282 1281
1283 if (setup_sorting() < 0) 1282 if (setup_sorting(NULL) < 0)
1284 usage_with_options(diff_usage, options); 1283 usage_with_options(diff_usage, options);
1285 1284
1286 setup_pager(); 1285 setup_pager();
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index f4d62510acbb..8a31f511e1a0 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -12,7 +12,7 @@
12#include "util/evlist.h" 12#include "util/evlist.h"
13#include "util/evsel.h" 13#include "util/evsel.h"
14#include "util/parse-events.h" 14#include "util/parse-events.h"
15#include "util/parse-options.h" 15#include <subcmd/parse-options.h>
16#include "util/session.h" 16#include "util/session.h"
17#include "util/data.h" 17#include "util/data.h"
18#include "util/debug.h" 18#include "util/debug.h"
@@ -26,14 +26,22 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
26 .mode = PERF_DATA_MODE_READ, 26 .mode = PERF_DATA_MODE_READ,
27 .force = details->force, 27 .force = details->force,
28 }; 28 };
29 bool has_tracepoint = false;
29 30
30 session = perf_session__new(&file, 0, NULL); 31 session = perf_session__new(&file, 0, NULL);
31 if (session == NULL) 32 if (session == NULL)
32 return -1; 33 return -1;
33 34
34 evlist__for_each(session->evlist, pos) 35 evlist__for_each(session->evlist, pos) {
35 perf_evsel__fprintf(pos, details, stdout); 36 perf_evsel__fprintf(pos, details, stdout);
36 37
38 if (pos->attr.type == PERF_TYPE_TRACEPOINT)
39 has_tracepoint = true;
40 }
41
42 if (has_tracepoint && !details->trace_fields)
43 printf("# Tip: use 'perf evlist --trace-fields' to show fields for tracepoint events\n");
44
37 perf_session__delete(session); 45 perf_session__delete(session);
38 return 0; 46 return 0;
39} 47}
@@ -49,6 +57,7 @@ int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
49 OPT_BOOLEAN('g', "group", &details.event_group, 57 OPT_BOOLEAN('g', "group", &details.event_group,
50 "Show event group information"), 58 "Show event group information"),
51 OPT_BOOLEAN('f', "force", &details.force, "don't complain, do it"), 59 OPT_BOOLEAN('f', "force", &details.force, "don't complain, do it"),
60 OPT_BOOLEAN(0, "trace-fields", &details.trace_fields, "Show tracepoint fields"),
52 OPT_END() 61 OPT_END()
53 }; 62 };
54 const char * const evlist_usage[] = { 63 const char * const evlist_usage[] = {
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index a7d588bf3cdd..96c1a4cfbbbf 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -6,11 +6,11 @@
6#include "perf.h" 6#include "perf.h"
7#include "util/cache.h" 7#include "util/cache.h"
8#include "builtin.h" 8#include "builtin.h"
9#include "util/exec_cmd.h" 9#include <subcmd/exec-cmd.h>
10#include "common-cmds.h" 10#include "common-cmds.h"
11#include "util/parse-options.h" 11#include <subcmd/parse-options.h>
12#include "util/run-command.h" 12#include <subcmd/run-command.h>
13#include "util/help.h" 13#include <subcmd/help.h>
14#include "util/debug.h" 14#include "util/debug.h"
15 15
16static struct man_viewer_list { 16static struct man_viewer_list {
@@ -407,7 +407,7 @@ static int get_html_page_path(struct strbuf *page_path, const char *page)
407#ifndef open_html 407#ifndef open_html
408static void open_html(const char *path) 408static void open_html(const char *path)
409{ 409{
410 execl_perf_cmd("web--browse", "-c", "help.browser", path, NULL); 410 execl_cmd("web--browse", "-c", "help.browser", path, NULL);
411} 411}
412#endif 412#endif
413 413
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 99d127fe9c35..0022e02ed31a 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -18,7 +18,7 @@
18#include "util/data.h" 18#include "util/data.h"
19#include "util/auxtrace.h" 19#include "util/auxtrace.h"
20 20
21#include "util/parse-options.h" 21#include <subcmd/parse-options.h>
22 22
23#include <linux/list.h> 23#include <linux/list.h>
24 24
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 93ce665f976f..118010553d0c 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -12,7 +12,7 @@
12#include "util/tool.h" 12#include "util/tool.h"
13#include "util/callchain.h" 13#include "util/callchain.h"
14 14
15#include "util/parse-options.h" 15#include <subcmd/parse-options.h>
16#include "util/trace-event.h" 16#include "util/trace-event.h"
17#include "util/data.h" 17#include "util/data.h"
18#include "util/cpumap.h" 18#include "util/cpumap.h"
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index dd94b4ca2213..4418d9214872 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -10,7 +10,7 @@
10#include "util/header.h" 10#include "util/header.h"
11#include "util/session.h" 11#include "util/session.h"
12#include "util/intlist.h" 12#include "util/intlist.h"
13#include "util/parse-options.h" 13#include <subcmd/parse-options.h>
14#include "util/trace-event.h" 14#include "util/trace-event.h"
15#include "util/debug.h" 15#include "util/debug.h"
16#include "util/tool.h" 16#include "util/tool.h"
@@ -1351,7 +1351,6 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1351 disable_buildid_cache(); 1351 disable_buildid_cache();
1352 1352
1353 use_browser = 0; 1353 use_browser = 0;
1354 setup_browser(false);
1355 1354
1356 if (argc) { 1355 if (argc) {
1357 argc = parse_options(argc, argv, live_options, 1356 argc = parse_options(argc, argv, live_options,
@@ -1409,8 +1408,6 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1409 err = kvm_events_live_report(kvm); 1408 err = kvm_events_live_report(kvm);
1410 1409
1411out: 1410out:
1412 exit_browser(0);
1413
1414 if (kvm->session) 1411 if (kvm->session)
1415 perf_session__delete(kvm->session); 1412 perf_session__delete(kvm->session);
1416 kvm->session = NULL; 1413 kvm->session = NULL;
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index bf679e2c978b..5e22db4684b8 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -14,7 +14,7 @@
14#include "util/parse-events.h" 14#include "util/parse-events.h"
15#include "util/cache.h" 15#include "util/cache.h"
16#include "util/pmu.h" 16#include "util/pmu.h"
17#include "util/parse-options.h" 17#include <subcmd/parse-options.h>
18 18
19int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) 19int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
20{ 20{
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index de16aaed516e..ce3bfb48b26f 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -9,7 +9,7 @@
9#include "util/thread.h" 9#include "util/thread.h"
10#include "util/header.h" 10#include "util/header.h"
11 11
12#include "util/parse-options.h" 12#include <subcmd/parse-options.h>
13#include "util/trace-event.h" 13#include "util/trace-event.h"
14 14
15#include "util/debug.h" 15#include "util/debug.h"
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 80170aace5d4..390170041696 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -1,7 +1,7 @@
1#include "builtin.h" 1#include "builtin.h"
2#include "perf.h" 2#include "perf.h"
3 3
4#include "util/parse-options.h" 4#include <subcmd/parse-options.h>
5#include "util/trace-event.h" 5#include "util/trace-event.h"
6#include "util/tool.h" 6#include "util/tool.h"
7#include "util/session.h" 7#include "util/session.h"
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 132afc97676c..9af859b28b15 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -37,7 +37,7 @@
37#include "util/strfilter.h" 37#include "util/strfilter.h"
38#include "util/symbol.h" 38#include "util/symbol.h"
39#include "util/debug.h" 39#include "util/debug.h"
40#include "util/parse-options.h" 40#include <subcmd/parse-options.h>
41#include "util/probe-finder.h" 41#include "util/probe-finder.h"
42#include "util/probe-event.h" 42#include "util/probe-event.h"
43#include "util/probe-file.h" 43#include "util/probe-file.h"
@@ -249,6 +249,9 @@ static int opt_show_vars(const struct option *opt,
249 249
250 return ret; 250 return ret;
251} 251}
252#else
253# define opt_show_lines NULL
254# define opt_show_vars NULL
252#endif 255#endif
253static int opt_add_probe_event(const struct option *opt, 256static int opt_add_probe_event(const struct option *opt,
254 const char *str, int unset __maybe_unused) 257 const char *str, int unset __maybe_unused)
@@ -473,7 +476,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
473 opt_add_probe_event), 476 opt_add_probe_event),
474 OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events" 477 OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
475 " with existing name"), 478 " with existing name"),
476#ifdef HAVE_DWARF_SUPPORT
477 OPT_CALLBACK('L', "line", NULL, 479 OPT_CALLBACK('L', "line", NULL,
478 "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]", 480 "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
479 "Show source code lines.", opt_show_lines), 481 "Show source code lines.", opt_show_lines),
@@ -490,7 +492,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
490 "directory", "path to kernel source"), 492 "directory", "path to kernel source"),
491 OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines, 493 OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines,
492 "Don't search inlined functions"), 494 "Don't search inlined functions"),
493#endif
494 OPT__DRY_RUN(&probe_event_dry_run), 495 OPT__DRY_RUN(&probe_event_dry_run),
495 OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes, 496 OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
496 "Set how many probe points can be found for a probe."), 497 "Set how many probe points can be found for a probe."),
@@ -521,6 +522,16 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
521#ifdef HAVE_DWARF_SUPPORT 522#ifdef HAVE_DWARF_SUPPORT
522 set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE); 523 set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
523 set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE); 524 set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE);
525#else
526# define set_nobuild(s, l, c) set_option_nobuild(options, s, l, "NO_DWARF=1", c)
527 set_nobuild('L', "line", false);
528 set_nobuild('V', "vars", false);
529 set_nobuild('\0', "externs", false);
530 set_nobuild('\0', "range", false);
531 set_nobuild('k', "vmlinux", true);
532 set_nobuild('s', "source", true);
533 set_nobuild('\0', "no-inlines", true);
534# undef set_nobuild
524#endif 535#endif
525 set_option_flag(options, 'F', "funcs", PARSE_OPT_EXCLUSIVE); 536 set_option_flag(options, 'F', "funcs", PARSE_OPT_EXCLUSIVE);
526 537
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 199fc31e3919..dc4e0adf5c5b 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -11,7 +11,7 @@
11 11
12#include "util/build-id.h" 12#include "util/build-id.h"
13#include "util/util.h" 13#include "util/util.h"
14#include "util/parse-options.h" 14#include <subcmd/parse-options.h>
15#include "util/parse-events.h" 15#include "util/parse-events.h"
16 16
17#include "util/callchain.h" 17#include "util/callchain.h"
@@ -452,6 +452,8 @@ static void record__init_features(struct record *rec)
452 452
453 if (!rec->opts.full_auxtrace) 453 if (!rec->opts.full_auxtrace)
454 perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 454 perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
455
456 perf_header__clear_feat(&session->header, HEADER_STAT);
455} 457}
456 458
457static volatile int workload_exec_errno; 459static volatile int workload_exec_errno;
@@ -813,8 +815,12 @@ int record_parse_callchain_opt(const struct option *opt,
813 } 815 }
814 816
815 ret = parse_callchain_record_opt(arg, &callchain_param); 817 ret = parse_callchain_record_opt(arg, &callchain_param);
816 if (!ret) 818 if (!ret) {
819 /* Enable data address sampling for DWARF unwind. */
820 if (callchain_param.record_mode == CALLCHAIN_DWARF)
821 record->sample_address = true;
817 callchain_debug(); 822 callchain_debug();
823 }
818 824
819 return ret; 825 return ret;
820} 826}
@@ -837,6 +843,19 @@ int record_callchain_opt(const struct option *opt,
837 843
838static int perf_record_config(const char *var, const char *value, void *cb) 844static int perf_record_config(const char *var, const char *value, void *cb)
839{ 845{
846 struct record *rec = cb;
847
848 if (!strcmp(var, "record.build-id")) {
849 if (!strcmp(value, "cache"))
850 rec->no_buildid_cache = false;
851 else if (!strcmp(value, "no-cache"))
852 rec->no_buildid_cache = true;
853 else if (!strcmp(value, "skip"))
854 rec->no_buildid = true;
855 else
856 return -1;
857 return 0;
858 }
840 if (!strcmp(var, "record.call-graph")) 859 if (!strcmp(var, "record.call-graph"))
841 var = "call-graph.record-mode"; /* fall-through */ 860 var = "call-graph.record-mode"; /* fall-through */
842 861
@@ -1113,12 +1132,12 @@ struct option __record_options[] = {
1113 "per thread proc mmap processing timeout in ms"), 1132 "per thread proc mmap processing timeout in ms"),
1114 OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1133 OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
1115 "Record context switch events"), 1134 "Record context switch events"),
1116#ifdef HAVE_LIBBPF_SUPPORT
1117 OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 1135 OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
1118 "clang binary to use for compiling BPF scriptlets"), 1136 "clang binary to use for compiling BPF scriptlets"),
1119 OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 1137 OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
1120 "options passed to clang when compiling BPF scriptlets"), 1138 "options passed to clang when compiling BPF scriptlets"),
1121#endif 1139 OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
1140 "file", "vmlinux pathname"),
1122 OPT_END() 1141 OPT_END()
1123}; 1142};
1124 1143
@@ -1130,6 +1149,27 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1130 struct record *rec = &record; 1149 struct record *rec = &record;
1131 char errbuf[BUFSIZ]; 1150 char errbuf[BUFSIZ];
1132 1151
1152#ifndef HAVE_LIBBPF_SUPPORT
1153# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
1154 set_nobuild('\0', "clang-path", true);
1155 set_nobuild('\0', "clang-opt", true);
1156# undef set_nobuild
1157#endif
1158
1159#ifndef HAVE_BPF_PROLOGUE
1160# if !defined (HAVE_DWARF_SUPPORT)
1161# define REASON "NO_DWARF=1"
1162# elif !defined (HAVE_LIBBPF_SUPPORT)
1163# define REASON "NO_LIBBPF=1"
1164# else
1165# define REASON "this architecture doesn't support BPF prologue"
1166# endif
1167# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
1168 set_nobuild('\0', "vmlinux", true);
1169# undef set_nobuild
1170# undef REASON
1171#endif
1172
1133 rec->evlist = perf_evlist__new(); 1173 rec->evlist = perf_evlist__new();
1134 if (rec->evlist == NULL) 1174 if (rec->evlist == NULL)
1135 return -ENOMEM; 1175 return -ENOMEM;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index f256fac1e722..d5a42ee12529 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -27,7 +27,7 @@
27#include "util/session.h" 27#include "util/session.h"
28#include "util/tool.h" 28#include "util/tool.h"
29 29
30#include "util/parse-options.h" 30#include <subcmd/parse-options.h>
31#include "util/parse-events.h" 31#include "util/parse-events.h"
32 32
33#include "util/thread.h" 33#include "util/thread.h"
@@ -45,7 +45,6 @@ struct report {
45 struct perf_tool tool; 45 struct perf_tool tool;
46 struct perf_session *session; 46 struct perf_session *session;
47 bool use_tui, use_gtk, use_stdio; 47 bool use_tui, use_gtk, use_stdio;
48 bool hide_unresolved;
49 bool dont_use_callchains; 48 bool dont_use_callchains;
50 bool show_full_info; 49 bool show_full_info;
51 bool show_threads; 50 bool show_threads;
@@ -146,7 +145,7 @@ static int process_sample_event(struct perf_tool *tool,
146 struct hist_entry_iter iter = { 145 struct hist_entry_iter iter = {
147 .evsel = evsel, 146 .evsel = evsel,
148 .sample = sample, 147 .sample = sample,
149 .hide_unresolved = rep->hide_unresolved, 148 .hide_unresolved = symbol_conf.hide_unresolved,
150 .add_entry_cb = hist_iter__report_callback, 149 .add_entry_cb = hist_iter__report_callback,
151 }; 150 };
152 int ret = 0; 151 int ret = 0;
@@ -157,7 +156,7 @@ static int process_sample_event(struct perf_tool *tool,
157 return -1; 156 return -1;
158 } 157 }
159 158
160 if (rep->hide_unresolved && al.sym == NULL) 159 if (symbol_conf.hide_unresolved && al.sym == NULL)
161 goto out_put; 160 goto out_put;
162 161
163 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap)) 162 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
@@ -434,7 +433,7 @@ static int report__browse_hists(struct report *rep)
434 int ret; 433 int ret;
435 struct perf_session *session = rep->session; 434 struct perf_session *session = rep->session;
436 struct perf_evlist *evlist = session->evlist; 435 struct perf_evlist *evlist = session->evlist;
437 const char *help = "For a higher level overview, try: perf report --sort comm,dso"; 436 const char *help = perf_tip(TIPDIR);
438 437
439 switch (use_browser) { 438 switch (use_browser) {
440 case 1: 439 case 1:
@@ -514,20 +513,26 @@ static int __cmd_report(struct report *rep)
514 if (rep->cpu_list) { 513 if (rep->cpu_list) {
515 ret = perf_session__cpu_bitmap(session, rep->cpu_list, 514 ret = perf_session__cpu_bitmap(session, rep->cpu_list,
516 rep->cpu_bitmap); 515 rep->cpu_bitmap);
517 if (ret) 516 if (ret) {
517 ui__error("failed to set cpu bitmap\n");
518 return ret; 518 return ret;
519 }
519 } 520 }
520 521
521 if (rep->show_threads) 522 if (rep->show_threads)
522 perf_read_values_init(&rep->show_threads_values); 523 perf_read_values_init(&rep->show_threads_values);
523 524
524 ret = report__setup_sample_type(rep); 525 ret = report__setup_sample_type(rep);
525 if (ret) 526 if (ret) {
527 /* report__setup_sample_type() already showed error message */
526 return ret; 528 return ret;
529 }
527 530
528 ret = perf_session__process_events(session); 531 ret = perf_session__process_events(session);
529 if (ret) 532 if (ret) {
533 ui__error("failed to process sample\n");
530 return ret; 534 return ret;
535 }
531 536
532 report__warn_kptr_restrict(rep); 537 report__warn_kptr_restrict(rep);
533 538
@@ -625,7 +630,7 @@ parse_percent_limit(const struct option *opt, const char *str,
625 return 0; 630 return 0;
626} 631}
627 632
628#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function" 633#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent"
629 634
630const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n" 635const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n"
631 CALLCHAIN_REPORT_HELP 636 CALLCHAIN_REPORT_HELP
@@ -708,7 +713,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
708 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, 713 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
709 "Only display entries with parent-match"), 714 "Only display entries with parent-match"),
710 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, 715 OPT_CALLBACK_DEFAULT('g', "call-graph", &report,
711 "print_type,threshold[,print_limit],order,sort_key[,branch]", 716 "print_type,threshold[,print_limit],order,sort_key[,branch],value",
712 report_callchain_help, &report_parse_callchain_opt, 717 report_callchain_help, &report_parse_callchain_opt,
713 callchain_default_opt), 718 callchain_default_opt),
714 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, 719 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
@@ -740,7 +745,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
740 OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator", 745 OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator",
741 "separator for columns, no spaces will be added between " 746 "separator for columns, no spaces will be added between "
742 "columns '.' is reserved."), 747 "columns '.' is reserved."),
743 OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved, 748 OPT_BOOLEAN('U', "hide-unresolved", &symbol_conf.hide_unresolved,
744 "Only display entries resolved to a symbol"), 749 "Only display entries resolved to a symbol"),
745 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 750 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
746 "Look for files with symbols relative to this directory"), 751 "Look for files with symbols relative to this directory"),
@@ -783,6 +788,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
783 "Show callgraph from reference event"), 788 "Show callgraph from reference event"),
784 OPT_INTEGER(0, "socket-filter", &report.socket_filter, 789 OPT_INTEGER(0, "socket-filter", &report.socket_filter,
785 "only show processor socket that match with this filter"), 790 "only show processor socket that match with this filter"),
791 OPT_BOOLEAN(0, "raw-trace", &symbol_conf.raw_trace,
792 "Show raw trace event output (do not use print fmt or plugins)"),
786 OPT_END() 793 OPT_END()
787 }; 794 };
788 struct perf_data_file file = { 795 struct perf_data_file file = {
@@ -796,6 +803,16 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
796 perf_config(report__config, &report); 803 perf_config(report__config, &report);
797 804
798 argc = parse_options(argc, argv, options, report_usage, 0); 805 argc = parse_options(argc, argv, options, report_usage, 0);
806 if (argc) {
807 /*
808 * Special case: if there's an argument left then assume that
809 * it's a symbol filter:
810 */
811 if (argc > 1)
812 usage_with_options(report_usage, options);
813
814 report.symbol_filter_str = argv[0];
815 }
799 816
800 if (symbol_conf.vmlinux_name && 817 if (symbol_conf.vmlinux_name &&
801 access(symbol_conf.vmlinux_name, R_OK)) { 818 access(symbol_conf.vmlinux_name, R_OK)) {
@@ -882,7 +899,7 @@ repeat:
882 symbol_conf.cumulate_callchain = false; 899 symbol_conf.cumulate_callchain = false;
883 } 900 }
884 901
885 if (setup_sorting() < 0) { 902 if (setup_sorting(session->evlist) < 0) {
886 if (sort_order) 903 if (sort_order)
887 parse_options_usage(report_usage, options, "s", 1); 904 parse_options_usage(report_usage, options, "s", 1);
888 if (field_order) 905 if (field_order)
@@ -941,17 +958,6 @@ repeat:
941 if (symbol__init(&session->header.env) < 0) 958 if (symbol__init(&session->header.env) < 0)
942 goto error; 959 goto error;
943 960
944 if (argc) {
945 /*
946 * Special case: if there's an argument left then assume that
947 * it's a symbol filter:
948 */
949 if (argc > 1)
950 usage_with_options(report_usage, options);
951
952 report.symbol_filter_str = argv[0];
953 }
954
955 sort__setup_elide(stdout); 961 sort__setup_elide(stdout);
956 962
957 ret = __cmd_report(&report); 963 ret = __cmd_report(&report);
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index e3d3e32c0a93..871b55ae22a4 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -12,7 +12,7 @@
12#include "util/tool.h" 12#include "util/tool.h"
13#include "util/cloexec.h" 13#include "util/cloexec.h"
14 14
15#include "util/parse-options.h" 15#include <subcmd/parse-options.h>
16#include "util/trace-event.h" 16#include "util/trace-event.h"
17 17
18#include "util/debug.h" 18#include "util/debug.h"
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 72b5deb4bd79..c691214d820f 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -3,9 +3,9 @@
3#include "perf.h" 3#include "perf.h"
4#include "util/cache.h" 4#include "util/cache.h"
5#include "util/debug.h" 5#include "util/debug.h"
6#include "util/exec_cmd.h" 6#include <subcmd/exec-cmd.h>
7#include "util/header.h" 7#include "util/header.h"
8#include "util/parse-options.h" 8#include <subcmd/parse-options.h>
9#include "util/perf_regs.h" 9#include "util/perf_regs.h"
10#include "util/session.h" 10#include "util/session.h"
11#include "util/tool.h" 11#include "util/tool.h"
@@ -18,7 +18,11 @@
18#include "util/sort.h" 18#include "util/sort.h"
19#include "util/data.h" 19#include "util/data.h"
20#include "util/auxtrace.h" 20#include "util/auxtrace.h"
21#include "util/cpumap.h"
22#include "util/thread_map.h"
23#include "util/stat.h"
21#include <linux/bitmap.h> 24#include <linux/bitmap.h>
25#include "asm/bug.h"
22 26
23static char const *script_name; 27static char const *script_name;
24static char const *generate_script_lang; 28static char const *generate_script_lang;
@@ -32,6 +36,7 @@ static bool print_flags;
32static bool nanosecs; 36static bool nanosecs;
33static const char *cpu_list; 37static const char *cpu_list;
34static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 38static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
39static struct perf_stat_config stat_config;
35 40
36unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH; 41unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;
37 42
@@ -130,6 +135,18 @@ static struct {
130 135
131 .invalid_fields = PERF_OUTPUT_TRACE, 136 .invalid_fields = PERF_OUTPUT_TRACE,
132 }, 137 },
138
139 [PERF_TYPE_BREAKPOINT] = {
140 .user_set = false,
141
142 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
143 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
144 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
145 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
146 PERF_OUTPUT_PERIOD,
147
148 .invalid_fields = PERF_OUTPUT_TRACE,
149 },
133}; 150};
134 151
135static bool output_set_by_user(void) 152static bool output_set_by_user(void)
@@ -204,6 +221,9 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
204 struct perf_event_attr *attr = &evsel->attr; 221 struct perf_event_attr *attr = &evsel->attr;
205 bool allow_user_set; 222 bool allow_user_set;
206 223
224 if (perf_header__has_feat(&session->header, HEADER_STAT))
225 return 0;
226
207 allow_user_set = perf_header__has_feat(&session->header, 227 allow_user_set = perf_header__has_feat(&session->header,
208 HEADER_AUXTRACE); 228 HEADER_AUXTRACE);
209 229
@@ -588,8 +608,35 @@ static void print_sample_flags(u32 flags)
588 printf(" %-4s ", str); 608 printf(" %-4s ", str);
589} 609}
590 610
591static void process_event(union perf_event *event, struct perf_sample *sample, 611struct perf_script {
592 struct perf_evsel *evsel, struct addr_location *al) 612 struct perf_tool tool;
613 struct perf_session *session;
614 bool show_task_events;
615 bool show_mmap_events;
616 bool show_switch_events;
617 bool allocated;
618 struct cpu_map *cpus;
619 struct thread_map *threads;
620 int name_width;
621};
622
623static int perf_evlist__max_name_len(struct perf_evlist *evlist)
624{
625 struct perf_evsel *evsel;
626 int max = 0;
627
628 evlist__for_each(evlist, evsel) {
629 int len = strlen(perf_evsel__name(evsel));
630
631 max = MAX(len, max);
632 }
633
634 return max;
635}
636
637static void process_event(struct perf_script *script, union perf_event *event,
638 struct perf_sample *sample, struct perf_evsel *evsel,
639 struct addr_location *al)
593{ 640{
594 struct thread *thread = al->thread; 641 struct thread *thread = al->thread;
595 struct perf_event_attr *attr = &evsel->attr; 642 struct perf_event_attr *attr = &evsel->attr;
@@ -604,7 +651,12 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
604 651
605 if (PRINT_FIELD(EVNAME)) { 652 if (PRINT_FIELD(EVNAME)) {
606 const char *evname = perf_evsel__name(evsel); 653 const char *evname = perf_evsel__name(evsel);
607 printf("%s: ", evname ? evname : "[unknown]"); 654
655 if (!script->name_width)
656 script->name_width = perf_evlist__max_name_len(script->session->evlist);
657
658 printf("%*s: ", script->name_width,
659 evname ? evname : "[unknown]");
608 } 660 }
609 661
610 if (print_flags) 662 if (print_flags)
@@ -643,65 +695,81 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
643 printf("\n"); 695 printf("\n");
644} 696}
645 697
646static int default_start_script(const char *script __maybe_unused, 698static struct scripting_ops *scripting_ops;
647 int argc __maybe_unused,
648 const char **argv __maybe_unused)
649{
650 return 0;
651}
652 699
653static int default_flush_script(void) 700static void __process_stat(struct perf_evsel *counter, u64 tstamp)
654{ 701{
655 return 0; 702 int nthreads = thread_map__nr(counter->threads);
703 int ncpus = perf_evsel__nr_cpus(counter);
704 int cpu, thread;
705 static int header_printed;
706
707 if (counter->system_wide)
708 nthreads = 1;
709
710 if (!header_printed) {
711 printf("%3s %8s %15s %15s %15s %15s %s\n",
712 "CPU", "THREAD", "VAL", "ENA", "RUN", "TIME", "EVENT");
713 header_printed = 1;
714 }
715
716 for (thread = 0; thread < nthreads; thread++) {
717 for (cpu = 0; cpu < ncpus; cpu++) {
718 struct perf_counts_values *counts;
719
720 counts = perf_counts(counter->counts, cpu, thread);
721
722 printf("%3d %8d %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %s\n",
723 counter->cpus->map[cpu],
724 thread_map__pid(counter->threads, thread),
725 counts->val,
726 counts->ena,
727 counts->run,
728 tstamp,
729 perf_evsel__name(counter));
730 }
731 }
656} 732}
657 733
658static int default_stop_script(void) 734static void process_stat(struct perf_evsel *counter, u64 tstamp)
659{ 735{
660 return 0; 736 if (scripting_ops && scripting_ops->process_stat)
737 scripting_ops->process_stat(&stat_config, counter, tstamp);
738 else
739 __process_stat(counter, tstamp);
661} 740}
662 741
663static int default_generate_script(struct pevent *pevent __maybe_unused, 742static void process_stat_interval(u64 tstamp)
664 const char *outfile __maybe_unused)
665{ 743{
666 return 0; 744 if (scripting_ops && scripting_ops->process_stat_interval)
745 scripting_ops->process_stat_interval(tstamp);
667} 746}
668 747
669static struct scripting_ops default_scripting_ops = {
670 .start_script = default_start_script,
671 .flush_script = default_flush_script,
672 .stop_script = default_stop_script,
673 .process_event = process_event,
674 .generate_script = default_generate_script,
675};
676
677static struct scripting_ops *scripting_ops;
678
679static void setup_scripting(void) 748static void setup_scripting(void)
680{ 749{
681 setup_perl_scripting(); 750 setup_perl_scripting();
682 setup_python_scripting(); 751 setup_python_scripting();
683
684 scripting_ops = &default_scripting_ops;
685} 752}
686 753
687static int flush_scripting(void) 754static int flush_scripting(void)
688{ 755{
689 return scripting_ops->flush_script(); 756 return scripting_ops ? scripting_ops->flush_script() : 0;
690} 757}
691 758
692static int cleanup_scripting(void) 759static int cleanup_scripting(void)
693{ 760{
694 pr_debug("\nperf script stopped\n"); 761 pr_debug("\nperf script stopped\n");
695 762
696 return scripting_ops->stop_script(); 763 return scripting_ops ? scripting_ops->stop_script() : 0;
697} 764}
698 765
699static int process_sample_event(struct perf_tool *tool __maybe_unused, 766static int process_sample_event(struct perf_tool *tool,
700 union perf_event *event, 767 union perf_event *event,
701 struct perf_sample *sample, 768 struct perf_sample *sample,
702 struct perf_evsel *evsel, 769 struct perf_evsel *evsel,
703 struct machine *machine) 770 struct machine *machine)
704{ 771{
772 struct perf_script *scr = container_of(tool, struct perf_script, tool);
705 struct addr_location al; 773 struct addr_location al;
706 774
707 if (debug_mode) { 775 if (debug_mode) {
@@ -727,20 +795,16 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
727 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 795 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
728 goto out_put; 796 goto out_put;
729 797
730 scripting_ops->process_event(event, sample, evsel, &al); 798 if (scripting_ops)
799 scripting_ops->process_event(event, sample, evsel, &al);
800 else
801 process_event(scr, event, sample, evsel, &al);
802
731out_put: 803out_put:
732 addr_location__put(&al); 804 addr_location__put(&al);
733 return 0; 805 return 0;
734} 806}
735 807
736struct perf_script {
737 struct perf_tool tool;
738 struct perf_session *session;
739 bool show_task_events;
740 bool show_mmap_events;
741 bool show_switch_events;
742};
743
744static int process_attr(struct perf_tool *tool, union perf_event *event, 808static int process_attr(struct perf_tool *tool, union perf_event *event,
745 struct perf_evlist **pevlist) 809 struct perf_evlist **pevlist)
746{ 810{
@@ -1156,6 +1220,8 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
1156 type = PERF_TYPE_TRACEPOINT; 1220 type = PERF_TYPE_TRACEPOINT;
1157 else if (!strcmp(str, "raw")) 1221 else if (!strcmp(str, "raw"))
1158 type = PERF_TYPE_RAW; 1222 type = PERF_TYPE_RAW;
1223 else if (!strcmp(str, "break"))
1224 type = PERF_TYPE_BREAKPOINT;
1159 else { 1225 else {
1160 fprintf(stderr, "Invalid event type in field string.\n"); 1226 fprintf(stderr, "Invalid event type in field string.\n");
1161 rc = -EINVAL; 1227 rc = -EINVAL;
@@ -1421,7 +1487,7 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
1421 char first_half[BUFSIZ]; 1487 char first_half[BUFSIZ];
1422 char *script_root; 1488 char *script_root;
1423 1489
1424 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path()); 1490 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
1425 1491
1426 scripts_dir = opendir(scripts_path); 1492 scripts_dir = opendir(scripts_path);
1427 if (!scripts_dir) 1493 if (!scripts_dir)
@@ -1542,7 +1608,7 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
1542 if (!session) 1608 if (!session)
1543 return -1; 1609 return -1;
1544 1610
1545 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path()); 1611 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
1546 1612
1547 scripts_dir = opendir(scripts_path); 1613 scripts_dir = opendir(scripts_path);
1548 if (!scripts_dir) { 1614 if (!scripts_dir) {
@@ -1600,7 +1666,7 @@ static char *get_script_path(const char *script_root, const char *suffix)
1600 char lang_path[MAXPATHLEN]; 1666 char lang_path[MAXPATHLEN];
1601 char *__script_root; 1667 char *__script_root;
1602 1668
1603 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path()); 1669 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
1604 1670
1605 scripts_dir = opendir(scripts_path); 1671 scripts_dir = opendir(scripts_path);
1606 if (!scripts_dir) 1672 if (!scripts_dir)
@@ -1695,6 +1761,87 @@ static void script__setup_sample_type(struct perf_script *script)
1695 } 1761 }
1696} 1762}
1697 1763
1764static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
1765 union perf_event *event,
1766 struct perf_session *session)
1767{
1768 struct stat_round_event *round = &event->stat_round;
1769 struct perf_evsel *counter;
1770
1771 evlist__for_each(session->evlist, counter) {
1772 perf_stat_process_counter(&stat_config, counter);
1773 process_stat(counter, round->time);
1774 }
1775
1776 process_stat_interval(round->time);
1777 return 0;
1778}
1779
1780static int process_stat_config_event(struct perf_tool *tool __maybe_unused,
1781 union perf_event *event,
1782 struct perf_session *session __maybe_unused)
1783{
1784 perf_event__read_stat_config(&stat_config, &event->stat_config);
1785 return 0;
1786}
1787
1788static int set_maps(struct perf_script *script)
1789{
1790 struct perf_evlist *evlist = script->session->evlist;
1791
1792 if (!script->cpus || !script->threads)
1793 return 0;
1794
1795 if (WARN_ONCE(script->allocated, "stats double allocation\n"))
1796 return -EINVAL;
1797
1798 perf_evlist__set_maps(evlist, script->cpus, script->threads);
1799
1800 if (perf_evlist__alloc_stats(evlist, true))
1801 return -ENOMEM;
1802
1803 script->allocated = true;
1804 return 0;
1805}
1806
1807static
1808int process_thread_map_event(struct perf_tool *tool,
1809 union perf_event *event,
1810 struct perf_session *session __maybe_unused)
1811{
1812 struct perf_script *script = container_of(tool, struct perf_script, tool);
1813
1814 if (script->threads) {
1815 pr_warning("Extra thread map event, ignoring.\n");
1816 return 0;
1817 }
1818
1819 script->threads = thread_map__new_event(&event->thread_map);
1820 if (!script->threads)
1821 return -ENOMEM;
1822
1823 return set_maps(script);
1824}
1825
1826static
1827int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
1828 union perf_event *event,
1829 struct perf_session *session __maybe_unused)
1830{
1831 struct perf_script *script = container_of(tool, struct perf_script, tool);
1832
1833 if (script->cpus) {
1834 pr_warning("Extra cpu map event, ignoring.\n");
1835 return 0;
1836 }
1837
1838 script->cpus = cpu_map__new_data(&event->cpu_map.data);
1839 if (!script->cpus)
1840 return -ENOMEM;
1841
1842 return set_maps(script);
1843}
1844
1698int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) 1845int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1699{ 1846{
1700 bool show_full_info = false; 1847 bool show_full_info = false;
@@ -1723,6 +1870,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1723 .auxtrace_info = perf_event__process_auxtrace_info, 1870 .auxtrace_info = perf_event__process_auxtrace_info,
1724 .auxtrace = perf_event__process_auxtrace, 1871 .auxtrace = perf_event__process_auxtrace,
1725 .auxtrace_error = perf_event__process_auxtrace_error, 1872 .auxtrace_error = perf_event__process_auxtrace_error,
1873 .stat = perf_event__process_stat_event,
1874 .stat_round = process_stat_round_event,
1875 .stat_config = process_stat_config_event,
1876 .thread_map = process_thread_map_event,
1877 .cpu_map = process_cpu_map_event,
1726 .ordered_events = true, 1878 .ordered_events = true,
1727 .ordering_requires_timestamps = true, 1879 .ordering_requires_timestamps = true,
1728 }, 1880 },
@@ -1836,7 +1988,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1836 scripting_max_stack = itrace_synth_opts.callchain_sz; 1988 scripting_max_stack = itrace_synth_opts.callchain_sz;
1837 1989
1838 /* make sure PERF_EXEC_PATH is set for scripts */ 1990 /* make sure PERF_EXEC_PATH is set for scripts */
1839 perf_set_argv_exec_path(perf_exec_path()); 1991 set_argv_exec_path(get_argv_exec_path());
1840 1992
1841 if (argc && !script_name && !rec_script_path && !rep_script_path) { 1993 if (argc && !script_name && !rec_script_path && !rep_script_path) {
1842 int live_pipe[2]; 1994 int live_pipe[2];
@@ -2076,6 +2228,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2076 flush_scripting(); 2228 flush_scripting();
2077 2229
2078out_delete: 2230out_delete:
2231 perf_evlist__free_stats(session->evlist);
2079 perf_session__delete(session); 2232 perf_session__delete(session);
2080 2233
2081 if (script_started) 2234 if (script_started)
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e77880b5094d..7f568244662b 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -45,7 +45,7 @@
45#include "builtin.h" 45#include "builtin.h"
46#include "util/cgroup.h" 46#include "util/cgroup.h"
47#include "util/util.h" 47#include "util/util.h"
48#include "util/parse-options.h" 48#include <subcmd/parse-options.h>
49#include "util/parse-events.h" 49#include "util/parse-events.h"
50#include "util/pmu.h" 50#include "util/pmu.h"
51#include "util/event.h" 51#include "util/event.h"
@@ -59,6 +59,9 @@
59#include "util/thread.h" 59#include "util/thread.h"
60#include "util/thread_map.h" 60#include "util/thread_map.h"
61#include "util/counts.h" 61#include "util/counts.h"
62#include "util/session.h"
63#include "util/tool.h"
64#include "asm/bug.h"
62 65
63#include <stdlib.h> 66#include <stdlib.h>
64#include <sys/prctl.h> 67#include <sys/prctl.h>
@@ -126,6 +129,21 @@ static bool append_file;
126static const char *output_name; 129static const char *output_name;
127static int output_fd; 130static int output_fd;
128 131
132struct perf_stat {
133 bool record;
134 struct perf_data_file file;
135 struct perf_session *session;
136 u64 bytes_written;
137 struct perf_tool tool;
138 bool maps_allocated;
139 struct cpu_map *cpus;
140 struct thread_map *threads;
141 enum aggr_mode aggr_mode;
142};
143
144static struct perf_stat perf_stat;
145#define STAT_RECORD perf_stat.record
146
129static volatile int done = 0; 147static volatile int done = 0;
130 148
131static struct perf_stat_config stat_config = { 149static struct perf_stat_config stat_config = {
@@ -161,15 +179,43 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
161 179
162 attr->inherit = !no_inherit; 180 attr->inherit = !no_inherit;
163 181
164 if (target__has_cpu(&target)) 182 /*
165 return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); 183 * Some events get initialized with sample_(period/type) set,
184 * like tracepoints. Clear it up for counting.
185 */
186 attr->sample_period = 0;
187
188 /*
189 * But set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless
190 * while avoiding that older tools show confusing messages.
191 *
192 * However for pipe sessions we need to keep it zero,
193 * because script's perf_evsel__check_attr is triggered
194 * by attr->sample_type != 0, and we can't run it on
195 * stat sessions.
196 */
197 if (!(STAT_RECORD && perf_stat.file.is_pipe))
198 attr->sample_type = PERF_SAMPLE_IDENTIFIER;
166 199
167 if (!target__has_task(&target) && perf_evsel__is_group_leader(evsel)) { 200 /*
201 * Disabling all counters initially, they will be enabled
202 * either manually by us or by kernel via enable_on_exec
203 * set later.
204 */
205 if (perf_evsel__is_group_leader(evsel)) {
168 attr->disabled = 1; 206 attr->disabled = 1;
169 if (!initial_delay) 207
208 /*
209 * In case of initial_delay we enable tracee
210 * events manually.
211 */
212 if (target__none(&target) && !initial_delay)
170 attr->enable_on_exec = 1; 213 attr->enable_on_exec = 1;
171 } 214 }
172 215
216 if (target__has_cpu(&target))
217 return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
218
173 return perf_evsel__open_per_thread(evsel, evsel_list->threads); 219 return perf_evsel__open_per_thread(evsel, evsel_list->threads);
174} 220}
175 221
@@ -185,6 +231,42 @@ static inline int nsec_counter(struct perf_evsel *evsel)
185 return 0; 231 return 0;
186} 232}
187 233
234static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
235 union perf_event *event,
236 struct perf_sample *sample __maybe_unused,
237 struct machine *machine __maybe_unused)
238{
239 if (perf_data_file__write(&perf_stat.file, event, event->header.size) < 0) {
240 pr_err("failed to write perf data, error: %m\n");
241 return -1;
242 }
243
244 perf_stat.bytes_written += event->header.size;
245 return 0;
246}
247
248static int write_stat_round_event(u64 tm, u64 type)
249{
250 return perf_event__synthesize_stat_round(NULL, tm, type,
251 process_synthesized_event,
252 NULL);
253}
254
255#define WRITE_STAT_ROUND_EVENT(time, interval) \
256 write_stat_round_event(time, PERF_STAT_ROUND_TYPE__ ## interval)
257
258#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
259
260static int
261perf_evsel__write_stat_event(struct perf_evsel *counter, u32 cpu, u32 thread,
262 struct perf_counts_values *count)
263{
264 struct perf_sample_id *sid = SID(counter, cpu, thread);
265
266 return perf_event__synthesize_stat(NULL, cpu, thread, sid->id, count,
267 process_synthesized_event, NULL);
268}
269
188/* 270/*
189 * Read out the results of a single counter: 271 * Read out the results of a single counter:
190 * do not aggregate counts across CPUs in system-wide mode 272 * do not aggregate counts across CPUs in system-wide mode
@@ -208,6 +290,13 @@ static int read_counter(struct perf_evsel *counter)
208 count = perf_counts(counter->counts, cpu, thread); 290 count = perf_counts(counter->counts, cpu, thread);
209 if (perf_evsel__read(counter, cpu, thread, count)) 291 if (perf_evsel__read(counter, cpu, thread, count))
210 return -1; 292 return -1;
293
294 if (STAT_RECORD) {
295 if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
296 pr_err("failed to write stat event\n");
297 return -1;
298 }
299 }
211 } 300 }
212 } 301 }
213 302
@@ -241,21 +330,26 @@ static void process_interval(void)
241 clock_gettime(CLOCK_MONOTONIC, &ts); 330 clock_gettime(CLOCK_MONOTONIC, &ts);
242 diff_timespec(&rs, &ts, &ref_time); 331 diff_timespec(&rs, &ts, &ref_time);
243 332
333 if (STAT_RECORD) {
334 if (WRITE_STAT_ROUND_EVENT(rs.tv_sec * NSECS_PER_SEC + rs.tv_nsec, INTERVAL))
335 pr_err("failed to write stat round event\n");
336 }
337
244 print_counters(&rs, 0, NULL); 338 print_counters(&rs, 0, NULL);
245} 339}
246 340
247static void handle_initial_delay(void) 341static void enable_counters(void)
248{ 342{
249 struct perf_evsel *counter; 343 if (initial_delay)
250
251 if (initial_delay) {
252 const int ncpus = cpu_map__nr(evsel_list->cpus),
253 nthreads = thread_map__nr(evsel_list->threads);
254
255 usleep(initial_delay * 1000); 344 usleep(initial_delay * 1000);
256 evlist__for_each(evsel_list, counter) 345
257 perf_evsel__enable(counter, ncpus, nthreads); 346 /*
258 } 347 * We need to enable counters only if:
348 * - we don't have tracee (attaching to task or cpu)
349 * - we have initial delay configured
350 */
351 if (!target__none(&target) || initial_delay)
352 perf_evlist__enable(evsel_list);
259} 353}
260 354
261static volatile int workload_exec_errno; 355static volatile int workload_exec_errno;
@@ -271,6 +365,135 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
271 workload_exec_errno = info->si_value.sival_int; 365 workload_exec_errno = info->si_value.sival_int;
272} 366}
273 367
368static bool has_unit(struct perf_evsel *counter)
369{
370 return counter->unit && *counter->unit;
371}
372
373static bool has_scale(struct perf_evsel *counter)
374{
375 return counter->scale != 1;
376}
377
378static int perf_stat_synthesize_config(bool is_pipe)
379{
380 struct perf_evsel *counter;
381 int err;
382
383 if (is_pipe) {
384 err = perf_event__synthesize_attrs(NULL, perf_stat.session,
385 process_synthesized_event);
386 if (err < 0) {
387 pr_err("Couldn't synthesize attrs.\n");
388 return err;
389 }
390 }
391
392 /*
393 * Synthesize other events stuff not carried within
394 * attr event - unit, scale, name
395 */
396 evlist__for_each(evsel_list, counter) {
397 if (!counter->supported)
398 continue;
399
400 /*
401 * Synthesize unit and scale only if it's defined.
402 */
403 if (has_unit(counter)) {
404 err = perf_event__synthesize_event_update_unit(NULL, counter, process_synthesized_event);
405 if (err < 0) {
406 pr_err("Couldn't synthesize evsel unit.\n");
407 return err;
408 }
409 }
410
411 if (has_scale(counter)) {
412 err = perf_event__synthesize_event_update_scale(NULL, counter, process_synthesized_event);
413 if (err < 0) {
414 pr_err("Couldn't synthesize evsel scale.\n");
415 return err;
416 }
417 }
418
419 if (counter->own_cpus) {
420 err = perf_event__synthesize_event_update_cpus(NULL, counter, process_synthesized_event);
421 if (err < 0) {
422 pr_err("Couldn't synthesize evsel scale.\n");
423 return err;
424 }
425 }
426
427 /*
428 * Name is needed only for pipe output,
429 * perf.data carries event names.
430 */
431 if (is_pipe) {
432 err = perf_event__synthesize_event_update_name(NULL, counter, process_synthesized_event);
433 if (err < 0) {
434 pr_err("Couldn't synthesize evsel name.\n");
435 return err;
436 }
437 }
438 }
439
440 err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads,
441 process_synthesized_event,
442 NULL);
443 if (err < 0) {
444 pr_err("Couldn't synthesize thread map.\n");
445 return err;
446 }
447
448 err = perf_event__synthesize_cpu_map(NULL, evsel_list->cpus,
449 process_synthesized_event, NULL);
450 if (err < 0) {
451 pr_err("Couldn't synthesize thread map.\n");
452 return err;
453 }
454
455 err = perf_event__synthesize_stat_config(NULL, &stat_config,
456 process_synthesized_event, NULL);
457 if (err < 0) {
458 pr_err("Couldn't synthesize config.\n");
459 return err;
460 }
461
462 return 0;
463}
464
465#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
466
467static int __store_counter_ids(struct perf_evsel *counter,
468 struct cpu_map *cpus,
469 struct thread_map *threads)
470{
471 int cpu, thread;
472
473 for (cpu = 0; cpu < cpus->nr; cpu++) {
474 for (thread = 0; thread < threads->nr; thread++) {
475 int fd = FD(counter, cpu, thread);
476
477 if (perf_evlist__id_add_fd(evsel_list, counter,
478 cpu, thread, fd) < 0)
479 return -1;
480 }
481 }
482
483 return 0;
484}
485
486static int store_counter_ids(struct perf_evsel *counter)
487{
488 struct cpu_map *cpus = counter->cpus;
489 struct thread_map *threads = counter->threads;
490
491 if (perf_evsel__alloc_id(counter, cpus->nr, threads->nr))
492 return -ENOMEM;
493
494 return __store_counter_ids(counter, cpus, threads);
495}
496
274static int __run_perf_stat(int argc, const char **argv) 497static int __run_perf_stat(int argc, const char **argv)
275{ 498{
276 int interval = stat_config.interval; 499 int interval = stat_config.interval;
@@ -281,6 +504,7 @@ static int __run_perf_stat(int argc, const char **argv)
281 size_t l; 504 size_t l;
282 int status = 0; 505 int status = 0;
283 const bool forks = (argc > 0); 506 const bool forks = (argc > 0);
507 bool is_pipe = STAT_RECORD ? perf_stat.file.is_pipe : false;
284 508
285 if (interval) { 509 if (interval) {
286 ts.tv_sec = interval / 1000; 510 ts.tv_sec = interval / 1000;
@@ -291,7 +515,7 @@ static int __run_perf_stat(int argc, const char **argv)
291 } 515 }
292 516
293 if (forks) { 517 if (forks) {
294 if (perf_evlist__prepare_workload(evsel_list, &target, argv, false, 518 if (perf_evlist__prepare_workload(evsel_list, &target, argv, is_pipe,
295 workload_exec_failed_signal) < 0) { 519 workload_exec_failed_signal) < 0) {
296 perror("failed to prepare workload"); 520 perror("failed to prepare workload");
297 return -1; 521 return -1;
@@ -335,6 +559,9 @@ static int __run_perf_stat(int argc, const char **argv)
335 l = strlen(counter->unit); 559 l = strlen(counter->unit);
336 if (l > unit_width) 560 if (l > unit_width)
337 unit_width = l; 561 unit_width = l;
562
563 if (STAT_RECORD && store_counter_ids(counter))
564 return -1;
338 } 565 }
339 566
340 if (perf_evlist__apply_filters(evsel_list, &counter)) { 567 if (perf_evlist__apply_filters(evsel_list, &counter)) {
@@ -344,6 +571,24 @@ static int __run_perf_stat(int argc, const char **argv)
344 return -1; 571 return -1;
345 } 572 }
346 573
574 if (STAT_RECORD) {
575 int err, fd = perf_data_file__fd(&perf_stat.file);
576
577 if (is_pipe) {
578 err = perf_header__write_pipe(perf_data_file__fd(&perf_stat.file));
579 } else {
580 err = perf_session__write_header(perf_stat.session, evsel_list,
581 fd, false);
582 }
583
584 if (err < 0)
585 return err;
586
587 err = perf_stat_synthesize_config(is_pipe);
588 if (err < 0)
589 return err;
590 }
591
347 /* 592 /*
348 * Enable counters and exec the command: 593 * Enable counters and exec the command:
349 */ 594 */
@@ -352,7 +597,7 @@ static int __run_perf_stat(int argc, const char **argv)
352 597
353 if (forks) { 598 if (forks) {
354 perf_evlist__start_workload(evsel_list); 599 perf_evlist__start_workload(evsel_list);
355 handle_initial_delay(); 600 enable_counters();
356 601
357 if (interval) { 602 if (interval) {
358 while (!waitpid(child_pid, &status, WNOHANG)) { 603 while (!waitpid(child_pid, &status, WNOHANG)) {
@@ -371,7 +616,7 @@ static int __run_perf_stat(int argc, const char **argv)
371 if (WIFSIGNALED(status)) 616 if (WIFSIGNALED(status))
372 psignal(WTERMSIG(status), argv[0]); 617 psignal(WTERMSIG(status), argv[0]);
373 } else { 618 } else {
374 handle_initial_delay(); 619 enable_counters();
375 while (!done) { 620 while (!done) {
376 nanosleep(&ts, NULL); 621 nanosleep(&ts, NULL);
377 if (interval) 622 if (interval)
@@ -810,8 +1055,8 @@ static void print_header(int argc, const char **argv)
810 else if (target.cpu_list) 1055 else if (target.cpu_list)
811 fprintf(output, "\'CPU(s) %s", target.cpu_list); 1056 fprintf(output, "\'CPU(s) %s", target.cpu_list);
812 else if (!target__has_task(&target)) { 1057 else if (!target__has_task(&target)) {
813 fprintf(output, "\'%s", argv[0]); 1058 fprintf(output, "\'%s", argv ? argv[0] : "pipe");
814 for (i = 1; i < argc; i++) 1059 for (i = 1; argv && (i < argc); i++)
815 fprintf(output, " %s", argv[i]); 1060 fprintf(output, " %s", argv[i]);
816 } else if (target.pid) 1061 } else if (target.pid)
817 fprintf(output, "process id \'%s", target.pid); 1062 fprintf(output, "process id \'%s", target.pid);
@@ -847,6 +1092,10 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
847 struct perf_evsel *counter; 1092 struct perf_evsel *counter;
848 char buf[64], *prefix = NULL; 1093 char buf[64], *prefix = NULL;
849 1094
1095 /* Do not print anything if we record to the pipe. */
1096 if (STAT_RECORD && perf_stat.file.is_pipe)
1097 return;
1098
850 if (interval) 1099 if (interval)
851 print_interval(prefix = buf, ts); 1100 print_interval(prefix = buf, ts);
852 else 1101 else
@@ -1077,6 +1326,109 @@ static int perf_stat_init_aggr_mode(void)
1077 return cpus_aggr_map ? 0 : -ENOMEM; 1326 return cpus_aggr_map ? 0 : -ENOMEM;
1078} 1327}
1079 1328
1329static void perf_stat__exit_aggr_mode(void)
1330{
1331 cpu_map__put(aggr_map);
1332 cpu_map__put(cpus_aggr_map);
1333 aggr_map = NULL;
1334 cpus_aggr_map = NULL;
1335}
1336
1337static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, int idx)
1338{
1339 int cpu;
1340
1341 if (idx > map->nr)
1342 return -1;
1343
1344 cpu = map->map[idx];
1345
1346 if (cpu >= env->nr_cpus_online)
1347 return -1;
1348
1349 return cpu;
1350}
1351
1352static int perf_env__get_socket(struct cpu_map *map, int idx, void *data)
1353{
1354 struct perf_env *env = data;
1355 int cpu = perf_env__get_cpu(env, map, idx);
1356
1357 return cpu == -1 ? -1 : env->cpu[cpu].socket_id;
1358}
1359
1360static int perf_env__get_core(struct cpu_map *map, int idx, void *data)
1361{
1362 struct perf_env *env = data;
1363 int core = -1, cpu = perf_env__get_cpu(env, map, idx);
1364
1365 if (cpu != -1) {
1366 int socket_id = env->cpu[cpu].socket_id;
1367
1368 /*
1369 * Encode socket in upper 16 bits
1370 * core_id is relative to socket, and
1371 * we need a global id. So we combine
1372 * socket + core id.
1373 */
1374 core = (socket_id << 16) | (env->cpu[cpu].core_id & 0xffff);
1375 }
1376
1377 return core;
1378}
1379
1380static int perf_env__build_socket_map(struct perf_env *env, struct cpu_map *cpus,
1381 struct cpu_map **sockp)
1382{
1383 return cpu_map__build_map(cpus, sockp, perf_env__get_socket, env);
1384}
1385
1386static int perf_env__build_core_map(struct perf_env *env, struct cpu_map *cpus,
1387 struct cpu_map **corep)
1388{
1389 return cpu_map__build_map(cpus, corep, perf_env__get_core, env);
1390}
1391
1392static int perf_stat__get_socket_file(struct cpu_map *map, int idx)
1393{
1394 return perf_env__get_socket(map, idx, &perf_stat.session->header.env);
1395}
1396
1397static int perf_stat__get_core_file(struct cpu_map *map, int idx)
1398{
1399 return perf_env__get_core(map, idx, &perf_stat.session->header.env);
1400}
1401
1402static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
1403{
1404 struct perf_env *env = &st->session->header.env;
1405
1406 switch (stat_config.aggr_mode) {
1407 case AGGR_SOCKET:
1408 if (perf_env__build_socket_map(env, evsel_list->cpus, &aggr_map)) {
1409 perror("cannot build socket map");
1410 return -1;
1411 }
1412 aggr_get_id = perf_stat__get_socket_file;
1413 break;
1414 case AGGR_CORE:
1415 if (perf_env__build_core_map(env, evsel_list->cpus, &aggr_map)) {
1416 perror("cannot build core map");
1417 return -1;
1418 }
1419 aggr_get_id = perf_stat__get_core_file;
1420 break;
1421 case AGGR_NONE:
1422 case AGGR_GLOBAL:
1423 case AGGR_THREAD:
1424 case AGGR_UNSET:
1425 default:
1426 break;
1427 }
1428
1429 return 0;
1430}
1431
1080/* 1432/*
1081 * Add default attributes, if there were no attributes specified or 1433 * Add default attributes, if there were no attributes specified or
1082 * if -d/--detailed, -d -d or -d -d -d is used: 1434 * if -d/--detailed, -d -d or -d -d -d is used:
@@ -1236,6 +1588,225 @@ static int add_default_attributes(void)
1236 return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); 1588 return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs);
1237} 1589}
1238 1590
1591static const char * const recort_usage[] = {
1592 "perf stat record [<options>]",
1593 NULL,
1594};
1595
1596static void init_features(struct perf_session *session)
1597{
1598 int feat;
1599
1600 for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
1601 perf_header__set_feat(&session->header, feat);
1602
1603 perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
1604 perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
1605 perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
1606 perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
1607}
1608
1609static int __cmd_record(int argc, const char **argv)
1610{
1611 struct perf_session *session;
1612 struct perf_data_file *file = &perf_stat.file;
1613
1614 argc = parse_options(argc, argv, stat_options, record_usage,
1615 PARSE_OPT_STOP_AT_NON_OPTION);
1616
1617 if (output_name)
1618 file->path = output_name;
1619
1620 if (run_count != 1 || forever) {
1621 pr_err("Cannot use -r option with perf stat record.\n");
1622 return -1;
1623 }
1624
1625 session = perf_session__new(file, false, NULL);
1626 if (session == NULL) {
1627 pr_err("Perf session creation failed.\n");
1628 return -1;
1629 }
1630
1631 init_features(session);
1632
1633 session->evlist = evsel_list;
1634 perf_stat.session = session;
1635 perf_stat.record = true;
1636 return argc;
1637}
1638
1639static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
1640 union perf_event *event,
1641 struct perf_session *session)
1642{
1643 struct stat_round_event *round = &event->stat_round;
1644 struct perf_evsel *counter;
1645 struct timespec tsh, *ts = NULL;
1646 const char **argv = session->header.env.cmdline_argv;
1647 int argc = session->header.env.nr_cmdline;
1648
1649 evlist__for_each(evsel_list, counter)
1650 perf_stat_process_counter(&stat_config, counter);
1651
1652 if (round->type == PERF_STAT_ROUND_TYPE__FINAL)
1653 update_stats(&walltime_nsecs_stats, round->time);
1654
1655 if (stat_config.interval && round->time) {
1656 tsh.tv_sec = round->time / NSECS_PER_SEC;
1657 tsh.tv_nsec = round->time % NSECS_PER_SEC;
1658 ts = &tsh;
1659 }
1660
1661 print_counters(ts, argc, argv);
1662 return 0;
1663}
1664
1665static
1666int process_stat_config_event(struct perf_tool *tool __maybe_unused,
1667 union perf_event *event,
1668 struct perf_session *session __maybe_unused)
1669{
1670 struct perf_stat *st = container_of(tool, struct perf_stat, tool);
1671
1672 perf_event__read_stat_config(&stat_config, &event->stat_config);
1673
1674 if (cpu_map__empty(st->cpus)) {
1675 if (st->aggr_mode != AGGR_UNSET)
1676 pr_warning("warning: processing task data, aggregation mode not set\n");
1677 return 0;
1678 }
1679
1680 if (st->aggr_mode != AGGR_UNSET)
1681 stat_config.aggr_mode = st->aggr_mode;
1682
1683 if (perf_stat.file.is_pipe)
1684 perf_stat_init_aggr_mode();
1685 else
1686 perf_stat_init_aggr_mode_file(st);
1687
1688 return 0;
1689}
1690
1691static int set_maps(struct perf_stat *st)
1692{
1693 if (!st->cpus || !st->threads)
1694 return 0;
1695
1696 if (WARN_ONCE(st->maps_allocated, "stats double allocation\n"))
1697 return -EINVAL;
1698
1699 perf_evlist__set_maps(evsel_list, st->cpus, st->threads);
1700
1701 if (perf_evlist__alloc_stats(evsel_list, true))
1702 return -ENOMEM;
1703
1704 st->maps_allocated = true;
1705 return 0;
1706}
1707
1708static
1709int process_thread_map_event(struct perf_tool *tool __maybe_unused,
1710 union perf_event *event,
1711 struct perf_session *session __maybe_unused)
1712{
1713 struct perf_stat *st = container_of(tool, struct perf_stat, tool);
1714
1715 if (st->threads) {
1716 pr_warning("Extra thread map event, ignoring.\n");
1717 return 0;
1718 }
1719
1720 st->threads = thread_map__new_event(&event->thread_map);
1721 if (!st->threads)
1722 return -ENOMEM;
1723
1724 return set_maps(st);
1725}
1726
1727static
1728int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
1729 union perf_event *event,
1730 struct perf_session *session __maybe_unused)
1731{
1732 struct perf_stat *st = container_of(tool, struct perf_stat, tool);
1733 struct cpu_map *cpus;
1734
1735 if (st->cpus) {
1736 pr_warning("Extra cpu map event, ignoring.\n");
1737 return 0;
1738 }
1739
1740 cpus = cpu_map__new_data(&event->cpu_map.data);
1741 if (!cpus)
1742 return -ENOMEM;
1743
1744 st->cpus = cpus;
1745 return set_maps(st);
1746}
1747
1748static const char * const report_usage[] = {
1749 "perf stat report [<options>]",
1750 NULL,
1751};
1752
1753static struct perf_stat perf_stat = {
1754 .tool = {
1755 .attr = perf_event__process_attr,
1756 .event_update = perf_event__process_event_update,
1757 .thread_map = process_thread_map_event,
1758 .cpu_map = process_cpu_map_event,
1759 .stat_config = process_stat_config_event,
1760 .stat = perf_event__process_stat_event,
1761 .stat_round = process_stat_round_event,
1762 },
1763 .aggr_mode = AGGR_UNSET,
1764};
1765
1766static int __cmd_report(int argc, const char **argv)
1767{
1768 struct perf_session *session;
1769 const struct option options[] = {
1770 OPT_STRING('i', "input", &input_name, "file", "input file name"),
1771 OPT_SET_UINT(0, "per-socket", &perf_stat.aggr_mode,
1772 "aggregate counts per processor socket", AGGR_SOCKET),
1773 OPT_SET_UINT(0, "per-core", &perf_stat.aggr_mode,
1774 "aggregate counts per physical processor core", AGGR_CORE),
1775 OPT_SET_UINT('A', "no-aggr", &perf_stat.aggr_mode,
1776 "disable CPU count aggregation", AGGR_NONE),
1777 OPT_END()
1778 };
1779 struct stat st;
1780 int ret;
1781
1782 argc = parse_options(argc, argv, options, report_usage, 0);
1783
1784 if (!input_name || !strlen(input_name)) {
1785 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
1786 input_name = "-";
1787 else
1788 input_name = "perf.data";
1789 }
1790
1791 perf_stat.file.path = input_name;
1792 perf_stat.file.mode = PERF_DATA_MODE_READ;
1793
1794 session = perf_session__new(&perf_stat.file, false, &perf_stat.tool);
1795 if (session == NULL)
1796 return -1;
1797
1798 perf_stat.session = session;
1799 stat_config.output = stderr;
1800 evsel_list = session->evlist;
1801
1802 ret = perf_session__process_events(session);
1803 if (ret)
1804 return ret;
1805
1806 perf_session__delete(session);
1807 return 0;
1808}
1809
1239int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) 1810int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1240{ 1811{
1241 const char * const stat_usage[] = { 1812 const char * const stat_usage[] = {
@@ -1246,6 +1817,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1246 const char *mode; 1817 const char *mode;
1247 FILE *output = stderr; 1818 FILE *output = stderr;
1248 unsigned int interval; 1819 unsigned int interval;
1820 const char * const stat_subcommands[] = { "record", "report" };
1249 1821
1250 setlocale(LC_ALL, ""); 1822 setlocale(LC_ALL, "");
1251 1823
@@ -1253,12 +1825,30 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1253 if (evsel_list == NULL) 1825 if (evsel_list == NULL)
1254 return -ENOMEM; 1826 return -ENOMEM;
1255 1827
1256 argc = parse_options(argc, argv, stat_options, stat_usage, 1828 argc = parse_options_subcommand(argc, argv, stat_options, stat_subcommands,
1257 PARSE_OPT_STOP_AT_NON_OPTION); 1829 (const char **) stat_usage,
1830 PARSE_OPT_STOP_AT_NON_OPTION);
1831
1832 if (csv_sep) {
1833 csv_output = true;
1834 if (!strcmp(csv_sep, "\\t"))
1835 csv_sep = "\t";
1836 } else
1837 csv_sep = DEFAULT_SEPARATOR;
1838
1839 if (argc && !strncmp(argv[0], "rec", 3)) {
1840 argc = __cmd_record(argc, argv);
1841 if (argc < 0)
1842 return -1;
1843 } else if (argc && !strncmp(argv[0], "rep", 3))
1844 return __cmd_report(argc, argv);
1258 1845
1259 interval = stat_config.interval; 1846 interval = stat_config.interval;
1260 1847
1261 if (output_name && strcmp(output_name, "-")) 1848 /*
1849 * For record command the -o is already taken care of.
1850 */
1851 if (!STAT_RECORD && output_name && strcmp(output_name, "-"))
1262 output = NULL; 1852 output = NULL;
1263 1853
1264 if (output_name && output_fd) { 1854 if (output_name && output_fd) {
@@ -1296,13 +1886,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1296 1886
1297 stat_config.output = output; 1887 stat_config.output = output;
1298 1888
1299 if (csv_sep) {
1300 csv_output = true;
1301 if (!strcmp(csv_sep, "\\t"))
1302 csv_sep = "\t";
1303 } else
1304 csv_sep = DEFAULT_SEPARATOR;
1305
1306 /* 1889 /*
1307 * let the spreadsheet do the pretty-printing 1890 * let the spreadsheet do the pretty-printing
1308 */ 1891 */
@@ -1425,6 +2008,42 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1425 if (!forever && status != -1 && !interval) 2008 if (!forever && status != -1 && !interval)
1426 print_counters(NULL, argc, argv); 2009 print_counters(NULL, argc, argv);
1427 2010
2011 if (STAT_RECORD) {
2012 /*
2013 * We synthesize the kernel mmap record just so that older tools
2014 * don't emit warnings about not being able to resolve symbols
2015 * due to /proc/sys/kernel/kptr_restrict settings and instear provide
2016 * a saner message about no samples being in the perf.data file.
2017 *
2018 * This also serves to suppress a warning about f_header.data.size == 0
2019 * in header.c at the moment 'perf stat record' gets introduced, which
2020 * is not really needed once we start adding the stat specific PERF_RECORD_
2021 * records, but the need to suppress the kptr_restrict messages in older
2022 * tools remain -acme
2023 */
2024 int fd = perf_data_file__fd(&perf_stat.file);
2025 int err = perf_event__synthesize_kernel_mmap((void *)&perf_stat,
2026 process_synthesized_event,
2027 &perf_stat.session->machines.host);
2028 if (err) {
2029 pr_warning("Couldn't synthesize the kernel mmap record, harmless, "
2030 "older tools may produce warnings about this file\n.");
2031 }
2032
2033 if (!interval) {
2034 if (WRITE_STAT_ROUND_EVENT(walltime_nsecs_stats.max, FINAL))
2035 pr_err("failed to write stat round event\n");
2036 }
2037
2038 if (!perf_stat.file.is_pipe) {
2039 perf_stat.session->header.data_size += perf_stat.bytes_written;
2040 perf_session__write_header(perf_stat.session, evsel_list, fd, true);
2041 }
2042
2043 perf_session__delete(perf_stat.session);
2044 }
2045
2046 perf_stat__exit_aggr_mode();
1428 perf_evlist__free_stats(evsel_list); 2047 perf_evlist__free_stats(evsel_list);
1429out: 2048out:
1430 perf_evlist__delete(evsel_list); 2049 perf_evlist__delete(evsel_list);
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 30e59620179d..bd7a7757176f 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -30,7 +30,7 @@
30 30
31#include "perf.h" 31#include "perf.h"
32#include "util/header.h" 32#include "util/header.h"
33#include "util/parse-options.h" 33#include <subcmd/parse-options.h>
34#include "util/parse-events.h" 34#include "util/parse-events.h"
35#include "util/event.h" 35#include "util/event.h"
36#include "util/session.h" 36#include "util/session.h"
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 7e2e72e6d9d1..bf01cbb0ef23 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -34,7 +34,7 @@
34#include "util/top.h" 34#include "util/top.h"
35#include "util/util.h" 35#include "util/util.h"
36#include <linux/rbtree.h> 36#include <linux/rbtree.h>
37#include "util/parse-options.h" 37#include <subcmd/parse-options.h>
38#include "util/parse-events.h" 38#include "util/parse-events.h"
39#include "util/cpumap.h" 39#include "util/cpumap.h"
40#include "util/xyarray.h" 40#include "util/xyarray.h"
@@ -175,42 +175,40 @@ static void perf_top__record_precise_ip(struct perf_top *top,
175 int counter, u64 ip) 175 int counter, u64 ip)
176{ 176{
177 struct annotation *notes; 177 struct annotation *notes;
178 struct symbol *sym; 178 struct symbol *sym = he->ms.sym;
179 int err = 0; 179 int err = 0;
180 180
181 if (he == NULL || he->ms.sym == NULL || 181 if (sym == NULL || (use_browser == 0 &&
182 ((top->sym_filter_entry == NULL || 182 (top->sym_filter_entry == NULL ||
183 top->sym_filter_entry->ms.sym != he->ms.sym) && use_browser != 1)) 183 top->sym_filter_entry->ms.sym != sym)))
184 return; 184 return;
185 185
186 sym = he->ms.sym;
187 notes = symbol__annotation(sym); 186 notes = symbol__annotation(sym);
188 187
189 if (pthread_mutex_trylock(&notes->lock)) 188 if (pthread_mutex_trylock(&notes->lock))
190 return; 189 return;
191 190
192 ip = he->ms.map->map_ip(he->ms.map, ip); 191 err = hist_entry__inc_addr_samples(he, counter, ip);
193
194 if (ui__has_annotation())
195 err = hist_entry__inc_addr_samples(he, counter, ip);
196 192
197 pthread_mutex_unlock(&notes->lock); 193 pthread_mutex_unlock(&notes->lock);
198 194
199 /* 195 if (unlikely(err)) {
200 * This function is now called with he->hists->lock held. 196 /*
201 * Release it before going to sleep. 197 * This function is now called with he->hists->lock held.
202 */ 198 * Release it before going to sleep.
203 pthread_mutex_unlock(&he->hists->lock); 199 */
200 pthread_mutex_unlock(&he->hists->lock);
201
202 if (err == -ERANGE && !he->ms.map->erange_warned)
203 ui__warn_map_erange(he->ms.map, sym, ip);
204 else if (err == -ENOMEM) {
205 pr_err("Not enough memory for annotating '%s' symbol!\n",
206 sym->name);
207 sleep(1);
208 }
204 209
205 if (err == -ERANGE && !he->ms.map->erange_warned) 210 pthread_mutex_lock(&he->hists->lock);
206 ui__warn_map_erange(he->ms.map, sym, ip);
207 else if (err == -ENOMEM) {
208 pr_err("Not enough memory for annotating '%s' symbol!\n",
209 sym->name);
210 sleep(1);
211 } 211 }
212
213 pthread_mutex_lock(&he->hists->lock);
214} 212}
215 213
216static void perf_top__show_details(struct perf_top *top) 214static void perf_top__show_details(struct perf_top *top)
@@ -687,14 +685,8 @@ static int hist_iter__top_callback(struct hist_entry_iter *iter,
687 struct hist_entry *he = iter->he; 685 struct hist_entry *he = iter->he;
688 struct perf_evsel *evsel = iter->evsel; 686 struct perf_evsel *evsel = iter->evsel;
689 687
690 if (sort__has_sym && single) { 688 if (sort__has_sym && single)
691 u64 ip = al->addr; 689 perf_top__record_precise_ip(top, he, evsel->idx, al->addr);
692
693 if (al->map)
694 ip = al->map->unmap_ip(al->map, ip);
695
696 perf_top__record_precise_ip(top, he, evsel->idx, ip);
697 }
698 690
699 hist__account_cycles(iter->sample->branch_stack, al, iter->sample, 691 hist__account_cycles(iter->sample->branch_stack, al, iter->sample,
700 !(top->record_opts.branch_stack & PERF_SAMPLE_BRANCH_ANY)); 692 !(top->record_opts.branch_stack & PERF_SAMPLE_BRANCH_ANY));
@@ -964,7 +956,7 @@ static int __cmd_top(struct perf_top *top)
964 if (ret) 956 if (ret)
965 goto out_delete; 957 goto out_delete;
966 958
967 if (perf_session__register_idle_thread(top->session) == NULL) 959 if (perf_session__register_idle_thread(top->session) < 0)
968 goto out_delete; 960 goto out_delete;
969 961
970 machine__synthesize_threads(&top->session->machines.host, &opts->target, 962 machine__synthesize_threads(&top->session->machines.host, &opts->target,
@@ -1218,6 +1210,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1218 OPT_CALLBACK('j', "branch-filter", &opts->branch_stack, 1210 OPT_CALLBACK('j', "branch-filter", &opts->branch_stack,
1219 "branch filter mask", "branch stack filter modes", 1211 "branch filter mask", "branch stack filter modes",
1220 parse_branch_stack), 1212 parse_branch_stack),
1213 OPT_BOOLEAN(0, "raw-trace", &symbol_conf.raw_trace,
1214 "Show raw trace event output (do not use print fmt or plugins)"),
1221 OPT_END() 1215 OPT_END()
1222 }; 1216 };
1223 const char * const top_usage[] = { 1217 const char * const top_usage[] = {
@@ -1239,11 +1233,17 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1239 if (argc) 1233 if (argc)
1240 usage_with_options(top_usage, options); 1234 usage_with_options(top_usage, options);
1241 1235
1236 if (!top.evlist->nr_entries &&
1237 perf_evlist__add_default(top.evlist) < 0) {
1238 pr_err("Not enough memory for event selector list\n");
1239 goto out_delete_evlist;
1240 }
1241
1242 sort__mode = SORT_MODE__TOP; 1242 sort__mode = SORT_MODE__TOP;
1243 /* display thread wants entries to be collapsed in a different tree */ 1243 /* display thread wants entries to be collapsed in a different tree */
1244 sort__need_collapse = 1; 1244 sort__need_collapse = 1;
1245 1245
1246 if (setup_sorting() < 0) { 1246 if (setup_sorting(top.evlist) < 0) {
1247 if (sort_order) 1247 if (sort_order)
1248 parse_options_usage(top_usage, options, "s", 1); 1248 parse_options_usage(top_usage, options, "s", 1);
1249 if (field_order) 1249 if (field_order)
@@ -1279,12 +1279,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1279 if (target__none(target)) 1279 if (target__none(target))
1280 target->system_wide = true; 1280 target->system_wide = true;
1281 1281
1282 if (perf_evlist__create_maps(top.evlist, target) < 0) 1282 if (perf_evlist__create_maps(top.evlist, target) < 0) {
1283 usage_with_options(top_usage, options); 1283 ui__error("Couldn't create thread/CPU maps: %s\n",
1284 1284 errno == ENOENT ? "No such process" : strerror_r(errno, errbuf, sizeof(errbuf)));
1285 if (!top.evlist->nr_entries &&
1286 perf_evlist__add_default(top.evlist) < 0) {
1287 ui__error("Not enough memory for event selector list\n");
1288 goto out_delete_evlist; 1285 goto out_delete_evlist;
1289 } 1286 }
1290 1287
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index c783d8fd3a80..20916dd77aac 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -22,11 +22,11 @@
22#include "util/color.h" 22#include "util/color.h"
23#include "util/debug.h" 23#include "util/debug.h"
24#include "util/evlist.h" 24#include "util/evlist.h"
25#include "util/exec_cmd.h" 25#include <subcmd/exec-cmd.h>
26#include "util/machine.h" 26#include "util/machine.h"
27#include "util/session.h" 27#include "util/session.h"
28#include "util/thread.h" 28#include "util/thread.h"
29#include "util/parse-options.h" 29#include <subcmd/parse-options.h>
30#include "util/strlist.h" 30#include "util/strlist.h"
31#include "util/intlist.h" 31#include "util/intlist.h"
32#include "util/thread_map.h" 32#include "util/thread_map.h"
diff --git a/tools/perf/builtin-version.c b/tools/perf/builtin-version.c
new file mode 100644
index 000000000000..9b10cda6b6dc
--- /dev/null
+++ b/tools/perf/builtin-version.c
@@ -0,0 +1,10 @@
1#include "util/util.h"
2#include "builtin.h"
3#include "perf.h"
4
5int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused,
6 const char *prefix __maybe_unused)
7{
8 printf("perf version %s\n", perf_version_string);
9 return 0;
10}
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 3688ad29085f..3f871b54e261 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -17,6 +17,7 @@ extern int cmd_annotate(int argc, const char **argv, const char *prefix);
17extern int cmd_bench(int argc, const char **argv, const char *prefix); 17extern int cmd_bench(int argc, const char **argv, const char *prefix);
18extern int cmd_buildid_cache(int argc, const char **argv, const char *prefix); 18extern int cmd_buildid_cache(int argc, const char **argv, const char *prefix);
19extern int cmd_buildid_list(int argc, const char **argv, const char *prefix); 19extern int cmd_buildid_list(int argc, const char **argv, const char *prefix);
20extern int cmd_config(int argc, const char **argv, const char *prefix);
20extern int cmd_diff(int argc, const char **argv, const char *prefix); 21extern int cmd_diff(int argc, const char **argv, const char *prefix);
21extern int cmd_evlist(int argc, const char **argv, const char *prefix); 22extern int cmd_evlist(int argc, const char **argv, const char *prefix);
22extern int cmd_help(int argc, const char **argv, const char *prefix); 23extern int cmd_help(int argc, const char **argv, const char *prefix);
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 00fcaf8a5b8d..ab5cbaa170d0 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-config mainporcelain common
12perf-evlist mainporcelain common 13perf-evlist mainporcelain common
13perf-inject mainporcelain common 14perf-inject mainporcelain common
14perf-kmem mainporcelain common 15perf-kmem mainporcelain common
@@ -25,4 +26,4 @@ perf-stat mainporcelain common
25perf-test mainporcelain common 26perf-test mainporcelain common
26perf-timechart mainporcelain common 27perf-timechart mainporcelain common
27perf-top mainporcelain common 28perf-top mainporcelain common
28perf-trace mainporcelain common 29perf-trace mainporcelain audit
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index de89ec574361..254d06e39bea 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -135,8 +135,6 @@ endif
135 135
136ifeq ($(DEBUG),0) 136ifeq ($(DEBUG),0)
137 CFLAGS += -O6 137 CFLAGS += -O6
138else
139 CFLAGS += $(call cc-option,-Og,-O0)
140endif 138endif
141 139
142ifdef PARSER_DEBUG 140ifdef PARSER_DEBUG
@@ -318,6 +316,18 @@ ifndef NO_LIBELF
318 CFLAGS += -DHAVE_LIBBPF_SUPPORT 316 CFLAGS += -DHAVE_LIBBPF_SUPPORT
319 $(call detected,CONFIG_LIBBPF) 317 $(call detected,CONFIG_LIBBPF)
320 endif 318 endif
319
320 ifndef NO_DWARF
321 ifdef PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
322 CFLAGS += -DHAVE_BPF_PROLOGUE
323 $(call detected,CONFIG_BPF_PROLOGUE)
324 else
325 msg := $(warning BPF prologue is not supported by architecture $(ARCH), missing regs_query_register_offset());
326 endif
327 else
328 msg := $(warning DWARF support is off, BPF prologue is disabled);
329 endif
330
321 endif # NO_LIBBPF 331 endif # NO_LIBBPF
322endif # NO_LIBELF 332endif # NO_LIBELF
323 333
@@ -681,6 +691,7 @@ sharedir = $(prefix)/share
681template_dir = share/perf-core/templates 691template_dir = share/perf-core/templates
682STRACE_GROUPS_DIR = share/perf-core/strace/groups 692STRACE_GROUPS_DIR = share/perf-core/strace/groups
683htmldir = share/doc/perf-doc 693htmldir = share/doc/perf-doc
694tipdir = share/doc/perf-tip
684ifeq ($(prefix),/usr) 695ifeq ($(prefix),/usr)
685sysconfdir = /etc 696sysconfdir = /etc
686ETC_PERFCONFIG = $(sysconfdir)/perfconfig 697ETC_PERFCONFIG = $(sysconfdir)/perfconfig
@@ -707,6 +718,7 @@ infodir_SQ = $(subst ','\'',$(infodir))
707perfexecdir_SQ = $(subst ','\'',$(perfexecdir)) 718perfexecdir_SQ = $(subst ','\'',$(perfexecdir))
708template_dir_SQ = $(subst ','\'',$(template_dir)) 719template_dir_SQ = $(subst ','\'',$(template_dir))
709htmldir_SQ = $(subst ','\'',$(htmldir)) 720htmldir_SQ = $(subst ','\'',$(htmldir))
721tipdir_SQ = $(subst ','\'',$(tipdir))
710prefix_SQ = $(subst ','\'',$(prefix)) 722prefix_SQ = $(subst ','\'',$(prefix))
711sysconfdir_SQ = $(subst ','\'',$(sysconfdir)) 723sysconfdir_SQ = $(subst ','\'',$(sysconfdir))
712libdir_SQ = $(subst ','\'',$(libdir)) 724libdir_SQ = $(subst ','\'',$(libdir))
@@ -714,12 +726,15 @@ libdir_SQ = $(subst ','\'',$(libdir))
714ifneq ($(filter /%,$(firstword $(perfexecdir))),) 726ifneq ($(filter /%,$(firstword $(perfexecdir))),)
715perfexec_instdir = $(perfexecdir) 727perfexec_instdir = $(perfexecdir)
716STRACE_GROUPS_INSTDIR = $(STRACE_GROUPS_DIR) 728STRACE_GROUPS_INSTDIR = $(STRACE_GROUPS_DIR)
729tip_instdir = $(tipdir)
717else 730else
718perfexec_instdir = $(prefix)/$(perfexecdir) 731perfexec_instdir = $(prefix)/$(perfexecdir)
719STRACE_GROUPS_INSTDIR = $(prefix)/$(STRACE_GROUPS_DIR) 732STRACE_GROUPS_INSTDIR = $(prefix)/$(STRACE_GROUPS_DIR)
733tip_instdir = $(prefix)/$(tipdir)
720endif 734endif
721perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir)) 735perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir))
722STRACE_GROUPS_INSTDIR_SQ = $(subst ','\'',$(STRACE_GROUPS_INSTDIR)) 736STRACE_GROUPS_INSTDIR_SQ = $(subst ','\'',$(STRACE_GROUPS_INSTDIR))
737tip_instdir_SQ = $(subst ','\'',$(tip_instdir))
723 738
724# If we install to $(HOME) we keep the traceevent default: 739# If we install to $(HOME) we keep the traceevent default:
725# $(HOME)/.traceevent/plugins 740# $(HOME)/.traceevent/plugins
@@ -741,6 +756,10 @@ ifeq ($(VF),1)
741 $(call print_var,sysconfdir) 756 $(call print_var,sysconfdir)
742 $(call print_var,LIBUNWIND_DIR) 757 $(call print_var,LIBUNWIND_DIR)
743 $(call print_var,LIBDW_DIR) 758 $(call print_var,LIBDW_DIR)
759
760 ifeq ($(dwarf-post-unwind),1)
761 $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
762 endif
744 $(info ) 763 $(info )
745endif 764endif
746 765
@@ -756,6 +775,7 @@ $(call detected_var,ETC_PERFCONFIG_SQ)
756$(call detected_var,STRACE_GROUPS_DIR_SQ) 775$(call detected_var,STRACE_GROUPS_DIR_SQ)
757$(call detected_var,prefix_SQ) 776$(call detected_var,prefix_SQ)
758$(call detected_var,perfexecdir_SQ) 777$(call detected_var,perfexecdir_SQ)
778$(call detected_var,tipdir_SQ)
759$(call detected_var,LIBDIR) 779$(call detected_var,LIBDIR)
760$(call detected_var,GTK_CFLAGS) 780$(call detected_var,GTK_CFLAGS)
761$(call detected_var,PERL_EMBED_CCOPTS) 781$(call detected_var,PERL_EMBED_CCOPTS)
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
index 0ebef09c0842..c16ce833079c 100644
--- a/tools/perf/config/utilities.mak
+++ b/tools/perf/config/utilities.mak
@@ -177,22 +177,3 @@ $(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2)))
177endef 177endef
178_ge_attempt = $(if $(get-executable),$(get-executable),$(call _gea_err,$(2))) 178_ge_attempt = $(if $(get-executable),$(get-executable),$(call _gea_err,$(2)))
179_gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) 179_gea_err = $(if $(1),$(error Please set '$(1)' appropriately))
180
181# try-run
182# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
183# Exit code chooses option. "$$TMP" is can be used as temporary file and
184# is automatically cleaned up.
185try-run = $(shell set -e; \
186 TMP="$(TMPOUT).$$$$.tmp"; \
187 TMPO="$(TMPOUT).$$$$.o"; \
188 if ($(1)) >/dev/null 2>&1; \
189 then echo "$(2)"; \
190 else echo "$(3)"; \
191 fi; \
192 rm -f "$$TMP" "$$TMPO")
193
194# cc-option
195# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
196
197cc-option = $(call try-run,\
198 $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 3d4c7c09adea..a929618b8eb6 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -9,16 +9,18 @@
9#include "builtin.h" 9#include "builtin.h"
10 10
11#include "util/env.h" 11#include "util/env.h"
12#include "util/exec_cmd.h" 12#include <subcmd/exec-cmd.h>
13#include "util/cache.h" 13#include "util/cache.h"
14#include "util/quote.h" 14#include "util/quote.h"
15#include "util/run-command.h" 15#include <subcmd/run-command.h>
16#include "util/parse-events.h" 16#include "util/parse-events.h"
17#include "util/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 <api/fs/tracing_path.h> 20#include <api/fs/tracing_path.h>
21#include <pthread.h> 21#include <pthread.h>
22#include <stdlib.h>
23#include <time.h>
22 24
23const char perf_usage_string[] = 25const char perf_usage_string[] =
24 "perf [--version] [--help] [OPTIONS] COMMAND [ARGS]"; 26 "perf [--version] [--help] [OPTIONS] COMMAND [ARGS]";
@@ -39,6 +41,7 @@ struct cmd_struct {
39static struct cmd_struct commands[] = { 41static struct cmd_struct commands[] = {
40 { "buildid-cache", cmd_buildid_cache, 0 }, 42 { "buildid-cache", cmd_buildid_cache, 0 },
41 { "buildid-list", cmd_buildid_list, 0 }, 43 { "buildid-list", cmd_buildid_list, 0 },
44 { "config", cmd_config, 0 },
42 { "diff", cmd_diff, 0 }, 45 { "diff", cmd_diff, 0 },
43 { "evlist", cmd_evlist, 0 }, 46 { "evlist", cmd_evlist, 0 },
44 { "help", cmd_help, 0 }, 47 { "help", cmd_help, 0 },
@@ -118,7 +121,7 @@ static void commit_pager_choice(void)
118{ 121{
119 switch (use_pager) { 122 switch (use_pager) {
120 case 0: 123 case 0:
121 setenv("PERF_PAGER", "cat", 1); 124 setenv(PERF_PAGER_ENVIRONMENT, "cat", 1);
122 break; 125 break;
123 case 1: 126 case 1:
124 /* setup_pager(); */ 127 /* setup_pager(); */
@@ -182,9 +185,9 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
182 if (!prefixcmp(cmd, CMD_EXEC_PATH)) { 185 if (!prefixcmp(cmd, CMD_EXEC_PATH)) {
183 cmd += strlen(CMD_EXEC_PATH); 186 cmd += strlen(CMD_EXEC_PATH);
184 if (*cmd == '=') 187 if (*cmd == '=')
185 perf_set_argv_exec_path(cmd + 1); 188 set_argv_exec_path(cmd + 1);
186 else { 189 else {
187 puts(perf_exec_path()); 190 puts(get_argv_exec_path());
188 exit(0); 191 exit(0);
189 } 192 }
190 } else if (!strcmp(cmd, "--html-path")) { 193 } else if (!strcmp(cmd, "--html-path")) {
@@ -383,6 +386,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
383 use_pager = 1; 386 use_pager = 1;
384 commit_pager_choice(); 387 commit_pager_choice();
385 388
389 perf_env__set_cmdline(&perf_env, argc, argv);
386 status = p->fn(argc, argv, prefix); 390 status = p->fn(argc, argv, prefix);
387 exit_browser(status); 391 exit_browser(status);
388 perf_env__exit(&perf_env); 392 perf_env__exit(&perf_env);
@@ -528,14 +532,20 @@ int main(int argc, const char **argv)
528 const char *cmd; 532 const char *cmd;
529 char sbuf[STRERR_BUFSIZE]; 533 char sbuf[STRERR_BUFSIZE];
530 534
535 /* libsubcmd init */
536 exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT);
537 pager_init(PERF_PAGER_ENVIRONMENT);
538
531 /* The page_size is placed in util object. */ 539 /* The page_size is placed in util object. */
532 page_size = sysconf(_SC_PAGE_SIZE); 540 page_size = sysconf(_SC_PAGE_SIZE);
533 cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); 541 cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
534 542
535 cmd = perf_extract_argv0_path(argv[0]); 543 cmd = extract_argv0_path(argv[0]);
536 if (!cmd) 544 if (!cmd)
537 cmd = "perf-help"; 545 cmd = "perf-help";
538 546
547 srandom(time(NULL));
548
539 /* get debugfs/tracefs mount point from /proc/mounts */ 549 /* get debugfs/tracefs mount point from /proc/mounts */
540 tracing_path_mount(); 550 tracing_path_mount();
541 551
diff --git a/tools/perf/scripts/python/stat-cpi.py b/tools/perf/scripts/python/stat-cpi.py
new file mode 100644
index 000000000000..8b60f343dd07
--- /dev/null
+++ b/tools/perf/scripts/python/stat-cpi.py
@@ -0,0 +1,77 @@
1#!/usr/bin/env python
2
3data = {}
4times = []
5threads = []
6cpus = []
7
8def get_key(time, event, cpu, thread):
9 return "%d-%s-%d-%d" % (time, event, cpu, thread)
10
11def store_key(time, cpu, thread):
12 if (time not in times):
13 times.append(time)
14
15 if (cpu not in cpus):
16 cpus.append(cpu)
17
18 if (thread not in threads):
19 threads.append(thread)
20
21def store(time, event, cpu, thread, val, ena, run):
22 #print "event %s cpu %d, thread %d, time %d, val %d, ena %d, run %d" % \
23 # (event, cpu, thread, time, val, ena, run)
24
25 store_key(time, cpu, thread)
26 key = get_key(time, event, cpu, thread)
27 data[key] = [ val, ena, run]
28
29def get(time, event, cpu, thread):
30 key = get_key(time, event, cpu, thread)
31 return data[key][0]
32
33def stat__cycles_k(cpu, thread, time, val, ena, run):
34 store(time, "cycles", cpu, thread, val, ena, run);
35
36def stat__instructions_k(cpu, thread, time, val, ena, run):
37 store(time, "instructions", cpu, thread, val, ena, run);
38
39def stat__cycles_u(cpu, thread, time, val, ena, run):
40 store(time, "cycles", cpu, thread, val, ena, run);
41
42def stat__instructions_u(cpu, thread, time, val, ena, run):
43 store(time, "instructions", cpu, thread, val, ena, run);
44
45def stat__cycles(cpu, thread, time, val, ena, run):
46 store(time, "cycles", cpu, thread, val, ena, run);
47
48def stat__instructions(cpu, thread, time, val, ena, run):
49 store(time, "instructions", cpu, thread, val, ena, run);
50
51def stat__interval(time):
52 for cpu in cpus:
53 for thread in threads:
54 cyc = get(time, "cycles", cpu, thread)
55 ins = get(time, "instructions", cpu, thread)
56 cpi = 0
57
58 if ins != 0:
59 cpi = cyc/float(ins)
60
61 print "%15f: cpu %d, thread %d -> cpi %f (%d/%d)" % (time/(float(1000000000)), cpu, thread, cpi, cyc, ins)
62
63def trace_end():
64 pass
65# XXX trace_end callback could be used as an alternative place
66# to compute same values as in the script above:
67#
68# for time in times:
69# for cpu in cpus:
70# for thread in threads:
71# cyc = get(time, "cycles", cpu, thread)
72# ins = get(time, "instructions", cpu, thread)
73#
74# if ins != 0:
75# cpi = cyc/float(ins)
76#
77# print "time %.9f, cpu %d, thread %d -> cpi %f" % (time/(float(1000000000)), cpu, thread, cpi)
diff --git a/tools/perf/tests/.gitignore b/tools/perf/tests/.gitignore
index 489fc9ffbcb0..bf016c439fbd 100644
--- a/tools/perf/tests/.gitignore
+++ b/tools/perf/tests/.gitignore
@@ -1,2 +1,3 @@
1llvm-src-base.c 1llvm-src-base.c
2llvm-src-kbuild.c 2llvm-src-kbuild.c
3llvm-src-prologue.c
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index f41ebf8849fe..614899b88b37 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -31,24 +31,34 @@ perf-y += sample-parsing.o
31perf-y += parse-no-sample-id-all.o 31perf-y += parse-no-sample-id-all.o
32perf-y += kmod-path.o 32perf-y += kmod-path.o
33perf-y += thread-map.o 33perf-y += thread-map.o
34perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o 34perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o llvm-src-prologue.o
35perf-y += bpf.o 35perf-y += bpf.o
36perf-y += topology.o 36perf-y += topology.o
37perf-y += cpumap.o
38perf-y += stat.o
39perf-y += event_update.o
37 40
38$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c 41$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
39 $(call rule_mkdir) 42 $(call rule_mkdir)
40 $(Q)echo '#include <tests/llvm.h>' > $@ 43 $(Q)echo '#include <tests/llvm.h>' > $@
41 $(Q)echo 'const char test_llvm__bpf_base_prog[] =' >> $@ 44 $(Q)echo 'const char test_llvm__bpf_base_prog[] =' >> $@
42 $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@ 45 $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
43 $(Q)echo ';' >> $@ 46 $(Q)echo ';' >> $@
44 47
45$(OUTPUT)tests/llvm-src-kbuild.c: tests/bpf-script-test-kbuild.c 48$(OUTPUT)tests/llvm-src-kbuild.c: tests/bpf-script-test-kbuild.c tests/Build
46 $(call rule_mkdir) 49 $(call rule_mkdir)
47 $(Q)echo '#include <tests/llvm.h>' > $@ 50 $(Q)echo '#include <tests/llvm.h>' > $@
48 $(Q)echo 'const char test_llvm__bpf_test_kbuild_prog[] =' >> $@ 51 $(Q)echo 'const char test_llvm__bpf_test_kbuild_prog[] =' >> $@
49 $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@ 52 $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
50 $(Q)echo ';' >> $@ 53 $(Q)echo ';' >> $@
51 54
55$(OUTPUT)tests/llvm-src-prologue.c: tests/bpf-script-test-prologue.c tests/Build
56 $(call rule_mkdir)
57 $(Q)echo '#include <tests/llvm.h>' > $@
58 $(Q)echo 'const char test_llvm__bpf_test_prologue_prog[] =' >> $@
59 $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
60 $(Q)echo ';' >> $@
61
52ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64)) 62ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64))
53perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o 63perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
54endif 64endif
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c
index 638875a0960a..28d1605b0338 100644
--- a/tools/perf/tests/attr.c
+++ b/tools/perf/tests/attr.c
@@ -24,7 +24,7 @@
24#include <linux/kernel.h> 24#include <linux/kernel.h>
25#include "../perf.h" 25#include "../perf.h"
26#include "util.h" 26#include "util.h"
27#include "exec_cmd.h" 27#include <subcmd/exec-cmd.h>
28#include "tests.h" 28#include "tests.h"
29 29
30#define ENV "PERF_TEST_ATTR" 30#define ENV "PERF_TEST_ATTR"
@@ -153,7 +153,7 @@ static int run_dir(const char *d, const char *perf)
153 return system(cmd); 153 return system(cmd);
154} 154}
155 155
156int test__attr(void) 156int test__attr(int subtest __maybe_unused)
157{ 157{
158 struct stat st; 158 struct stat st;
159 char path_perf[PATH_MAX]; 159 char path_perf[PATH_MAX];
@@ -164,7 +164,7 @@ int test__attr(void)
164 return run_dir("./tests", "./perf"); 164 return run_dir("./tests", "./perf");
165 165
166 /* Then installed path. */ 166 /* Then installed path. */
167 snprintf(path_dir, PATH_MAX, "%s/tests", perf_exec_path()); 167 snprintf(path_dir, PATH_MAX, "%s/tests", get_argv_exec_path());
168 snprintf(path_perf, PATH_MAX, "%s/perf", BINDIR); 168 snprintf(path_perf, PATH_MAX, "%s/perf", BINDIR);
169 169
170 if (!lstat(path_dir, &st) && 170 if (!lstat(path_dir, &st) &&
diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c
index a02b035fd5aa..fb80c9eb6a95 100644
--- a/tools/perf/tests/bp_signal.c
+++ b/tools/perf/tests/bp_signal.c
@@ -111,7 +111,7 @@ static long long bp_count(int fd)
111 return count; 111 return count;
112} 112}
113 113
114int test__bp_signal(void) 114int test__bp_signal(int subtest __maybe_unused)
115{ 115{
116 struct sigaction sa; 116 struct sigaction sa;
117 long long count1, count2; 117 long long count1, count2;
diff --git a/tools/perf/tests/bp_signal_overflow.c b/tools/perf/tests/bp_signal_overflow.c
index e76537724491..89f92fa67cc4 100644
--- a/tools/perf/tests/bp_signal_overflow.c
+++ b/tools/perf/tests/bp_signal_overflow.c
@@ -58,7 +58,7 @@ static long long bp_count(int fd)
58#define EXECUTIONS 10000 58#define EXECUTIONS 10000
59#define THRESHOLD 100 59#define THRESHOLD 100
60 60
61int test__bp_signal_overflow(void) 61int test__bp_signal_overflow(int subtest __maybe_unused)
62{ 62{
63 struct perf_event_attr pe; 63 struct perf_event_attr pe;
64 struct sigaction sa; 64 struct sigaction sa;
diff --git a/tools/perf/tests/bpf-script-test-prologue.c b/tools/perf/tests/bpf-script-test-prologue.c
new file mode 100644
index 000000000000..7230e62c70fc
--- /dev/null
+++ b/tools/perf/tests/bpf-script-test-prologue.c
@@ -0,0 +1,35 @@
1/*
2 * bpf-script-test-prologue.c
3 * Test BPF prologue
4 */
5#ifndef LINUX_VERSION_CODE
6# error Need LINUX_VERSION_CODE
7# error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig'
8#endif
9#define SEC(NAME) __attribute__((section(NAME), used))
10
11#include <uapi/linux/fs.h>
12
13#define FMODE_READ 0x1
14#define FMODE_WRITE 0x2
15
16static void (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
17 (void *) 6;
18
19SEC("func=null_lseek file->f_mode offset orig")
20int bpf_func__null_lseek(void *ctx, int err, unsigned long f_mode,
21 unsigned long offset, unsigned long orig)
22{
23 if (err)
24 return 0;
25 if (f_mode & FMODE_WRITE)
26 return 0;
27 if (offset & 1)
28 return 0;
29 if (orig == SEEK_CUR)
30 return 0;
31 return 1;
32}
33
34char _license[] SEC("license") = "GPL";
35int _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index ec16f7812c8b..33689a0cf821 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -19,6 +19,29 @@ static int epoll_pwait_loop(void)
19 return 0; 19 return 0;
20} 20}
21 21
22#ifdef HAVE_BPF_PROLOGUE
23
24static int llseek_loop(void)
25{
26 int fds[2], i;
27
28 fds[0] = open("/dev/null", O_RDONLY);
29 fds[1] = open("/dev/null", O_RDWR);
30
31 if (fds[0] < 0 || fds[1] < 0)
32 return -1;
33
34 for (i = 0; i < NR_ITERS; i++) {
35 lseek(fds[i % 2], i, (i / 2) % 2 ? SEEK_CUR : SEEK_SET);
36 lseek(fds[(i + 1) % 2], i, (i / 2) % 2 ? SEEK_CUR : SEEK_SET);
37 }
38 close(fds[0]);
39 close(fds[1]);
40 return 0;
41}
42
43#endif
44
22static struct { 45static struct {
23 enum test_llvm__testcase prog_id; 46 enum test_llvm__testcase prog_id;
24 const char *desc; 47 const char *desc;
@@ -37,6 +60,17 @@ static struct {
37 &epoll_pwait_loop, 60 &epoll_pwait_loop,
38 (NR_ITERS + 1) / 2, 61 (NR_ITERS + 1) / 2,
39 }, 62 },
63#ifdef HAVE_BPF_PROLOGUE
64 {
65 LLVM_TESTCASE_BPF_PROLOGUE,
66 "Test BPF prologue generation",
67 "[bpf_prologue_test]",
68 "fix kbuild first",
69 "check your vmlinux setting?",
70 &llseek_loop,
71 (NR_ITERS + 1) / 4,
72 },
73#endif
40}; 74};
41 75
42static int do_test(struct bpf_object *obj, int (*func)(void), 76static int do_test(struct bpf_object *obj, int (*func)(void),
@@ -68,8 +102,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
68 err = parse_events_load_bpf_obj(&parse_evlist, &parse_evlist.list, obj); 102 err = parse_events_load_bpf_obj(&parse_evlist, &parse_evlist.list, obj);
69 if (err || list_empty(&parse_evlist.list)) { 103 if (err || list_empty(&parse_evlist.list)) {
70 pr_debug("Failed to add events selected by BPF\n"); 104 pr_debug("Failed to add events selected by BPF\n");
71 if (!err) 105 return TEST_FAIL;
72 return TEST_FAIL;
73 } 106 }
74 107
75 snprintf(pid, sizeof(pid), "%d", getpid()); 108 snprintf(pid, sizeof(pid), "%d", getpid());
@@ -123,8 +156,10 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
123 } 156 }
124 } 157 }
125 158
126 if (count != expect) 159 if (count != expect) {
127 pr_debug("BPF filter result incorrect\n"); 160 pr_debug("BPF filter result incorrect\n");
161 goto out_delete_evlist;
162 }
128 163
129 ret = TEST_OK; 164 ret = TEST_OK;
130 165
@@ -146,7 +181,7 @@ prepare_bpf(void *obj_buf, size_t obj_buf_sz, const char *name)
146 return obj; 181 return obj;
147} 182}
148 183
149static int __test__bpf(int index) 184static int __test__bpf(int idx)
150{ 185{
151 int ret; 186 int ret;
152 void *obj_buf; 187 void *obj_buf;
@@ -154,54 +189,72 @@ static int __test__bpf(int index)
154 struct bpf_object *obj; 189 struct bpf_object *obj;
155 190
156 ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz, 191 ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
157 bpf_testcase_table[index].prog_id, 192 bpf_testcase_table[idx].prog_id,
158 true); 193 true);
159 if (ret != TEST_OK || !obj_buf || !obj_buf_sz) { 194 if (ret != TEST_OK || !obj_buf || !obj_buf_sz) {
160 pr_debug("Unable to get BPF object, %s\n", 195 pr_debug("Unable to get BPF object, %s\n",
161 bpf_testcase_table[index].msg_compile_fail); 196 bpf_testcase_table[idx].msg_compile_fail);
162 if (index == 0) 197 if (idx == 0)
163 return TEST_SKIP; 198 return TEST_SKIP;
164 else 199 else
165 return TEST_FAIL; 200 return TEST_FAIL;
166 } 201 }
167 202
168 obj = prepare_bpf(obj_buf, obj_buf_sz, 203 obj = prepare_bpf(obj_buf, obj_buf_sz,
169 bpf_testcase_table[index].name); 204 bpf_testcase_table[idx].name);
170 if (!obj) { 205 if (!obj) {
171 ret = TEST_FAIL; 206 ret = TEST_FAIL;
172 goto out; 207 goto out;
173 } 208 }
174 209
175 ret = do_test(obj, 210 ret = do_test(obj,
176 bpf_testcase_table[index].target_func, 211 bpf_testcase_table[idx].target_func,
177 bpf_testcase_table[index].expect_result); 212 bpf_testcase_table[idx].expect_result);
178out: 213out:
179 bpf__clear(); 214 bpf__clear();
180 return ret; 215 return ret;
181} 216}
182 217
183int test__bpf(void) 218int test__bpf_subtest_get_nr(void)
219{
220 return (int)ARRAY_SIZE(bpf_testcase_table);
221}
222
223const char *test__bpf_subtest_get_desc(int i)
224{
225 if (i < 0 || i >= (int)ARRAY_SIZE(bpf_testcase_table))
226 return NULL;
227 return bpf_testcase_table[i].desc;
228}
229
230int test__bpf(int i)
184{ 231{
185 unsigned int i;
186 int err; 232 int err;
187 233
234 if (i < 0 || i >= (int)ARRAY_SIZE(bpf_testcase_table))
235 return TEST_FAIL;
236
188 if (geteuid() != 0) { 237 if (geteuid() != 0) {
189 pr_debug("Only root can run BPF test\n"); 238 pr_debug("Only root can run BPF test\n");
190 return TEST_SKIP; 239 return TEST_SKIP;
191 } 240 }
192 241
193 for (i = 0; i < ARRAY_SIZE(bpf_testcase_table); i++) { 242 err = __test__bpf(i);
194 err = __test__bpf(i); 243 return err;
244}
195 245
196 if (err != TEST_OK) 246#else
197 return err; 247int test__bpf_subtest_get_nr(void)
198 } 248{
249 return 0;
250}
199 251
200 return TEST_OK; 252const char *test__bpf_subtest_get_desc(int i __maybe_unused)
253{
254 return NULL;
201} 255}
202 256
203#else 257int test__bpf(int i __maybe_unused)
204int test__bpf(void)
205{ 258{
206 pr_debug("Skip BPF test because BPF support is not compiled\n"); 259 pr_debug("Skip BPF test because BPF support is not compiled\n");
207 return TEST_SKIP; 260 return TEST_SKIP;
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 80c442eab767..f2b1dcac45d3 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -11,7 +11,7 @@
11#include "tests.h" 11#include "tests.h"
12#include "debug.h" 12#include "debug.h"
13#include "color.h" 13#include "color.h"
14#include "parse-options.h" 14#include <subcmd/parse-options.h>
15#include "symbol.h" 15#include "symbol.h"
16 16
17struct test __weak arch_tests[] = { 17struct test __weak arch_tests[] = {
@@ -160,6 +160,11 @@ static struct test generic_tests[] = {
160 { 160 {
161 .desc = "Test LLVM searching and compiling", 161 .desc = "Test LLVM searching and compiling",
162 .func = test__llvm, 162 .func = test__llvm,
163 .subtest = {
164 .skip_if_fail = true,
165 .get_nr = test__llvm_subtest_get_nr,
166 .get_desc = test__llvm_subtest_get_desc,
167 },
163 }, 168 },
164 { 169 {
165 .desc = "Test topology in session", 170 .desc = "Test topology in session",
@@ -168,6 +173,35 @@ static struct test generic_tests[] = {
168 { 173 {
169 .desc = "Test BPF filter", 174 .desc = "Test BPF filter",
170 .func = test__bpf, 175 .func = test__bpf,
176 .subtest = {
177 .skip_if_fail = true,
178 .get_nr = test__bpf_subtest_get_nr,
179 .get_desc = test__bpf_subtest_get_desc,
180 },
181 },
182 {
183 .desc = "Test thread map synthesize",
184 .func = test__thread_map_synthesize,
185 },
186 {
187 .desc = "Test cpu map synthesize",
188 .func = test__cpu_map_synthesize,
189 },
190 {
191 .desc = "Test stat config synthesize",
192 .func = test__synthesize_stat_config,
193 },
194 {
195 .desc = "Test stat synthesize",
196 .func = test__synthesize_stat,
197 },
198 {
199 .desc = "Test stat round synthesize",
200 .func = test__synthesize_stat_round,
201 },
202 {
203 .desc = "Test attr update synthesize",
204 .func = test__event_update,
171 }, 205 },
172 { 206 {
173 .func = NULL, 207 .func = NULL,
@@ -203,7 +237,7 @@ static bool perf_test__matches(struct test *test, int curr, int argc, const char
203 return false; 237 return false;
204} 238}
205 239
206static int run_test(struct test *test) 240static int run_test(struct test *test, int subtest)
207{ 241{
208 int status, err = -1, child = fork(); 242 int status, err = -1, child = fork();
209 char sbuf[STRERR_BUFSIZE]; 243 char sbuf[STRERR_BUFSIZE];
@@ -216,7 +250,22 @@ static int run_test(struct test *test)
216 250
217 if (!child) { 251 if (!child) {
218 pr_debug("test child forked, pid %d\n", getpid()); 252 pr_debug("test child forked, pid %d\n", getpid());
219 err = test->func(); 253 if (!verbose) {
254 int nullfd = open("/dev/null", O_WRONLY);
255 if (nullfd >= 0) {
256 close(STDERR_FILENO);
257 close(STDOUT_FILENO);
258
259 dup2(nullfd, STDOUT_FILENO);
260 dup2(STDOUT_FILENO, STDERR_FILENO);
261 close(nullfd);
262 }
263 } else {
264 signal(SIGSEGV, sighandler_dump_stack);
265 signal(SIGFPE, sighandler_dump_stack);
266 }
267
268 err = test->func(subtest);
220 exit(err); 269 exit(err);
221 } 270 }
222 271
@@ -237,6 +286,40 @@ static int run_test(struct test *test)
237 for (j = 0; j < ARRAY_SIZE(tests); j++) \ 286 for (j = 0; j < ARRAY_SIZE(tests); j++) \
238 for (t = &tests[j][0]; t->func; t++) 287 for (t = &tests[j][0]; t->func; t++)
239 288
289static int test_and_print(struct test *t, bool force_skip, int subtest)
290{
291 int err;
292
293 if (!force_skip) {
294 pr_debug("\n--- start ---\n");
295 err = run_test(t, subtest);
296 pr_debug("---- end ----\n");
297 } else {
298 pr_debug("\n--- force skipped ---\n");
299 err = TEST_SKIP;
300 }
301
302 if (!t->subtest.get_nr)
303 pr_debug("%s:", t->desc);
304 else
305 pr_debug("%s subtest %d:", t->desc, subtest);
306
307 switch (err) {
308 case TEST_OK:
309 pr_info(" Ok\n");
310 break;
311 case TEST_SKIP:
312 color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip\n");
313 break;
314 case TEST_FAIL:
315 default:
316 color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n");
317 break;
318 }
319
320 return err;
321}
322
240static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) 323static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
241{ 324{
242 struct test *t; 325 struct test *t;
@@ -264,21 +347,43 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
264 continue; 347 continue;
265 } 348 }
266 349
267 pr_debug("\n--- start ---\n"); 350 if (!t->subtest.get_nr) {
268 err = run_test(t); 351 test_and_print(t, false, -1);
269 pr_debug("---- end ----\n%s:", t->desc); 352 } else {
270 353 int subn = t->subtest.get_nr();
271 switch (err) { 354 /*
272 case TEST_OK: 355 * minus 2 to align with normal testcases.
273 pr_info(" Ok\n"); 356 * For subtest we print additional '.x' in number.
274 break; 357 * for example:
275 case TEST_SKIP: 358 *
276 color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip\n"); 359 * 35: Test LLVM searching and compiling :
277 break; 360 * 35.1: Basic BPF llvm compiling test : Ok
278 case TEST_FAIL: 361 */
279 default: 362 int subw = width > 2 ? width - 2 : width;
280 color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n"); 363 bool skip = false;
281 break; 364 int subi;
365
366 if (subn <= 0) {
367 color_fprintf(stderr, PERF_COLOR_YELLOW,
368 " Skip (not compiled in)\n");
369 continue;
370 }
371 pr_info("\n");
372
373 for (subi = 0; subi < subn; subi++) {
374 int len = strlen(t->subtest.get_desc(subi));
375
376 if (subw < len)
377 subw = len;
378 }
379
380 for (subi = 0; subi < subn; subi++) {
381 pr_info("%2d.%1d: %-*s:", i, subi + 1, subw,
382 t->subtest.get_desc(subi));
383 err = test_and_print(t, skip, subi);
384 if (err != TEST_OK && t->subtest.skip_if_fail)
385 skip = true;
386 }
282 } 387 }
283 } 388 }
284 389
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index a767a6400c5c..313a48c6b2bc 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -433,7 +433,6 @@ enum {
433 433
434static int do_test_code_reading(bool try_kcore) 434static int do_test_code_reading(bool try_kcore)
435{ 435{
436 struct machines machines;
437 struct machine *machine; 436 struct machine *machine;
438 struct thread *thread; 437 struct thread *thread;
439 struct record_opts opts = { 438 struct record_opts opts = {
@@ -459,8 +458,7 @@ static int do_test_code_reading(bool try_kcore)
459 458
460 pid = getpid(); 459 pid = getpid();
461 460
462 machines__init(&machines); 461 machine = machine__new_host();
463 machine = &machines.host;
464 462
465 ret = machine__create_kernel_maps(machine); 463 ret = machine__create_kernel_maps(machine);
466 if (ret < 0) { 464 if (ret < 0) {
@@ -549,6 +547,13 @@ static int do_test_code_reading(bool try_kcore)
549 if (ret < 0) { 547 if (ret < 0) {
550 if (!excl_kernel) { 548 if (!excl_kernel) {
551 excl_kernel = true; 549 excl_kernel = true;
550 /*
551 * Both cpus and threads are now owned by evlist
552 * and will be freed by following perf_evlist__set_maps
553 * call. Getting refference to keep them alive.
554 */
555 cpu_map__get(cpus);
556 thread_map__get(threads);
552 perf_evlist__set_maps(evlist, NULL, NULL); 557 perf_evlist__set_maps(evlist, NULL, NULL);
553 perf_evlist__delete(evlist); 558 perf_evlist__delete(evlist);
554 evlist = NULL; 559 evlist = NULL;
@@ -594,14 +599,13 @@ out_err:
594 cpu_map__put(cpus); 599 cpu_map__put(cpus);
595 thread_map__put(threads); 600 thread_map__put(threads);
596 } 601 }
597 machines__destroy_kernel_maps(&machines);
598 machine__delete_threads(machine); 602 machine__delete_threads(machine);
599 machines__exit(&machines); 603 machine__delete(machine);
600 604
601 return err; 605 return err;
602} 606}
603 607
604int test__code_reading(void) 608int test__code_reading(int subtest __maybe_unused)
605{ 609{
606 int ret; 610 int ret;
607 611
diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c
new file mode 100644
index 000000000000..4cb6418a8ffc
--- /dev/null
+++ b/tools/perf/tests/cpumap.c
@@ -0,0 +1,88 @@
1#include "tests.h"
2#include "cpumap.h"
3
4static int process_event_mask(struct perf_tool *tool __maybe_unused,
5 union perf_event *event,
6 struct perf_sample *sample __maybe_unused,
7 struct machine *machine __maybe_unused)
8{
9 struct cpu_map_event *map_event = &event->cpu_map;
10 struct cpu_map_mask *mask;
11 struct cpu_map_data *data;
12 struct cpu_map *map;
13 int i;
14
15 data = &map_event->data;
16
17 TEST_ASSERT_VAL("wrong type", data->type == PERF_CPU_MAP__MASK);
18
19 mask = (struct cpu_map_mask *)data->data;
20
21 TEST_ASSERT_VAL("wrong nr", mask->nr == 1);
22
23 for (i = 0; i < 20; i++) {
24 TEST_ASSERT_VAL("wrong cpu", test_bit(i, mask->mask));
25 }
26
27 map = cpu_map__new_data(data);
28 TEST_ASSERT_VAL("wrong nr", map->nr == 20);
29
30 for (i = 0; i < 20; i++) {
31 TEST_ASSERT_VAL("wrong cpu", map->map[i] == i);
32 }
33
34 cpu_map__put(map);
35 return 0;
36}
37
38static int process_event_cpus(struct perf_tool *tool __maybe_unused,
39 union perf_event *event,
40 struct perf_sample *sample __maybe_unused,
41 struct machine *machine __maybe_unused)
42{
43 struct cpu_map_event *map_event = &event->cpu_map;
44 struct cpu_map_entries *cpus;
45 struct cpu_map_data *data;
46 struct cpu_map *map;
47
48 data = &map_event->data;
49
50 TEST_ASSERT_VAL("wrong type", data->type == PERF_CPU_MAP__CPUS);
51
52 cpus = (struct cpu_map_entries *)data->data;
53
54 TEST_ASSERT_VAL("wrong nr", cpus->nr == 2);
55 TEST_ASSERT_VAL("wrong cpu", cpus->cpu[0] == 1);
56 TEST_ASSERT_VAL("wrong cpu", cpus->cpu[1] == 256);
57
58 map = cpu_map__new_data(data);
59 TEST_ASSERT_VAL("wrong nr", map->nr == 2);
60 TEST_ASSERT_VAL("wrong cpu", map->map[0] == 1);
61 TEST_ASSERT_VAL("wrong cpu", map->map[1] == 256);
62 TEST_ASSERT_VAL("wrong refcnt", atomic_read(&map->refcnt) == 1);
63 cpu_map__put(map);
64 return 0;
65}
66
67
68int test__cpu_map_synthesize(int subtest __maybe_unused)
69{
70 struct cpu_map *cpus;
71
72 /* This one is better stores in mask. */
73 cpus = cpu_map__new("0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19");
74
75 TEST_ASSERT_VAL("failed to synthesize map",
76 !perf_event__synthesize_cpu_map(NULL, cpus, process_event_mask, NULL));
77
78 cpu_map__put(cpus);
79
80 /* This one is better stores in cpu values. */
81 cpus = cpu_map__new("1,256");
82
83 TEST_ASSERT_VAL("failed to synthesize map",
84 !perf_event__synthesize_cpu_map(NULL, cpus, process_event_cpus, NULL));
85
86 cpu_map__put(cpus);
87 return 0;
88}
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index a218aeaf56a0..dc673ff7c437 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -110,7 +110,7 @@ static int dso__data_fd(struct dso *dso, struct machine *machine)
110 return fd; 110 return fd;
111} 111}
112 112
113int test__dso_data(void) 113int test__dso_data(int subtest __maybe_unused)
114{ 114{
115 struct machine machine; 115 struct machine machine;
116 struct dso *dso; 116 struct dso *dso;
@@ -245,7 +245,7 @@ static int set_fd_limit(int n)
245 return setrlimit(RLIMIT_NOFILE, &rlim); 245 return setrlimit(RLIMIT_NOFILE, &rlim);
246} 246}
247 247
248int test__dso_data_cache(void) 248int test__dso_data_cache(int subtest __maybe_unused)
249{ 249{
250 struct machine machine; 250 struct machine machine;
251 long nr_end, nr = open_files_cnt(); 251 long nr_end, nr = open_files_cnt();
@@ -302,7 +302,7 @@ int test__dso_data_cache(void)
302 return 0; 302 return 0;
303} 303}
304 304
305int test__dso_data_reopen(void) 305int test__dso_data_reopen(int subtest __maybe_unused)
306{ 306{
307 struct machine machine; 307 struct machine machine;
308 long nr_end, nr = open_files_cnt(); 308 long nr_end, nr = open_files_cnt();
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 07221793a3ac..1c5c0221cea2 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -51,6 +51,12 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
51 "krava_1", 51 "krava_1",
52 "test__dwarf_unwind" 52 "test__dwarf_unwind"
53 }; 53 };
54 /*
55 * The funcs[MAX_STACK] array index, based on the
56 * callchain order setup.
57 */
58 int idx = callchain_param.order == ORDER_CALLER ?
59 MAX_STACK - *cnt - 1 : *cnt;
54 60
55 if (*cnt >= MAX_STACK) { 61 if (*cnt >= MAX_STACK) {
56 pr_debug("failed: crossed the max stack value %d\n", MAX_STACK); 62 pr_debug("failed: crossed the max stack value %d\n", MAX_STACK);
@@ -63,8 +69,10 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
63 return -1; 69 return -1;
64 } 70 }
65 71
66 pr_debug("got: %s 0x%" PRIx64 "\n", symbol, entry->ip); 72 (*cnt)++;
67 return strcmp((const char *) symbol, funcs[(*cnt)++]); 73 pr_debug("got: %s 0x%" PRIx64 ", expecting %s\n",
74 symbol, entry->ip, funcs[idx]);
75 return strcmp((const char *) symbol, funcs[idx]);
68} 76}
69 77
70__attribute__ ((noinline)) 78__attribute__ ((noinline))
@@ -105,8 +113,16 @@ static int compare(void *p1, void *p2)
105 /* Any possible value should be 'thread' */ 113 /* Any possible value should be 'thread' */
106 struct thread *thread = *(struct thread **)p1; 114 struct thread *thread = *(struct thread **)p1;
107 115
108 if (global_unwind_retval == -INT_MAX) 116 if (global_unwind_retval == -INT_MAX) {
117 /* Call unwinder twice for both callchain orders. */
118 callchain_param.order = ORDER_CALLER;
119
109 global_unwind_retval = unwind_thread(thread); 120 global_unwind_retval = unwind_thread(thread);
121 if (!global_unwind_retval) {
122 callchain_param.order = ORDER_CALLEE;
123 global_unwind_retval = unwind_thread(thread);
124 }
125 }
110 126
111 return p1 - p2; 127 return p1 - p2;
112} 128}
@@ -142,21 +158,23 @@ static int krava_1(struct thread *thread)
142 return krava_2(thread); 158 return krava_2(thread);
143} 159}
144 160
145int test__dwarf_unwind(void) 161int test__dwarf_unwind(int subtest __maybe_unused)
146{ 162{
147 struct machines machines;
148 struct machine *machine; 163 struct machine *machine;
149 struct thread *thread; 164 struct thread *thread;
150 int err = -1; 165 int err = -1;
151 166
152 machines__init(&machines); 167 machine = machine__new_host();
153
154 machine = machines__find(&machines, HOST_KERNEL_ID);
155 if (!machine) { 168 if (!machine) {
156 pr_err("Could not get machine\n"); 169 pr_err("Could not get machine\n");
157 return -1; 170 return -1;
158 } 171 }
159 172
173 if (machine__create_kernel_maps(machine)) {
174 pr_err("Failed to create kernel maps\n");
175 return -1;
176 }
177
160 callchain_param.record_mode = CALLCHAIN_DWARF; 178 callchain_param.record_mode = CALLCHAIN_DWARF;
161 179
162 if (init_live_machine(machine)) { 180 if (init_live_machine(machine)) {
@@ -178,7 +196,6 @@ int test__dwarf_unwind(void)
178 196
179 out: 197 out:
180 machine__delete_threads(machine); 198 machine__delete_threads(machine);
181 machine__exit(machine); 199 machine__delete(machine);
182 machines__exit(&machines);
183 return err; 200 return err;
184} 201}
diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c
new file mode 100644
index 000000000000..012eab5d1df1
--- /dev/null
+++ b/tools/perf/tests/event_update.c
@@ -0,0 +1,117 @@
1#include <linux/compiler.h>
2#include "evlist.h"
3#include "evsel.h"
4#include "machine.h"
5#include "tests.h"
6#include "debug.h"
7
8static int process_event_unit(struct perf_tool *tool __maybe_unused,
9 union perf_event *event,
10 struct perf_sample *sample __maybe_unused,
11 struct machine *machine __maybe_unused)
12{
13 struct event_update_event *ev = (struct event_update_event *) event;
14
15 TEST_ASSERT_VAL("wrong id", ev->id == 123);
16 TEST_ASSERT_VAL("wrong id", ev->type == PERF_EVENT_UPDATE__UNIT);
17 TEST_ASSERT_VAL("wrong unit", !strcmp(ev->data, "KRAVA"));
18 return 0;
19}
20
21static int process_event_scale(struct perf_tool *tool __maybe_unused,
22 union perf_event *event,
23 struct perf_sample *sample __maybe_unused,
24 struct machine *machine __maybe_unused)
25{
26 struct event_update_event *ev = (struct event_update_event *) event;
27 struct event_update_event_scale *ev_data;
28
29 ev_data = (struct event_update_event_scale *) ev->data;
30
31 TEST_ASSERT_VAL("wrong id", ev->id == 123);
32 TEST_ASSERT_VAL("wrong id", ev->type == PERF_EVENT_UPDATE__SCALE);
33 TEST_ASSERT_VAL("wrong scale", ev_data->scale = 0.123);
34 return 0;
35}
36
37struct event_name {
38 struct perf_tool tool;
39 const char *name;
40};
41
42static int process_event_name(struct perf_tool *tool,
43 union perf_event *event,
44 struct perf_sample *sample __maybe_unused,
45 struct machine *machine __maybe_unused)
46{
47 struct event_name *tmp = container_of(tool, struct event_name, tool);
48 struct event_update_event *ev = (struct event_update_event*) event;
49
50 TEST_ASSERT_VAL("wrong id", ev->id == 123);
51 TEST_ASSERT_VAL("wrong id", ev->type == PERF_EVENT_UPDATE__NAME);
52 TEST_ASSERT_VAL("wrong name", !strcmp(ev->data, tmp->name));
53 return 0;
54}
55
56static int process_event_cpus(struct perf_tool *tool __maybe_unused,
57 union perf_event *event,
58 struct perf_sample *sample __maybe_unused,
59 struct machine *machine __maybe_unused)
60{
61 struct event_update_event *ev = (struct event_update_event*) event;
62 struct event_update_event_cpus *ev_data;
63 struct cpu_map *map;
64
65 ev_data = (struct event_update_event_cpus*) ev->data;
66
67 map = cpu_map__new_data(&ev_data->cpus);
68
69 TEST_ASSERT_VAL("wrong id", ev->id == 123);
70 TEST_ASSERT_VAL("wrong type", ev->type == PERF_EVENT_UPDATE__CPUS);
71 TEST_ASSERT_VAL("wrong cpus", map->nr == 3);
72 TEST_ASSERT_VAL("wrong cpus", map->map[0] == 1);
73 TEST_ASSERT_VAL("wrong cpus", map->map[1] == 2);
74 TEST_ASSERT_VAL("wrong cpus", map->map[2] == 3);
75 cpu_map__put(map);
76 return 0;
77}
78
79int test__event_update(int subtest __maybe_unused)
80{
81 struct perf_evlist *evlist;
82 struct perf_evsel *evsel;
83 struct event_name tmp;
84
85 evlist = perf_evlist__new_default();
86 TEST_ASSERT_VAL("failed to get evlist", evlist);
87
88 evsel = perf_evlist__first(evlist);
89
90 TEST_ASSERT_VAL("failed to allos ids",
91 !perf_evsel__alloc_id(evsel, 1, 1));
92
93 perf_evlist__id_add(evlist, evsel, 0, 0, 123);
94
95 evsel->unit = strdup("KRAVA");
96
97 TEST_ASSERT_VAL("failed to synthesize attr update unit",
98 !perf_event__synthesize_event_update_unit(NULL, evsel, process_event_unit));
99
100 evsel->scale = 0.123;
101
102 TEST_ASSERT_VAL("failed to synthesize attr update scale",
103 !perf_event__synthesize_event_update_scale(NULL, evsel, process_event_scale));
104
105 tmp.name = perf_evsel__name(evsel);
106
107 TEST_ASSERT_VAL("failed to synthesize attr update name",
108 !perf_event__synthesize_event_update_name(&tmp.tool, evsel, process_event_name));
109
110 evsel->own_cpus = cpu_map__new("1,2,3");
111
112 TEST_ASSERT_VAL("failed to synthesize attr update cpus",
113 !perf_event__synthesize_event_update_cpus(&tmp.tool, evsel, process_event_cpus));
114
115 cpu_map__put(evsel->own_cpus);
116 return 0;
117}
diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c
index 3fa715987a5e..2de4a4f2c3ed 100644
--- a/tools/perf/tests/evsel-roundtrip-name.c
+++ b/tools/perf/tests/evsel-roundtrip-name.c
@@ -95,7 +95,7 @@ out_delete_evlist:
95#define perf_evsel__name_array_test(names) \ 95#define perf_evsel__name_array_test(names) \
96 __perf_evsel__name_array_test(names, ARRAY_SIZE(names)) 96 __perf_evsel__name_array_test(names, ARRAY_SIZE(names))
97 97
98int test__perf_evsel__roundtrip_name_test(void) 98int test__perf_evsel__roundtrip_name_test(int subtest __maybe_unused)
99{ 99{
100 int err = 0, ret = 0; 100 int err = 0, ret = 0;
101 101
@@ -103,7 +103,8 @@ int test__perf_evsel__roundtrip_name_test(void)
103 if (err) 103 if (err)
104 ret = err; 104 ret = err;
105 105
106 err = perf_evsel__name_array_test(perf_evsel__sw_names); 106 err = __perf_evsel__name_array_test(perf_evsel__sw_names,
107 PERF_COUNT_SW_DUMMY + 1);
107 if (err) 108 if (err)
108 ret = err; 109 ret = err;
109 110
diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c
index 790e413d9a1f..1984b3bbfe15 100644
--- a/tools/perf/tests/evsel-tp-sched.c
+++ b/tools/perf/tests/evsel-tp-sched.c
@@ -32,7 +32,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
32 return ret; 32 return ret;
33} 33}
34 34
35int test__perf_evsel__tp_sched_test(void) 35int test__perf_evsel__tp_sched_test(int subtest __maybe_unused)
36{ 36{
37 struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch"); 37 struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch");
38 int ret = 0; 38 int ret = 0;
diff --git a/tools/perf/tests/fdarray.c b/tools/perf/tests/fdarray.c
index d24b837951d4..c809463edbe5 100644
--- a/tools/perf/tests/fdarray.c
+++ b/tools/perf/tests/fdarray.c
@@ -25,7 +25,7 @@ static int fdarray__fprintf_prefix(struct fdarray *fda, const char *prefix, FILE
25 return printed + fdarray__fprintf(fda, fp); 25 return printed + fdarray__fprintf(fda, fp);
26} 26}
27 27
28int test__fdarray__filter(void) 28int test__fdarray__filter(int subtest __maybe_unused)
29{ 29{
30 int nr_fds, expected_fd[2], fd, err = TEST_FAIL; 30 int nr_fds, expected_fd[2], fd, err = TEST_FAIL;
31 struct fdarray *fda = fdarray__new(5, 5); 31 struct fdarray *fda = fdarray__new(5, 5);
@@ -103,7 +103,7 @@ out:
103 return err; 103 return err;
104} 104}
105 105
106int test__fdarray__add(void) 106int test__fdarray__add(int subtest __maybe_unused)
107{ 107{
108 int err = TEST_FAIL; 108 int err = TEST_FAIL;
109 struct fdarray *fda = fdarray__new(2, 2); 109 struct fdarray *fda = fdarray__new(2, 2);
diff --git a/tools/perf/tests/hists_common.c b/tools/perf/tests/hists_common.c
index ce80b274b097..bcfd081ee1d2 100644
--- a/tools/perf/tests/hists_common.c
+++ b/tools/perf/tests/hists_common.c
@@ -87,6 +87,11 @@ struct machine *setup_fake_machine(struct machines *machines)
87 return NULL; 87 return NULL;
88 } 88 }
89 89
90 if (machine__create_kernel_maps(machine)) {
91 pr_debug("Cannot create kernel maps\n");
92 return NULL;
93 }
94
90 for (i = 0; i < ARRAY_SIZE(fake_threads); i++) { 95 for (i = 0; i < ARRAY_SIZE(fake_threads); i++) {
91 struct thread *thread; 96 struct thread *thread;
92 97
@@ -150,7 +155,6 @@ struct machine *setup_fake_machine(struct machines *machines)
150out: 155out:
151 pr_debug("Not enough memory for machine setup\n"); 156 pr_debug("Not enough memory for machine setup\n");
152 machine__delete_threads(machine); 157 machine__delete_threads(machine);
153 machine__delete(machine);
154 return NULL; 158 return NULL;
155} 159}
156 160
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index 7ed737019de7..e36089212061 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -281,7 +281,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine)
281 symbol_conf.cumulate_callchain = false; 281 symbol_conf.cumulate_callchain = false;
282 perf_evsel__reset_sample_bit(evsel, CALLCHAIN); 282 perf_evsel__reset_sample_bit(evsel, CALLCHAIN);
283 283
284 setup_sorting(); 284 setup_sorting(NULL);
285 callchain_register_param(&callchain_param); 285 callchain_register_param(&callchain_param);
286 286
287 err = add_hist_entries(hists, machine); 287 err = add_hist_entries(hists, machine);
@@ -428,7 +428,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine)
428 symbol_conf.cumulate_callchain = false; 428 symbol_conf.cumulate_callchain = false;
429 perf_evsel__set_sample_bit(evsel, CALLCHAIN); 429 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
430 430
431 setup_sorting(); 431 setup_sorting(NULL);
432 callchain_register_param(&callchain_param); 432 callchain_register_param(&callchain_param);
433 433
434 err = add_hist_entries(hists, machine); 434 err = add_hist_entries(hists, machine);
@@ -486,7 +486,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
486 symbol_conf.cumulate_callchain = true; 486 symbol_conf.cumulate_callchain = true;
487 perf_evsel__reset_sample_bit(evsel, CALLCHAIN); 487 perf_evsel__reset_sample_bit(evsel, CALLCHAIN);
488 488
489 setup_sorting(); 489 setup_sorting(NULL);
490 callchain_register_param(&callchain_param); 490 callchain_register_param(&callchain_param);
491 491
492 err = add_hist_entries(hists, machine); 492 err = add_hist_entries(hists, machine);
@@ -670,7 +670,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
670 symbol_conf.cumulate_callchain = true; 670 symbol_conf.cumulate_callchain = true;
671 perf_evsel__set_sample_bit(evsel, CALLCHAIN); 671 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
672 672
673 setup_sorting(); 673 setup_sorting(NULL);
674 callchain_register_param(&callchain_param); 674 callchain_register_param(&callchain_param);
675 675
676 err = add_hist_entries(hists, machine); 676 err = add_hist_entries(hists, machine);
@@ -686,7 +686,7 @@ out:
686 return err; 686 return err;
687} 687}
688 688
689int test__hists_cumulate(void) 689int test__hists_cumulate(int subtest __maybe_unused)
690{ 690{
691 int err = TEST_FAIL; 691 int err = TEST_FAIL;
692 struct machines machines; 692 struct machines machines;
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index 818acf875dd0..2a784befd9ce 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -104,7 +104,7 @@ out:
104 return TEST_FAIL; 104 return TEST_FAIL;
105} 105}
106 106
107int test__hists_filter(void) 107int test__hists_filter(int subtest __maybe_unused)
108{ 108{
109 int err = TEST_FAIL; 109 int err = TEST_FAIL;
110 struct machines machines; 110 struct machines machines;
@@ -122,7 +122,7 @@ int test__hists_filter(void)
122 goto out; 122 goto out;
123 123
124 /* default sort order (comm,dso,sym) will be used */ 124 /* default sort order (comm,dso,sym) will be used */
125 if (setup_sorting() < 0) 125 if (setup_sorting(NULL) < 0)
126 goto out; 126 goto out;
127 127
128 machines__init(&machines); 128 machines__init(&machines);
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index 8c102b011424..c764d69ac6ef 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -64,7 +64,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
64 struct perf_evsel *evsel; 64 struct perf_evsel *evsel;
65 struct addr_location al; 65 struct addr_location al;
66 struct hist_entry *he; 66 struct hist_entry *he;
67 struct perf_sample sample = { .period = 1, }; 67 struct perf_sample sample = { .period = 1, .weight = 1, };
68 size_t i = 0, k; 68 size_t i = 0, k;
69 69
70 /* 70 /*
@@ -90,7 +90,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
90 goto out; 90 goto out;
91 91
92 he = __hists__add_entry(hists, &al, NULL, 92 he = __hists__add_entry(hists, &al, NULL,
93 NULL, NULL, 1, 1, 0, true); 93 NULL, NULL, &sample, true);
94 if (he == NULL) { 94 if (he == NULL) {
95 addr_location__put(&al); 95 addr_location__put(&al);
96 goto out; 96 goto out;
@@ -116,7 +116,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
116 goto out; 116 goto out;
117 117
118 he = __hists__add_entry(hists, &al, NULL, 118 he = __hists__add_entry(hists, &al, NULL,
119 NULL, NULL, 1, 1, 0, true); 119 NULL, NULL, &sample, true);
120 if (he == NULL) { 120 if (he == NULL) {
121 addr_location__put(&al); 121 addr_location__put(&al);
122 goto out; 122 goto out;
@@ -274,7 +274,7 @@ static int validate_link(struct hists *leader, struct hists *other)
274 return __validate_link(leader, 0) || __validate_link(other, 1); 274 return __validate_link(leader, 0) || __validate_link(other, 1);
275} 275}
276 276
277int test__hists_link(void) 277int test__hists_link(int subtest __maybe_unused)
278{ 278{
279 int err = -1; 279 int err = -1;
280 struct hists *hists, *first_hists; 280 struct hists *hists, *first_hists;
@@ -294,7 +294,7 @@ int test__hists_link(void)
294 goto out; 294 goto out;
295 295
296 /* default sort order (comm,dso,sym) will be used */ 296 /* default sort order (comm,dso,sym) will be used */
297 if (setup_sorting() < 0) 297 if (setup_sorting(NULL) < 0)
298 goto out; 298 goto out;
299 299
300 machines__init(&machines); 300 machines__init(&machines);
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index adbebc852cc8..ebe6cd485b5d 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -134,7 +134,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine)
134 field_order = NULL; 134 field_order = NULL;
135 sort_order = NULL; /* equivalent to sort_order = "comm,dso,sym" */ 135 sort_order = NULL; /* equivalent to sort_order = "comm,dso,sym" */
136 136
137 setup_sorting(); 137 setup_sorting(NULL);
138 138
139 /* 139 /*
140 * expected output: 140 * expected output:
@@ -236,7 +236,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine)
236 field_order = "overhead,cpu"; 236 field_order = "overhead,cpu";
237 sort_order = "pid"; 237 sort_order = "pid";
238 238
239 setup_sorting(); 239 setup_sorting(NULL);
240 240
241 /* 241 /*
242 * expected output: 242 * expected output:
@@ -292,7 +292,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
292 field_order = "comm,overhead,dso"; 292 field_order = "comm,overhead,dso";
293 sort_order = NULL; 293 sort_order = NULL;
294 294
295 setup_sorting(); 295 setup_sorting(NULL);
296 296
297 /* 297 /*
298 * expected output: 298 * expected output:
@@ -366,7 +366,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
366 field_order = "dso,sym,comm,overhead,dso"; 366 field_order = "dso,sym,comm,overhead,dso";
367 sort_order = "sym"; 367 sort_order = "sym";
368 368
369 setup_sorting(); 369 setup_sorting(NULL);
370 370
371 /* 371 /*
372 * expected output: 372 * expected output:
@@ -468,7 +468,7 @@ static int test5(struct perf_evsel *evsel, struct machine *machine)
468 field_order = "cpu,pid,comm,dso,sym"; 468 field_order = "cpu,pid,comm,dso,sym";
469 sort_order = "dso,pid"; 469 sort_order = "dso,pid";
470 470
471 setup_sorting(); 471 setup_sorting(NULL);
472 472
473 /* 473 /*
474 * expected output: 474 * expected output:
@@ -576,7 +576,7 @@ out:
576 return err; 576 return err;
577} 577}
578 578
579int test__hists_output(void) 579int test__hists_output(int subtest __maybe_unused)
580{ 580{
581 int err = TEST_FAIL; 581 int err = TEST_FAIL;
582 struct machines machines; 582 struct machines machines;
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index a2e2269aa093..ddb78fae064a 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -49,13 +49,12 @@ static int find_comm(struct perf_evlist *evlist, const char *comm)
49 * when an event is disabled but a dummy software event is not disabled. If the 49 * when an event is disabled but a dummy software event is not disabled. If the
50 * test passes %0 is returned, otherwise %-1 is returned. 50 * test passes %0 is returned, otherwise %-1 is returned.
51 */ 51 */
52int test__keep_tracking(void) 52int test__keep_tracking(int subtest __maybe_unused)
53{ 53{
54 struct record_opts opts = { 54 struct record_opts opts = {
55 .mmap_pages = UINT_MAX, 55 .mmap_pages = UINT_MAX,
56 .user_freq = UINT_MAX, 56 .user_freq = UINT_MAX,
57 .user_interval = ULLONG_MAX, 57 .user_interval = ULLONG_MAX,
58 .freq = 4000,
59 .target = { 58 .target = {
60 .uses_mmap = true, 59 .uses_mmap = true,
61 }, 60 },
@@ -124,7 +123,7 @@ int test__keep_tracking(void)
124 123
125 evsel = perf_evlist__last(evlist); 124 evsel = perf_evlist__last(evlist);
126 125
127 CHECK__(perf_evlist__disable_event(evlist, evsel)); 126 CHECK__(perf_evsel__disable(evsel));
128 127
129 comm = "Test COMM 2"; 128 comm = "Test COMM 2";
130 CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0)); 129 CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0));
diff --git a/tools/perf/tests/kmod-path.c b/tools/perf/tests/kmod-path.c
index 08c433b4bf4f..d2af78193153 100644
--- a/tools/perf/tests/kmod-path.c
+++ b/tools/perf/tests/kmod-path.c
@@ -49,7 +49,7 @@ static int test_is_kernel_module(const char *path, int cpumode, bool expect)
49#define M(path, c, e) \ 49#define M(path, c, e) \
50 TEST_ASSERT_VAL("failed", !test_is_kernel_module(path, c, e)) 50 TEST_ASSERT_VAL("failed", !test_is_kernel_module(path, c, e))
51 51
52int test__kmod_path__parse(void) 52int test__kmod_path__parse(int subtest __maybe_unused)
53{ 53{
54 /* path alloc_name alloc_ext kmod comp name ext */ 54 /* path alloc_name alloc_ext kmod comp name ext */
55 T("/xxxx/xxxx/x-x.ko", true , true , true, false, "[x_x]", NULL); 55 T("/xxxx/xxxx/x-x.ko", true , true , true, false, "[x_x]", NULL);
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index bc4cf507cde5..06f45c1d4256 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -44,13 +44,17 @@ static struct {
44 .source = test_llvm__bpf_test_kbuild_prog, 44 .source = test_llvm__bpf_test_kbuild_prog,
45 .desc = "Test kbuild searching", 45 .desc = "Test kbuild searching",
46 }, 46 },
47 [LLVM_TESTCASE_BPF_PROLOGUE] = {
48 .source = test_llvm__bpf_test_prologue_prog,
49 .desc = "Compile source for BPF prologue generation test",
50 },
47}; 51};
48 52
49 53
50int 54int
51test_llvm__fetch_bpf_obj(void **p_obj_buf, 55test_llvm__fetch_bpf_obj(void **p_obj_buf,
52 size_t *p_obj_buf_sz, 56 size_t *p_obj_buf_sz,
53 enum test_llvm__testcase index, 57 enum test_llvm__testcase idx,
54 bool force) 58 bool force)
55{ 59{
56 const char *source; 60 const char *source;
@@ -59,11 +63,11 @@ test_llvm__fetch_bpf_obj(void **p_obj_buf,
59 char *tmpl_new = NULL, *clang_opt_new = NULL; 63 char *tmpl_new = NULL, *clang_opt_new = NULL;
60 int err, old_verbose, ret = TEST_FAIL; 64 int err, old_verbose, ret = TEST_FAIL;
61 65
62 if (index >= __LLVM_TESTCASE_MAX) 66 if (idx >= __LLVM_TESTCASE_MAX)
63 return TEST_FAIL; 67 return TEST_FAIL;
64 68
65 source = bpf_source_table[index].source; 69 source = bpf_source_table[idx].source;
66 desc = bpf_source_table[index].desc; 70 desc = bpf_source_table[idx].desc;
67 71
68 perf_config(perf_config_cb, NULL); 72 perf_config(perf_config_cb, NULL);
69 73
@@ -127,44 +131,39 @@ out:
127 return ret; 131 return ret;
128} 132}
129 133
130int test__llvm(void) 134int test__llvm(int subtest)
131{ 135{
132 enum test_llvm__testcase i; 136 int ret;
137 void *obj_buf = NULL;
138 size_t obj_buf_sz = 0;
133 139
134 for (i = 0; i < __LLVM_TESTCASE_MAX; i++) { 140 if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
135 int ret; 141 return TEST_FAIL;
136 void *obj_buf = NULL;
137 size_t obj_buf_sz = 0;
138 142
139 ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz, 143 ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
140 i, false); 144 subtest, false);
141 145
142 if (ret == TEST_OK) { 146 if (ret == TEST_OK) {
143 ret = test__bpf_parsing(obj_buf, obj_buf_sz); 147 ret = test__bpf_parsing(obj_buf, obj_buf_sz);
144 if (ret != TEST_OK) 148 if (ret != TEST_OK) {
145 pr_debug("Failed to parse test case '%s'\n", 149 pr_debug("Failed to parse test case '%s'\n",
146 bpf_source_table[i].desc); 150 bpf_source_table[subtest].desc);
147 }
148 free(obj_buf);
149
150 switch (ret) {
151 case TEST_SKIP:
152 return TEST_SKIP;
153 case TEST_OK:
154 break;
155 default:
156 /*
157 * Test 0 is the basic LLVM test. If test 0
158 * fail, the basic LLVM support not functional
159 * so the whole test should fail. If other test
160 * case fail, it can be fixed by adjusting
161 * config so don't report error.
162 */
163 if (i == 0)
164 return TEST_FAIL;
165 else
166 return TEST_SKIP;
167 } 151 }
168 } 152 }
169 return TEST_OK; 153 free(obj_buf);
154
155 return ret;
156}
157
158int test__llvm_subtest_get_nr(void)
159{
160 return __LLVM_TESTCASE_MAX;
161}
162
163const char *test__llvm_subtest_get_desc(int subtest)
164{
165 if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
166 return NULL;
167
168 return bpf_source_table[subtest].desc;
170} 169}
diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h
index d91d8f44efee..5150b4d6ef50 100644
--- a/tools/perf/tests/llvm.h
+++ b/tools/perf/tests/llvm.h
@@ -6,10 +6,12 @@
6 6
7extern const char test_llvm__bpf_base_prog[]; 7extern const char test_llvm__bpf_base_prog[];
8extern const char test_llvm__bpf_test_kbuild_prog[]; 8extern const char test_llvm__bpf_test_kbuild_prog[];
9extern const char test_llvm__bpf_test_prologue_prog[];
9 10
10enum test_llvm__testcase { 11enum test_llvm__testcase {
11 LLVM_TESTCASE_BASE, 12 LLVM_TESTCASE_BASE,
12 LLVM_TESTCASE_KBUILD, 13 LLVM_TESTCASE_KBUILD,
14 LLVM_TESTCASE_BPF_PROLOGUE,
13 __LLVM_TESTCASE_MAX, 15 __LLVM_TESTCASE_MAX,
14}; 16};
15 17
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 8ea3dffc5065..c1fbb8e884c0 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -259,7 +259,8 @@ $(run_O):
259tarpkg: 259tarpkg:
260 @cmd="$(PERF)/tests/perf-targz-src-pkg $(PERF)"; \ 260 @cmd="$(PERF)/tests/perf-targz-src-pkg $(PERF)"; \
261 echo "- $@: $$cmd" && echo $$cmd > $@ && \ 261 echo "- $@: $$cmd" && echo $$cmd > $@ && \
262 ( eval $$cmd ) >> $@ 2>&1 262 ( eval $$cmd ) >> $@ 2>&1 && \
263 rm -f $@
263 264
264make_kernelsrc: 265make_kernelsrc:
265 @echo "- make -C <kernelsrc> tools/perf" 266 @echo "- make -C <kernelsrc> tools/perf"
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 4495493c9431..359e98fcd94c 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -16,7 +16,7 @@
16 * Then it checks if the number of syscalls reported as perf events by 16 * Then it checks if the number of syscalls reported as perf events by
17 * the kernel corresponds to the number of syscalls made. 17 * the kernel corresponds to the number of syscalls made.
18 */ 18 */
19int test__basic_mmap(void) 19int test__basic_mmap(int subtest __maybe_unused)
20{ 20{
21 int err = -1; 21 int err = -1;
22 union perf_event *event; 22 union perf_event *event;
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c
index 145050e2e544..0c5ce44f723f 100644
--- a/tools/perf/tests/mmap-thread-lookup.c
+++ b/tools/perf/tests/mmap-thread-lookup.c
@@ -149,7 +149,6 @@ static int synth_process(struct machine *machine)
149 149
150static int mmap_events(synth_cb synth) 150static int mmap_events(synth_cb synth)
151{ 151{
152 struct machines machines;
153 struct machine *machine; 152 struct machine *machine;
154 int err, i; 153 int err, i;
155 154
@@ -162,8 +161,7 @@ static int mmap_events(synth_cb synth)
162 */ 161 */
163 TEST_ASSERT_VAL("failed to create threads", !threads_create()); 162 TEST_ASSERT_VAL("failed to create threads", !threads_create());
164 163
165 machines__init(&machines); 164 machine = machine__new_host();
166 machine = &machines.host;
167 165
168 dump_trace = verbose > 1 ? 1 : 0; 166 dump_trace = verbose > 1 ? 1 : 0;
169 167
@@ -203,7 +201,7 @@ static int mmap_events(synth_cb synth)
203 } 201 }
204 202
205 machine__delete_threads(machine); 203 machine__delete_threads(machine);
206 machines__exit(&machines); 204 machine__delete(machine);
207 return err; 205 return err;
208} 206}
209 207
@@ -221,7 +219,7 @@ static int mmap_events(synth_cb synth)
221 * 219 *
222 * by using all thread objects. 220 * by using all thread objects.
223 */ 221 */
224int test__mmap_thread_lookup(void) 222int test__mmap_thread_lookup(int subtest __maybe_unused)
225{ 223{
226 /* perf_event__synthesize_threads synthesize */ 224 /* perf_event__synthesize_threads synthesize */
227 TEST_ASSERT_VAL("failed with sythesizing all", 225 TEST_ASSERT_VAL("failed with sythesizing all",
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index 2006485a2859..53c2273e8859 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -7,7 +7,7 @@
7#include "debug.h" 7#include "debug.h"
8#include "stat.h" 8#include "stat.h"
9 9
10int test__openat_syscall_event_on_all_cpus(void) 10int test__openat_syscall_event_on_all_cpus(int subtest __maybe_unused)
11{ 11{
12 int err = -1, fd, cpu; 12 int err = -1, fd, cpu;
13 struct cpu_map *cpus; 13 struct cpu_map *cpus;
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
index 5e811cd8f1c3..eb99a105f31c 100644
--- a/tools/perf/tests/openat-syscall-tp-fields.c
+++ b/tools/perf/tests/openat-syscall-tp-fields.c
@@ -6,7 +6,7 @@
6#include "tests.h" 6#include "tests.h"
7#include "debug.h" 7#include "debug.h"
8 8
9int test__syscall_openat_tp_fields(void) 9int test__syscall_openat_tp_fields(int subtest __maybe_unused)
10{ 10{
11 struct record_opts opts = { 11 struct record_opts opts = {
12 .target = { 12 .target = {
diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c
index 033b54797b8a..1184f9ba6499 100644
--- a/tools/perf/tests/openat-syscall.c
+++ b/tools/perf/tests/openat-syscall.c
@@ -5,7 +5,7 @@
5#include "debug.h" 5#include "debug.h"
6#include "tests.h" 6#include "tests.h"
7 7
8int test__openat_syscall_event(void) 8int test__openat_syscall_event(int subtest __maybe_unused)
9{ 9{
10 int err = -1, fd; 10 int err = -1, fd;
11 struct perf_evsel *evsel; 11 struct perf_evsel *evsel;
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 636d7b42d844..abe8849d1d70 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -1765,7 +1765,7 @@ static void debug_warn(const char *warn, va_list params)
1765 fprintf(stderr, " Warning: %s\n", msg); 1765 fprintf(stderr, " Warning: %s\n", msg);
1766} 1766}
1767 1767
1768int test__parse_events(void) 1768int test__parse_events(int subtest __maybe_unused)
1769{ 1769{
1770 int ret1, ret2 = 0; 1770 int ret1, ret2 = 0;
1771 1771
diff --git a/tools/perf/tests/parse-no-sample-id-all.c b/tools/perf/tests/parse-no-sample-id-all.c
index 2c63ea658541..294c76b01b41 100644
--- a/tools/perf/tests/parse-no-sample-id-all.c
+++ b/tools/perf/tests/parse-no-sample-id-all.c
@@ -67,7 +67,7 @@ struct test_attr_event {
67 * 67 *
68 * Return: %0 on success, %-1 if the test fails. 68 * Return: %0 on success, %-1 if the test fails.
69 */ 69 */
70int test__parse_no_sample_id_all(void) 70int test__parse_no_sample_id_all(int subtest __maybe_unused)
71{ 71{
72 int err; 72 int err;
73 73
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 7a228a2a070b..1cc78cefe399 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -32,7 +32,7 @@ realloc:
32 return cpu; 32 return cpu;
33} 33}
34 34
35int test__PERF_RECORD(void) 35int test__PERF_RECORD(int subtest __maybe_unused)
36{ 36{
37 struct record_opts opts = { 37 struct record_opts opts = {
38 .target = { 38 .target = {
@@ -40,12 +40,11 @@ int test__PERF_RECORD(void)
40 .uses_mmap = true, 40 .uses_mmap = true,
41 }, 41 },
42 .no_buffering = true, 42 .no_buffering = true,
43 .freq = 10,
44 .mmap_pages = 256, 43 .mmap_pages = 256,
45 }; 44 };
46 cpu_set_t cpu_mask; 45 cpu_set_t cpu_mask;
47 size_t cpu_mask_size = sizeof(cpu_mask); 46 size_t cpu_mask_size = sizeof(cpu_mask);
48 struct perf_evlist *evlist = perf_evlist__new_default(); 47 struct perf_evlist *evlist = perf_evlist__new_dummy();
49 struct perf_evsel *evsel; 48 struct perf_evsel *evsel;
50 struct perf_sample sample; 49 struct perf_sample sample;
51 const char *cmd = "sleep"; 50 const char *cmd = "sleep";
@@ -61,6 +60,9 @@ int test__PERF_RECORD(void)
61 int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, }; 60 int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };
62 char sbuf[STRERR_BUFSIZE]; 61 char sbuf[STRERR_BUFSIZE];
63 62
63 if (evlist == NULL) /* Fallback for kernels lacking PERF_COUNT_SW_DUMMY */
64 evlist = perf_evlist__new_default();
65
64 if (evlist == NULL || argv == NULL) { 66 if (evlist == NULL || argv == NULL) {
65 pr_debug("Not enough memory to create evlist\n"); 67 pr_debug("Not enough memory to create evlist\n");
66 goto out; 68 goto out;
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index faa04e9d5d5f..1e2ba2602930 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -133,7 +133,7 @@ static struct list_head *test_terms_list(void)
133 return &terms; 133 return &terms;
134} 134}
135 135
136int test__pmu(void) 136int test__pmu(int subtest __maybe_unused)
137{ 137{
138 char *format = test_format_dir_get(); 138 char *format = test_format_dir_get();
139 LIST_HEAD(formats); 139 LIST_HEAD(formats);
diff --git a/tools/perf/tests/python-use.c b/tools/perf/tests/python-use.c
index 7760277c6def..7a52834ee0d0 100644
--- a/tools/perf/tests/python-use.c
+++ b/tools/perf/tests/python-use.c
@@ -4,11 +4,12 @@
4 4
5#include <stdio.h> 5#include <stdio.h>
6#include <stdlib.h> 6#include <stdlib.h>
7#include <linux/compiler.h>
7#include "tests.h" 8#include "tests.h"
8 9
9extern int verbose; 10extern int verbose;
10 11
11int test__python_use(void) 12int test__python_use(int subtest __maybe_unused)
12{ 13{
13 char *cmd; 14 char *cmd;
14 int ret; 15 int ret;
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index 30c02181e78b..5f23710b9fee 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -290,7 +290,7 @@ out_free:
290 * checks sample format bits separately and together. If the test passes %0 is 290 * checks sample format bits separately and together. If the test passes %0 is
291 * returned, otherwise %-1 is returned. 291 * returned, otherwise %-1 is returned.
292 */ 292 */
293int test__sample_parsing(void) 293int test__sample_parsing(int subtest __maybe_unused)
294{ 294{
295 const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15}; 295 const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15};
296 u64 sample_type; 296 u64 sample_type;
diff --git a/tools/perf/tests/stat.c b/tools/perf/tests/stat.c
new file mode 100644
index 000000000000..6a20ff2326bb
--- /dev/null
+++ b/tools/perf/tests/stat.c
@@ -0,0 +1,111 @@
1#include <linux/compiler.h>
2#include "event.h"
3#include "tests.h"
4#include "stat.h"
5#include "counts.h"
6#include "debug.h"
7
8static bool has_term(struct stat_config_event *config,
9 u64 tag, u64 val)
10{
11 unsigned i;
12
13 for (i = 0; i < config->nr; i++) {
14 if ((config->data[i].tag == tag) &&
15 (config->data[i].val == val))
16 return true;
17 }
18
19 return false;
20}
21
22static int process_stat_config_event(struct perf_tool *tool __maybe_unused,
23 union perf_event *event,
24 struct perf_sample *sample __maybe_unused,
25 struct machine *machine __maybe_unused)
26{
27 struct stat_config_event *config = &event->stat_config;
28 struct perf_stat_config stat_config;
29
30#define HAS(term, val) \
31 has_term(config, PERF_STAT_CONFIG_TERM__##term, val)
32
33 TEST_ASSERT_VAL("wrong nr", config->nr == PERF_STAT_CONFIG_TERM__MAX);
34 TEST_ASSERT_VAL("wrong aggr_mode", HAS(AGGR_MODE, AGGR_CORE));
35 TEST_ASSERT_VAL("wrong scale", HAS(SCALE, 1));
36 TEST_ASSERT_VAL("wrong interval", HAS(INTERVAL, 1));
37
38#undef HAS
39
40 perf_event__read_stat_config(&stat_config, config);
41
42 TEST_ASSERT_VAL("wrong aggr_mode", stat_config.aggr_mode == AGGR_CORE);
43 TEST_ASSERT_VAL("wrong scale", stat_config.scale == 1);
44 TEST_ASSERT_VAL("wrong interval", stat_config.interval == 1);
45 return 0;
46}
47
48int test__synthesize_stat_config(int subtest __maybe_unused)
49{
50 struct perf_stat_config stat_config = {
51 .aggr_mode = AGGR_CORE,
52 .scale = 1,
53 .interval = 1,
54 };
55
56 TEST_ASSERT_VAL("failed to synthesize stat_config",
57 !perf_event__synthesize_stat_config(NULL, &stat_config, process_stat_config_event, NULL));
58
59 return 0;
60}
61
62static int process_stat_event(struct perf_tool *tool __maybe_unused,
63 union perf_event *event,
64 struct perf_sample *sample __maybe_unused,
65 struct machine *machine __maybe_unused)
66{
67 struct stat_event *st = &event->stat;
68
69 TEST_ASSERT_VAL("wrong cpu", st->cpu == 1);
70 TEST_ASSERT_VAL("wrong thread", st->thread == 2);
71 TEST_ASSERT_VAL("wrong id", st->id == 3);
72 TEST_ASSERT_VAL("wrong val", st->val == 100);
73 TEST_ASSERT_VAL("wrong run", st->ena == 200);
74 TEST_ASSERT_VAL("wrong ena", st->run == 300);
75 return 0;
76}
77
78int test__synthesize_stat(int subtest __maybe_unused)
79{
80 struct perf_counts_values count;
81
82 count.val = 100;
83 count.ena = 200;
84 count.run = 300;
85
86 TEST_ASSERT_VAL("failed to synthesize stat_config",
87 !perf_event__synthesize_stat(NULL, 1, 2, 3, &count, process_stat_event, NULL));
88
89 return 0;
90}
91
92static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
93 union perf_event *event,
94 struct perf_sample *sample __maybe_unused,
95 struct machine *machine __maybe_unused)
96{
97 struct stat_round_event *stat_round = &event->stat_round;
98
99 TEST_ASSERT_VAL("wrong time", stat_round->time == 0xdeadbeef);
100 TEST_ASSERT_VAL("wrong type", stat_round->type == PERF_STAT_ROUND_TYPE__INTERVAL);
101 return 0;
102}
103
104int test__synthesize_stat_round(int subtest __maybe_unused)
105{
106 TEST_ASSERT_VAL("failed to synthesize stat_config",
107 !perf_event__synthesize_stat_round(NULL, 0xdeadbeef, PERF_STAT_ROUND_TYPE__INTERVAL,
108 process_stat_round_event, NULL));
109
110 return 0;
111}
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index 5b83f56a3b6f..36e8ce1550e3 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -122,7 +122,7 @@ out_delete_evlist:
122 return err; 122 return err;
123} 123}
124 124
125int test__sw_clock_freq(void) 125int test__sw_clock_freq(int subtest __maybe_unused)
126{ 126{
127 int ret; 127 int ret;
128 128
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
index a02af503100c..ebd80168d51e 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -305,7 +305,7 @@ out_free_nodes:
305 * evsel->system_wide and evsel->tracking flags (respectively) with other events 305 * evsel->system_wide and evsel->tracking flags (respectively) with other events
306 * sometimes enabled or disabled. 306 * sometimes enabled or disabled.
307 */ 307 */
308int test__switch_tracking(void) 308int test__switch_tracking(int subtest __maybe_unused)
309{ 309{
310 const char *sched_switch = "sched:sched_switch"; 310 const char *sched_switch = "sched:sched_switch";
311 struct switch_tracking switch_tracking = { .tids = NULL, }; 311 struct switch_tracking switch_tracking = { .tids = NULL, };
@@ -455,7 +455,7 @@ int test__switch_tracking(void)
455 455
456 perf_evlist__enable(evlist); 456 perf_evlist__enable(evlist);
457 457
458 err = perf_evlist__disable_event(evlist, cpu_clocks_evsel); 458 err = perf_evsel__disable(cpu_clocks_evsel);
459 if (err) { 459 if (err) {
460 pr_debug("perf_evlist__disable_event failed!\n"); 460 pr_debug("perf_evlist__disable_event failed!\n");
461 goto out_err; 461 goto out_err;
@@ -474,7 +474,7 @@ int test__switch_tracking(void)
474 goto out_err; 474 goto out_err;
475 } 475 }
476 476
477 err = perf_evlist__disable_event(evlist, cycles_evsel); 477 err = perf_evsel__disable(cycles_evsel);
478 if (err) { 478 if (err) {
479 pr_debug("perf_evlist__disable_event failed!\n"); 479 pr_debug("perf_evlist__disable_event failed!\n");
480 goto out_err; 480 goto out_err;
@@ -500,7 +500,7 @@ int test__switch_tracking(void)
500 goto out_err; 500 goto out_err;
501 } 501 }
502 502
503 err = perf_evlist__enable_event(evlist, cycles_evsel); 503 err = perf_evsel__enable(cycles_evsel);
504 if (err) { 504 if (err) {
505 pr_debug("perf_evlist__disable_event failed!\n"); 505 pr_debug("perf_evlist__disable_event failed!\n");
506 goto out_err; 506 goto out_err;
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index add16385f13e..2dfff7ac8ef3 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -31,7 +31,7 @@ static void workload_exec_failed_signal(int signo __maybe_unused,
31 * if the number of exit event reported by the kernel is 1 or not 31 * if the number of exit event reported by the kernel is 1 or not
32 * in order to check the kernel returns correct number of event. 32 * in order to check the kernel returns correct number of event.
33 */ 33 */
34int test__task_exit(void) 34int test__task_exit(int subtest __maybe_unused)
35{ 35{
36 int err = -1; 36 int err = -1;
37 union perf_event *event; 37 union perf_event *event;
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 3c8734a3abbc..82b2b5e6ba7c 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -1,6 +1,8 @@
1#ifndef TESTS_H 1#ifndef TESTS_H
2#define TESTS_H 2#define TESTS_H
3 3
4#include <stdbool.h>
5
4#define TEST_ASSERT_VAL(text, cond) \ 6#define TEST_ASSERT_VAL(text, cond) \
5do { \ 7do { \
6 if (!(cond)) { \ 8 if (!(cond)) { \
@@ -26,48 +28,63 @@ enum {
26 28
27struct test { 29struct test {
28 const char *desc; 30 const char *desc;
29 int (*func)(void); 31 int (*func)(int subtest);
32 struct {
33 bool skip_if_fail;
34 int (*get_nr)(void);
35 const char *(*get_desc)(int subtest);
36 } subtest;
30}; 37};
31 38
32/* Tests */ 39/* Tests */
33int test__vmlinux_matches_kallsyms(void); 40int test__vmlinux_matches_kallsyms(int subtest);
34int test__openat_syscall_event(void); 41int test__openat_syscall_event(int subtest);
35int test__openat_syscall_event_on_all_cpus(void); 42int test__openat_syscall_event_on_all_cpus(int subtest);
36int test__basic_mmap(void); 43int test__basic_mmap(int subtest);
37int test__PERF_RECORD(void); 44int test__PERF_RECORD(int subtest);
38int test__perf_evsel__roundtrip_name_test(void); 45int test__perf_evsel__roundtrip_name_test(int subtest);
39int test__perf_evsel__tp_sched_test(void); 46int test__perf_evsel__tp_sched_test(int subtest);
40int test__syscall_openat_tp_fields(void); 47int test__syscall_openat_tp_fields(int subtest);
41int test__pmu(void); 48int test__pmu(int subtest);
42int test__attr(void); 49int test__attr(int subtest);
43int test__dso_data(void); 50int test__dso_data(int subtest);
44int test__dso_data_cache(void); 51int test__dso_data_cache(int subtest);
45int test__dso_data_reopen(void); 52int test__dso_data_reopen(int subtest);
46int test__parse_events(void); 53int test__parse_events(int subtest);
47int test__hists_link(void); 54int test__hists_link(int subtest);
48int test__python_use(void); 55int test__python_use(int subtest);
49int test__bp_signal(void); 56int test__bp_signal(int subtest);
50int test__bp_signal_overflow(void); 57int test__bp_signal_overflow(int subtest);
51int test__task_exit(void); 58int test__task_exit(int subtest);
52int test__sw_clock_freq(void); 59int test__sw_clock_freq(int subtest);
53int test__code_reading(void); 60int test__code_reading(int subtest);
54int test__sample_parsing(void); 61int test__sample_parsing(int subtest);
55int test__keep_tracking(void); 62int test__keep_tracking(int subtest);
56int test__parse_no_sample_id_all(void); 63int test__parse_no_sample_id_all(int subtest);
57int test__dwarf_unwind(void); 64int test__dwarf_unwind(int subtest);
58int test__hists_filter(void); 65int test__hists_filter(int subtest);
59int test__mmap_thread_lookup(void); 66int test__mmap_thread_lookup(int subtest);
60int test__thread_mg_share(void); 67int test__thread_mg_share(int subtest);
61int test__hists_output(void); 68int test__hists_output(int subtest);
62int test__hists_cumulate(void); 69int test__hists_cumulate(int subtest);
63int test__switch_tracking(void); 70int test__switch_tracking(int subtest);
64int test__fdarray__filter(void); 71int test__fdarray__filter(int subtest);
65int test__fdarray__add(void); 72int test__fdarray__add(int subtest);
66int test__kmod_path__parse(void); 73int test__kmod_path__parse(int subtest);
67int test__thread_map(void); 74int test__thread_map(int subtest);
68int test__llvm(void); 75int test__llvm(int subtest);
69int test__bpf(void); 76const char *test__llvm_subtest_get_desc(int subtest);
70int test_session_topology(void); 77int test__llvm_subtest_get_nr(void);
78int test__bpf(int subtest);
79const char *test__bpf_subtest_get_desc(int subtest);
80int test__bpf_subtest_get_nr(void);
81int test_session_topology(int subtest);
82int test__thread_map_synthesize(int subtest);
83int test__cpu_map_synthesize(int subtest);
84int test__synthesize_stat_config(int subtest);
85int test__synthesize_stat(int subtest);
86int test__synthesize_stat_round(int subtest);
87int test__event_update(int subtest);
71 88
72#if defined(__arm__) || defined(__aarch64__) 89#if defined(__arm__) || defined(__aarch64__)
73#ifdef HAVE_DWARF_UNWIND_SUPPORT 90#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
index 138a0e3431fa..fccde848fe9c 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -4,7 +4,7 @@
4#include "thread_map.h" 4#include "thread_map.h"
5#include "debug.h" 5#include "debug.h"
6 6
7int test__thread_map(void) 7int test__thread_map(int subtest __maybe_unused)
8{ 8{
9 struct thread_map *map; 9 struct thread_map *map;
10 10
@@ -40,3 +40,46 @@ int test__thread_map(void)
40 thread_map__put(map); 40 thread_map__put(map);
41 return 0; 41 return 0;
42} 42}
43
44static int process_event(struct perf_tool *tool __maybe_unused,
45 union perf_event *event,
46 struct perf_sample *sample __maybe_unused,
47 struct machine *machine __maybe_unused)
48{
49 struct thread_map_event *map = &event->thread_map;
50 struct thread_map *threads;
51
52 TEST_ASSERT_VAL("wrong nr", map->nr == 1);
53 TEST_ASSERT_VAL("wrong pid", map->entries[0].pid == (u64) getpid());
54 TEST_ASSERT_VAL("wrong comm", !strcmp(map->entries[0].comm, "perf"));
55
56 threads = thread_map__new_event(&event->thread_map);
57 TEST_ASSERT_VAL("failed to alloc map", threads);
58
59 TEST_ASSERT_VAL("wrong nr", threads->nr == 1);
60 TEST_ASSERT_VAL("wrong pid",
61 thread_map__pid(threads, 0) == getpid());
62 TEST_ASSERT_VAL("wrong comm",
63 thread_map__comm(threads, 0) &&
64 !strcmp(thread_map__comm(threads, 0), "perf"));
65 TEST_ASSERT_VAL("wrong refcnt",
66 atomic_read(&threads->refcnt) == 1);
67 thread_map__put(threads);
68 return 0;
69}
70
71int test__thread_map_synthesize(int subtest __maybe_unused)
72{
73 struct thread_map *threads;
74
75 /* test map on current pid */
76 threads = thread_map__new_by_pid(getpid());
77 TEST_ASSERT_VAL("failed to alloc map", threads);
78
79 thread_map__read_comms(threads);
80
81 TEST_ASSERT_VAL("failed to synthesize map",
82 !perf_event__synthesize_thread_map2(NULL, threads, process_event, NULL));
83
84 return 0;
85}
diff --git a/tools/perf/tests/thread-mg-share.c b/tools/perf/tests/thread-mg-share.c
index 01fabb19d746..188b63140fc8 100644
--- a/tools/perf/tests/thread-mg-share.c
+++ b/tools/perf/tests/thread-mg-share.c
@@ -4,7 +4,7 @@
4#include "map.h" 4#include "map.h"
5#include "debug.h" 5#include "debug.h"
6 6
7int test__thread_mg_share(void) 7int test__thread_mg_share(int subtest __maybe_unused)
8{ 8{
9 struct machines machines; 9 struct machines machines;
10 struct machine *machine; 10 struct machine *machine;
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c
index f5bb096c3bd9..98fe69ac553c 100644
--- a/tools/perf/tests/topology.c
+++ b/tools/perf/tests/topology.c
@@ -84,7 +84,7 @@ static int check_cpu_topology(char *path, struct cpu_map *map)
84 return 0; 84 return 0;
85} 85}
86 86
87int test_session_topology(void) 87int test_session_topology(int subtest __maybe_unused)
88{ 88{
89 char path[PATH_MAX]; 89 char path[PATH_MAX];
90 struct cpu_map *map; 90 struct cpu_map *map;
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index d677e018e504..f0bfc9e8fd9f 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -18,7 +18,7 @@ static int vmlinux_matches_kallsyms_filter(struct map *map __maybe_unused,
18 18
19#define UM(x) kallsyms_map->unmap_ip(kallsyms_map, (x)) 19#define UM(x) kallsyms_map->unmap_ip(kallsyms_map, (x))
20 20
21int test__vmlinux_matches_kallsyms(void) 21int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
22{ 22{
23 int err = -1; 23 int err = -1;
24 struct rb_node *nd; 24 struct rb_node *nd;
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index e9703c0829f1..d37202121689 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -528,7 +528,7 @@ static struct ui_browser_colorset {
528 .colorset = HE_COLORSET_SELECTED, 528 .colorset = HE_COLORSET_SELECTED,
529 .name = "selected", 529 .name = "selected",
530 .fg = "black", 530 .fg = "black",
531 .bg = "lightgray", 531 .bg = "yellow",
532 }, 532 },
533 { 533 {
534 .colorset = HE_COLORSET_CODE, 534 .colorset = HE_COLORSET_CODE,
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 81def6c3f24b..901d481e6cea 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -178,12 +178,51 @@ static int callchain_node__count_rows_rb_tree(struct callchain_node *node)
178 return n; 178 return n;
179} 179}
180 180
181static int callchain_node__count_flat_rows(struct callchain_node *node)
182{
183 struct callchain_list *chain;
184 char folded_sign = 0;
185 int n = 0;
186
187 list_for_each_entry(chain, &node->parent_val, list) {
188 if (!folded_sign) {
189 /* only check first chain list entry */
190 folded_sign = callchain_list__folded(chain);
191 if (folded_sign == '+')
192 return 1;
193 }
194 n++;
195 }
196
197 list_for_each_entry(chain, &node->val, list) {
198 if (!folded_sign) {
199 /* node->parent_val list might be empty */
200 folded_sign = callchain_list__folded(chain);
201 if (folded_sign == '+')
202 return 1;
203 }
204 n++;
205 }
206
207 return n;
208}
209
210static int callchain_node__count_folded_rows(struct callchain_node *node __maybe_unused)
211{
212 return 1;
213}
214
181static int callchain_node__count_rows(struct callchain_node *node) 215static int callchain_node__count_rows(struct callchain_node *node)
182{ 216{
183 struct callchain_list *chain; 217 struct callchain_list *chain;
184 bool unfolded = false; 218 bool unfolded = false;
185 int n = 0; 219 int n = 0;
186 220
221 if (callchain_param.mode == CHAIN_FLAT)
222 return callchain_node__count_flat_rows(node);
223 else if (callchain_param.mode == CHAIN_FOLDED)
224 return callchain_node__count_folded_rows(node);
225
187 list_for_each_entry(chain, &node->val, list) { 226 list_for_each_entry(chain, &node->val, list) {
188 ++n; 227 ++n;
189 unfolded = chain->unfolded; 228 unfolded = chain->unfolded;
@@ -263,7 +302,7 @@ static void callchain_node__init_have_children(struct callchain_node *node,
263 chain = list_entry(node->val.next, struct callchain_list, list); 302 chain = list_entry(node->val.next, struct callchain_list, list);
264 chain->has_children = has_sibling; 303 chain->has_children = has_sibling;
265 304
266 if (!list_empty(&node->val)) { 305 if (node->val.next != node->val.prev) {
267 chain = list_entry(node->val.prev, struct callchain_list, list); 306 chain = list_entry(node->val.prev, struct callchain_list, list);
268 chain->has_children = !RB_EMPTY_ROOT(&node->rb_root); 307 chain->has_children = !RB_EMPTY_ROOT(&node->rb_root);
269 } 308 }
@@ -279,6 +318,9 @@ static void callchain__init_have_children(struct rb_root *root)
279 for (nd = rb_first(root); nd; nd = rb_next(nd)) { 318 for (nd = rb_first(root); nd; nd = rb_next(nd)) {
280 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node); 319 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
281 callchain_node__init_have_children(node, has_sibling); 320 callchain_node__init_have_children(node, has_sibling);
321 if (callchain_param.mode == CHAIN_FLAT ||
322 callchain_param.mode == CHAIN_FOLDED)
323 callchain_node__make_parent_list(node);
282 } 324 }
283} 325}
284 326
@@ -577,6 +619,231 @@ static bool hist_browser__check_dump_full(struct hist_browser *browser __maybe_u
577 619
578#define LEVEL_OFFSET_STEP 3 620#define LEVEL_OFFSET_STEP 3
579 621
622static int hist_browser__show_callchain_list(struct hist_browser *browser,
623 struct callchain_node *node,
624 struct callchain_list *chain,
625 unsigned short row, u64 total,
626 bool need_percent, int offset,
627 print_callchain_entry_fn print,
628 struct callchain_print_arg *arg)
629{
630 char bf[1024], *alloc_str;
631 const char *str;
632
633 if (arg->row_offset != 0) {
634 arg->row_offset--;
635 return 0;
636 }
637
638 alloc_str = NULL;
639 str = callchain_list__sym_name(chain, bf, sizeof(bf),
640 browser->show_dso);
641
642 if (need_percent) {
643 char buf[64];
644
645 callchain_node__scnprintf_value(node, buf, sizeof(buf),
646 total);
647
648 if (asprintf(&alloc_str, "%s %s", buf, str) < 0)
649 str = "Not enough memory!";
650 else
651 str = alloc_str;
652 }
653
654 print(browser, chain, str, offset, row, arg);
655
656 free(alloc_str);
657 return 1;
658}
659
660static int hist_browser__show_callchain_flat(struct hist_browser *browser,
661 struct rb_root *root,
662 unsigned short row, u64 total,
663 print_callchain_entry_fn print,
664 struct callchain_print_arg *arg,
665 check_output_full_fn is_output_full)
666{
667 struct rb_node *node;
668 int first_row = row, offset = LEVEL_OFFSET_STEP;
669 bool need_percent;
670
671 node = rb_first(root);
672 need_percent = node && rb_next(node);
673
674 while (node) {
675 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
676 struct rb_node *next = rb_next(node);
677 struct callchain_list *chain;
678 char folded_sign = ' ';
679 int first = true;
680 int extra_offset = 0;
681
682 list_for_each_entry(chain, &child->parent_val, list) {
683 bool was_first = first;
684
685 if (first)
686 first = false;
687 else if (need_percent)
688 extra_offset = LEVEL_OFFSET_STEP;
689
690 folded_sign = callchain_list__folded(chain);
691
692 row += hist_browser__show_callchain_list(browser, child,
693 chain, row, total,
694 was_first && need_percent,
695 offset + extra_offset,
696 print, arg);
697
698 if (is_output_full(browser, row))
699 goto out;
700
701 if (folded_sign == '+')
702 goto next;
703 }
704
705 list_for_each_entry(chain, &child->val, list) {
706 bool was_first = first;
707
708 if (first)
709 first = false;
710 else if (need_percent)
711 extra_offset = LEVEL_OFFSET_STEP;
712
713 folded_sign = callchain_list__folded(chain);
714
715 row += hist_browser__show_callchain_list(browser, child,
716 chain, row, total,
717 was_first && need_percent,
718 offset + extra_offset,
719 print, arg);
720
721 if (is_output_full(browser, row))
722 goto out;
723
724 if (folded_sign == '+')
725 break;
726 }
727
728next:
729 if (is_output_full(browser, row))
730 break;
731 node = next;
732 }
733out:
734 return row - first_row;
735}
736
737static char *hist_browser__folded_callchain_str(struct hist_browser *browser,
738 struct callchain_list *chain,
739 char *value_str, char *old_str)
740{
741 char bf[1024];
742 const char *str;
743 char *new;
744
745 str = callchain_list__sym_name(chain, bf, sizeof(bf),
746 browser->show_dso);
747 if (old_str) {
748 if (asprintf(&new, "%s%s%s", old_str,
749 symbol_conf.field_sep ?: ";", str) < 0)
750 new = NULL;
751 } else {
752 if (value_str) {
753 if (asprintf(&new, "%s %s", value_str, str) < 0)
754 new = NULL;
755 } else {
756 if (asprintf(&new, "%s", str) < 0)
757 new = NULL;
758 }
759 }
760 return new;
761}
762
763static int hist_browser__show_callchain_folded(struct hist_browser *browser,
764 struct rb_root *root,
765 unsigned short row, u64 total,
766 print_callchain_entry_fn print,
767 struct callchain_print_arg *arg,
768 check_output_full_fn is_output_full)
769{
770 struct rb_node *node;
771 int first_row = row, offset = LEVEL_OFFSET_STEP;
772 bool need_percent;
773
774 node = rb_first(root);
775 need_percent = node && rb_next(node);
776
777 while (node) {
778 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
779 struct rb_node *next = rb_next(node);
780 struct callchain_list *chain, *first_chain = NULL;
781 int first = true;
782 char *value_str = NULL, *value_str_alloc = NULL;
783 char *chain_str = NULL, *chain_str_alloc = NULL;
784
785 if (arg->row_offset != 0) {
786 arg->row_offset--;
787 goto next;
788 }
789
790 if (need_percent) {
791 char buf[64];
792
793 callchain_node__scnprintf_value(child, buf, sizeof(buf), total);
794 if (asprintf(&value_str, "%s", buf) < 0) {
795 value_str = (char *)"<...>";
796 goto do_print;
797 }
798 value_str_alloc = value_str;
799 }
800
801 list_for_each_entry(chain, &child->parent_val, list) {
802 chain_str = hist_browser__folded_callchain_str(browser,
803 chain, value_str, chain_str);
804 if (first) {
805 first = false;
806 first_chain = chain;
807 }
808
809 if (chain_str == NULL) {
810 chain_str = (char *)"Not enough memory!";
811 goto do_print;
812 }
813
814 chain_str_alloc = chain_str;
815 }
816
817 list_for_each_entry(chain, &child->val, list) {
818 chain_str = hist_browser__folded_callchain_str(browser,
819 chain, value_str, chain_str);
820 if (first) {
821 first = false;
822 first_chain = chain;
823 }
824
825 if (chain_str == NULL) {
826 chain_str = (char *)"Not enough memory!";
827 goto do_print;
828 }
829
830 chain_str_alloc = chain_str;
831 }
832
833do_print:
834 print(browser, first_chain, chain_str, offset, row++, arg);
835 free(value_str_alloc);
836 free(chain_str_alloc);
837
838next:
839 if (is_output_full(browser, row))
840 break;
841 node = next;
842 }
843
844 return row - first_row;
845}
846
580static int hist_browser__show_callchain(struct hist_browser *browser, 847static int hist_browser__show_callchain(struct hist_browser *browser,
581 struct rb_root *root, int level, 848 struct rb_root *root, int level,
582 unsigned short row, u64 total, 849 unsigned short row, u64 total,
@@ -595,15 +862,12 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
595 while (node) { 862 while (node) {
596 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); 863 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
597 struct rb_node *next = rb_next(node); 864 struct rb_node *next = rb_next(node);
598 u64 cumul = callchain_cumul_hits(child);
599 struct callchain_list *chain; 865 struct callchain_list *chain;
600 char folded_sign = ' '; 866 char folded_sign = ' ';
601 int first = true; 867 int first = true;
602 int extra_offset = 0; 868 int extra_offset = 0;
603 869
604 list_for_each_entry(chain, &child->val, list) { 870 list_for_each_entry(chain, &child->val, list) {
605 char bf[1024], *alloc_str;
606 const char *str;
607 bool was_first = first; 871 bool was_first = first;
608 872
609 if (first) 873 if (first)
@@ -612,31 +876,16 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
612 extra_offset = LEVEL_OFFSET_STEP; 876 extra_offset = LEVEL_OFFSET_STEP;
613 877
614 folded_sign = callchain_list__folded(chain); 878 folded_sign = callchain_list__folded(chain);
615 if (arg->row_offset != 0) {
616 arg->row_offset--;
617 goto do_next;
618 }
619
620 alloc_str = NULL;
621 str = callchain_list__sym_name(chain, bf, sizeof(bf),
622 browser->show_dso);
623
624 if (was_first && need_percent) {
625 double percent = cumul * 100.0 / total;
626
627 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
628 str = "Not enough memory!";
629 else
630 str = alloc_str;
631 }
632 879
633 print(browser, chain, str, offset + extra_offset, row, arg); 880 row += hist_browser__show_callchain_list(browser, child,
881 chain, row, total,
882 was_first && need_percent,
883 offset + extra_offset,
884 print, arg);
634 885
635 free(alloc_str); 886 if (is_output_full(browser, row))
636
637 if (is_output_full(browser, ++row))
638 goto out; 887 goto out;
639do_next: 888
640 if (folded_sign == '+') 889 if (folded_sign == '+')
641 break; 890 break;
642 } 891 }
@@ -792,7 +1041,8 @@ static int hist_browser__show_entry(struct hist_browser *browser,
792 hist_browser__gotorc(browser, row, 0); 1041 hist_browser__gotorc(browser, row, 0);
793 1042
794 perf_hpp__for_each_format(fmt) { 1043 perf_hpp__for_each_format(fmt) {
795 if (perf_hpp__should_skip(fmt) || column++ < browser->b.horiz_scroll) 1044 if (perf_hpp__should_skip(fmt, entry->hists) ||
1045 column++ < browser->b.horiz_scroll)
796 continue; 1046 continue;
797 1047
798 if (current_entry && browser->b.navkeypressed) { 1048 if (current_entry && browser->b.navkeypressed) {
@@ -847,10 +1097,22 @@ static int hist_browser__show_entry(struct hist_browser *browser,
847 total = entry->stat.period; 1097 total = entry->stat.period;
848 } 1098 }
849 1099
850 printed += hist_browser__show_callchain(browser, 1100 if (callchain_param.mode == CHAIN_FLAT) {
1101 printed += hist_browser__show_callchain_flat(browser,
1102 &entry->sorted_chain, row, total,
1103 hist_browser__show_callchain_entry, &arg,
1104 hist_browser__check_output_full);
1105 } else if (callchain_param.mode == CHAIN_FOLDED) {
1106 printed += hist_browser__show_callchain_folded(browser,
1107 &entry->sorted_chain, row, total,
1108 hist_browser__show_callchain_entry, &arg,
1109 hist_browser__check_output_full);
1110 } else {
1111 printed += hist_browser__show_callchain(browser,
851 &entry->sorted_chain, 1, row, total, 1112 &entry->sorted_chain, 1, row, total,
852 hist_browser__show_callchain_entry, &arg, 1113 hist_browser__show_callchain_entry, &arg,
853 hist_browser__check_output_full); 1114 hist_browser__check_output_full);
1115 }
854 1116
855 if (arg.is_current_entry) 1117 if (arg.is_current_entry)
856 browser->he_selection = entry; 1118 browser->he_selection = entry;
@@ -883,7 +1145,7 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *
883 } 1145 }
884 1146
885 perf_hpp__for_each_format(fmt) { 1147 perf_hpp__for_each_format(fmt) {
886 if (perf_hpp__should_skip(fmt) || column++ < browser->b.horiz_scroll) 1148 if (perf_hpp__should_skip(fmt, hists) || column++ < browser->b.horiz_scroll)
887 continue; 1149 continue;
888 1150
889 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 1151 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
@@ -1153,7 +1415,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
1153 printed += fprintf(fp, "%c ", folded_sign); 1415 printed += fprintf(fp, "%c ", folded_sign);
1154 1416
1155 perf_hpp__for_each_format(fmt) { 1417 perf_hpp__for_each_format(fmt) {
1156 if (perf_hpp__should_skip(fmt)) 1418 if (perf_hpp__should_skip(fmt, he->hists))
1157 continue; 1419 continue;
1158 1420
1159 if (!first) { 1421 if (!first) {
@@ -1802,10 +2064,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1802 SLang_reset_tty(); 2064 SLang_reset_tty();
1803 SLang_init_tty(0, 0, 0); 2065 SLang_init_tty(0, 0, 0);
1804 2066
1805 if (min_pcnt) { 2067 if (min_pcnt)
1806 browser->min_pcnt = min_pcnt; 2068 browser->min_pcnt = min_pcnt;
1807 hist_browser__update_nr_entries(browser); 2069 hist_browser__update_nr_entries(browser);
1808 }
1809 2070
1810 browser->pstack = pstack__new(3); 2071 browser->pstack = pstack__new(3);
1811 if (browser->pstack == NULL) 2072 if (browser->pstack == NULL)
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 4b3585eed1e8..0f8dcfdfb10f 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -89,8 +89,8 @@ void perf_gtk__init_hpp(void)
89 perf_gtk__hpp_color_overhead_acc; 89 perf_gtk__hpp_color_overhead_acc;
90} 90}
91 91
92static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, 92static void perf_gtk__add_callchain_flat(struct rb_root *root, GtkTreeStore *store,
93 GtkTreeIter *parent, int col, u64 total) 93 GtkTreeIter *parent, int col, u64 total)
94{ 94{
95 struct rb_node *nd; 95 struct rb_node *nd;
96 bool has_single_node = (rb_first(root) == rb_last(root)); 96 bool has_single_node = (rb_first(root) == rb_last(root));
@@ -100,13 +100,132 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
100 struct callchain_list *chain; 100 struct callchain_list *chain;
101 GtkTreeIter iter, new_parent; 101 GtkTreeIter iter, new_parent;
102 bool need_new_parent; 102 bool need_new_parent;
103 double percent;
104 u64 hits, child_total;
105 103
106 node = rb_entry(nd, struct callchain_node, rb_node); 104 node = rb_entry(nd, struct callchain_node, rb_node);
107 105
108 hits = callchain_cumul_hits(node); 106 new_parent = *parent;
109 percent = 100.0 * hits / total; 107 need_new_parent = !has_single_node;
108
109 callchain_node__make_parent_list(node);
110
111 list_for_each_entry(chain, &node->parent_val, list) {
112 char buf[128];
113
114 gtk_tree_store_append(store, &iter, &new_parent);
115
116 callchain_node__scnprintf_value(node, buf, sizeof(buf), total);
117 gtk_tree_store_set(store, &iter, 0, buf, -1);
118
119 callchain_list__sym_name(chain, buf, sizeof(buf), false);
120 gtk_tree_store_set(store, &iter, col, buf, -1);
121
122 if (need_new_parent) {
123 /*
124 * Only show the top-most symbol in a callchain
125 * if it's not the only callchain.
126 */
127 new_parent = iter;
128 need_new_parent = false;
129 }
130 }
131
132 list_for_each_entry(chain, &node->val, list) {
133 char buf[128];
134
135 gtk_tree_store_append(store, &iter, &new_parent);
136
137 callchain_node__scnprintf_value(node, buf, sizeof(buf), total);
138 gtk_tree_store_set(store, &iter, 0, buf, -1);
139
140 callchain_list__sym_name(chain, buf, sizeof(buf), false);
141 gtk_tree_store_set(store, &iter, col, buf, -1);
142
143 if (need_new_parent) {
144 /*
145 * Only show the top-most symbol in a callchain
146 * if it's not the only callchain.
147 */
148 new_parent = iter;
149 need_new_parent = false;
150 }
151 }
152 }
153}
154
155static void perf_gtk__add_callchain_folded(struct rb_root *root, GtkTreeStore *store,
156 GtkTreeIter *parent, int col, u64 total)
157{
158 struct rb_node *nd;
159
160 for (nd = rb_first(root); nd; nd = rb_next(nd)) {
161 struct callchain_node *node;
162 struct callchain_list *chain;
163 GtkTreeIter iter;
164 char buf[64];
165 char *str, *str_alloc = NULL;
166 bool first = true;
167
168 node = rb_entry(nd, struct callchain_node, rb_node);
169
170 callchain_node__make_parent_list(node);
171
172 list_for_each_entry(chain, &node->parent_val, list) {
173 char name[1024];
174
175 callchain_list__sym_name(chain, name, sizeof(name), false);
176
177 if (asprintf(&str, "%s%s%s",
178 first ? "" : str_alloc,
179 first ? "" : symbol_conf.field_sep ?: "; ",
180 name) < 0)
181 return;
182
183 first = false;
184 free(str_alloc);
185 str_alloc = str;
186 }
187
188 list_for_each_entry(chain, &node->val, list) {
189 char name[1024];
190
191 callchain_list__sym_name(chain, name, sizeof(name), false);
192
193 if (asprintf(&str, "%s%s%s",
194 first ? "" : str_alloc,
195 first ? "" : symbol_conf.field_sep ?: "; ",
196 name) < 0)
197 return;
198
199 first = false;
200 free(str_alloc);
201 str_alloc = str;
202 }
203
204 gtk_tree_store_append(store, &iter, parent);
205
206 callchain_node__scnprintf_value(node, buf, sizeof(buf), total);
207 gtk_tree_store_set(store, &iter, 0, buf, -1);
208
209 gtk_tree_store_set(store, &iter, col, str, -1);
210
211 free(str_alloc);
212 }
213}
214
215static void perf_gtk__add_callchain_graph(struct rb_root *root, GtkTreeStore *store,
216 GtkTreeIter *parent, int col, u64 total)
217{
218 struct rb_node *nd;
219 bool has_single_node = (rb_first(root) == rb_last(root));
220
221 for (nd = rb_first(root); nd; nd = rb_next(nd)) {
222 struct callchain_node *node;
223 struct callchain_list *chain;
224 GtkTreeIter iter, new_parent;
225 bool need_new_parent;
226 u64 child_total;
227
228 node = rb_entry(nd, struct callchain_node, rb_node);
110 229
111 new_parent = *parent; 230 new_parent = *parent;
112 need_new_parent = !has_single_node && (node->val_nr > 1); 231 need_new_parent = !has_single_node && (node->val_nr > 1);
@@ -116,7 +235,7 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
116 235
117 gtk_tree_store_append(store, &iter, &new_parent); 236 gtk_tree_store_append(store, &iter, &new_parent);
118 237
119 scnprintf(buf, sizeof(buf), "%5.2f%%", percent); 238 callchain_node__scnprintf_value(node, buf, sizeof(buf), total);
120 gtk_tree_store_set(store, &iter, 0, buf, -1); 239 gtk_tree_store_set(store, &iter, 0, buf, -1);
121 240
122 callchain_list__sym_name(chain, buf, sizeof(buf), false); 241 callchain_list__sym_name(chain, buf, sizeof(buf), false);
@@ -138,11 +257,22 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
138 child_total = total; 257 child_total = total;
139 258
140 /* Now 'iter' contains info of the last callchain_list */ 259 /* Now 'iter' contains info of the last callchain_list */
141 perf_gtk__add_callchain(&node->rb_root, store, &iter, col, 260 perf_gtk__add_callchain_graph(&node->rb_root, store, &iter, col,
142 child_total); 261 child_total);
143 } 262 }
144} 263}
145 264
265static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
266 GtkTreeIter *parent, int col, u64 total)
267{
268 if (callchain_param.mode == CHAIN_FLAT)
269 perf_gtk__add_callchain_flat(root, store, parent, col, total);
270 else if (callchain_param.mode == CHAIN_FOLDED)
271 perf_gtk__add_callchain_folded(root, store, parent, col, total);
272 else
273 perf_gtk__add_callchain_graph(root, store, parent, col, total);
274}
275
146static void on_row_activated(GtkTreeView *view, GtkTreePath *path, 276static void on_row_activated(GtkTreeView *view, GtkTreePath *path,
147 GtkTreeViewColumn *col __maybe_unused, 277 GtkTreeViewColumn *col __maybe_unused,
148 gpointer user_data __maybe_unused) 278 gpointer user_data __maybe_unused)
@@ -188,7 +318,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
188 col_idx = 0; 318 col_idx = 0;
189 319
190 perf_hpp__for_each_format(fmt) { 320 perf_hpp__for_each_format(fmt) {
191 if (perf_hpp__should_skip(fmt)) 321 if (perf_hpp__should_skip(fmt, hists))
192 continue; 322 continue;
193 323
194 /* 324 /*
@@ -238,7 +368,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
238 col_idx = 0; 368 col_idx = 0;
239 369
240 perf_hpp__for_each_format(fmt) { 370 perf_hpp__for_each_format(fmt) {
241 if (perf_hpp__should_skip(fmt)) 371 if (perf_hpp__should_skip(fmt, h->hists))
242 continue; 372 continue;
243 373
244 if (fmt->color) 374 if (fmt->color)
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 5029ba2b55af..bf2a66e254ea 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -443,7 +443,6 @@ LIST_HEAD(perf_hpp__sort_list);
443 443
444void perf_hpp__init(void) 444void perf_hpp__init(void)
445{ 445{
446 struct list_head *list;
447 int i; 446 int i;
448 447
449 for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { 448 for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
@@ -484,17 +483,6 @@ void perf_hpp__init(void)
484 483
485 if (symbol_conf.show_total_period) 484 if (symbol_conf.show_total_period)
486 hpp_dimension__add_output(PERF_HPP__PERIOD); 485 hpp_dimension__add_output(PERF_HPP__PERIOD);
487
488 /* prepend overhead field for backward compatiblity. */
489 list = &perf_hpp__format[PERF_HPP__OVERHEAD].sort_list;
490 if (list_empty(list))
491 list_add(list, &perf_hpp__sort_list);
492
493 if (symbol_conf.cumulate_callchain) {
494 list = &perf_hpp__format[PERF_HPP__OVERHEAD_ACC].sort_list;
495 if (list_empty(list))
496 list_add(list, &perf_hpp__sort_list);
497 }
498} 486}
499 487
500void perf_hpp__column_register(struct perf_hpp_fmt *format) 488void perf_hpp__column_register(struct perf_hpp_fmt *format)
@@ -619,7 +607,7 @@ unsigned int hists__sort_list_width(struct hists *hists)
619 struct perf_hpp dummy_hpp; 607 struct perf_hpp dummy_hpp;
620 608
621 perf_hpp__for_each_format(fmt) { 609 perf_hpp__for_each_format(fmt) {
622 if (perf_hpp__should_skip(fmt)) 610 if (perf_hpp__should_skip(fmt, hists))
623 continue; 611 continue;
624 612
625 if (first) 613 if (first)
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index dfcbc90146ef..387110d50b00 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -34,10 +34,10 @@ static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
34 return ret; 34 return ret;
35} 35}
36 36
37static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, 37static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
38 struct callchain_list *chain,
38 int depth, int depth_mask, int period, 39 int depth, int depth_mask, int period,
39 u64 total_samples, u64 hits, 40 u64 total_samples, int left_margin)
40 int left_margin)
41{ 41{
42 int i; 42 int i;
43 size_t ret = 0; 43 size_t ret = 0;
@@ -50,10 +50,9 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
50 else 50 else
51 ret += fprintf(fp, " "); 51 ret += fprintf(fp, " ");
52 if (!period && i == depth - 1) { 52 if (!period && i == depth - 1) {
53 double percent; 53 ret += fprintf(fp, "--");
54 54 ret += callchain_node__fprintf_value(node, fp, total_samples);
55 percent = hits * 100.0 / total_samples; 55 ret += fprintf(fp, "--");
56 ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
57 } else 56 } else
58 ret += fprintf(fp, "%s", " "); 57 ret += fprintf(fp, "%s", " ");
59 } 58 }
@@ -82,13 +81,14 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
82 int depth_mask, int left_margin) 81 int depth_mask, int left_margin)
83{ 82{
84 struct rb_node *node, *next; 83 struct rb_node *node, *next;
85 struct callchain_node *child; 84 struct callchain_node *child = NULL;
86 struct callchain_list *chain; 85 struct callchain_list *chain;
87 int new_depth_mask = depth_mask; 86 int new_depth_mask = depth_mask;
88 u64 remaining; 87 u64 remaining;
89 size_t ret = 0; 88 size_t ret = 0;
90 int i; 89 int i;
91 uint entries_printed = 0; 90 uint entries_printed = 0;
91 int cumul_count = 0;
92 92
93 remaining = total_samples; 93 remaining = total_samples;
94 94
@@ -100,6 +100,7 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
100 child = rb_entry(node, struct callchain_node, rb_node); 100 child = rb_entry(node, struct callchain_node, rb_node);
101 cumul = callchain_cumul_hits(child); 101 cumul = callchain_cumul_hits(child);
102 remaining -= cumul; 102 remaining -= cumul;
103 cumul_count += callchain_cumul_counts(child);
103 104
104 /* 105 /*
105 * The depth mask manages the output of pipes that show 106 * The depth mask manages the output of pipes that show
@@ -120,10 +121,9 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
120 left_margin); 121 left_margin);
121 i = 0; 122 i = 0;
122 list_for_each_entry(chain, &child->val, list) { 123 list_for_each_entry(chain, &child->val, list) {
123 ret += ipchain__fprintf_graph(fp, chain, depth, 124 ret += ipchain__fprintf_graph(fp, child, chain, depth,
124 new_depth_mask, i++, 125 new_depth_mask, i++,
125 total_samples, 126 total_samples,
126 cumul,
127 left_margin); 127 left_margin);
128 } 128 }
129 129
@@ -143,14 +143,23 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
143 143
144 if (callchain_param.mode == CHAIN_GRAPH_REL && 144 if (callchain_param.mode == CHAIN_GRAPH_REL &&
145 remaining && remaining != total_samples) { 145 remaining && remaining != total_samples) {
146 struct callchain_node rem_node = {
147 .hit = remaining,
148 };
146 149
147 if (!rem_sq_bracket) 150 if (!rem_sq_bracket)
148 return ret; 151 return ret;
149 152
153 if (callchain_param.value == CCVAL_COUNT && child && child->parent) {
154 rem_node.count = child->parent->children_count - cumul_count;
155 if (rem_node.count <= 0)
156 return ret;
157 }
158
150 new_depth_mask &= ~(1 << (depth - 1)); 159 new_depth_mask &= ~(1 << (depth - 1));
151 ret += ipchain__fprintf_graph(fp, &rem_hits, depth, 160 ret += ipchain__fprintf_graph(fp, &rem_node, &rem_hits, depth,
152 new_depth_mask, 0, total_samples, 161 new_depth_mask, 0, total_samples,
153 remaining, left_margin); 162 left_margin);
154 } 163 }
155 164
156 return ret; 165 return ret;
@@ -243,12 +252,11 @@ static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *tree,
243 struct rb_node *rb_node = rb_first(tree); 252 struct rb_node *rb_node = rb_first(tree);
244 253
245 while (rb_node) { 254 while (rb_node) {
246 double percent;
247
248 chain = rb_entry(rb_node, struct callchain_node, rb_node); 255 chain = rb_entry(rb_node, struct callchain_node, rb_node);
249 percent = chain->hit * 100.0 / total_samples;
250 256
251 ret = percent_color_fprintf(fp, " %6.2f%%\n", percent); 257 ret += fprintf(fp, " ");
258 ret += callchain_node__fprintf_value(chain, fp, total_samples);
259 ret += fprintf(fp, "\n");
252 ret += __callchain__fprintf_flat(fp, chain, total_samples); 260 ret += __callchain__fprintf_flat(fp, chain, total_samples);
253 ret += fprintf(fp, "\n"); 261 ret += fprintf(fp, "\n");
254 if (++entries_printed == callchain_param.print_limit) 262 if (++entries_printed == callchain_param.print_limit)
@@ -260,6 +268,57 @@ static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *tree,
260 return ret; 268 return ret;
261} 269}
262 270
271static size_t __callchain__fprintf_folded(FILE *fp, struct callchain_node *node)
272{
273 const char *sep = symbol_conf.field_sep ?: ";";
274 struct callchain_list *chain;
275 size_t ret = 0;
276 char bf[1024];
277 bool first;
278
279 if (!node)
280 return 0;
281
282 ret += __callchain__fprintf_folded(fp, node->parent);
283
284 first = (ret == 0);
285 list_for_each_entry(chain, &node->val, list) {
286 if (chain->ip >= PERF_CONTEXT_MAX)
287 continue;
288 ret += fprintf(fp, "%s%s", first ? "" : sep,
289 callchain_list__sym_name(chain,
290 bf, sizeof(bf), false));
291 first = false;
292 }
293
294 return ret;
295}
296
297static size_t callchain__fprintf_folded(FILE *fp, struct rb_root *tree,
298 u64 total_samples)
299{
300 size_t ret = 0;
301 u32 entries_printed = 0;
302 struct callchain_node *chain;
303 struct rb_node *rb_node = rb_first(tree);
304
305 while (rb_node) {
306
307 chain = rb_entry(rb_node, struct callchain_node, rb_node);
308
309 ret += callchain_node__fprintf_value(chain, fp, total_samples);
310 ret += fprintf(fp, " ");
311 ret += __callchain__fprintf_folded(fp, chain);
312 ret += fprintf(fp, "\n");
313 if (++entries_printed == callchain_param.print_limit)
314 break;
315
316 rb_node = rb_next(rb_node);
317 }
318
319 return ret;
320}
321
263static size_t hist_entry_callchain__fprintf(struct hist_entry *he, 322static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
264 u64 total_samples, int left_margin, 323 u64 total_samples, int left_margin,
265 FILE *fp) 324 FILE *fp)
@@ -278,6 +337,9 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
278 case CHAIN_FLAT: 337 case CHAIN_FLAT:
279 return callchain__fprintf_flat(fp, &he->sorted_chain, total_samples); 338 return callchain__fprintf_flat(fp, &he->sorted_chain, total_samples);
280 break; 339 break;
340 case CHAIN_FOLDED:
341 return callchain__fprintf_folded(fp, &he->sorted_chain, total_samples);
342 break;
281 case CHAIN_NONE: 343 case CHAIN_NONE:
282 break; 344 break;
283 default: 345 default:
@@ -323,7 +385,7 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp)
323 return 0; 385 return 0;
324 386
325 perf_hpp__for_each_format(fmt) { 387 perf_hpp__for_each_format(fmt) {
326 if (perf_hpp__should_skip(fmt)) 388 if (perf_hpp__should_skip(fmt, he->hists))
327 continue; 389 continue;
328 390
329 /* 391 /*
@@ -402,7 +464,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
402 fprintf(fp, "# "); 464 fprintf(fp, "# ");
403 465
404 perf_hpp__for_each_format(fmt) { 466 perf_hpp__for_each_format(fmt) {
405 if (perf_hpp__should_skip(fmt)) 467 if (perf_hpp__should_skip(fmt, hists))
406 continue; 468 continue;
407 469
408 if (!first) 470 if (!first)
@@ -428,7 +490,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
428 perf_hpp__for_each_format(fmt) { 490 perf_hpp__for_each_format(fmt) {
429 unsigned int i; 491 unsigned int i;
430 492
431 if (perf_hpp__should_skip(fmt)) 493 if (perf_hpp__should_skip(fmt, hists))
432 continue; 494 continue;
433 495
434 if (!first) 496 if (!first)
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 591b3fe3ed49..5eec53a3f4ac 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -6,24 +6,20 @@ libperf-y += config.o
6libperf-y += ctype.o 6libperf-y += ctype.o
7libperf-y += db-export.o 7libperf-y += db-export.o
8libperf-y += env.o 8libperf-y += env.o
9libperf-y += environment.o
10libperf-y += event.o 9libperf-y += event.o
11libperf-y += evlist.o 10libperf-y += evlist.o
12libperf-y += evsel.o 11libperf-y += evsel.o
13libperf-y += exec_cmd.o 12libperf-y += find_bit.o
14libperf-y += find_next_bit.o
15libperf-y += help.o
16libperf-y += kallsyms.o 13libperf-y += kallsyms.o
17libperf-y += levenshtein.o 14libperf-y += levenshtein.o
18libperf-y += llvm-utils.o 15libperf-y += llvm-utils.o
19libperf-y += parse-options.o
20libperf-y += parse-events.o 16libperf-y += parse-events.o
21libperf-y += perf_regs.o 17libperf-y += perf_regs.o
22libperf-y += path.o 18libperf-y += path.o
23libperf-y += rbtree.o 19libperf-y += rbtree.o
20libperf-y += libstring.o
24libperf-y += bitmap.o 21libperf-y += bitmap.o
25libperf-y += hweight.o 22libperf-y += hweight.o
26libperf-y += run-command.o
27libperf-y += quote.o 23libperf-y += quote.o
28libperf-y += strbuf.o 24libperf-y += strbuf.o
29libperf-y += string.o 25libperf-y += string.o
@@ -32,11 +28,9 @@ libperf-y += strfilter.o
32libperf-y += top.o 28libperf-y += top.o
33libperf-y += usage.o 29libperf-y += usage.o
34libperf-y += wrapper.o 30libperf-y += wrapper.o
35libperf-y += sigchain.o
36libperf-y += dso.o 31libperf-y += dso.o
37libperf-y += symbol.o 32libperf-y += symbol.o
38libperf-y += color.o 33libperf-y += color.o
39libperf-y += pager.o
40libperf-y += header.o 34libperf-y += header.o
41libperf-y += callchain.o 35libperf-y += callchain.o
42libperf-y += values.o 36libperf-y += values.o
@@ -86,8 +80,11 @@ libperf-$(CONFIG_AUXTRACE) += intel-pt.o
86libperf-$(CONFIG_AUXTRACE) += intel-bts.o 80libperf-$(CONFIG_AUXTRACE) += intel-bts.o
87libperf-y += parse-branch-options.o 81libperf-y += parse-branch-options.o
88libperf-y += parse-regs-options.o 82libperf-y += parse-regs-options.o
83libperf-y += term.o
84libperf-y += help-unknown-cmd.o
89 85
90libperf-$(CONFIG_LIBBPF) += bpf-loader.o 86libperf-$(CONFIG_LIBBPF) += bpf-loader.o
87libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
91libperf-$(CONFIG_LIBELF) += symbol-elf.o 88libperf-$(CONFIG_LIBELF) += symbol-elf.o
92libperf-$(CONFIG_LIBELF) += probe-file.o 89libperf-$(CONFIG_LIBELF) += probe-file.o
93libperf-$(CONFIG_LIBELF) += probe-event.o 90libperf-$(CONFIG_LIBELF) += probe-event.o
@@ -110,7 +107,6 @@ libperf-$(CONFIG_ZLIB) += zlib.o
110libperf-$(CONFIG_LZMA) += lzma.o 107libperf-$(CONFIG_LZMA) += lzma.o
111 108
112CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" 109CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
113CFLAGS_exec_cmd.o += -DPERF_EXEC_PATH="BUILD_STR($(perfexecdir_SQ))" -DPREFIX="BUILD_STR($(prefix_SQ))"
114 110
115$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c 111$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
116 $(call rule_mkdir) 112 $(call rule_mkdir)
@@ -136,8 +132,10 @@ CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w
136$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c 132$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
137$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c 133$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
138 134
139CFLAGS_find_next_bit.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" 135CFLAGS_bitmap.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
136CFLAGS_find_bit.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
140CFLAGS_rbtree.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" 137CFLAGS_rbtree.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
138CFLAGS_libstring.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
141CFLAGS_hweight.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" 139CFLAGS_hweight.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
142CFLAGS_parse-events.o += -Wno-redundant-decls 140CFLAGS_parse-events.o += -Wno-redundant-decls
143 141
@@ -145,7 +143,11 @@ $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE
145 $(call rule_mkdir) 143 $(call rule_mkdir)
146 $(call if_changed_dep,cc_o_c) 144 $(call if_changed_dep,cc_o_c)
147 145
148$(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c FORCE 146$(OUTPUT)util/bitmap.o: ../lib/bitmap.c FORCE
147 $(call rule_mkdir)
148 $(call if_changed_dep,cc_o_c)
149
150$(OUTPUT)util/find_bit.o: ../lib/find_bit.c FORCE
149 $(call rule_mkdir) 151 $(call rule_mkdir)
150 $(call if_changed_dep,cc_o_c) 152 $(call if_changed_dep,cc_o_c)
151 153
@@ -153,6 +155,10 @@ $(OUTPUT)util/rbtree.o: ../lib/rbtree.c FORCE
153 $(call rule_mkdir) 155 $(call rule_mkdir)
154 $(call if_changed_dep,cc_o_c) 156 $(call if_changed_dep,cc_o_c)
155 157
158$(OUTPUT)util/libstring.o: ../lib/string.c FORCE
159 $(call rule_mkdir)
160 $(call if_changed_dep,cc_o_c)
161
156$(OUTPUT)util/hweight.o: ../lib/hweight.c FORCE 162$(OUTPUT)util/hweight.o: ../lib/hweight.c FORCE
157 $(call rule_mkdir) 163 $(call rule_mkdir)
158 $(call if_changed_dep,cc_o_c) 164 $(call if_changed_dep,cc_o_c)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 1dd1949b0e79..b795b6994144 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -65,6 +65,11 @@ static int call__parse(struct ins_operands *ops)
65 65
66 name++; 66 name++;
67 67
68#ifdef __arm__
69 if (strchr(name, '+'))
70 return -1;
71#endif
72
68 tok = strchr(name, '>'); 73 tok = strchr(name, '>');
69 if (tok == NULL) 74 if (tok == NULL)
70 return -1; 75 return -1;
@@ -246,7 +251,11 @@ static int mov__parse(struct ins_operands *ops)
246 return -1; 251 return -1;
247 252
248 target = ++s; 253 target = ++s;
254#ifdef __arm__
255 comment = strchr(s, ';');
256#else
249 comment = strchr(s, '#'); 257 comment = strchr(s, '#');
258#endif
250 259
251 if (comment != NULL) 260 if (comment != NULL)
252 s = comment - 1; 261 s = comment - 1;
@@ -354,6 +363,20 @@ static struct ins instructions[] = {
354 { .name = "addq", .ops = &mov_ops, }, 363 { .name = "addq", .ops = &mov_ops, },
355 { .name = "addw", .ops = &mov_ops, }, 364 { .name = "addw", .ops = &mov_ops, },
356 { .name = "and", .ops = &mov_ops, }, 365 { .name = "and", .ops = &mov_ops, },
366#ifdef __arm__
367 { .name = "b", .ops = &jump_ops, }, // might also be a call
368 { .name = "bcc", .ops = &jump_ops, },
369 { .name = "bcs", .ops = &jump_ops, },
370 { .name = "beq", .ops = &jump_ops, },
371 { .name = "bge", .ops = &jump_ops, },
372 { .name = "bgt", .ops = &jump_ops, },
373 { .name = "bhi", .ops = &jump_ops, },
374 { .name = "bl", .ops = &call_ops, },
375 { .name = "blt", .ops = &jump_ops, },
376 { .name = "bls", .ops = &jump_ops, },
377 { .name = "blx", .ops = &call_ops, },
378 { .name = "bne", .ops = &jump_ops, },
379#endif
357 { .name = "bts", .ops = &mov_ops, }, 380 { .name = "bts", .ops = &mov_ops, },
358 { .name = "call", .ops = &call_ops, }, 381 { .name = "call", .ops = &call_ops, },
359 { .name = "callq", .ops = &call_ops, }, 382 { .name = "callq", .ops = &call_ops, },
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 7f10430af39c..360fda01f3b0 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -45,7 +45,7 @@
45#include "event.h" 45#include "event.h"
46#include "session.h" 46#include "session.h"
47#include "debug.h" 47#include "debug.h"
48#include "parse-options.h" 48#include <subcmd/parse-options.h>
49 49
50#include "intel-pt.h" 50#include "intel-pt.h"
51#include "intel-bts.h" 51#include "intel-bts.h"
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 4c50411371db..540a7efa657e 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -5,11 +5,15 @@
5 * Copyright (C) 2015 Huawei Inc. 5 * Copyright (C) 2015 Huawei Inc.
6 */ 6 */
7 7
8#include <linux/bpf.h>
8#include <bpf/libbpf.h> 9#include <bpf/libbpf.h>
9#include <linux/err.h> 10#include <linux/err.h>
11#include <linux/string.h>
10#include "perf.h" 12#include "perf.h"
11#include "debug.h" 13#include "debug.h"
12#include "bpf-loader.h" 14#include "bpf-loader.h"
15#include "bpf-prologue.h"
16#include "llvm-utils.h"
13#include "probe-event.h" 17#include "probe-event.h"
14#include "probe-finder.h" // for MAX_PROBES 18#include "probe-finder.h" // for MAX_PROBES
15#include "llvm-utils.h" 19#include "llvm-utils.h"
@@ -32,6 +36,10 @@ DEFINE_PRINT_FN(debug, 1)
32 36
33struct bpf_prog_priv { 37struct bpf_prog_priv {
34 struct perf_probe_event pev; 38 struct perf_probe_event pev;
39 bool need_prologue;
40 struct bpf_insn *insns_buf;
41 int nr_types;
42 int *type_mapping;
35}; 43};
36 44
37static bool libbpf_initialized; 45static bool libbpf_initialized;
@@ -106,10 +114,178 @@ bpf_prog_priv__clear(struct bpf_program *prog __maybe_unused,
106 struct bpf_prog_priv *priv = _priv; 114 struct bpf_prog_priv *priv = _priv;
107 115
108 cleanup_perf_probe_events(&priv->pev, 1); 116 cleanup_perf_probe_events(&priv->pev, 1);
117 zfree(&priv->insns_buf);
118 zfree(&priv->type_mapping);
109 free(priv); 119 free(priv);
110} 120}
111 121
112static int 122static int
123prog_config__exec(const char *value, struct perf_probe_event *pev)
124{
125 pev->uprobes = true;
126 pev->target = strdup(value);
127 if (!pev->target)
128 return -ENOMEM;
129 return 0;
130}
131
132static int
133prog_config__module(const char *value, struct perf_probe_event *pev)
134{
135 pev->uprobes = false;
136 pev->target = strdup(value);
137 if (!pev->target)
138 return -ENOMEM;
139 return 0;
140}
141
142static int
143prog_config__bool(const char *value, bool *pbool, bool invert)
144{
145 int err;
146 bool bool_value;
147
148 if (!pbool)
149 return -EINVAL;
150
151 err = strtobool(value, &bool_value);
152 if (err)
153 return err;
154
155 *pbool = invert ? !bool_value : bool_value;
156 return 0;
157}
158
159static int
160prog_config__inlines(const char *value,
161 struct perf_probe_event *pev __maybe_unused)
162{
163 return prog_config__bool(value, &probe_conf.no_inlines, true);
164}
165
166static int
167prog_config__force(const char *value,
168 struct perf_probe_event *pev __maybe_unused)
169{
170 return prog_config__bool(value, &probe_conf.force_add, false);
171}
172
173static struct {
174 const char *key;
175 const char *usage;
176 const char *desc;
177 int (*func)(const char *, struct perf_probe_event *);
178} bpf_prog_config_terms[] = {
179 {
180 .key = "exec",
181 .usage = "exec=<full path of file>",
182 .desc = "Set uprobe target",
183 .func = prog_config__exec,
184 },
185 {
186 .key = "module",
187 .usage = "module=<module name> ",
188 .desc = "Set kprobe module",
189 .func = prog_config__module,
190 },
191 {
192 .key = "inlines",
193 .usage = "inlines=[yes|no] ",
194 .desc = "Probe at inline symbol",
195 .func = prog_config__inlines,
196 },
197 {
198 .key = "force",
199 .usage = "force=[yes|no] ",
200 .desc = "Forcibly add events with existing name",
201 .func = prog_config__force,
202 },
203};
204
205static int
206do_prog_config(const char *key, const char *value,
207 struct perf_probe_event *pev)
208{
209 unsigned int i;
210
211 pr_debug("config bpf program: %s=%s\n", key, value);
212 for (i = 0; i < ARRAY_SIZE(bpf_prog_config_terms); i++)
213 if (strcmp(key, bpf_prog_config_terms[i].key) == 0)
214 return bpf_prog_config_terms[i].func(value, pev);
215
216 pr_debug("BPF: ERROR: invalid program config option: %s=%s\n",
217 key, value);
218
219 pr_debug("\nHint: Valid options are:\n");
220 for (i = 0; i < ARRAY_SIZE(bpf_prog_config_terms); i++)
221 pr_debug("\t%s:\t%s\n", bpf_prog_config_terms[i].usage,
222 bpf_prog_config_terms[i].desc);
223 pr_debug("\n");
224
225 return -BPF_LOADER_ERRNO__PROGCONF_TERM;
226}
227
228static const char *
229parse_prog_config_kvpair(const char *config_str, struct perf_probe_event *pev)
230{
231 char *text = strdup(config_str);
232 char *sep, *line;
233 const char *main_str = NULL;
234 int err = 0;
235
236 if (!text) {
237 pr_debug("No enough memory: dup config_str failed\n");
238 return ERR_PTR(-ENOMEM);
239 }
240
241 line = text;
242 while ((sep = strchr(line, ';'))) {
243 char *equ;
244
245 *sep = '\0';
246 equ = strchr(line, '=');
247 if (!equ) {
248 pr_warning("WARNING: invalid config in BPF object: %s\n",
249 line);
250 pr_warning("\tShould be 'key=value'.\n");
251 goto nextline;
252 }
253 *equ = '\0';
254
255 err = do_prog_config(line, equ + 1, pev);
256 if (err)
257 break;
258nextline:
259 line = sep + 1;
260 }
261
262 if (!err)
263 main_str = config_str + (line - text);
264 free(text);
265
266 return err ? ERR_PTR(err) : main_str;
267}
268
269static int
270parse_prog_config(const char *config_str, struct perf_probe_event *pev)
271{
272 int err;
273 const char *main_str = parse_prog_config_kvpair(config_str, pev);
274
275 if (IS_ERR(main_str))
276 return PTR_ERR(main_str);
277
278 err = parse_perf_probe_command(main_str, pev);
279 if (err < 0) {
280 pr_debug("bpf: '%s' is not a valid config string\n",
281 config_str);
282 /* parse failed, don't need clear pev. */
283 return -BPF_LOADER_ERRNO__CONFIG;
284 }
285 return 0;
286}
287
288static int
113config_bpf_program(struct bpf_program *prog) 289config_bpf_program(struct bpf_program *prog)
114{ 290{
115 struct perf_probe_event *pev = NULL; 291 struct perf_probe_event *pev = NULL;
@@ -117,6 +293,10 @@ config_bpf_program(struct bpf_program *prog)
117 const char *config_str; 293 const char *config_str;
118 int err; 294 int err;
119 295
296 /* Initialize per-program probing setting */
297 probe_conf.no_inlines = false;
298 probe_conf.force_add = false;
299
120 config_str = bpf_program__title(prog, false); 300 config_str = bpf_program__title(prog, false);
121 if (IS_ERR(config_str)) { 301 if (IS_ERR(config_str)) {
122 pr_debug("bpf: unable to get title for program\n"); 302 pr_debug("bpf: unable to get title for program\n");
@@ -131,13 +311,9 @@ config_bpf_program(struct bpf_program *prog)
131 pev = &priv->pev; 311 pev = &priv->pev;
132 312
133 pr_debug("bpf: config program '%s'\n", config_str); 313 pr_debug("bpf: config program '%s'\n", config_str);
134 err = parse_perf_probe_command(config_str, pev); 314 err = parse_prog_config(config_str, pev);
135 if (err < 0) { 315 if (err)
136 pr_debug("bpf: '%s' is not a valid config string\n",
137 config_str);
138 err = -BPF_LOADER_ERRNO__CONFIG;
139 goto errout; 316 goto errout;
140 }
141 317
142 if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) { 318 if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) {
143 pr_debug("bpf: '%s': group for event is set and not '%s'.\n", 319 pr_debug("bpf: '%s': group for event is set and not '%s'.\n",
@@ -197,6 +373,220 @@ static int bpf__prepare_probe(void)
197 return err; 373 return err;
198} 374}
199 375
376static int
377preproc_gen_prologue(struct bpf_program *prog, int n,
378 struct bpf_insn *orig_insns, int orig_insns_cnt,
379 struct bpf_prog_prep_result *res)
380{
381 struct probe_trace_event *tev;
382 struct perf_probe_event *pev;
383 struct bpf_prog_priv *priv;
384 struct bpf_insn *buf;
385 size_t prologue_cnt = 0;
386 int i, err;
387
388 err = bpf_program__get_private(prog, (void **)&priv);
389 if (err || !priv)
390 goto errout;
391
392 pev = &priv->pev;
393
394 if (n < 0 || n >= priv->nr_types)
395 goto errout;
396
397 /* Find a tev belongs to that type */
398 for (i = 0; i < pev->ntevs; i++) {
399 if (priv->type_mapping[i] == n)
400 break;
401 }
402
403 if (i >= pev->ntevs) {
404 pr_debug("Internal error: prologue type %d not found\n", n);
405 return -BPF_LOADER_ERRNO__PROLOGUE;
406 }
407
408 tev = &pev->tevs[i];
409
410 buf = priv->insns_buf;
411 err = bpf__gen_prologue(tev->args, tev->nargs,
412 buf, &prologue_cnt,
413 BPF_MAXINSNS - orig_insns_cnt);
414 if (err) {
415 const char *title;
416
417 title = bpf_program__title(prog, false);
418 if (!title)
419 title = "[unknown]";
420
421 pr_debug("Failed to generate prologue for program %s\n",
422 title);
423 return err;
424 }
425
426 memcpy(&buf[prologue_cnt], orig_insns,
427 sizeof(struct bpf_insn) * orig_insns_cnt);
428
429 res->new_insn_ptr = buf;
430 res->new_insn_cnt = prologue_cnt + orig_insns_cnt;
431 res->pfd = NULL;
432 return 0;
433
434errout:
435 pr_debug("Internal error in preproc_gen_prologue\n");
436 return -BPF_LOADER_ERRNO__PROLOGUE;
437}
438
439/*
440 * compare_tev_args is reflexive, transitive and antisymmetric.
441 * I can proof it but this margin is too narrow to contain.
442 */
443static int compare_tev_args(const void *ptev1, const void *ptev2)
444{
445 int i, ret;
446 const struct probe_trace_event *tev1 =
447 *(const struct probe_trace_event **)ptev1;
448 const struct probe_trace_event *tev2 =
449 *(const struct probe_trace_event **)ptev2;
450
451 ret = tev2->nargs - tev1->nargs;
452 if (ret)
453 return ret;
454
455 for (i = 0; i < tev1->nargs; i++) {
456 struct probe_trace_arg *arg1, *arg2;
457 struct probe_trace_arg_ref *ref1, *ref2;
458
459 arg1 = &tev1->args[i];
460 arg2 = &tev2->args[i];
461
462 ret = strcmp(arg1->value, arg2->value);
463 if (ret)
464 return ret;
465
466 ref1 = arg1->ref;
467 ref2 = arg2->ref;
468
469 while (ref1 && ref2) {
470 ret = ref2->offset - ref1->offset;
471 if (ret)
472 return ret;
473
474 ref1 = ref1->next;
475 ref2 = ref2->next;
476 }
477
478 if (ref1 || ref2)
479 return ref2 ? 1 : -1;
480 }
481
482 return 0;
483}
484
485/*
486 * Assign a type number to each tevs in a pev.
487 * mapping is an array with same slots as tevs in that pev.
488 * nr_types will be set to number of types.
489 */
490static int map_prologue(struct perf_probe_event *pev, int *mapping,
491 int *nr_types)
492{
493 int i, type = 0;
494 struct probe_trace_event **ptevs;
495
496 size_t array_sz = sizeof(*ptevs) * pev->ntevs;
497
498 ptevs = malloc(array_sz);
499 if (!ptevs) {
500 pr_debug("No ehough memory: alloc ptevs failed\n");
501 return -ENOMEM;
502 }
503
504 pr_debug("In map_prologue, ntevs=%d\n", pev->ntevs);
505 for (i = 0; i < pev->ntevs; i++)
506 ptevs[i] = &pev->tevs[i];
507
508 qsort(ptevs, pev->ntevs, sizeof(*ptevs),
509 compare_tev_args);
510
511 for (i = 0; i < pev->ntevs; i++) {
512 int n;
513
514 n = ptevs[i] - pev->tevs;
515 if (i == 0) {
516 mapping[n] = type;
517 pr_debug("mapping[%d]=%d\n", n, type);
518 continue;
519 }
520
521 if (compare_tev_args(ptevs + i, ptevs + i - 1) == 0)
522 mapping[n] = type;
523 else
524 mapping[n] = ++type;
525
526 pr_debug("mapping[%d]=%d\n", n, mapping[n]);
527 }
528 free(ptevs);
529 *nr_types = type + 1;
530
531 return 0;
532}
533
534static int hook_load_preprocessor(struct bpf_program *prog)
535{
536 struct perf_probe_event *pev;
537 struct bpf_prog_priv *priv;
538 bool need_prologue = false;
539 int err, i;
540
541 err = bpf_program__get_private(prog, (void **)&priv);
542 if (err || !priv) {
543 pr_debug("Internal error when hook preprocessor\n");
544 return -BPF_LOADER_ERRNO__INTERNAL;
545 }
546
547 pev = &priv->pev;
548 for (i = 0; i < pev->ntevs; i++) {
549 struct probe_trace_event *tev = &pev->tevs[i];
550
551 if (tev->nargs > 0) {
552 need_prologue = true;
553 break;
554 }
555 }
556
557 /*
558 * Since all tevs don't have argument, we don't need generate
559 * prologue.
560 */
561 if (!need_prologue) {
562 priv->need_prologue = false;
563 return 0;
564 }
565
566 priv->need_prologue = true;
567 priv->insns_buf = malloc(sizeof(struct bpf_insn) * BPF_MAXINSNS);
568 if (!priv->insns_buf) {
569 pr_debug("No enough memory: alloc insns_buf failed\n");
570 return -ENOMEM;
571 }
572
573 priv->type_mapping = malloc(sizeof(int) * pev->ntevs);
574 if (!priv->type_mapping) {
575 pr_debug("No enough memory: alloc type_mapping failed\n");
576 return -ENOMEM;
577 }
578 memset(priv->type_mapping, -1,
579 sizeof(int) * pev->ntevs);
580
581 err = map_prologue(pev, priv->type_mapping, &priv->nr_types);
582 if (err)
583 return err;
584
585 err = bpf_program__set_prep(prog, priv->nr_types,
586 preproc_gen_prologue);
587 return err;
588}
589
200int bpf__probe(struct bpf_object *obj) 590int bpf__probe(struct bpf_object *obj)
201{ 591{
202 int err = 0; 592 int err = 0;
@@ -231,6 +621,18 @@ int bpf__probe(struct bpf_object *obj)
231 pr_debug("bpf_probe: failed to apply perf probe events"); 621 pr_debug("bpf_probe: failed to apply perf probe events");
232 goto out; 622 goto out;
233 } 623 }
624
625 /*
626 * After probing, let's consider prologue, which
627 * adds program fetcher to BPF programs.
628 *
629 * hook_load_preprocessorr() hooks pre-processor
630 * to bpf_program, let it generate prologue
631 * dynamically during loading.
632 */
633 err = hook_load_preprocessor(prog);
634 if (err)
635 goto out;
234 } 636 }
235out: 637out:
236 return err < 0 ? err : 0; 638 return err < 0 ? err : 0;
@@ -314,7 +716,14 @@ int bpf__foreach_tev(struct bpf_object *obj,
314 for (i = 0; i < pev->ntevs; i++) { 716 for (i = 0; i < pev->ntevs; i++) {
315 tev = &pev->tevs[i]; 717 tev = &pev->tevs[i];
316 718
317 fd = bpf_program__fd(prog); 719 if (priv->need_prologue) {
720 int type = priv->type_mapping[i];
721
722 fd = bpf_program__nth_fd(prog, type);
723 } else {
724 fd = bpf_program__fd(prog);
725 }
726
318 if (fd < 0) { 727 if (fd < 0) {
319 pr_debug("bpf: failed to get file descriptor\n"); 728 pr_debug("bpf: failed to get file descriptor\n");
320 return fd; 729 return fd;
@@ -340,6 +749,10 @@ static const char *bpf_loader_strerror_table[NR_ERRNO] = {
340 [ERRCODE_OFFSET(EVENTNAME)] = "No event name found in config string", 749 [ERRCODE_OFFSET(EVENTNAME)] = "No event name found in config string",
341 [ERRCODE_OFFSET(INTERNAL)] = "BPF loader internal error", 750 [ERRCODE_OFFSET(INTERNAL)] = "BPF loader internal error",
342 [ERRCODE_OFFSET(COMPILE)] = "Error when compiling BPF scriptlet", 751 [ERRCODE_OFFSET(COMPILE)] = "Error when compiling BPF scriptlet",
752 [ERRCODE_OFFSET(PROGCONF_TERM)] = "Invalid program config term in config string",
753 [ERRCODE_OFFSET(PROLOGUE)] = "Failed to generate prologue",
754 [ERRCODE_OFFSET(PROLOGUE2BIG)] = "Prologue too big for program",
755 [ERRCODE_OFFSET(PROLOGUEOOB)] = "Offset out of bound for prologue",
343}; 756};
344 757
345static int 758static int
@@ -420,7 +833,11 @@ int bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
420 int err, char *buf, size_t size) 833 int err, char *buf, size_t size)
421{ 834{
422 bpf__strerror_head(err, buf, size); 835 bpf__strerror_head(err, buf, size);
423 bpf__strerror_entry(EEXIST, "Probe point exist. Try use 'perf probe -d \"*\"'"); 836 case BPF_LOADER_ERRNO__PROGCONF_TERM: {
837 scnprintf(buf, size, "%s (add -v to see detail)", emsg);
838 break;
839 }
840 bpf__strerror_entry(EEXIST, "Probe point exist. Try 'perf probe -d \"*\"' and set 'force=yes'");
424 bpf__strerror_entry(EACCES, "You need to be root"); 841 bpf__strerror_entry(EACCES, "You need to be root");
425 bpf__strerror_entry(EPERM, "You need to be root, and /proc/sys/kernel/kptr_restrict should be 0"); 842 bpf__strerror_entry(EPERM, "You need to be root, and /proc/sys/kernel/kptr_restrict should be 0");
426 bpf__strerror_entry(ENOENT, "You need to check probing points in BPF file"); 843 bpf__strerror_entry(ENOENT, "You need to check probing points in BPF file");
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 9caf3ae4acf3..6fdc0457e2b6 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -20,6 +20,10 @@ enum bpf_loader_errno {
20 BPF_LOADER_ERRNO__EVENTNAME, /* Event name is missing */ 20 BPF_LOADER_ERRNO__EVENTNAME, /* Event name is missing */
21 BPF_LOADER_ERRNO__INTERNAL, /* BPF loader internal error */ 21 BPF_LOADER_ERRNO__INTERNAL, /* BPF loader internal error */
22 BPF_LOADER_ERRNO__COMPILE, /* Error when compiling BPF scriptlet */ 22 BPF_LOADER_ERRNO__COMPILE, /* Error when compiling BPF scriptlet */
23 BPF_LOADER_ERRNO__PROGCONF_TERM,/* Invalid program config term in config string */
24 BPF_LOADER_ERRNO__PROLOGUE, /* Failed to generate prologue */
25 BPF_LOADER_ERRNO__PROLOGUE2BIG, /* Prologue too big for program */
26 BPF_LOADER_ERRNO__PROLOGUEOOB, /* Offset out of bound for prologue */
23 __BPF_LOADER_ERRNO__END, 27 __BPF_LOADER_ERRNO__END,
24}; 28};
25 29
diff --git a/tools/perf/util/bpf-prologue.c b/tools/perf/util/bpf-prologue.c
new file mode 100644
index 000000000000..6cdbee119ceb
--- /dev/null
+++ b/tools/perf/util/bpf-prologue.c
@@ -0,0 +1,455 @@
1/*
2 * bpf-prologue.c
3 *
4 * Copyright (C) 2015 He Kuang <hekuang@huawei.com>
5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
6 * Copyright (C) 2015 Huawei Inc.
7 */
8
9#include <bpf/libbpf.h>
10#include "perf.h"
11#include "debug.h"
12#include "bpf-loader.h"
13#include "bpf-prologue.h"
14#include "probe-finder.h"
15#include <dwarf-regs.h>
16#include <linux/filter.h>
17
18#define BPF_REG_SIZE 8
19
20#define JMP_TO_ERROR_CODE -1
21#define JMP_TO_SUCCESS_CODE -2
22#define JMP_TO_USER_CODE -3
23
24struct bpf_insn_pos {
25 struct bpf_insn *begin;
26 struct bpf_insn *end;
27 struct bpf_insn *pos;
28};
29
30static inline int
31pos_get_cnt(struct bpf_insn_pos *pos)
32{
33 return pos->pos - pos->begin;
34}
35
36static int
37append_insn(struct bpf_insn new_insn, struct bpf_insn_pos *pos)
38{
39 if (!pos->pos)
40 return -BPF_LOADER_ERRNO__PROLOGUE2BIG;
41
42 if (pos->pos + 1 >= pos->end) {
43 pr_err("bpf prologue: prologue too long\n");
44 pos->pos = NULL;
45 return -BPF_LOADER_ERRNO__PROLOGUE2BIG;
46 }
47
48 *(pos->pos)++ = new_insn;
49 return 0;
50}
51
52static int
53check_pos(struct bpf_insn_pos *pos)
54{
55 if (!pos->pos || pos->pos >= pos->end)
56 return -BPF_LOADER_ERRNO__PROLOGUE2BIG;
57 return 0;
58}
59
60/* Give it a shorter name */
61#define ins(i, p) append_insn((i), (p))
62
63/*
64 * Give a register name (in 'reg'), generate instruction to
65 * load register into an eBPF register rd:
66 * 'ldd target_reg, offset(ctx_reg)', where:
67 * ctx_reg is pre initialized to pointer of 'struct pt_regs'.
68 */
69static int
70gen_ldx_reg_from_ctx(struct bpf_insn_pos *pos, int ctx_reg,
71 const char *reg, int target_reg)
72{
73 int offset = regs_query_register_offset(reg);
74
75 if (offset < 0) {
76 pr_err("bpf: prologue: failed to get register %s\n",
77 reg);
78 return offset;
79 }
80 ins(BPF_LDX_MEM(BPF_DW, target_reg, ctx_reg, offset), pos);
81
82 return check_pos(pos);
83}
84
85/*
86 * Generate a BPF_FUNC_probe_read function call.
87 *
88 * src_base_addr_reg is a register holding base address,
89 * dst_addr_reg is a register holding dest address (on stack),
90 * result is:
91 *
92 * *[dst_addr_reg] = *([src_base_addr_reg] + offset)
93 *
94 * Arguments of BPF_FUNC_probe_read:
95 * ARG1: ptr to stack (dest)
96 * ARG2: size (8)
97 * ARG3: unsafe ptr (src)
98 */
99static int
100gen_read_mem(struct bpf_insn_pos *pos,
101 int src_base_addr_reg,
102 int dst_addr_reg,
103 long offset)
104{
105 /* mov arg3, src_base_addr_reg */
106 if (src_base_addr_reg != BPF_REG_ARG3)
107 ins(BPF_MOV64_REG(BPF_REG_ARG3, src_base_addr_reg), pos);
108 /* add arg3, #offset */
109 if (offset)
110 ins(BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG3, offset), pos);
111
112 /* mov arg2, #reg_size */
113 ins(BPF_ALU64_IMM(BPF_MOV, BPF_REG_ARG2, BPF_REG_SIZE), pos);
114
115 /* mov arg1, dst_addr_reg */
116 if (dst_addr_reg != BPF_REG_ARG1)
117 ins(BPF_MOV64_REG(BPF_REG_ARG1, dst_addr_reg), pos);
118
119 /* Call probe_read */
120 ins(BPF_EMIT_CALL(BPF_FUNC_probe_read), pos);
121 /*
122 * Error processing: if read fail, goto error code,
123 * will be relocated. Target should be the start of
124 * error processing code.
125 */
126 ins(BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, JMP_TO_ERROR_CODE),
127 pos);
128
129 return check_pos(pos);
130}
131
132/*
133 * Each arg should be bare register. Fetch and save them into argument
134 * registers (r3 - r5).
135 *
136 * BPF_REG_1 should have been initialized with pointer to
137 * 'struct pt_regs'.
138 */
139static int
140gen_prologue_fastpath(struct bpf_insn_pos *pos,
141 struct probe_trace_arg *args, int nargs)
142{
143 int i, err = 0;
144
145 for (i = 0; i < nargs; i++) {
146 err = gen_ldx_reg_from_ctx(pos, BPF_REG_1, args[i].value,
147 BPF_PROLOGUE_START_ARG_REG + i);
148 if (err)
149 goto errout;
150 }
151
152 return check_pos(pos);
153errout:
154 return err;
155}
156
157/*
158 * Slow path:
159 * At least one argument has the form of 'offset($rx)'.
160 *
161 * Following code first stores them into stack, then loads all of then
162 * to r2 - r5.
163 * Before final loading, the final result should be:
164 *
165 * low address
166 * BPF_REG_FP - 24 ARG3
167 * BPF_REG_FP - 16 ARG2
168 * BPF_REG_FP - 8 ARG1
169 * BPF_REG_FP
170 * high address
171 *
172 * For each argument (described as: offn(...off2(off1(reg)))),
173 * generates following code:
174 *
175 * r7 <- fp
176 * r7 <- r7 - stack_offset // Ideal code should initialize r7 using
177 * // fp before generating args. However,
178 * // eBPF won't regard r7 as stack pointer
179 * // if it is generated by minus 8 from
180 * // another stack pointer except fp.
181 * // This is why we have to set r7
182 * // to fp for each variable.
183 * r3 <- value of 'reg'-> generated using gen_ldx_reg_from_ctx()
184 * (r7) <- r3 // skip following instructions for bare reg
185 * r3 <- r3 + off1 . // skip if off1 == 0
186 * r2 <- 8 \
187 * r1 <- r7 |-> generated by gen_read_mem()
188 * call probe_read /
189 * jnei r0, 0, err ./
190 * r3 <- (r7)
191 * r3 <- r3 + off2 . // skip if off2 == 0
192 * r2 <- 8 \ // r2 may be broken by probe_read, so set again
193 * r1 <- r7 |-> generated by gen_read_mem()
194 * call probe_read /
195 * jnei r0, 0, err ./
196 * ...
197 */
198static int
199gen_prologue_slowpath(struct bpf_insn_pos *pos,
200 struct probe_trace_arg *args, int nargs)
201{
202 int err, i;
203
204 for (i = 0; i < nargs; i++) {
205 struct probe_trace_arg *arg = &args[i];
206 const char *reg = arg->value;
207 struct probe_trace_arg_ref *ref = NULL;
208 int stack_offset = (i + 1) * -8;
209
210 pr_debug("prologue: fetch arg %d, base reg is %s\n",
211 i, reg);
212
213 /* value of base register is stored into ARG3 */
214 err = gen_ldx_reg_from_ctx(pos, BPF_REG_CTX, reg,
215 BPF_REG_ARG3);
216 if (err) {
217 pr_err("prologue: failed to get offset of register %s\n",
218 reg);
219 goto errout;
220 }
221
222 /* Make r7 the stack pointer. */
223 ins(BPF_MOV64_REG(BPF_REG_7, BPF_REG_FP), pos);
224 /* r7 += -8 */
225 ins(BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, stack_offset), pos);
226 /*
227 * Store r3 (base register) onto stack
228 * Ensure fp[offset] is set.
229 * fp is the only valid base register when storing
230 * into stack. We are not allowed to use r7 as base
231 * register here.
232 */
233 ins(BPF_STX_MEM(BPF_DW, BPF_REG_FP, BPF_REG_ARG3,
234 stack_offset), pos);
235
236 ref = arg->ref;
237 while (ref) {
238 pr_debug("prologue: arg %d: offset %ld\n",
239 i, ref->offset);
240 err = gen_read_mem(pos, BPF_REG_3, BPF_REG_7,
241 ref->offset);
242 if (err) {
243 pr_err("prologue: failed to generate probe_read function call\n");
244 goto errout;
245 }
246
247 ref = ref->next;
248 /*
249 * Load previous result into ARG3. Use
250 * BPF_REG_FP instead of r7 because verifier
251 * allows FP based addressing only.
252 */
253 if (ref)
254 ins(BPF_LDX_MEM(BPF_DW, BPF_REG_ARG3,
255 BPF_REG_FP, stack_offset), pos);
256 }
257 }
258
259 /* Final pass: read to registers */
260 for (i = 0; i < nargs; i++)
261 ins(BPF_LDX_MEM(BPF_DW, BPF_PROLOGUE_START_ARG_REG + i,
262 BPF_REG_FP, -BPF_REG_SIZE * (i + 1)), pos);
263
264 ins(BPF_JMP_IMM(BPF_JA, BPF_REG_0, 0, JMP_TO_SUCCESS_CODE), pos);
265
266 return check_pos(pos);
267errout:
268 return err;
269}
270
271static int
272prologue_relocate(struct bpf_insn_pos *pos, struct bpf_insn *error_code,
273 struct bpf_insn *success_code, struct bpf_insn *user_code)
274{
275 struct bpf_insn *insn;
276
277 if (check_pos(pos))
278 return -BPF_LOADER_ERRNO__PROLOGUE2BIG;
279
280 for (insn = pos->begin; insn < pos->pos; insn++) {
281 struct bpf_insn *target;
282 u8 class = BPF_CLASS(insn->code);
283 u8 opcode;
284
285 if (class != BPF_JMP)
286 continue;
287 opcode = BPF_OP(insn->code);
288 if (opcode == BPF_CALL)
289 continue;
290
291 switch (insn->off) {
292 case JMP_TO_ERROR_CODE:
293 target = error_code;
294 break;
295 case JMP_TO_SUCCESS_CODE:
296 target = success_code;
297 break;
298 case JMP_TO_USER_CODE:
299 target = user_code;
300 break;
301 default:
302 pr_err("bpf prologue: internal error: relocation failed\n");
303 return -BPF_LOADER_ERRNO__PROLOGUE;
304 }
305
306 insn->off = target - (insn + 1);
307 }
308 return 0;
309}
310
311int bpf__gen_prologue(struct probe_trace_arg *args, int nargs,
312 struct bpf_insn *new_prog, size_t *new_cnt,
313 size_t cnt_space)
314{
315 struct bpf_insn *success_code = NULL;
316 struct bpf_insn *error_code = NULL;
317 struct bpf_insn *user_code = NULL;
318 struct bpf_insn_pos pos;
319 bool fastpath = true;
320 int err = 0, i;
321
322 if (!new_prog || !new_cnt)
323 return -EINVAL;
324
325 if (cnt_space > BPF_MAXINSNS)
326 cnt_space = BPF_MAXINSNS;
327
328 pos.begin = new_prog;
329 pos.end = new_prog + cnt_space;
330 pos.pos = new_prog;
331
332 if (!nargs) {
333 ins(BPF_ALU64_IMM(BPF_MOV, BPF_PROLOGUE_FETCH_RESULT_REG, 0),
334 &pos);
335
336 if (check_pos(&pos))
337 goto errout;
338
339 *new_cnt = pos_get_cnt(&pos);
340 return 0;
341 }
342
343 if (nargs > BPF_PROLOGUE_MAX_ARGS) {
344 pr_warning("bpf: prologue: %d arguments are dropped\n",
345 nargs - BPF_PROLOGUE_MAX_ARGS);
346 nargs = BPF_PROLOGUE_MAX_ARGS;
347 }
348
349 /* First pass: validation */
350 for (i = 0; i < nargs; i++) {
351 struct probe_trace_arg_ref *ref = args[i].ref;
352
353 if (args[i].value[0] == '@') {
354 /* TODO: fetch global variable */
355 pr_err("bpf: prologue: global %s%+ld not support\n",
356 args[i].value, ref ? ref->offset : 0);
357 return -ENOTSUP;
358 }
359
360 while (ref) {
361 /* fastpath is true if all args has ref == NULL */
362 fastpath = false;
363
364 /*
365 * Instruction encodes immediate value using
366 * s32, ref->offset is long. On systems which
367 * can't fill long in s32, refuse to process if
368 * ref->offset too large (or small).
369 */
370#ifdef __LP64__
371#define OFFSET_MAX ((1LL << 31) - 1)
372#define OFFSET_MIN ((1LL << 31) * -1)
373 if (ref->offset > OFFSET_MAX ||
374 ref->offset < OFFSET_MIN) {
375 pr_err("bpf: prologue: offset out of bound: %ld\n",
376 ref->offset);
377 return -BPF_LOADER_ERRNO__PROLOGUEOOB;
378 }
379#endif
380 ref = ref->next;
381 }
382 }
383 pr_debug("prologue: pass validation\n");
384
385 if (fastpath) {
386 /* If all variables are registers... */
387 pr_debug("prologue: fast path\n");
388 err = gen_prologue_fastpath(&pos, args, nargs);
389 if (err)
390 goto errout;
391 } else {
392 pr_debug("prologue: slow path\n");
393
394 /* Initialization: move ctx to a callee saved register. */
395 ins(BPF_MOV64_REG(BPF_REG_CTX, BPF_REG_ARG1), &pos);
396
397 err = gen_prologue_slowpath(&pos, args, nargs);
398 if (err)
399 goto errout;
400 /*
401 * start of ERROR_CODE (only slow pass needs error code)
402 * mov r2 <- 1 // r2 is error number
403 * mov r3 <- 0 // r3, r4... should be touched or
404 * // verifier would complain
405 * mov r4 <- 0
406 * ...
407 * goto usercode
408 */
409 error_code = pos.pos;
410 ins(BPF_ALU64_IMM(BPF_MOV, BPF_PROLOGUE_FETCH_RESULT_REG, 1),
411 &pos);
412
413 for (i = 0; i < nargs; i++)
414 ins(BPF_ALU64_IMM(BPF_MOV,
415 BPF_PROLOGUE_START_ARG_REG + i,
416 0),
417 &pos);
418 ins(BPF_JMP_IMM(BPF_JA, BPF_REG_0, 0, JMP_TO_USER_CODE),
419 &pos);
420 }
421
422 /*
423 * start of SUCCESS_CODE:
424 * mov r2 <- 0
425 * goto usercode // skip
426 */
427 success_code = pos.pos;
428 ins(BPF_ALU64_IMM(BPF_MOV, BPF_PROLOGUE_FETCH_RESULT_REG, 0), &pos);
429
430 /*
431 * start of USER_CODE:
432 * Restore ctx to r1
433 */
434 user_code = pos.pos;
435 if (!fastpath) {
436 /*
437 * Only slow path needs restoring of ctx. In fast path,
438 * register are loaded directly from r1.
439 */
440 ins(BPF_MOV64_REG(BPF_REG_ARG1, BPF_REG_CTX), &pos);
441 err = prologue_relocate(&pos, error_code, success_code,
442 user_code);
443 if (err)
444 goto errout;
445 }
446
447 err = check_pos(&pos);
448 if (err)
449 goto errout;
450
451 *new_cnt = pos_get_cnt(&pos);
452 return 0;
453errout:
454 return err;
455}
diff --git a/tools/perf/util/bpf-prologue.h b/tools/perf/util/bpf-prologue.h
new file mode 100644
index 000000000000..d94cbea12899
--- /dev/null
+++ b/tools/perf/util/bpf-prologue.h
@@ -0,0 +1,34 @@
1/*
2 * Copyright (C) 2015, He Kuang <hekuang@huawei.com>
3 * Copyright (C) 2015, Huawei Inc.
4 */
5#ifndef __BPF_PROLOGUE_H
6#define __BPF_PROLOGUE_H
7
8#include <linux/compiler.h>
9#include <linux/filter.h>
10#include "probe-event.h"
11
12#define BPF_PROLOGUE_MAX_ARGS 3
13#define BPF_PROLOGUE_START_ARG_REG BPF_REG_3
14#define BPF_PROLOGUE_FETCH_RESULT_REG BPF_REG_2
15
16#ifdef HAVE_BPF_PROLOGUE
17int bpf__gen_prologue(struct probe_trace_arg *args, int nargs,
18 struct bpf_insn *new_prog, size_t *new_cnt,
19 size_t cnt_space);
20#else
21static inline int
22bpf__gen_prologue(struct probe_trace_arg *args __maybe_unused,
23 int nargs __maybe_unused,
24 struct bpf_insn *new_prog __maybe_unused,
25 size_t *new_cnt,
26 size_t cnt_space __maybe_unused)
27{
28 if (!new_cnt)
29 return -EINVAL;
30 *new_cnt = 0;
31 return -ENOTSUP;
32}
33#endif
34#endif /* __BPF_PROLOGUE_H */
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index c861373aaed3..07b5d63947b1 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -4,9 +4,12 @@
4#include <stdbool.h> 4#include <stdbool.h>
5#include "util.h" 5#include "util.h"
6#include "strbuf.h" 6#include "strbuf.h"
7#include <subcmd/pager.h>
7#include "../perf.h" 8#include "../perf.h"
8#include "../ui/ui.h" 9#include "../ui/ui.h"
9 10
11#include <linux/string.h>
12
10#define CMD_EXEC_PATH "--exec-path" 13#define CMD_EXEC_PATH "--exec-path"
11#define CMD_PERF_DIR "--perf-dir=" 14#define CMD_PERF_DIR "--perf-dir="
12#define CMD_WORK_TREE "--work-tree=" 15#define CMD_WORK_TREE "--work-tree="
@@ -18,6 +21,7 @@
18#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf" 21#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
19#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" 22#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
20#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR" 23#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
24#define PERF_PAGER_ENVIRONMENT "PERF_PAGER"
21 25
22typedef int (*config_fn_t)(const char *, const char *, void *); 26typedef int (*config_fn_t)(const char *, const char *, void *);
23extern int perf_default_config(const char *, const char *, void *); 27extern int perf_default_config(const char *, const char *, void *);
@@ -28,11 +32,6 @@ extern int perf_config_bool(const char *, const char *);
28extern int config_error_nonbool(const char *); 32extern int config_error_nonbool(const char *);
29extern const char *perf_config_dirname(const char *, const char *); 33extern const char *perf_config_dirname(const char *, const char *);
30 34
31/* pager.c */
32extern void setup_pager(void);
33extern int pager_in_use(void);
34extern int pager_use_color;
35
36char *alias_lookup(const char *alias); 35char *alias_lookup(const char *alias);
37int split_cmdline(char *cmdline, const char ***argv); 36int split_cmdline(char *cmdline, const char ***argv);
38 37
@@ -71,9 +70,4 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
71extern char *perf_pathdup(const char *fmt, ...) 70extern char *perf_pathdup(const char *fmt, ...)
72 __attribute__((format (printf, 1, 2))); 71 __attribute__((format (printf, 1, 2)));
73 72
74#ifndef __UCLIBC__
75/* Matches the libc/libbsd function attribute so we declare this unconditionally: */
76extern size_t strlcpy(char *dest, const char *src, size_t size);
77#endif
78
79#endif /* __PERF_CACHE_H */ 73#endif /* __PERF_CACHE_H */
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 735ad48e1858..53c43eb9489e 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -44,6 +44,10 @@ static int parse_callchain_mode(const char *value)
44 callchain_param.mode = CHAIN_GRAPH_REL; 44 callchain_param.mode = CHAIN_GRAPH_REL;
45 return 0; 45 return 0;
46 } 46 }
47 if (!strncmp(value, "folded", strlen(value))) {
48 callchain_param.mode = CHAIN_FOLDED;
49 return 0;
50 }
47 return -1; 51 return -1;
48} 52}
49 53
@@ -79,6 +83,23 @@ static int parse_callchain_sort_key(const char *value)
79 return -1; 83 return -1;
80} 84}
81 85
86static int parse_callchain_value(const char *value)
87{
88 if (!strncmp(value, "percent", strlen(value))) {
89 callchain_param.value = CCVAL_PERCENT;
90 return 0;
91 }
92 if (!strncmp(value, "period", strlen(value))) {
93 callchain_param.value = CCVAL_PERIOD;
94 return 0;
95 }
96 if (!strncmp(value, "count", strlen(value))) {
97 callchain_param.value = CCVAL_COUNT;
98 return 0;
99 }
100 return -1;
101}
102
82static int 103static int
83__parse_callchain_report_opt(const char *arg, bool allow_record_opt) 104__parse_callchain_report_opt(const char *arg, bool allow_record_opt)
84{ 105{
@@ -102,7 +123,8 @@ __parse_callchain_report_opt(const char *arg, bool allow_record_opt)
102 123
103 if (!parse_callchain_mode(tok) || 124 if (!parse_callchain_mode(tok) ||
104 !parse_callchain_order(tok) || 125 !parse_callchain_order(tok) ||
105 !parse_callchain_sort_key(tok)) { 126 !parse_callchain_sort_key(tok) ||
127 !parse_callchain_value(tok)) {
106 /* parsing ok - move on to the next */ 128 /* parsing ok - move on to the next */
107 try_stack_size = false; 129 try_stack_size = false;
108 goto next; 130 goto next;
@@ -218,6 +240,7 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
218 240
219 switch (mode) { 241 switch (mode) {
220 case CHAIN_FLAT: 242 case CHAIN_FLAT:
243 case CHAIN_FOLDED:
221 if (rnode->hit < chain->hit) 244 if (rnode->hit < chain->hit)
222 p = &(*p)->rb_left; 245 p = &(*p)->rb_left;
223 else 246 else
@@ -267,6 +290,7 @@ static void
267sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root, 290sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root,
268 u64 min_hit, struct callchain_param *param __maybe_unused) 291 u64 min_hit, struct callchain_param *param __maybe_unused)
269{ 292{
293 *rb_root = RB_ROOT;
270 __sort_chain_flat(rb_root, &root->node, min_hit); 294 __sort_chain_flat(rb_root, &root->node, min_hit);
271} 295}
272 296
@@ -338,6 +362,7 @@ int callchain_register_param(struct callchain_param *param)
338 param->sort = sort_chain_graph_rel; 362 param->sort = sort_chain_graph_rel;
339 break; 363 break;
340 case CHAIN_FLAT: 364 case CHAIN_FLAT:
365 case CHAIN_FOLDED:
341 param->sort = sort_chain_flat; 366 param->sort = sort_chain_flat;
342 break; 367 break;
343 case CHAIN_NONE: 368 case CHAIN_NONE:
@@ -363,6 +388,7 @@ create_child(struct callchain_node *parent, bool inherit_children)
363 } 388 }
364 new->parent = parent; 389 new->parent = parent;
365 INIT_LIST_HEAD(&new->val); 390 INIT_LIST_HEAD(&new->val);
391 INIT_LIST_HEAD(&new->parent_val);
366 392
367 if (inherit_children) { 393 if (inherit_children) {
368 struct rb_node *n; 394 struct rb_node *n;
@@ -431,6 +457,8 @@ add_child(struct callchain_node *parent,
431 457
432 new->children_hit = 0; 458 new->children_hit = 0;
433 new->hit = period; 459 new->hit = period;
460 new->children_count = 0;
461 new->count = 1;
434 return new; 462 return new;
435} 463}
436 464
@@ -478,6 +506,9 @@ split_add_child(struct callchain_node *parent,
478 parent->children_hit = callchain_cumul_hits(new); 506 parent->children_hit = callchain_cumul_hits(new);
479 new->val_nr = parent->val_nr - idx_local; 507 new->val_nr = parent->val_nr - idx_local;
480 parent->val_nr = idx_local; 508 parent->val_nr = idx_local;
509 new->count = parent->count;
510 new->children_count = parent->children_count;
511 parent->children_count = callchain_cumul_counts(new);
481 512
482 /* create a new child for the new branch if any */ 513 /* create a new child for the new branch if any */
483 if (idx_total < cursor->nr) { 514 if (idx_total < cursor->nr) {
@@ -488,6 +519,8 @@ split_add_child(struct callchain_node *parent,
488 519
489 parent->hit = 0; 520 parent->hit = 0;
490 parent->children_hit += period; 521 parent->children_hit += period;
522 parent->count = 0;
523 parent->children_count += 1;
491 524
492 node = callchain_cursor_current(cursor); 525 node = callchain_cursor_current(cursor);
493 new = add_child(parent, cursor, period); 526 new = add_child(parent, cursor, period);
@@ -510,6 +543,7 @@ split_add_child(struct callchain_node *parent,
510 rb_insert_color(&new->rb_node_in, &parent->rb_root_in); 543 rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
511 } else { 544 } else {
512 parent->hit = period; 545 parent->hit = period;
546 parent->count = 1;
513 } 547 }
514} 548}
515 549
@@ -556,6 +590,7 @@ append_chain_children(struct callchain_node *root,
556 590
557inc_children_hit: 591inc_children_hit:
558 root->children_hit += period; 592 root->children_hit += period;
593 root->children_count++;
559} 594}
560 595
561static int 596static int
@@ -608,6 +643,7 @@ append_chain(struct callchain_node *root,
608 /* we match 100% of the path, increment the hit */ 643 /* we match 100% of the path, increment the hit */
609 if (matches == root->val_nr && cursor->pos == cursor->nr) { 644 if (matches == root->val_nr && cursor->pos == cursor->nr) {
610 root->hit += period; 645 root->hit += period;
646 root->count++;
611 return 0; 647 return 0;
612 } 648 }
613 649
@@ -799,12 +835,72 @@ char *callchain_list__sym_name(struct callchain_list *cl,
799 return bf; 835 return bf;
800} 836}
801 837
838char *callchain_node__scnprintf_value(struct callchain_node *node,
839 char *bf, size_t bfsize, u64 total)
840{
841 double percent = 0.0;
842 u64 period = callchain_cumul_hits(node);
843 unsigned count = callchain_cumul_counts(node);
844
845 if (callchain_param.mode == CHAIN_FOLDED) {
846 period = node->hit;
847 count = node->count;
848 }
849
850 switch (callchain_param.value) {
851 case CCVAL_PERIOD:
852 scnprintf(bf, bfsize, "%"PRIu64, period);
853 break;
854 case CCVAL_COUNT:
855 scnprintf(bf, bfsize, "%u", count);
856 break;
857 case CCVAL_PERCENT:
858 default:
859 if (total)
860 percent = period * 100.0 / total;
861 scnprintf(bf, bfsize, "%.2f%%", percent);
862 break;
863 }
864 return bf;
865}
866
867int callchain_node__fprintf_value(struct callchain_node *node,
868 FILE *fp, u64 total)
869{
870 double percent = 0.0;
871 u64 period = callchain_cumul_hits(node);
872 unsigned count = callchain_cumul_counts(node);
873
874 if (callchain_param.mode == CHAIN_FOLDED) {
875 period = node->hit;
876 count = node->count;
877 }
878
879 switch (callchain_param.value) {
880 case CCVAL_PERIOD:
881 return fprintf(fp, "%"PRIu64, period);
882 case CCVAL_COUNT:
883 return fprintf(fp, "%u", count);
884 case CCVAL_PERCENT:
885 default:
886 if (total)
887 percent = period * 100.0 / total;
888 return percent_color_fprintf(fp, "%.2f%%", percent);
889 }
890 return 0;
891}
892
802static void free_callchain_node(struct callchain_node *node) 893static void free_callchain_node(struct callchain_node *node)
803{ 894{
804 struct callchain_list *list, *tmp; 895 struct callchain_list *list, *tmp;
805 struct callchain_node *child; 896 struct callchain_node *child;
806 struct rb_node *n; 897 struct rb_node *n;
807 898
899 list_for_each_entry_safe(list, tmp, &node->parent_val, list) {
900 list_del(&list->list);
901 free(list);
902 }
903
808 list_for_each_entry_safe(list, tmp, &node->val, list) { 904 list_for_each_entry_safe(list, tmp, &node->val, list) {
809 list_del(&list->list); 905 list_del(&list->list);
810 free(list); 906 free(list);
@@ -828,3 +924,69 @@ void free_callchain(struct callchain_root *root)
828 924
829 free_callchain_node(&root->node); 925 free_callchain_node(&root->node);
830} 926}
927
928static u64 decay_callchain_node(struct callchain_node *node)
929{
930 struct callchain_node *child;
931 struct rb_node *n;
932 u64 child_hits = 0;
933
934 n = rb_first(&node->rb_root_in);
935 while (n) {
936 child = container_of(n, struct callchain_node, rb_node_in);
937
938 child_hits += decay_callchain_node(child);
939 n = rb_next(n);
940 }
941
942 node->hit = (node->hit * 7) / 8;
943 node->children_hit = child_hits;
944
945 return node->hit;
946}
947
948void decay_callchain(struct callchain_root *root)
949{
950 if (!symbol_conf.use_callchain)
951 return;
952
953 decay_callchain_node(&root->node);
954}
955
956int callchain_node__make_parent_list(struct callchain_node *node)
957{
958 struct callchain_node *parent = node->parent;
959 struct callchain_list *chain, *new;
960 LIST_HEAD(head);
961
962 while (parent) {
963 list_for_each_entry_reverse(chain, &parent->val, list) {
964 new = malloc(sizeof(*new));
965 if (new == NULL)
966 goto out;
967 *new = *chain;
968 new->has_children = false;
969 list_add_tail(&new->list, &head);
970 }
971 parent = parent->parent;
972 }
973
974 list_for_each_entry_safe_reverse(chain, new, &head, list)
975 list_move_tail(&chain->list, &node->parent_val);
976
977 if (!list_empty(&node->parent_val)) {
978 chain = list_first_entry(&node->parent_val, struct callchain_list, list);
979 chain->has_children = rb_prev(&node->rb_node) || rb_next(&node->rb_node);
980
981 chain = list_first_entry(&node->val, struct callchain_list, list);
982 chain->has_children = false;
983 }
984 return 0;
985
986out:
987 list_for_each_entry_safe(chain, new, &head, list) {
988 list_del(&chain->list);
989 free(chain);
990 }
991 return -ENOMEM;
992}
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index fce8161e54db..18dd22269764 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -24,12 +24,13 @@
24#define CALLCHAIN_RECORD_HELP CALLCHAIN_HELP RECORD_MODE_HELP RECORD_SIZE_HELP 24#define CALLCHAIN_RECORD_HELP CALLCHAIN_HELP RECORD_MODE_HELP RECORD_SIZE_HELP
25 25
26#define CALLCHAIN_REPORT_HELP \ 26#define CALLCHAIN_REPORT_HELP \
27 HELP_PAD "print_type:\tcall graph printing style (graph|flat|fractal|none)\n" \ 27 HELP_PAD "print_type:\tcall graph printing style (graph|flat|fractal|folded|none)\n" \
28 HELP_PAD "threshold:\tminimum call graph inclusion threshold (<percent>)\n" \ 28 HELP_PAD "threshold:\tminimum call graph inclusion threshold (<percent>)\n" \
29 HELP_PAD "print_limit:\tmaximum number of call graph entry (<number>)\n" \ 29 HELP_PAD "print_limit:\tmaximum number of call graph entry (<number>)\n" \
30 HELP_PAD "order:\t\tcall graph order (caller|callee)\n" \ 30 HELP_PAD "order:\t\tcall graph order (caller|callee)\n" \
31 HELP_PAD "sort_key:\tcall graph sort key (function|address)\n" \ 31 HELP_PAD "sort_key:\tcall graph sort key (function|address)\n" \
32 HELP_PAD "branch:\t\tinclude last branch info to call graph (branch)\n" 32 HELP_PAD "branch:\t\tinclude last branch info to call graph (branch)\n" \
33 HELP_PAD "value:\t\tcall graph value (percent|period|count)\n"
33 34
34enum perf_call_graph_mode { 35enum perf_call_graph_mode {
35 CALLCHAIN_NONE, 36 CALLCHAIN_NONE,
@@ -43,7 +44,8 @@ enum chain_mode {
43 CHAIN_NONE, 44 CHAIN_NONE,
44 CHAIN_FLAT, 45 CHAIN_FLAT,
45 CHAIN_GRAPH_ABS, 46 CHAIN_GRAPH_ABS,
46 CHAIN_GRAPH_REL 47 CHAIN_GRAPH_REL,
48 CHAIN_FOLDED,
47}; 49};
48 50
49enum chain_order { 51enum chain_order {
@@ -54,11 +56,14 @@ enum chain_order {
54struct callchain_node { 56struct callchain_node {
55 struct callchain_node *parent; 57 struct callchain_node *parent;
56 struct list_head val; 58 struct list_head val;
59 struct list_head parent_val;
57 struct rb_node rb_node_in; /* to insert nodes in an rbtree */ 60 struct rb_node rb_node_in; /* to insert nodes in an rbtree */
58 struct rb_node rb_node; /* to sort nodes in an output tree */ 61 struct rb_node rb_node; /* to sort nodes in an output tree */
59 struct rb_root rb_root_in; /* input tree of children */ 62 struct rb_root rb_root_in; /* input tree of children */
60 struct rb_root rb_root; /* sorted output tree of children */ 63 struct rb_root rb_root; /* sorted output tree of children */
61 unsigned int val_nr; 64 unsigned int val_nr;
65 unsigned int count;
66 unsigned int children_count;
62 u64 hit; 67 u64 hit;
63 u64 children_hit; 68 u64 children_hit;
64}; 69};
@@ -78,6 +83,12 @@ enum chain_key {
78 CCKEY_ADDRESS 83 CCKEY_ADDRESS
79}; 84};
80 85
86enum chain_value {
87 CCVAL_PERCENT,
88 CCVAL_PERIOD,
89 CCVAL_COUNT,
90};
91
81struct callchain_param { 92struct callchain_param {
82 bool enabled; 93 bool enabled;
83 enum perf_call_graph_mode record_mode; 94 enum perf_call_graph_mode record_mode;
@@ -90,6 +101,7 @@ struct callchain_param {
90 bool order_set; 101 bool order_set;
91 enum chain_key key; 102 enum chain_key key;
92 bool branch_callstack; 103 bool branch_callstack;
104 enum chain_value value;
93}; 105};
94 106
95extern struct callchain_param callchain_param; 107extern struct callchain_param callchain_param;
@@ -131,6 +143,7 @@ extern __thread struct callchain_cursor callchain_cursor;
131static inline void callchain_init(struct callchain_root *root) 143static inline void callchain_init(struct callchain_root *root)
132{ 144{
133 INIT_LIST_HEAD(&root->node.val); 145 INIT_LIST_HEAD(&root->node.val);
146 INIT_LIST_HEAD(&root->node.parent_val);
134 147
135 root->node.parent = NULL; 148 root->node.parent = NULL;
136 root->node.hit = 0; 149 root->node.hit = 0;
@@ -144,6 +157,11 @@ static inline u64 callchain_cumul_hits(struct callchain_node *node)
144 return node->hit + node->children_hit; 157 return node->hit + node->children_hit;
145} 158}
146 159
160static inline unsigned callchain_cumul_counts(struct callchain_node *node)
161{
162 return node->count + node->children_count;
163}
164
147int callchain_register_param(struct callchain_param *param); 165int callchain_register_param(struct callchain_param *param);
148int callchain_append(struct callchain_root *root, 166int callchain_append(struct callchain_root *root,
149 struct callchain_cursor *cursor, 167 struct callchain_cursor *cursor,
@@ -229,7 +247,13 @@ static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused,
229 247
230char *callchain_list__sym_name(struct callchain_list *cl, 248char *callchain_list__sym_name(struct callchain_list *cl,
231 char *bf, size_t bfsize, bool show_dso); 249 char *bf, size_t bfsize, bool show_dso);
250char *callchain_node__scnprintf_value(struct callchain_node *node,
251 char *bf, size_t bfsize, u64 total);
252int callchain_node__fprintf_value(struct callchain_node *node,
253 FILE *fp, u64 total);
232 254
233void free_callchain(struct callchain_root *root); 255void free_callchain(struct callchain_root *root);
256void decay_callchain(struct callchain_root *root);
257int callchain_node__make_parent_list(struct callchain_node *node);
234 258
235#endif /* __PERF_CALLCHAIN_H */ 259#endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 32e12ecfe9c5..90aa1b46b2e5 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -1,6 +1,6 @@
1#include "util.h" 1#include "util.h"
2#include "../perf.h" 2#include "../perf.h"
3#include "parse-options.h" 3#include <subcmd/parse-options.h>
4#include "evsel.h" 4#include "evsel.h"
5#include "cgroup.h" 5#include "cgroup.h"
6#include "evlist.h" 6#include "evlist.h"
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 9b9565416f90..e5fb88bab9e1 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -24,7 +24,7 @@ int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty)
24 auto_color: 24 auto_color:
25 if (stdout_is_tty < 0) 25 if (stdout_is_tty < 0)
26 stdout_is_tty = isatty(1); 26 stdout_is_tty = isatty(1);
27 if (stdout_is_tty || (pager_in_use() && pager_use_color)) { 27 if (stdout_is_tty || pager_in_use()) {
28 char *term = getenv("TERM"); 28 char *term = getenv("TERM");
29 if (term && strcmp(term, "dumb")) 29 if (term && strcmp(term, "dumb"))
30 return 1; 30 return 1;
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 2e452ac1353d..d3e12e30e1d5 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -10,7 +10,7 @@
10 */ 10 */
11#include "util.h" 11#include "util.h"
12#include "cache.h" 12#include "cache.h"
13#include "exec_cmd.h" 13#include <subcmd/exec-cmd.h>
14#include "util/hist.h" /* perf_hist_config */ 14#include "util/hist.h" /* perf_hist_config */
15#include "util/llvm-utils.h" /* perf_llvm_config */ 15#include "util/llvm-utils.h" /* perf_llvm_config */
16 16
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 10af1e7524fb..fa935093a599 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -5,6 +5,7 @@
5#include <assert.h> 5#include <assert.h>
6#include <stdio.h> 6#include <stdio.h>
7#include <stdlib.h> 7#include <stdlib.h>
8#include <linux/bitmap.h>
8#include "asm/bug.h" 9#include "asm/bug.h"
9 10
10static struct cpu_map *cpu_map__default_new(void) 11static struct cpu_map *cpu_map__default_new(void)
@@ -179,6 +180,56 @@ out:
179 return cpus; 180 return cpus;
180} 181}
181 182
183static struct cpu_map *cpu_map__from_entries(struct cpu_map_entries *cpus)
184{
185 struct cpu_map *map;
186
187 map = cpu_map__empty_new(cpus->nr);
188 if (map) {
189 unsigned i;
190
191 for (i = 0; i < cpus->nr; i++) {
192 /*
193 * Special treatment for -1, which is not real cpu number,
194 * and we need to use (int) -1 to initialize map[i],
195 * otherwise it would become 65535.
196 */
197 if (cpus->cpu[i] == (u16) -1)
198 map->map[i] = -1;
199 else
200 map->map[i] = (int) cpus->cpu[i];
201 }
202 }
203
204 return map;
205}
206
207static struct cpu_map *cpu_map__from_mask(struct cpu_map_mask *mask)
208{
209 struct cpu_map *map;
210 int nr, nbits = mask->nr * mask->long_size * BITS_PER_BYTE;
211
212 nr = bitmap_weight(mask->mask, nbits);
213
214 map = cpu_map__empty_new(nr);
215 if (map) {
216 int cpu, i = 0;
217
218 for_each_set_bit(cpu, mask->mask, nbits)
219 map->map[i++] = cpu;
220 }
221 return map;
222
223}
224
225struct cpu_map *cpu_map__new_data(struct cpu_map_data *data)
226{
227 if (data->type == PERF_CPU_MAP__CPUS)
228 return cpu_map__from_entries((struct cpu_map_entries *)data->data);
229 else
230 return cpu_map__from_mask((struct cpu_map_mask *)data->data);
231}
232
182size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp) 233size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp)
183{ 234{
184 int i; 235 int i;
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 85f7772457fa..71c41b9efabb 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -17,6 +17,7 @@ struct cpu_map {
17struct cpu_map *cpu_map__new(const char *cpu_list); 17struct cpu_map *cpu_map__new(const char *cpu_list);
18struct cpu_map *cpu_map__empty_new(int nr); 18struct cpu_map *cpu_map__empty_new(int nr);
19struct cpu_map *cpu_map__dummy_new(void); 19struct cpu_map *cpu_map__dummy_new(void);
20struct cpu_map *cpu_map__new_data(struct cpu_map_data *data);
20struct cpu_map *cpu_map__read(FILE *file); 21struct cpu_map *cpu_map__read(FILE *file);
21size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); 22size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
22int cpu_map__get_socket_id(int cpu); 23int cpu_map__get_socket_id(int cpu);
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 5bfc1198ab46..34cd1e4039d3 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -63,6 +63,7 @@ struct ctf_writer {
63 struct bt_ctf_field_type *s32; 63 struct bt_ctf_field_type *s32;
64 struct bt_ctf_field_type *u32; 64 struct bt_ctf_field_type *u32;
65 struct bt_ctf_field_type *string; 65 struct bt_ctf_field_type *string;
66 struct bt_ctf_field_type *u32_hex;
66 struct bt_ctf_field_type *u64_hex; 67 struct bt_ctf_field_type *u64_hex;
67 }; 68 };
68 struct bt_ctf_field_type *array[6]; 69 struct bt_ctf_field_type *array[6];
@@ -982,6 +983,7 @@ do { \
982 CREATE_INT_TYPE(cw->data.u64, 64, false, false); 983 CREATE_INT_TYPE(cw->data.u64, 64, false, false);
983 CREATE_INT_TYPE(cw->data.s32, 32, true, false); 984 CREATE_INT_TYPE(cw->data.s32, 32, true, false);
984 CREATE_INT_TYPE(cw->data.u32, 32, false, false); 985 CREATE_INT_TYPE(cw->data.u32, 32, false, false);
986 CREATE_INT_TYPE(cw->data.u32_hex, 32, false, true);
985 CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true); 987 CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true);
986 988
987 cw->data.string = bt_ctf_field_type_string_create(); 989 cw->data.string = bt_ctf_field_type_string_create();
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 425df5c86c9c..e8e9a9dbf5e3 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -1243,6 +1243,8 @@ struct dso *__dsos__addnew(struct dsos *dsos, const char *name)
1243 if (dso != NULL) { 1243 if (dso != NULL) {
1244 __dsos__add(dsos, dso); 1244 __dsos__add(dsos, dso);
1245 dso__set_basename(dso); 1245 dso__set_basename(dso);
1246 /* Put dso here because __dsos_add already got it */
1247 dso__put(dso);
1246 } 1248 }
1247 return dso; 1249 return dso;
1248} 1250}
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index 6af4f7c36820..7dd5939dea2e 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -25,15 +25,6 @@ int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[])
25{ 25{
26 int i; 26 int i;
27 27
28 /*
29 * If env->cmdline_argv has already been set, do not override it. This allows
30 * a command to set the cmdline, parse args and then call another
31 * builtin function that implements a command -- e.g, cmd_kvm calling
32 * cmd_record.
33 */
34 if (env->cmdline_argv != NULL)
35 return 0;
36
37 /* do not include NULL termination */ 28 /* do not include NULL termination */
38 env->cmdline_argv = calloc(argc, sizeof(char *)); 29 env->cmdline_argv = calloc(argc, sizeof(char *));
39 if (env->cmdline_argv == NULL) 30 if (env->cmdline_argv == NULL)
diff --git a/tools/perf/util/environment.c b/tools/perf/util/environment.c
deleted file mode 100644
index 7405123692f1..000000000000
--- a/tools/perf/util/environment.c
+++ /dev/null
@@ -1,8 +0,0 @@
1/*
2 * We put all the perf config variables in this same object
3 * file, so that programs can link against the config parser
4 * without having to link against all the rest of perf.
5 */
6#include "cache.h"
7
8int pager_use_color = 1;
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 8b10621b415c..cd61bb1f3917 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -10,6 +10,8 @@
10#include "thread.h" 10#include "thread.h"
11#include "thread_map.h" 11#include "thread_map.h"
12#include "symbol/kallsyms.h" 12#include "symbol/kallsyms.h"
13#include "asm/bug.h"
14#include "stat.h"
13 15
14static const char *perf_event__names[] = { 16static const char *perf_event__names[] = {
15 [0] = "TOTAL", 17 [0] = "TOTAL",
@@ -37,6 +39,12 @@ static const char *perf_event__names[] = {
37 [PERF_RECORD_AUXTRACE_INFO] = "AUXTRACE_INFO", 39 [PERF_RECORD_AUXTRACE_INFO] = "AUXTRACE_INFO",
38 [PERF_RECORD_AUXTRACE] = "AUXTRACE", 40 [PERF_RECORD_AUXTRACE] = "AUXTRACE",
39 [PERF_RECORD_AUXTRACE_ERROR] = "AUXTRACE_ERROR", 41 [PERF_RECORD_AUXTRACE_ERROR] = "AUXTRACE_ERROR",
42 [PERF_RECORD_THREAD_MAP] = "THREAD_MAP",
43 [PERF_RECORD_CPU_MAP] = "CPU_MAP",
44 [PERF_RECORD_STAT_CONFIG] = "STAT_CONFIG",
45 [PERF_RECORD_STAT] = "STAT",
46 [PERF_RECORD_STAT_ROUND] = "STAT_ROUND",
47 [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE",
40}; 48};
41 49
42const char *perf_event__name(unsigned int id) 50const char *perf_event__name(unsigned int id)
@@ -699,6 +707,274 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
699 return err; 707 return err;
700} 708}
701 709
710int perf_event__synthesize_thread_map2(struct perf_tool *tool,
711 struct thread_map *threads,
712 perf_event__handler_t process,
713 struct machine *machine)
714{
715 union perf_event *event;
716 int i, err, size;
717
718 size = sizeof(event->thread_map);
719 size += threads->nr * sizeof(event->thread_map.entries[0]);
720
721 event = zalloc(size);
722 if (!event)
723 return -ENOMEM;
724
725 event->header.type = PERF_RECORD_THREAD_MAP;
726 event->header.size = size;
727 event->thread_map.nr = threads->nr;
728
729 for (i = 0; i < threads->nr; i++) {
730 struct thread_map_event_entry *entry = &event->thread_map.entries[i];
731 char *comm = thread_map__comm(threads, i);
732
733 if (!comm)
734 comm = (char *) "";
735
736 entry->pid = thread_map__pid(threads, i);
737 strncpy((char *) &entry->comm, comm, sizeof(entry->comm));
738 }
739
740 err = process(tool, event, NULL, machine);
741
742 free(event);
743 return err;
744}
745
746static void synthesize_cpus(struct cpu_map_entries *cpus,
747 struct cpu_map *map)
748{
749 int i;
750
751 cpus->nr = map->nr;
752
753 for (i = 0; i < map->nr; i++)
754 cpus->cpu[i] = map->map[i];
755}
756
757static void synthesize_mask(struct cpu_map_mask *mask,
758 struct cpu_map *map, int max)
759{
760 int i;
761
762 mask->nr = BITS_TO_LONGS(max);
763 mask->long_size = sizeof(long);
764
765 for (i = 0; i < map->nr; i++)
766 set_bit(map->map[i], mask->mask);
767}
768
769static size_t cpus_size(struct cpu_map *map)
770{
771 return sizeof(struct cpu_map_entries) + map->nr * sizeof(u16);
772}
773
774static size_t mask_size(struct cpu_map *map, int *max)
775{
776 int i;
777
778 *max = 0;
779
780 for (i = 0; i < map->nr; i++) {
781 /* bit possition of the cpu is + 1 */
782 int bit = map->map[i] + 1;
783
784 if (bit > *max)
785 *max = bit;
786 }
787
788 return sizeof(struct cpu_map_mask) + BITS_TO_LONGS(*max) * sizeof(long);
789}
790
791void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max)
792{
793 size_t size_cpus, size_mask;
794 bool is_dummy = cpu_map__empty(map);
795
796 /*
797 * Both array and mask data have variable size based
798 * on the number of cpus and their actual values.
799 * The size of the 'struct cpu_map_data' is:
800 *
801 * array = size of 'struct cpu_map_entries' +
802 * number of cpus * sizeof(u64)
803 *
804 * mask = size of 'struct cpu_map_mask' +
805 * maximum cpu bit converted to size of longs
806 *
807 * and finaly + the size of 'struct cpu_map_data'.
808 */
809 size_cpus = cpus_size(map);
810 size_mask = mask_size(map, max);
811
812 if (is_dummy || (size_cpus < size_mask)) {
813 *size += size_cpus;
814 *type = PERF_CPU_MAP__CPUS;
815 } else {
816 *size += size_mask;
817 *type = PERF_CPU_MAP__MASK;
818 }
819
820 *size += sizeof(struct cpu_map_data);
821 return zalloc(*size);
822}
823
824void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map,
825 u16 type, int max)
826{
827 data->type = type;
828
829 switch (type) {
830 case PERF_CPU_MAP__CPUS:
831 synthesize_cpus((struct cpu_map_entries *) data->data, map);
832 break;
833 case PERF_CPU_MAP__MASK:
834 synthesize_mask((struct cpu_map_mask *) data->data, map, max);
835 default:
836 break;
837 };
838}
839
840static struct cpu_map_event* cpu_map_event__new(struct cpu_map *map)
841{
842 size_t size = sizeof(struct cpu_map_event);
843 struct cpu_map_event *event;
844 int max;
845 u16 type;
846
847 event = cpu_map_data__alloc(map, &size, &type, &max);
848 if (!event)
849 return NULL;
850
851 event->header.type = PERF_RECORD_CPU_MAP;
852 event->header.size = size;
853 event->data.type = type;
854
855 cpu_map_data__synthesize(&event->data, map, type, max);
856 return event;
857}
858
859int perf_event__synthesize_cpu_map(struct perf_tool *tool,
860 struct cpu_map *map,
861 perf_event__handler_t process,
862 struct machine *machine)
863{
864 struct cpu_map_event *event;
865 int err;
866
867 event = cpu_map_event__new(map);
868 if (!event)
869 return -ENOMEM;
870
871 err = process(tool, (union perf_event *) event, NULL, machine);
872
873 free(event);
874 return err;
875}
876
877int perf_event__synthesize_stat_config(struct perf_tool *tool,
878 struct perf_stat_config *config,
879 perf_event__handler_t process,
880 struct machine *machine)
881{
882 struct stat_config_event *event;
883 int size, i = 0, err;
884
885 size = sizeof(*event);
886 size += (PERF_STAT_CONFIG_TERM__MAX * sizeof(event->data[0]));
887
888 event = zalloc(size);
889 if (!event)
890 return -ENOMEM;
891
892 event->header.type = PERF_RECORD_STAT_CONFIG;
893 event->header.size = size;
894 event->nr = PERF_STAT_CONFIG_TERM__MAX;
895
896#define ADD(__term, __val) \
897 event->data[i].tag = PERF_STAT_CONFIG_TERM__##__term; \
898 event->data[i].val = __val; \
899 i++;
900
901 ADD(AGGR_MODE, config->aggr_mode)
902 ADD(INTERVAL, config->interval)
903 ADD(SCALE, config->scale)
904
905 WARN_ONCE(i != PERF_STAT_CONFIG_TERM__MAX,
906 "stat config terms unbalanced\n");
907#undef ADD
908
909 err = process(tool, (union perf_event *) event, NULL, machine);
910
911 free(event);
912 return err;
913}
914
915int perf_event__synthesize_stat(struct perf_tool *tool,
916 u32 cpu, u32 thread, u64 id,
917 struct perf_counts_values *count,
918 perf_event__handler_t process,
919 struct machine *machine)
920{
921 struct stat_event event;
922
923 event.header.type = PERF_RECORD_STAT;
924 event.header.size = sizeof(event);
925 event.header.misc = 0;
926
927 event.id = id;
928 event.cpu = cpu;
929 event.thread = thread;
930 event.val = count->val;
931 event.ena = count->ena;
932 event.run = count->run;
933
934 return process(tool, (union perf_event *) &event, NULL, machine);
935}
936
937int perf_event__synthesize_stat_round(struct perf_tool *tool,
938 u64 evtime, u64 type,
939 perf_event__handler_t process,
940 struct machine *machine)
941{
942 struct stat_round_event event;
943
944 event.header.type = PERF_RECORD_STAT_ROUND;
945 event.header.size = sizeof(event);
946 event.header.misc = 0;
947
948 event.time = evtime;
949 event.type = type;
950
951 return process(tool, (union perf_event *) &event, NULL, machine);
952}
953
954void perf_event__read_stat_config(struct perf_stat_config *config,
955 struct stat_config_event *event)
956{
957 unsigned i;
958
959 for (i = 0; i < event->nr; i++) {
960
961 switch (event->data[i].tag) {
962#define CASE(__term, __val) \
963 case PERF_STAT_CONFIG_TERM__##__term: \
964 config->__val = event->data[i].val; \
965 break;
966
967 CASE(AGGR_MODE, aggr_mode)
968 CASE(SCALE, scale)
969 CASE(INTERVAL, interval)
970#undef CASE
971 default:
972 pr_warning("unknown stat config term %" PRIu64 "\n",
973 event->data[i].tag);
974 }
975 }
976}
977
702size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp) 978size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
703{ 979{
704 const char *s; 980 const char *s;
@@ -783,6 +1059,38 @@ size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
783 event->mmap2.filename); 1059 event->mmap2.filename);
784} 1060}
785 1061
1062size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp)
1063{
1064 struct thread_map *threads = thread_map__new_event(&event->thread_map);
1065 size_t ret;
1066
1067 ret = fprintf(fp, " nr: ");
1068
1069 if (threads)
1070 ret += thread_map__fprintf(threads, fp);
1071 else
1072 ret += fprintf(fp, "failed to get threads from event\n");
1073
1074 thread_map__put(threads);
1075 return ret;
1076}
1077
1078size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp)
1079{
1080 struct cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data);
1081 size_t ret;
1082
1083 ret = fprintf(fp, " nr: ");
1084
1085 if (cpus)
1086 ret += cpu_map__fprintf(cpus, fp);
1087 else
1088 ret += fprintf(fp, "failed to get cpumap from event\n");
1089
1090 cpu_map__put(cpus);
1091 return ret;
1092}
1093
786int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, 1094int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
787 union perf_event *event, 1095 union perf_event *event,
788 struct perf_sample *sample, 1096 struct perf_sample *sample,
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index a0dbcbd4f6d8..b7ffb7ee9971 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -226,6 +226,12 @@ enum perf_user_event_type { /* above any possible kernel type */
226 PERF_RECORD_AUXTRACE_INFO = 70, 226 PERF_RECORD_AUXTRACE_INFO = 70,
227 PERF_RECORD_AUXTRACE = 71, 227 PERF_RECORD_AUXTRACE = 71,
228 PERF_RECORD_AUXTRACE_ERROR = 72, 228 PERF_RECORD_AUXTRACE_ERROR = 72,
229 PERF_RECORD_THREAD_MAP = 73,
230 PERF_RECORD_CPU_MAP = 74,
231 PERF_RECORD_STAT_CONFIG = 75,
232 PERF_RECORD_STAT = 76,
233 PERF_RECORD_STAT_ROUND = 77,
234 PERF_RECORD_EVENT_UPDATE = 78,
229 PERF_RECORD_HEADER_MAX 235 PERF_RECORD_HEADER_MAX
230}; 236};
231 237
@@ -270,12 +276,61 @@ struct events_stats {
270 u32 nr_proc_map_timeout; 276 u32 nr_proc_map_timeout;
271}; 277};
272 278
279enum {
280 PERF_CPU_MAP__CPUS = 0,
281 PERF_CPU_MAP__MASK = 1,
282};
283
284struct cpu_map_entries {
285 u16 nr;
286 u16 cpu[];
287};
288
289struct cpu_map_mask {
290 u16 nr;
291 u16 long_size;
292 unsigned long mask[];
293};
294
295struct cpu_map_data {
296 u16 type;
297 char data[];
298};
299
300struct cpu_map_event {
301 struct perf_event_header header;
302 struct cpu_map_data data;
303};
304
273struct attr_event { 305struct attr_event {
274 struct perf_event_header header; 306 struct perf_event_header header;
275 struct perf_event_attr attr; 307 struct perf_event_attr attr;
276 u64 id[]; 308 u64 id[];
277}; 309};
278 310
311enum {
312 PERF_EVENT_UPDATE__UNIT = 0,
313 PERF_EVENT_UPDATE__SCALE = 1,
314 PERF_EVENT_UPDATE__NAME = 2,
315 PERF_EVENT_UPDATE__CPUS = 3,
316};
317
318struct event_update_event_cpus {
319 struct cpu_map_data cpus;
320};
321
322struct event_update_event_scale {
323 double scale;
324};
325
326struct event_update_event {
327 struct perf_event_header header;
328 u64 type;
329 u64 id;
330
331 char data[];
332};
333
279#define MAX_EVENT_NAME 64 334#define MAX_EVENT_NAME 64
280 335
281struct perf_trace_event_type { 336struct perf_trace_event_type {
@@ -356,6 +411,63 @@ struct context_switch_event {
356 u32 next_prev_tid; 411 u32 next_prev_tid;
357}; 412};
358 413
414struct thread_map_event_entry {
415 u64 pid;
416 char comm[16];
417};
418
419struct thread_map_event {
420 struct perf_event_header header;
421 u64 nr;
422 struct thread_map_event_entry entries[];
423};
424
425enum {
426 PERF_STAT_CONFIG_TERM__AGGR_MODE = 0,
427 PERF_STAT_CONFIG_TERM__INTERVAL = 1,
428 PERF_STAT_CONFIG_TERM__SCALE = 2,
429 PERF_STAT_CONFIG_TERM__MAX = 3,
430};
431
432struct stat_config_event_entry {
433 u64 tag;
434 u64 val;
435};
436
437struct stat_config_event {
438 struct perf_event_header header;
439 u64 nr;
440 struct stat_config_event_entry data[];
441};
442
443struct stat_event {
444 struct perf_event_header header;
445
446 u64 id;
447 u32 cpu;
448 u32 thread;
449
450 union {
451 struct {
452 u64 val;
453 u64 ena;
454 u64 run;
455 };
456 u64 values[3];
457 };
458};
459
460enum {
461 PERF_STAT_ROUND_TYPE__INTERVAL = 0,
462 PERF_STAT_ROUND_TYPE__FINAL = 1,
463};
464
465struct stat_round_event {
466 struct perf_event_header header;
467 u64 type;
468 u64 time;
469};
470
359union perf_event { 471union perf_event {
360 struct perf_event_header header; 472 struct perf_event_header header;
361 struct mmap_event mmap; 473 struct mmap_event mmap;
@@ -368,6 +480,7 @@ union perf_event {
368 struct throttle_event throttle; 480 struct throttle_event throttle;
369 struct sample_event sample; 481 struct sample_event sample;
370 struct attr_event attr; 482 struct attr_event attr;
483 struct event_update_event event_update;
371 struct event_type_event event_type; 484 struct event_type_event event_type;
372 struct tracing_data_event tracing_data; 485 struct tracing_data_event tracing_data;
373 struct build_id_event build_id; 486 struct build_id_event build_id;
@@ -378,12 +491,20 @@ union perf_event {
378 struct aux_event aux; 491 struct aux_event aux;
379 struct itrace_start_event itrace_start; 492 struct itrace_start_event itrace_start;
380 struct context_switch_event context_switch; 493 struct context_switch_event context_switch;
494 struct thread_map_event thread_map;
495 struct cpu_map_event cpu_map;
496 struct stat_config_event stat_config;
497 struct stat_event stat;
498 struct stat_round_event stat_round;
381}; 499};
382 500
383void perf_event__print_totals(void); 501void perf_event__print_totals(void);
384 502
385struct perf_tool; 503struct perf_tool;
386struct thread_map; 504struct thread_map;
505struct cpu_map;
506struct perf_stat_config;
507struct perf_counts_values;
387 508
388typedef int (*perf_event__handler_t)(struct perf_tool *tool, 509typedef int (*perf_event__handler_t)(struct perf_tool *tool,
389 union perf_event *event, 510 union perf_event *event,
@@ -395,6 +516,14 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
395 perf_event__handler_t process, 516 perf_event__handler_t process,
396 struct machine *machine, bool mmap_data, 517 struct machine *machine, bool mmap_data,
397 unsigned int proc_map_timeout); 518 unsigned int proc_map_timeout);
519int perf_event__synthesize_thread_map2(struct perf_tool *tool,
520 struct thread_map *threads,
521 perf_event__handler_t process,
522 struct machine *machine);
523int perf_event__synthesize_cpu_map(struct perf_tool *tool,
524 struct cpu_map *cpus,
525 perf_event__handler_t process,
526 struct machine *machine);
398int perf_event__synthesize_threads(struct perf_tool *tool, 527int perf_event__synthesize_threads(struct perf_tool *tool,
399 perf_event__handler_t process, 528 perf_event__handler_t process,
400 struct machine *machine, bool mmap_data, 529 struct machine *machine, bool mmap_data,
@@ -402,7 +531,21 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
402int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, 531int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
403 perf_event__handler_t process, 532 perf_event__handler_t process,
404 struct machine *machine); 533 struct machine *machine);
405 534int perf_event__synthesize_stat_config(struct perf_tool *tool,
535 struct perf_stat_config *config,
536 perf_event__handler_t process,
537 struct machine *machine);
538void perf_event__read_stat_config(struct perf_stat_config *config,
539 struct stat_config_event *event);
540int perf_event__synthesize_stat(struct perf_tool *tool,
541 u32 cpu, u32 thread, u64 id,
542 struct perf_counts_values *count,
543 perf_event__handler_t process,
544 struct machine *machine);
545int perf_event__synthesize_stat_round(struct perf_tool *tool,
546 u64 time, u64 type,
547 perf_event__handler_t process,
548 struct machine *machine);
406int perf_event__synthesize_modules(struct perf_tool *tool, 549int perf_event__synthesize_modules(struct perf_tool *tool,
407 perf_event__handler_t process, 550 perf_event__handler_t process,
408 struct machine *machine); 551 struct machine *machine);
@@ -499,9 +642,14 @@ size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
499size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp); 642size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp);
500size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp); 643size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp);
501size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp); 644size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp);
645size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp);
646size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp);
502size_t perf_event__fprintf(union perf_event *event, FILE *fp); 647size_t perf_event__fprintf(union perf_event *event, FILE *fp);
503 648
504u64 kallsyms__get_function_start(const char *kallsyms_filename, 649u64 kallsyms__get_function_start(const char *kallsyms_filename,
505 const char *symbol_name); 650 const char *symbol_name);
506 651
652void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max);
653void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map,
654 u16 type, int max);
507#endif /* __PERF_RECORD_H */ 655#endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index d1392194a9a9..d81f13de2476 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -18,7 +18,7 @@
18#include <unistd.h> 18#include <unistd.h>
19 19
20#include "parse-events.h" 20#include "parse-events.h"
21#include "parse-options.h" 21#include <subcmd/parse-options.h>
22 22
23#include <sys/mman.h> 23#include <sys/mman.h>
24 24
@@ -68,6 +68,18 @@ struct perf_evlist *perf_evlist__new_default(void)
68 return evlist; 68 return evlist;
69} 69}
70 70
71struct perf_evlist *perf_evlist__new_dummy(void)
72{
73 struct perf_evlist *evlist = perf_evlist__new();
74
75 if (evlist && perf_evlist__add_dummy(evlist)) {
76 perf_evlist__delete(evlist);
77 evlist = NULL;
78 }
79
80 return evlist;
81}
82
71/** 83/**
72 * perf_evlist__set_id_pos - set the positions of event ids. 84 * perf_evlist__set_id_pos - set the positions of event ids.
73 * @evlist: selected event list 85 * @evlist: selected event list
@@ -248,6 +260,22 @@ error:
248 return -ENOMEM; 260 return -ENOMEM;
249} 261}
250 262
263int perf_evlist__add_dummy(struct perf_evlist *evlist)
264{
265 struct perf_event_attr attr = {
266 .type = PERF_TYPE_SOFTWARE,
267 .config = PERF_COUNT_SW_DUMMY,
268 .size = sizeof(attr), /* to capture ABI version */
269 };
270 struct perf_evsel *evsel = perf_evsel__new(&attr);
271
272 if (evsel == NULL)
273 return -ENOMEM;
274
275 perf_evlist__add(evlist, evsel);
276 return 0;
277}
278
251static int perf_evlist__add_attrs(struct perf_evlist *evlist, 279static int perf_evlist__add_attrs(struct perf_evlist *evlist,
252 struct perf_event_attr *attrs, size_t nr_attrs) 280 struct perf_event_attr *attrs, size_t nr_attrs)
253{ 281{
@@ -336,20 +364,12 @@ static int perf_evlist__nr_threads(struct perf_evlist *evlist,
336 364
337void perf_evlist__disable(struct perf_evlist *evlist) 365void perf_evlist__disable(struct perf_evlist *evlist)
338{ 366{
339 int cpu, thread;
340 struct perf_evsel *pos; 367 struct perf_evsel *pos;
341 int nr_cpus = cpu_map__nr(evlist->cpus);
342 int nr_threads;
343 368
344 for (cpu = 0; cpu < nr_cpus; cpu++) { 369 evlist__for_each(evlist, pos) {
345 evlist__for_each(evlist, pos) { 370 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
346 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 371 continue;
347 continue; 372 perf_evsel__disable(pos);
348 nr_threads = perf_evlist__nr_threads(evlist, pos);
349 for (thread = 0; thread < nr_threads; thread++)
350 ioctl(FD(pos, cpu, thread),
351 PERF_EVENT_IOC_DISABLE, 0);
352 }
353 } 373 }
354 374
355 evlist->enabled = false; 375 evlist->enabled = false;
@@ -357,20 +377,12 @@ void perf_evlist__disable(struct perf_evlist *evlist)
357 377
358void perf_evlist__enable(struct perf_evlist *evlist) 378void perf_evlist__enable(struct perf_evlist *evlist)
359{ 379{
360 int cpu, thread;
361 struct perf_evsel *pos; 380 struct perf_evsel *pos;
362 int nr_cpus = cpu_map__nr(evlist->cpus);
363 int nr_threads;
364 381
365 for (cpu = 0; cpu < nr_cpus; cpu++) { 382 evlist__for_each(evlist, pos) {
366 evlist__for_each(evlist, pos) { 383 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
367 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 384 continue;
368 continue; 385 perf_evsel__enable(pos);
369 nr_threads = perf_evlist__nr_threads(evlist, pos);
370 for (thread = 0; thread < nr_threads; thread++)
371 ioctl(FD(pos, cpu, thread),
372 PERF_EVENT_IOC_ENABLE, 0);
373 }
374 } 386 }
375 387
376 evlist->enabled = true; 388 evlist->enabled = true;
@@ -381,48 +393,6 @@ void perf_evlist__toggle_enable(struct perf_evlist *evlist)
381 (evlist->enabled ? perf_evlist__disable : perf_evlist__enable)(evlist); 393 (evlist->enabled ? perf_evlist__disable : perf_evlist__enable)(evlist);
382} 394}
383 395
384int perf_evlist__disable_event(struct perf_evlist *evlist,
385 struct perf_evsel *evsel)
386{
387 int cpu, thread, err;
388 int nr_cpus = cpu_map__nr(evlist->cpus);
389 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
390
391 if (!evsel->fd)
392 return 0;
393
394 for (cpu = 0; cpu < nr_cpus; cpu++) {
395 for (thread = 0; thread < nr_threads; thread++) {
396 err = ioctl(FD(evsel, cpu, thread),
397 PERF_EVENT_IOC_DISABLE, 0);
398 if (err)
399 return err;
400 }
401 }
402 return 0;
403}
404
405int perf_evlist__enable_event(struct perf_evlist *evlist,
406 struct perf_evsel *evsel)
407{
408 int cpu, thread, err;
409 int nr_cpus = cpu_map__nr(evlist->cpus);
410 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
411
412 if (!evsel->fd)
413 return -EINVAL;
414
415 for (cpu = 0; cpu < nr_cpus; cpu++) {
416 for (thread = 0; thread < nr_threads; thread++) {
417 err = ioctl(FD(evsel, cpu, thread),
418 PERF_EVENT_IOC_ENABLE, 0);
419 if (err)
420 return err;
421 }
422 }
423 return 0;
424}
425
426static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist, 396static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist,
427 struct perf_evsel *evsel, int cpu) 397 struct perf_evsel *evsel, int cpu)
428{ 398{
@@ -550,9 +520,9 @@ void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
550 evsel->id[evsel->ids++] = id; 520 evsel->id[evsel->ids++] = id;
551} 521}
552 522
553static int perf_evlist__id_add_fd(struct perf_evlist *evlist, 523int perf_evlist__id_add_fd(struct perf_evlist *evlist,
554 struct perf_evsel *evsel, 524 struct perf_evsel *evsel,
555 int cpu, int thread, int fd) 525 int cpu, int thread, int fd)
556{ 526{
557 u64 read_data[4] = { 0, }; 527 u64 read_data[4] = { 0, };
558 int id_idx = 1; /* The first entry is the counter value */ 528 int id_idx = 1; /* The first entry is the counter value */
@@ -1486,7 +1456,7 @@ int perf_evlist__open(struct perf_evlist *evlist)
1486 perf_evlist__update_id_pos(evlist); 1456 perf_evlist__update_id_pos(evlist);
1487 1457
1488 evlist__for_each(evlist, evsel) { 1458 evlist__for_each(evlist, evsel) {
1489 err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); 1459 err = perf_evsel__open(evsel, evsel->cpus, evsel->threads);
1490 if (err < 0) 1460 if (err < 0)
1491 goto out_err; 1461 goto out_err;
1492 } 1462 }
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index a459fe71b452..7c4d9a206776 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -67,6 +67,7 @@ struct perf_evsel_str_handler {
67 67
68struct perf_evlist *perf_evlist__new(void); 68struct perf_evlist *perf_evlist__new(void);
69struct perf_evlist *perf_evlist__new_default(void); 69struct perf_evlist *perf_evlist__new_default(void);
70struct perf_evlist *perf_evlist__new_dummy(void);
70void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, 71void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
71 struct thread_map *threads); 72 struct thread_map *threads);
72void perf_evlist__exit(struct perf_evlist *evlist); 73void perf_evlist__exit(struct perf_evlist *evlist);
@@ -81,6 +82,8 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
81#define perf_evlist__add_default_attrs(evlist, array) \ 82#define perf_evlist__add_default_attrs(evlist, array) \
82 __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) 83 __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array))
83 84
85int perf_evlist__add_dummy(struct perf_evlist *evlist);
86
84int perf_evlist__add_newtp(struct perf_evlist *evlist, 87int perf_evlist__add_newtp(struct perf_evlist *evlist,
85 const char *sys, const char *name, void *handler); 88 const char *sys, const char *name, void *handler);
86 89
@@ -97,6 +100,9 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
97 100
98void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 101void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
99 int cpu, int thread, u64 id); 102 int cpu, int thread, u64 id);
103int perf_evlist__id_add_fd(struct perf_evlist *evlist,
104 struct perf_evsel *evsel,
105 int cpu, int thread, int fd);
100 106
101int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd); 107int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
102int perf_evlist__alloc_pollfd(struct perf_evlist *evlist); 108int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
@@ -149,10 +155,6 @@ void perf_evlist__disable(struct perf_evlist *evlist);
149void perf_evlist__enable(struct perf_evlist *evlist); 155void perf_evlist__enable(struct perf_evlist *evlist);
150void perf_evlist__toggle_enable(struct perf_evlist *evlist); 156void perf_evlist__toggle_enable(struct perf_evlist *evlist);
151 157
152int perf_evlist__disable_event(struct perf_evlist *evlist,
153 struct perf_evsel *evsel);
154int perf_evlist__enable_event(struct perf_evlist *evlist,
155 struct perf_evsel *evsel);
156int perf_evlist__enable_event_idx(struct perf_evlist *evlist, 158int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
157 struct perf_evsel *evsel, int idx); 159 struct perf_evsel *evsel, int idx);
158 160
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 397fb4ed3c97..cdbaf9b51e42 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -36,6 +36,7 @@ static struct {
36 bool cloexec; 36 bool cloexec;
37 bool clockid; 37 bool clockid;
38 bool clockid_wrong; 38 bool clockid_wrong;
39 bool lbr_flags;
39} perf_missing_features; 40} perf_missing_features;
40 41
41static clockid_t clockid; 42static clockid_t clockid;
@@ -574,7 +575,9 @@ perf_evsel__config_callgraph(struct perf_evsel *evsel,
574 } else { 575 } else {
575 perf_evsel__set_sample_bit(evsel, BRANCH_STACK); 576 perf_evsel__set_sample_bit(evsel, BRANCH_STACK);
576 attr->branch_sample_type = PERF_SAMPLE_BRANCH_USER | 577 attr->branch_sample_type = PERF_SAMPLE_BRANCH_USER |
577 PERF_SAMPLE_BRANCH_CALL_STACK; 578 PERF_SAMPLE_BRANCH_CALL_STACK |
579 PERF_SAMPLE_BRANCH_NO_CYCLES |
580 PERF_SAMPLE_BRANCH_NO_FLAGS;
578 } 581 }
579 } else 582 } else
580 pr_warning("Cannot use LBR callstack with branch stack. " 583 pr_warning("Cannot use LBR callstack with branch stack. "
@@ -981,13 +984,26 @@ int perf_evsel__append_filter(struct perf_evsel *evsel,
981 return -1; 984 return -1;
982} 985}
983 986
984int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads) 987int perf_evsel__enable(struct perf_evsel *evsel)
985{ 988{
989 int nthreads = thread_map__nr(evsel->threads);
990 int ncpus = cpu_map__nr(evsel->cpus);
991
986 return perf_evsel__run_ioctl(evsel, ncpus, nthreads, 992 return perf_evsel__run_ioctl(evsel, ncpus, nthreads,
987 PERF_EVENT_IOC_ENABLE, 993 PERF_EVENT_IOC_ENABLE,
988 0); 994 0);
989} 995}
990 996
997int perf_evsel__disable(struct perf_evsel *evsel)
998{
999 int nthreads = thread_map__nr(evsel->threads);
1000 int ncpus = cpu_map__nr(evsel->cpus);
1001
1002 return perf_evsel__run_ioctl(evsel, ncpus, nthreads,
1003 PERF_EVENT_IOC_DISABLE,
1004 0);
1005}
1006
991int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 1007int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
992{ 1008{
993 if (ncpus == 0 || nthreads == 0) 1009 if (ncpus == 0 || nthreads == 0)
@@ -1192,6 +1208,7 @@ static void __p_sample_type(char *buf, size_t size, u64 value)
1192 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), 1208 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
1193 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), 1209 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
1194 bit_name(IDENTIFIER), bit_name(REGS_INTR), bit_name(DATA_SRC), 1210 bit_name(IDENTIFIER), bit_name(REGS_INTR), bit_name(DATA_SRC),
1211 bit_name(WEIGHT),
1195 { .name = NULL, } 1212 { .name = NULL, }
1196 }; 1213 };
1197#undef bit_name 1214#undef bit_name
@@ -1323,6 +1340,9 @@ fallback_missing_features:
1323 evsel->attr.mmap2 = 0; 1340 evsel->attr.mmap2 = 0;
1324 if (perf_missing_features.exclude_guest) 1341 if (perf_missing_features.exclude_guest)
1325 evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; 1342 evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
1343 if (perf_missing_features.lbr_flags)
1344 evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS |
1345 PERF_SAMPLE_BRANCH_NO_CYCLES);
1326retry_sample_id: 1346retry_sample_id:
1327 if (perf_missing_features.sample_id_all) 1347 if (perf_missing_features.sample_id_all)
1328 evsel->attr.sample_id_all = 0; 1348 evsel->attr.sample_id_all = 0;
@@ -1441,6 +1461,12 @@ try_fallback:
1441 } else if (!perf_missing_features.sample_id_all) { 1461 } else if (!perf_missing_features.sample_id_all) {
1442 perf_missing_features.sample_id_all = true; 1462 perf_missing_features.sample_id_all = true;
1443 goto retry_sample_id; 1463 goto retry_sample_id;
1464 } else if (!perf_missing_features.lbr_flags &&
1465 (evsel->attr.branch_sample_type &
1466 (PERF_SAMPLE_BRANCH_NO_CYCLES |
1467 PERF_SAMPLE_BRANCH_NO_FLAGS))) {
1468 perf_missing_features.lbr_flags = true;
1469 goto fallback_missing_features;
1444 } 1470 }
1445 1471
1446out_close: 1472out_close:
@@ -2272,6 +2298,29 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
2272 printed += comma_fprintf(fp, &first, " %s=%" PRIu64, 2298 printed += comma_fprintf(fp, &first, " %s=%" PRIu64,
2273 term, (u64)evsel->attr.sample_freq); 2299 term, (u64)evsel->attr.sample_freq);
2274 } 2300 }
2301
2302 if (details->trace_fields) {
2303 struct format_field *field;
2304
2305 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
2306 printed += comma_fprintf(fp, &first, " (not a tracepoint)");
2307 goto out;
2308 }
2309
2310 field = evsel->tp_format->format.fields;
2311 if (field == NULL) {
2312 printed += comma_fprintf(fp, &first, " (no trace field)");
2313 goto out;
2314 }
2315
2316 printed += comma_fprintf(fp, &first, " trace_fields: %s", field->name);
2317
2318 field = field->next;
2319 while (field) {
2320 printed += comma_fprintf(fp, &first, "%s", field->name);
2321 field = field->next;
2322 }
2323 }
2275out: 2324out:
2276 fputc('\n', fp); 2325 fputc('\n', fp);
2277 return ++printed; 2326 return ++printed;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 0e49bd742c63..8e75434bd01c 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -227,7 +227,8 @@ int perf_evsel__append_filter(struct perf_evsel *evsel,
227 const char *op, const char *filter); 227 const char *op, const char *filter);
228int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads, 228int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
229 const char *filter); 229 const char *filter);
230int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads); 230int perf_evsel__enable(struct perf_evsel *evsel);
231int perf_evsel__disable(struct perf_evsel *evsel);
231 232
232int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 233int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
233 struct cpu_map *cpus); 234 struct cpu_map *cpus);
@@ -368,6 +369,7 @@ struct perf_attr_details {
368 bool verbose; 369 bool verbose;
369 bool event_group; 370 bool event_group;
370 bool force; 371 bool force;
372 bool trace_fields;
371}; 373};
372 374
373int perf_evsel__fprintf(struct perf_evsel *evsel, 375int perf_evsel__fprintf(struct perf_evsel *evsel,
diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c
deleted file mode 100644
index 7adf4ad15d8f..000000000000
--- a/tools/perf/util/exec_cmd.c
+++ /dev/null
@@ -1,148 +0,0 @@
1#include "cache.h"
2#include "exec_cmd.h"
3#include "quote.h"
4
5#include <string.h>
6
7#define MAX_ARGS 32
8
9static const char *argv_exec_path;
10static const char *argv0_path;
11
12const char *system_path(const char *path)
13{
14 static const char *prefix = PREFIX;
15 struct strbuf d = STRBUF_INIT;
16
17 if (is_absolute_path(path))
18 return path;
19
20 strbuf_addf(&d, "%s/%s", prefix, path);
21 path = strbuf_detach(&d, NULL);
22 return path;
23}
24
25const char *perf_extract_argv0_path(const char *argv0)
26{
27 const char *slash;
28
29 if (!argv0 || !*argv0)
30 return NULL;
31 slash = argv0 + strlen(argv0);
32
33 while (argv0 <= slash && !is_dir_sep(*slash))
34 slash--;
35
36 if (slash >= argv0) {
37 argv0_path = strndup(argv0, slash - argv0);
38 return argv0_path ? slash + 1 : NULL;
39 }
40
41 return argv0;
42}
43
44void perf_set_argv_exec_path(const char *exec_path)
45{
46 argv_exec_path = exec_path;
47 /*
48 * Propagate this setting to external programs.
49 */
50 setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
51}
52
53
54/* Returns the highest-priority, location to look for perf programs. */
55const char *perf_exec_path(void)
56{
57 const char *env;
58
59 if (argv_exec_path)
60 return argv_exec_path;
61
62 env = getenv(EXEC_PATH_ENVIRONMENT);
63 if (env && *env) {
64 return env;
65 }
66
67 return system_path(PERF_EXEC_PATH);
68}
69
70static void add_path(struct strbuf *out, const char *path)
71{
72 if (path && *path) {
73 if (is_absolute_path(path))
74 strbuf_addstr(out, path);
75 else
76 strbuf_addstr(out, make_nonrelative_path(path));
77
78 strbuf_addch(out, PATH_SEP);
79 }
80}
81
82void setup_path(void)
83{
84 const char *old_path = getenv("PATH");
85 struct strbuf new_path = STRBUF_INIT;
86
87 add_path(&new_path, perf_exec_path());
88 add_path(&new_path, argv0_path);
89
90 if (old_path)
91 strbuf_addstr(&new_path, old_path);
92 else
93 strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
94
95 setenv("PATH", new_path.buf, 1);
96
97 strbuf_release(&new_path);
98}
99
100static const char **prepare_perf_cmd(const char **argv)
101{
102 int argc;
103 const char **nargv;
104
105 for (argc = 0; argv[argc]; argc++)
106 ; /* just counting */
107 nargv = malloc(sizeof(*nargv) * (argc + 2));
108
109 nargv[0] = "perf";
110 for (argc = 0; argv[argc]; argc++)
111 nargv[argc + 1] = argv[argc];
112 nargv[argc + 1] = NULL;
113 return nargv;
114}
115
116int execv_perf_cmd(const char **argv) {
117 const char **nargv = prepare_perf_cmd(argv);
118
119 /* execvp() can only ever return if it fails */
120 execvp("perf", (char **)nargv);
121
122 free(nargv);
123 return -1;
124}
125
126
127int execl_perf_cmd(const char *cmd,...)
128{
129 int argc;
130 const char *argv[MAX_ARGS + 1];
131 const char *arg;
132 va_list param;
133
134 va_start(param, cmd);
135 argv[0] = cmd;
136 argc = 1;
137 while (argc < MAX_ARGS) {
138 arg = argv[argc++] = va_arg(param, char *);
139 if (!arg)
140 break;
141 }
142 va_end(param);
143 if (MAX_ARGS <= argc)
144 return error("too many args to run %s", cmd);
145
146 argv[argc] = NULL;
147 return execv_perf_cmd(argv);
148}
diff --git a/tools/perf/util/exec_cmd.h b/tools/perf/util/exec_cmd.h
deleted file mode 100644
index bc4b915963f5..000000000000
--- a/tools/perf/util/exec_cmd.h
+++ /dev/null
@@ -1,12 +0,0 @@
1#ifndef __PERF_EXEC_CMD_H
2#define __PERF_EXEC_CMD_H
3
4extern void perf_set_argv_exec_path(const char *exec_path);
5extern const char *perf_extract_argv0_path(const char *path);
6extern const char *perf_exec_path(void);
7extern void setup_path(void);
8extern int execv_perf_cmd(const char **argv); /* NULL terminated */
9extern int execl_perf_cmd(const char *cmd, ...);
10extern const char *system_path(const char *path);
11
12#endif /* __PERF_EXEC_CMD_H */
diff --git a/tools/perf/util/generate-cmdlist.sh b/tools/perf/util/generate-cmdlist.sh
index 36a885d2cd22..0ac2037c970c 100755
--- a/tools/perf/util/generate-cmdlist.sh
+++ b/tools/perf/util/generate-cmdlist.sh
@@ -36,4 +36,19 @@ do
36 }' "Documentation/perf-$cmd.txt" 36 }' "Documentation/perf-$cmd.txt"
37done 37done
38echo "#endif /* HAVE_LIBELF_SUPPORT */" 38echo "#endif /* HAVE_LIBELF_SUPPORT */"
39
40echo "#ifdef HAVE_LIBAUDIT_SUPPORT"
41sed -n -e 's/^perf-\([^ ]*\)[ ].* audit*/\1/p' command-list.txt |
42sort |
43while read cmd
44do
45 sed -n '
46 /^NAME/,/perf-'"$cmd"'/H
47 ${
48 x
49 s/.*perf-'"$cmd"' - \(.*\)/ {"'"$cmd"'", "\1"},/
50 p
51 }' "Documentation/perf-$cmd.txt"
52done
53echo "#endif /* HAVE_LIBELF_SUPPORT */"
39echo "};" 54echo "};"
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 43838003c1a1..f50b7235ecb6 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -724,7 +724,7 @@ static int write_numa_topology(int fd, struct perf_header *h __maybe_unused,
724done: 724done:
725 free(buf); 725 free(buf);
726 fclose(fp); 726 fclose(fp);
727 free(node_map); 727 cpu_map__put(node_map);
728 return ret; 728 return ret;
729} 729}
730 730
@@ -868,6 +868,13 @@ static int write_auxtrace(int fd, struct perf_header *h,
868 return err; 868 return err;
869} 869}
870 870
871static int write_stat(int fd __maybe_unused,
872 struct perf_header *h __maybe_unused,
873 struct perf_evlist *evlist __maybe_unused)
874{
875 return 0;
876}
877
871static void print_hostname(struct perf_header *ph, int fd __maybe_unused, 878static void print_hostname(struct perf_header *ph, int fd __maybe_unused,
872 FILE *fp) 879 FILE *fp)
873{ 880{
@@ -1159,6 +1166,12 @@ static void print_auxtrace(struct perf_header *ph __maybe_unused,
1159 fprintf(fp, "# contains AUX area data (e.g. instruction trace)\n"); 1166 fprintf(fp, "# contains AUX area data (e.g. instruction trace)\n");
1160} 1167}
1161 1168
1169static void print_stat(struct perf_header *ph __maybe_unused,
1170 int fd __maybe_unused, FILE *fp)
1171{
1172 fprintf(fp, "# contains stat data\n");
1173}
1174
1162static void print_pmu_mappings(struct perf_header *ph, int fd __maybe_unused, 1175static void print_pmu_mappings(struct perf_header *ph, int fd __maybe_unused,
1163 FILE *fp) 1176 FILE *fp)
1164{ 1177{
@@ -1948,6 +1961,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
1948 FEAT_OPP(HEADER_PMU_MAPPINGS, pmu_mappings), 1961 FEAT_OPP(HEADER_PMU_MAPPINGS, pmu_mappings),
1949 FEAT_OPP(HEADER_GROUP_DESC, group_desc), 1962 FEAT_OPP(HEADER_GROUP_DESC, group_desc),
1950 FEAT_OPP(HEADER_AUXTRACE, auxtrace), 1963 FEAT_OPP(HEADER_AUXTRACE, auxtrace),
1964 FEAT_OPA(HEADER_STAT, stat),
1951}; 1965};
1952 1966
1953struct header_print_data { 1967struct header_print_data {
@@ -2686,6 +2700,152 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
2686 return err; 2700 return err;
2687} 2701}
2688 2702
2703static struct event_update_event *
2704event_update_event__new(size_t size, u64 type, u64 id)
2705{
2706 struct event_update_event *ev;
2707
2708 size += sizeof(*ev);
2709 size = PERF_ALIGN(size, sizeof(u64));
2710
2711 ev = zalloc(size);
2712 if (ev) {
2713 ev->header.type = PERF_RECORD_EVENT_UPDATE;
2714 ev->header.size = (u16)size;
2715 ev->type = type;
2716 ev->id = id;
2717 }
2718 return ev;
2719}
2720
2721int
2722perf_event__synthesize_event_update_unit(struct perf_tool *tool,
2723 struct perf_evsel *evsel,
2724 perf_event__handler_t process)
2725{
2726 struct event_update_event *ev;
2727 size_t size = strlen(evsel->unit);
2728 int err;
2729
2730 ev = event_update_event__new(size + 1, PERF_EVENT_UPDATE__UNIT, evsel->id[0]);
2731 if (ev == NULL)
2732 return -ENOMEM;
2733
2734 strncpy(ev->data, evsel->unit, size);
2735 err = process(tool, (union perf_event *)ev, NULL, NULL);
2736 free(ev);
2737 return err;
2738}
2739
2740int
2741perf_event__synthesize_event_update_scale(struct perf_tool *tool,
2742 struct perf_evsel *evsel,
2743 perf_event__handler_t process)
2744{
2745 struct event_update_event *ev;
2746 struct event_update_event_scale *ev_data;
2747 int err;
2748
2749 ev = event_update_event__new(sizeof(*ev_data), PERF_EVENT_UPDATE__SCALE, evsel->id[0]);
2750 if (ev == NULL)
2751 return -ENOMEM;
2752
2753 ev_data = (struct event_update_event_scale *) ev->data;
2754 ev_data->scale = evsel->scale;
2755 err = process(tool, (union perf_event*) ev, NULL, NULL);
2756 free(ev);
2757 return err;
2758}
2759
2760int
2761perf_event__synthesize_event_update_name(struct perf_tool *tool,
2762 struct perf_evsel *evsel,
2763 perf_event__handler_t process)
2764{
2765 struct event_update_event *ev;
2766 size_t len = strlen(evsel->name);
2767 int err;
2768
2769 ev = event_update_event__new(len + 1, PERF_EVENT_UPDATE__NAME, evsel->id[0]);
2770 if (ev == NULL)
2771 return -ENOMEM;
2772
2773 strncpy(ev->data, evsel->name, len);
2774 err = process(tool, (union perf_event*) ev, NULL, NULL);
2775 free(ev);
2776 return err;
2777}
2778
2779int
2780perf_event__synthesize_event_update_cpus(struct perf_tool *tool,
2781 struct perf_evsel *evsel,
2782 perf_event__handler_t process)
2783{
2784 size_t size = sizeof(struct event_update_event);
2785 struct event_update_event *ev;
2786 int max, err;
2787 u16 type;
2788
2789 if (!evsel->own_cpus)
2790 return 0;
2791
2792 ev = cpu_map_data__alloc(evsel->own_cpus, &size, &type, &max);
2793 if (!ev)
2794 return -ENOMEM;
2795
2796 ev->header.type = PERF_RECORD_EVENT_UPDATE;
2797 ev->header.size = (u16)size;
2798 ev->type = PERF_EVENT_UPDATE__CPUS;
2799 ev->id = evsel->id[0];
2800
2801 cpu_map_data__synthesize((struct cpu_map_data *) ev->data,
2802 evsel->own_cpus,
2803 type, max);
2804
2805 err = process(tool, (union perf_event*) ev, NULL, NULL);
2806 free(ev);
2807 return err;
2808}
2809
2810size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
2811{
2812 struct event_update_event *ev = &event->event_update;
2813 struct event_update_event_scale *ev_scale;
2814 struct event_update_event_cpus *ev_cpus;
2815 struct cpu_map *map;
2816 size_t ret;
2817
2818 ret = fprintf(fp, "\n... id: %" PRIu64 "\n", ev->id);
2819
2820 switch (ev->type) {
2821 case PERF_EVENT_UPDATE__SCALE:
2822 ev_scale = (struct event_update_event_scale *) ev->data;
2823 ret += fprintf(fp, "... scale: %f\n", ev_scale->scale);
2824 break;
2825 case PERF_EVENT_UPDATE__UNIT:
2826 ret += fprintf(fp, "... unit: %s\n", ev->data);
2827 break;
2828 case PERF_EVENT_UPDATE__NAME:
2829 ret += fprintf(fp, "... name: %s\n", ev->data);
2830 break;
2831 case PERF_EVENT_UPDATE__CPUS:
2832 ev_cpus = (struct event_update_event_cpus *) ev->data;
2833 ret += fprintf(fp, "... ");
2834
2835 map = cpu_map__new_data(&ev_cpus->cpus);
2836 if (map)
2837 ret += cpu_map__fprintf(map, fp);
2838 else
2839 ret += fprintf(fp, "failed to get cpus\n");
2840 break;
2841 default:
2842 ret += fprintf(fp, "... unknown type\n");
2843 break;
2844 }
2845
2846 return ret;
2847}
2848
2689int perf_event__synthesize_attrs(struct perf_tool *tool, 2849int perf_event__synthesize_attrs(struct perf_tool *tool,
2690 struct perf_session *session, 2850 struct perf_session *session,
2691 perf_event__handler_t process) 2851 perf_event__handler_t process)
@@ -2745,6 +2905,51 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
2745 return 0; 2905 return 0;
2746} 2906}
2747 2907
2908int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
2909 union perf_event *event,
2910 struct perf_evlist **pevlist)
2911{
2912 struct event_update_event *ev = &event->event_update;
2913 struct event_update_event_scale *ev_scale;
2914 struct event_update_event_cpus *ev_cpus;
2915 struct perf_evlist *evlist;
2916 struct perf_evsel *evsel;
2917 struct cpu_map *map;
2918
2919 if (!pevlist || *pevlist == NULL)
2920 return -EINVAL;
2921
2922 evlist = *pevlist;
2923
2924 evsel = perf_evlist__id2evsel(evlist, ev->id);
2925 if (evsel == NULL)
2926 return -EINVAL;
2927
2928 switch (ev->type) {
2929 case PERF_EVENT_UPDATE__UNIT:
2930 evsel->unit = strdup(ev->data);
2931 break;
2932 case PERF_EVENT_UPDATE__NAME:
2933 evsel->name = strdup(ev->data);
2934 break;
2935 case PERF_EVENT_UPDATE__SCALE:
2936 ev_scale = (struct event_update_event_scale *) ev->data;
2937 evsel->scale = ev_scale->scale;
2938 case PERF_EVENT_UPDATE__CPUS:
2939 ev_cpus = (struct event_update_event_cpus *) ev->data;
2940
2941 map = cpu_map__new_data(&ev_cpus->cpus);
2942 if (map)
2943 evsel->own_cpus = map;
2944 else
2945 pr_err("failed to get event_update cpus\n");
2946 default:
2947 break;
2948 }
2949
2950 return 0;
2951}
2952
2748int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, 2953int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
2749 struct perf_evlist *evlist, 2954 struct perf_evlist *evlist,
2750 perf_event__handler_t process) 2955 perf_event__handler_t process)
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 05f27cb6b7e3..cff9892452ee 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -31,6 +31,7 @@ enum {
31 HEADER_PMU_MAPPINGS, 31 HEADER_PMU_MAPPINGS,
32 HEADER_GROUP_DESC, 32 HEADER_GROUP_DESC,
33 HEADER_AUXTRACE, 33 HEADER_AUXTRACE,
34 HEADER_STAT,
34 HEADER_LAST_FEATURE, 35 HEADER_LAST_FEATURE,
35 HEADER_FEAT_BITS = 256, 36 HEADER_FEAT_BITS = 256,
36}; 37};
@@ -105,8 +106,24 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
105int perf_event__synthesize_attrs(struct perf_tool *tool, 106int perf_event__synthesize_attrs(struct perf_tool *tool,
106 struct perf_session *session, 107 struct perf_session *session,
107 perf_event__handler_t process); 108 perf_event__handler_t process);
109int perf_event__synthesize_event_update_unit(struct perf_tool *tool,
110 struct perf_evsel *evsel,
111 perf_event__handler_t process);
112int perf_event__synthesize_event_update_scale(struct perf_tool *tool,
113 struct perf_evsel *evsel,
114 perf_event__handler_t process);
115int perf_event__synthesize_event_update_name(struct perf_tool *tool,
116 struct perf_evsel *evsel,
117 perf_event__handler_t process);
118int perf_event__synthesize_event_update_cpus(struct perf_tool *tool,
119 struct perf_evsel *evsel,
120 perf_event__handler_t process);
108int perf_event__process_attr(struct perf_tool *tool, union perf_event *event, 121int perf_event__process_attr(struct perf_tool *tool, union perf_event *event,
109 struct perf_evlist **pevlist); 122 struct perf_evlist **pevlist);
123int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
124 union perf_event *event,
125 struct perf_evlist **pevlist);
126size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp);
110 127
111int perf_event__synthesize_tracing_data(struct perf_tool *tool, 128int perf_event__synthesize_tracing_data(struct perf_tool *tool,
112 int fd, struct perf_evlist *evlist, 129 int fd, struct perf_evlist *evlist,
diff --git a/tools/perf/util/help-unknown-cmd.c b/tools/perf/util/help-unknown-cmd.c
new file mode 100644
index 000000000000..dc1e41c9b054
--- /dev/null
+++ b/tools/perf/util/help-unknown-cmd.c
@@ -0,0 +1,103 @@
1#include "cache.h"
2#include <subcmd/help.h>
3#include "../builtin.h"
4#include "levenshtein.h"
5
6static int autocorrect;
7static struct cmdnames aliases;
8
9static int perf_unknown_cmd_config(const char *var, const char *value, void *cb)
10{
11 if (!strcmp(var, "help.autocorrect"))
12 autocorrect = perf_config_int(var,value);
13 /* Also use aliases for command lookup */
14 if (!prefixcmp(var, "alias."))
15 add_cmdname(&aliases, var + 6, strlen(var + 6));
16
17 return perf_default_config(var, value, cb);
18}
19
20static int levenshtein_compare(const void *p1, const void *p2)
21{
22 const struct cmdname *const *c1 = p1, *const *c2 = p2;
23 const char *s1 = (*c1)->name, *s2 = (*c2)->name;
24 int l1 = (*c1)->len;
25 int l2 = (*c2)->len;
26 return l1 != l2 ? l1 - l2 : strcmp(s1, s2);
27}
28
29static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
30{
31 unsigned int i;
32
33 ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc);
34
35 for (i = 0; i < old->cnt; i++)
36 cmds->names[cmds->cnt++] = old->names[i];
37 zfree(&old->names);
38 old->cnt = 0;
39}
40
41const char *help_unknown_cmd(const char *cmd)
42{
43 unsigned int i, n = 0, best_similarity = 0;
44 struct cmdnames main_cmds, other_cmds;
45
46 memset(&main_cmds, 0, sizeof(main_cmds));
47 memset(&other_cmds, 0, sizeof(main_cmds));
48 memset(&aliases, 0, sizeof(aliases));
49
50 perf_config(perf_unknown_cmd_config, NULL);
51
52 load_command_list("perf-", &main_cmds, &other_cmds);
53
54 add_cmd_list(&main_cmds, &aliases);
55 add_cmd_list(&main_cmds, &other_cmds);
56 qsort(main_cmds.names, main_cmds.cnt,
57 sizeof(main_cmds.names), cmdname_compare);
58 uniq(&main_cmds);
59
60 if (main_cmds.cnt) {
61 /* This reuses cmdname->len for similarity index */
62 for (i = 0; i < main_cmds.cnt; ++i)
63 main_cmds.names[i]->len =
64 levenshtein(cmd, main_cmds.names[i]->name, 0, 2, 1, 4);
65
66 qsort(main_cmds.names, main_cmds.cnt,
67 sizeof(*main_cmds.names), levenshtein_compare);
68
69 best_similarity = main_cmds.names[0]->len;
70 n = 1;
71 while (n < main_cmds.cnt && best_similarity == main_cmds.names[n]->len)
72 ++n;
73 }
74
75 if (autocorrect && n == 1) {
76 const char *assumed = main_cmds.names[0]->name;
77
78 main_cmds.names[0] = NULL;
79 clean_cmdnames(&main_cmds);
80 fprintf(stderr, "WARNING: You called a perf program named '%s', "
81 "which does not exist.\n"
82 "Continuing under the assumption that you meant '%s'\n",
83 cmd, assumed);
84 if (autocorrect > 0) {
85 fprintf(stderr, "in %0.1f seconds automatically...\n",
86 (float)autocorrect/10.0);
87 poll(NULL, 0, autocorrect * 100);
88 }
89 return assumed;
90 }
91
92 fprintf(stderr, "perf: '%s' is not a perf-command. See 'perf --help'.\n", cmd);
93
94 if (main_cmds.cnt && best_similarity < 6) {
95 fprintf(stderr, "\nDid you mean %s?\n",
96 n < 2 ? "this": "one of these");
97
98 for (i = 0; i < n; i++)
99 fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
100 }
101
102 exit(1);
103}
diff --git a/tools/perf/util/help-unknown-cmd.h b/tools/perf/util/help-unknown-cmd.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/perf/util/help-unknown-cmd.h
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 4fd37d6708cb..c226303e3da0 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -254,6 +254,7 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
254 he_stat__decay(&he->stat); 254 he_stat__decay(&he->stat);
255 if (symbol_conf.cumulate_callchain) 255 if (symbol_conf.cumulate_callchain)
256 he_stat__decay(he->stat_acc); 256 he_stat__decay(he->stat_acc);
257 decay_callchain(he->callchain);
257 258
258 diff = prev_period - he->stat.period; 259 diff = prev_period - he->stat.period;
259 260
@@ -270,6 +271,8 @@ static void hists__delete_entry(struct hists *hists, struct hist_entry *he)
270 271
271 if (sort__need_collapse) 272 if (sort__need_collapse)
272 rb_erase(&he->rb_node_in, &hists->entries_collapsed); 273 rb_erase(&he->rb_node_in, &hists->entries_collapsed);
274 else
275 rb_erase(&he->rb_node_in, hists->entries_in);
273 276
274 --hists->nr_entries; 277 --hists->nr_entries;
275 if (!he->filtered) 278 if (!he->filtered)
@@ -367,6 +370,25 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
367 if (symbol_conf.use_callchain) 370 if (symbol_conf.use_callchain)
368 callchain_init(he->callchain); 371 callchain_init(he->callchain);
369 372
373 if (he->raw_data) {
374 he->raw_data = memdup(he->raw_data, he->raw_size);
375
376 if (he->raw_data == NULL) {
377 map__put(he->ms.map);
378 if (he->branch_info) {
379 map__put(he->branch_info->from.map);
380 map__put(he->branch_info->to.map);
381 free(he->branch_info);
382 }
383 if (he->mem_info) {
384 map__put(he->mem_info->iaddr.map);
385 map__put(he->mem_info->daddr.map);
386 }
387 free(he->stat_acc);
388 free(he);
389 return NULL;
390 }
391 }
370 INIT_LIST_HEAD(&he->pairs.node); 392 INIT_LIST_HEAD(&he->pairs.node);
371 thread__get(he->thread); 393 thread__get(he->thread);
372 } 394 }
@@ -459,7 +481,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
459 struct symbol *sym_parent, 481 struct symbol *sym_parent,
460 struct branch_info *bi, 482 struct branch_info *bi,
461 struct mem_info *mi, 483 struct mem_info *mi,
462 u64 period, u64 weight, u64 transaction, 484 struct perf_sample *sample,
463 bool sample_self) 485 bool sample_self)
464{ 486{
465 struct hist_entry entry = { 487 struct hist_entry entry = {
@@ -476,15 +498,17 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
476 .level = al->level, 498 .level = al->level,
477 .stat = { 499 .stat = {
478 .nr_events = 1, 500 .nr_events = 1,
479 .period = period, 501 .period = sample->period,
480 .weight = weight, 502 .weight = sample->weight,
481 }, 503 },
482 .parent = sym_parent, 504 .parent = sym_parent,
483 .filtered = symbol__parent_filter(sym_parent) | al->filtered, 505 .filtered = symbol__parent_filter(sym_parent) | al->filtered,
484 .hists = hists, 506 .hists = hists,
485 .branch_info = bi, 507 .branch_info = bi,
486 .mem_info = mi, 508 .mem_info = mi,
487 .transaction = transaction, 509 .transaction = sample->transaction,
510 .raw_data = sample->raw_data,
511 .raw_size = sample->raw_size,
488 }; 512 };
489 513
490 return hists__findnew_entry(hists, &entry, al, sample_self); 514 return hists__findnew_entry(hists, &entry, al, sample_self);
@@ -524,12 +548,13 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
524 u64 cost; 548 u64 cost;
525 struct mem_info *mi = iter->priv; 549 struct mem_info *mi = iter->priv;
526 struct hists *hists = evsel__hists(iter->evsel); 550 struct hists *hists = evsel__hists(iter->evsel);
551 struct perf_sample *sample = iter->sample;
527 struct hist_entry *he; 552 struct hist_entry *he;
528 553
529 if (mi == NULL) 554 if (mi == NULL)
530 return -EINVAL; 555 return -EINVAL;
531 556
532 cost = iter->sample->weight; 557 cost = sample->weight;
533 if (!cost) 558 if (!cost)
534 cost = 1; 559 cost = 1;
535 560
@@ -540,8 +565,10 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
540 * and this is indirectly achieved by passing period=weight here 565 * and this is indirectly achieved by passing period=weight here
541 * and the he_stat__add_period() function. 566 * and the he_stat__add_period() function.
542 */ 567 */
568 sample->period = cost;
569
543 he = __hists__add_entry(hists, al, iter->parent, NULL, mi, 570 he = __hists__add_entry(hists, al, iter->parent, NULL, mi,
544 cost, cost, 0, true); 571 sample, true);
545 if (!he) 572 if (!he)
546 return -ENOMEM; 573 return -ENOMEM;
547 574
@@ -628,6 +655,7 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
628 struct branch_info *bi; 655 struct branch_info *bi;
629 struct perf_evsel *evsel = iter->evsel; 656 struct perf_evsel *evsel = iter->evsel;
630 struct hists *hists = evsel__hists(evsel); 657 struct hists *hists = evsel__hists(evsel);
658 struct perf_sample *sample = iter->sample;
631 struct hist_entry *he = NULL; 659 struct hist_entry *he = NULL;
632 int i = iter->curr; 660 int i = iter->curr;
633 int err = 0; 661 int err = 0;
@@ -641,9 +669,11 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
641 * The report shows the percentage of total branches captured 669 * The report shows the percentage of total branches captured
642 * and not events sampled. Thus we use a pseudo period of 1. 670 * and not events sampled. Thus we use a pseudo period of 1.
643 */ 671 */
672 sample->period = 1;
673 sample->weight = bi->flags.cycles ? bi->flags.cycles : 1;
674
644 he = __hists__add_entry(hists, al, iter->parent, &bi[i], NULL, 675 he = __hists__add_entry(hists, al, iter->parent, &bi[i], NULL,
645 1, bi->flags.cycles ? bi->flags.cycles : 1, 676 sample, true);
646 0, true);
647 if (he == NULL) 677 if (he == NULL)
648 return -ENOMEM; 678 return -ENOMEM;
649 679
@@ -680,8 +710,7 @@ iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_location
680 struct hist_entry *he; 710 struct hist_entry *he;
681 711
682 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL, 712 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
683 sample->period, sample->weight, 713 sample, true);
684 sample->transaction, true);
685 if (he == NULL) 714 if (he == NULL)
686 return -ENOMEM; 715 return -ENOMEM;
687 716
@@ -742,8 +771,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
742 int err = 0; 771 int err = 0;
743 772
744 he = __hists__add_entry(hists, al, iter->parent, NULL, NULL, 773 he = __hists__add_entry(hists, al, iter->parent, NULL, NULL,
745 sample->period, sample->weight, 774 sample, true);
746 sample->transaction, true);
747 if (he == NULL) 775 if (he == NULL)
748 return -ENOMEM; 776 return -ENOMEM;
749 777
@@ -795,6 +823,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
795 .sym = al->sym, 823 .sym = al->sym,
796 }, 824 },
797 .parent = iter->parent, 825 .parent = iter->parent,
826 .raw_data = sample->raw_data,
827 .raw_size = sample->raw_size,
798 }; 828 };
799 int i; 829 int i;
800 struct callchain_cursor cursor; 830 struct callchain_cursor cursor;
@@ -816,8 +846,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
816 } 846 }
817 847
818 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL, 848 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
819 sample->period, sample->weight, 849 sample, false);
820 sample->transaction, false);
821 if (he == NULL) 850 if (he == NULL)
822 return -ENOMEM; 851 return -ENOMEM;
823 852
@@ -924,9 +953,6 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
924 int64_t cmp = 0; 953 int64_t cmp = 0;
925 954
926 perf_hpp__for_each_sort_list(fmt) { 955 perf_hpp__for_each_sort_list(fmt) {
927 if (perf_hpp__should_skip(fmt))
928 continue;
929
930 cmp = fmt->cmp(fmt, left, right); 956 cmp = fmt->cmp(fmt, left, right);
931 if (cmp) 957 if (cmp)
932 break; 958 break;
@@ -942,9 +968,6 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
942 int64_t cmp = 0; 968 int64_t cmp = 0;
943 969
944 perf_hpp__for_each_sort_list(fmt) { 970 perf_hpp__for_each_sort_list(fmt) {
945 if (perf_hpp__should_skip(fmt))
946 continue;
947
948 cmp = fmt->collapse(fmt, left, right); 971 cmp = fmt->collapse(fmt, left, right);
949 if (cmp) 972 if (cmp)
950 break; 973 break;
@@ -975,6 +998,8 @@ void hist_entry__delete(struct hist_entry *he)
975 if (he->srcfile && he->srcfile[0]) 998 if (he->srcfile && he->srcfile[0])
976 free(he->srcfile); 999 free(he->srcfile);
977 free_callchain(he->callchain); 1000 free_callchain(he->callchain);
1001 free(he->trace_output);
1002 free(he->raw_data);
978 free(he); 1003 free(he);
979} 1004}
980 1005
@@ -982,9 +1007,8 @@ void hist_entry__delete(struct hist_entry *he)
982 * collapse the histogram 1007 * collapse the histogram
983 */ 1008 */
984 1009
985static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, 1010bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
986 struct rb_root *root, 1011 struct rb_root *root, struct hist_entry *he)
987 struct hist_entry *he)
988{ 1012{
989 struct rb_node **p = &root->rb_node; 1013 struct rb_node **p = &root->rb_node;
990 struct rb_node *parent = NULL; 1014 struct rb_node *parent = NULL;
@@ -1024,7 +1048,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
1024 return true; 1048 return true;
1025} 1049}
1026 1050
1027static struct rb_root *hists__get_rotate_entries_in(struct hists *hists) 1051struct rb_root *hists__get_rotate_entries_in(struct hists *hists)
1028{ 1052{
1029 struct rb_root *root; 1053 struct rb_root *root;
1030 1054
@@ -1088,7 +1112,7 @@ static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b)
1088 int64_t cmp = 0; 1112 int64_t cmp = 0;
1089 1113
1090 perf_hpp__for_each_sort_list(fmt) { 1114 perf_hpp__for_each_sort_list(fmt) {
1091 if (perf_hpp__should_skip(fmt)) 1115 if (perf_hpp__should_skip(fmt, a->hists))
1092 continue; 1116 continue;
1093 1117
1094 cmp = fmt->sort(fmt, a, b); 1118 cmp = fmt->sort(fmt, a, b);
@@ -1559,10 +1583,8 @@ int perf_hist_config(const char *var, const char *value)
1559 return 0; 1583 return 0;
1560} 1584}
1561 1585
1562static int hists_evsel__init(struct perf_evsel *evsel) 1586int __hists__init(struct hists *hists)
1563{ 1587{
1564 struct hists *hists = evsel__hists(evsel);
1565
1566 memset(hists, 0, sizeof(*hists)); 1588 memset(hists, 0, sizeof(*hists));
1567 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; 1589 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
1568 hists->entries_in = &hists->entries_in_array[0]; 1590 hists->entries_in = &hists->entries_in_array[0];
@@ -1573,6 +1595,43 @@ static int hists_evsel__init(struct perf_evsel *evsel)
1573 return 0; 1595 return 0;
1574} 1596}
1575 1597
1598static void hists__delete_remaining_entries(struct rb_root *root)
1599{
1600 struct rb_node *node;
1601 struct hist_entry *he;
1602
1603 while (!RB_EMPTY_ROOT(root)) {
1604 node = rb_first(root);
1605 rb_erase(node, root);
1606
1607 he = rb_entry(node, struct hist_entry, rb_node_in);
1608 hist_entry__delete(he);
1609 }
1610}
1611
1612static void hists__delete_all_entries(struct hists *hists)
1613{
1614 hists__delete_entries(hists);
1615 hists__delete_remaining_entries(&hists->entries_in_array[0]);
1616 hists__delete_remaining_entries(&hists->entries_in_array[1]);
1617 hists__delete_remaining_entries(&hists->entries_collapsed);
1618}
1619
1620static void hists_evsel__exit(struct perf_evsel *evsel)
1621{
1622 struct hists *hists = evsel__hists(evsel);
1623
1624 hists__delete_all_entries(hists);
1625}
1626
1627static int hists_evsel__init(struct perf_evsel *evsel)
1628{
1629 struct hists *hists = evsel__hists(evsel);
1630
1631 __hists__init(hists);
1632 return 0;
1633}
1634
1576/* 1635/*
1577 * XXX We probably need a hists_evsel__exit() to free the hist_entries 1636 * XXX We probably need a hists_evsel__exit() to free the hist_entries
1578 * stored in the rbtree... 1637 * stored in the rbtree...
@@ -1581,7 +1640,8 @@ static int hists_evsel__init(struct perf_evsel *evsel)
1581int hists__init(void) 1640int hists__init(void)
1582{ 1641{
1583 int err = perf_evsel__object_config(sizeof(struct hists_evsel), 1642 int err = perf_evsel__object_config(sizeof(struct hists_evsel),
1584 hists_evsel__init, NULL); 1643 hists_evsel__init,
1644 hists_evsel__exit);
1585 if (err) 1645 if (err)
1586 fputs("FATAL ERROR: Couldn't setup hists class\n", stderr); 1646 fputs("FATAL ERROR: Couldn't setup hists class\n", stderr);
1587 1647
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index a48a2078d288..d4ec4822a103 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -52,6 +52,7 @@ enum hist_column {
52 HISTC_MEM_IADDR_SYMBOL, 52 HISTC_MEM_IADDR_SYMBOL,
53 HISTC_TRANSACTION, 53 HISTC_TRANSACTION,
54 HISTC_CYCLES, 54 HISTC_CYCLES,
55 HISTC_TRACE,
55 HISTC_NR_COLS, /* Last entry */ 56 HISTC_NR_COLS, /* Last entry */
56}; 57};
57 58
@@ -114,8 +115,8 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
114 struct addr_location *al, 115 struct addr_location *al,
115 struct symbol *parent, 116 struct symbol *parent,
116 struct branch_info *bi, 117 struct branch_info *bi,
117 struct mem_info *mi, u64 period, 118 struct mem_info *mi,
118 u64 weight, u64 transaction, 119 struct perf_sample *sample,
119 bool sample_self); 120 bool sample_self);
120int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, 121int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
121 int max_stack_depth, void *arg); 122 int max_stack_depth, void *arg);
@@ -184,6 +185,11 @@ static inline struct hists *evsel__hists(struct perf_evsel *evsel)
184} 185}
185 186
186int hists__init(void); 187int hists__init(void);
188int __hists__init(struct hists *hists);
189
190struct rb_root *hists__get_rotate_entries_in(struct hists *hists);
191bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
192 struct rb_root *root, struct hist_entry *he);
187 193
188struct perf_hpp { 194struct perf_hpp {
189 char *buf; 195 char *buf;
@@ -261,10 +267,20 @@ void perf_hpp__append_sort_keys(void);
261 267
262bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format); 268bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format);
263bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b); 269bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b);
270bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *format);
271bool perf_hpp__defined_dynamic_entry(struct perf_hpp_fmt *fmt, struct hists *hists);
264 272
265static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format) 273static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format,
274 struct hists *hists)
266{ 275{
267 return format->elide; 276 if (format->elide)
277 return true;
278
279 if (perf_hpp__is_dynamic_entry(format) &&
280 !perf_hpp__defined_dynamic_entry(format, hists))
281 return true;
282
283 return false;
268} 284}
269 285
270void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists); 286void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists);
diff --git a/tools/perf/util/include/linux/string.h b/tools/perf/util/include/linux/string.h
deleted file mode 100644
index 6f19c548ecc0..000000000000
--- a/tools/perf/util/include/linux/string.h
+++ /dev/null
@@ -1,3 +0,0 @@
1#include <string.h>
2
3void *memdup(const void *src, size_t len);
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 97f963a3dcb9..81a2eb77ba7f 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1744,7 +1744,7 @@ static void intel_pt_free(struct perf_session *session)
1744 auxtrace_heap__free(&pt->heap); 1744 auxtrace_heap__free(&pt->heap);
1745 intel_pt_free_events(session); 1745 intel_pt_free_events(session);
1746 session->auxtrace = NULL; 1746 session->auxtrace = NULL;
1747 thread__delete(pt->unknown_thread); 1747 thread__put(pt->unknown_thread);
1748 free(pt); 1748 free(pt);
1749} 1749}
1750 1750
@@ -2153,7 +2153,7 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2153 return 0; 2153 return 0;
2154 2154
2155err_delete_thread: 2155err_delete_thread:
2156 thread__delete(pt->unknown_thread); 2156 thread__zput(pt->unknown_thread);
2157err_free_queues: 2157err_free_queues:
2158 intel_pt_log_disable(); 2158 intel_pt_log_disable();
2159 auxtrace_queues__free(&pt->queues); 2159 auxtrace_queues__free(&pt->queues);
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 8b303ff20289..ad79297c76c8 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -25,6 +25,7 @@ static void dsos__init(struct dsos *dsos)
25 25
26int machine__init(struct machine *machine, const char *root_dir, pid_t pid) 26int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
27{ 27{
28 memset(machine, 0, sizeof(*machine));
28 map_groups__init(&machine->kmaps, machine); 29 map_groups__init(&machine->kmaps, machine);
29 RB_CLEAR_NODE(&machine->rb_node); 30 RB_CLEAR_NODE(&machine->rb_node);
30 dsos__init(&machine->dsos); 31 dsos__init(&machine->dsos);
@@ -44,6 +45,8 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
44 machine->comm_exec = false; 45 machine->comm_exec = false;
45 machine->kernel_start = 0; 46 machine->kernel_start = 0;
46 47
48 memset(machine->vmlinux_maps, 0, sizeof(machine->vmlinux_maps));
49
47 machine->root_dir = strdup(root_dir); 50 machine->root_dir = strdup(root_dir);
48 if (machine->root_dir == NULL) 51 if (machine->root_dir == NULL)
49 return -ENOMEM; 52 return -ENOMEM;
@@ -122,6 +125,7 @@ void machine__delete_threads(struct machine *machine)
122 125
123void machine__exit(struct machine *machine) 126void machine__exit(struct machine *machine)
124{ 127{
128 machine__destroy_kernel_maps(machine);
125 map_groups__exit(&machine->kmaps); 129 map_groups__exit(&machine->kmaps);
126 dsos__exit(&machine->dsos); 130 dsos__exit(&machine->dsos);
127 machine__exit_vdso(machine); 131 machine__exit_vdso(machine);
@@ -348,13 +352,18 @@ static void machine__update_thread_pid(struct machine *machine,
348 } 352 }
349 353
350 th->mg = map_groups__get(leader->mg); 354 th->mg = map_groups__get(leader->mg);
351 355out_put:
356 thread__put(leader);
352 return; 357 return;
353
354out_err: 358out_err:
355 pr_err("Failed to join map groups for %d:%d\n", th->pid_, th->tid); 359 pr_err("Failed to join map groups for %d:%d\n", th->pid_, th->tid);
360 goto out_put;
356} 361}
357 362
363/*
364 * Caller must eventually drop thread->refcnt returned with a successfull
365 * lookup/new thread inserted.
366 */
358static struct thread *____machine__findnew_thread(struct machine *machine, 367static struct thread *____machine__findnew_thread(struct machine *machine,
359 pid_t pid, pid_t tid, 368 pid_t pid, pid_t tid,
360 bool create) 369 bool create)
@@ -372,7 +381,7 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
372 if (th != NULL) { 381 if (th != NULL) {
373 if (th->tid == tid) { 382 if (th->tid == tid) {
374 machine__update_thread_pid(machine, th, pid); 383 machine__update_thread_pid(machine, th, pid);
375 return th; 384 return thread__get(th);
376 } 385 }
377 386
378 machine->last_match = NULL; 387 machine->last_match = NULL;
@@ -385,7 +394,7 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
385 if (th->tid == tid) { 394 if (th->tid == tid) {
386 machine->last_match = th; 395 machine->last_match = th;
387 machine__update_thread_pid(machine, th, pid); 396 machine__update_thread_pid(machine, th, pid);
388 return th; 397 return thread__get(th);
389 } 398 }
390 399
391 if (tid < th->tid) 400 if (tid < th->tid)
@@ -413,7 +422,7 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
413 if (thread__init_map_groups(th, machine)) { 422 if (thread__init_map_groups(th, machine)) {
414 rb_erase_init(&th->rb_node, &machine->threads); 423 rb_erase_init(&th->rb_node, &machine->threads);
415 RB_CLEAR_NODE(&th->rb_node); 424 RB_CLEAR_NODE(&th->rb_node);
416 thread__delete(th); 425 thread__put(th);
417 return NULL; 426 return NULL;
418 } 427 }
419 /* 428 /*
@@ -437,7 +446,7 @@ struct thread *machine__findnew_thread(struct machine *machine, pid_t pid,
437 struct thread *th; 446 struct thread *th;
438 447
439 pthread_rwlock_wrlock(&machine->threads_lock); 448 pthread_rwlock_wrlock(&machine->threads_lock);
440 th = thread__get(__machine__findnew_thread(machine, pid, tid)); 449 th = __machine__findnew_thread(machine, pid, tid);
441 pthread_rwlock_unlock(&machine->threads_lock); 450 pthread_rwlock_unlock(&machine->threads_lock);
442 return th; 451 return th;
443} 452}
@@ -447,7 +456,7 @@ struct thread *machine__find_thread(struct machine *machine, pid_t pid,
447{ 456{
448 struct thread *th; 457 struct thread *th;
449 pthread_rwlock_rdlock(&machine->threads_lock); 458 pthread_rwlock_rdlock(&machine->threads_lock);
450 th = thread__get(____machine__findnew_thread(machine, pid, tid, false)); 459 th = ____machine__findnew_thread(machine, pid, tid, false);
451 pthread_rwlock_unlock(&machine->threads_lock); 460 pthread_rwlock_unlock(&machine->threads_lock);
452 return th; 461 return th;
453} 462}
@@ -560,11 +569,29 @@ int machine__process_switch_event(struct machine *machine __maybe_unused,
560 return 0; 569 return 0;
561} 570}
562 571
572static void dso__adjust_kmod_long_name(struct dso *dso, const char *filename)
573{
574 const char *dup_filename;
575
576 if (!filename || !dso || !dso->long_name)
577 return;
578 if (dso->long_name[0] != '[')
579 return;
580 if (!strchr(filename, '/'))
581 return;
582
583 dup_filename = strdup(filename);
584 if (!dup_filename)
585 return;
586
587 dso__set_long_name(dso, dup_filename, true);
588}
589
563struct map *machine__findnew_module_map(struct machine *machine, u64 start, 590struct map *machine__findnew_module_map(struct machine *machine, u64 start,
564 const char *filename) 591 const char *filename)
565{ 592{
566 struct map *map = NULL; 593 struct map *map = NULL;
567 struct dso *dso; 594 struct dso *dso = NULL;
568 struct kmod_path m; 595 struct kmod_path m;
569 596
570 if (kmod_path__parse_name(&m, filename)) 597 if (kmod_path__parse_name(&m, filename))
@@ -572,8 +599,15 @@ struct map *machine__findnew_module_map(struct machine *machine, u64 start,
572 599
573 map = map_groups__find_by_name(&machine->kmaps, MAP__FUNCTION, 600 map = map_groups__find_by_name(&machine->kmaps, MAP__FUNCTION,
574 m.name); 601 m.name);
575 if (map) 602 if (map) {
603 /*
604 * If the map's dso is an offline module, give dso__load()
605 * a chance to find the file path of that module by fixing
606 * long_name.
607 */
608 dso__adjust_kmod_long_name(map->dso, filename);
576 goto out; 609 goto out;
610 }
577 611
578 dso = machine__findnew_module_dso(machine, &m, filename); 612 dso = machine__findnew_module_dso(machine, &m, filename);
579 if (dso == NULL) 613 if (dso == NULL)
@@ -585,7 +619,11 @@ struct map *machine__findnew_module_map(struct machine *machine, u64 start,
585 619
586 map_groups__insert(&machine->kmaps, map); 620 map_groups__insert(&machine->kmaps, map);
587 621
622 /* Put the map here because map_groups__insert alread got it */
623 map__put(map);
588out: 624out:
625 /* put the dso here, corresponding to machine__findnew_module_dso */
626 dso__put(dso);
589 free(m.name); 627 free(m.name);
590 return map; 628 return map;
591} 629}
@@ -740,6 +778,9 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
740 enum map_type type; 778 enum map_type type;
741 u64 start = machine__get_running_kernel_start(machine, NULL); 779 u64 start = machine__get_running_kernel_start(machine, NULL);
742 780
781 /* In case of renewal the kernel map, destroy previous one */
782 machine__destroy_kernel_maps(machine);
783
743 for (type = 0; type < MAP__NR_TYPES; ++type) { 784 for (type = 0; type < MAP__NR_TYPES; ++type) {
744 struct kmap *kmap; 785 struct kmap *kmap;
745 struct map *map; 786 struct map *map;
@@ -788,6 +829,7 @@ void machine__destroy_kernel_maps(struct machine *machine)
788 kmap->ref_reloc_sym = NULL; 829 kmap->ref_reloc_sym = NULL;
789 } 830 }
790 831
832 map__put(machine->vmlinux_maps[type]);
791 machine->vmlinux_maps[type] = NULL; 833 machine->vmlinux_maps[type] = NULL;
792 } 834 }
793} 835}
@@ -1084,11 +1126,14 @@ int machine__create_kernel_maps(struct machine *machine)
1084 struct dso *kernel = machine__get_kernel(machine); 1126 struct dso *kernel = machine__get_kernel(machine);
1085 const char *name; 1127 const char *name;
1086 u64 addr = machine__get_running_kernel_start(machine, &name); 1128 u64 addr = machine__get_running_kernel_start(machine, &name);
1087 if (!addr) 1129 int ret;
1130
1131 if (!addr || kernel == NULL)
1088 return -1; 1132 return -1;
1089 1133
1090 if (kernel == NULL || 1134 ret = __machine__create_kernel_maps(machine, kernel);
1091 __machine__create_kernel_maps(machine, kernel) < 0) 1135 dso__put(kernel);
1136 if (ret < 0)
1092 return -1; 1137 return -1;
1093 1138
1094 if (symbol_conf.use_modules && machine__create_modules(machine) < 0) { 1139 if (symbol_conf.use_modules && machine__create_modules(machine) < 0) {
@@ -1609,6 +1654,8 @@ static int add_callchain_ip(struct thread *thread,
1609 } 1654 }
1610 } 1655 }
1611 1656
1657 if (symbol_conf.hide_unresolved && al.sym == NULL)
1658 return 0;
1612 return callchain_cursor_append(&callchain_cursor, al.addr, al.map, al.sym); 1659 return callchain_cursor_append(&callchain_cursor, al.addr, al.map, al.sym);
1613} 1660}
1614 1661
@@ -1863,6 +1910,9 @@ check_calls:
1863static int unwind_entry(struct unwind_entry *entry, void *arg) 1910static int unwind_entry(struct unwind_entry *entry, void *arg)
1864{ 1911{
1865 struct callchain_cursor *cursor = arg; 1912 struct callchain_cursor *cursor = arg;
1913
1914 if (symbol_conf.hide_unresolved && entry->sym == NULL)
1915 return 0;
1866 return callchain_cursor_append(cursor, entry->ip, 1916 return callchain_cursor_append(cursor, entry->ip,
1867 entry->map, entry->sym); 1917 entry->map, entry->sym);
1868} 1918}
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index afc6b56cf749..171b6d10a04b 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -26,8 +26,8 @@ const char *map_type__name[MAP__NR_TYPES] = {
26static inline int is_anon_memory(const char *filename) 26static inline int is_anon_memory(const char *filename)
27{ 27{
28 return !strcmp(filename, "//anon") || 28 return !strcmp(filename, "//anon") ||
29 !strcmp(filename, "/dev/zero (deleted)") || 29 !strncmp(filename, "/dev/zero", sizeof("/dev/zero") - 1) ||
30 !strcmp(filename, "/anon_hugepage (deleted)"); 30 !strncmp(filename, "/anon_hugepage", sizeof("/anon_hugepage") - 1);
31} 31}
32 32
33static inline int is_no_dso_memory(const char *filename) 33static inline int is_no_dso_memory(const char *filename)
@@ -691,6 +691,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
691 __map_groups__insert(pos->groups, before); 691 __map_groups__insert(pos->groups, before);
692 if (verbose >= 2) 692 if (verbose >= 2)
693 map__fprintf(before, fp); 693 map__fprintf(before, fp);
694 map__put(before);
694 } 695 }
695 696
696 if (map->end < pos->end) { 697 if (map->end < pos->end) {
@@ -705,6 +706,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
705 __map_groups__insert(pos->groups, after); 706 __map_groups__insert(pos->groups, after);
706 if (verbose >= 2) 707 if (verbose >= 2)
707 map__fprintf(after, fp); 708 map__fprintf(after, fp);
709 map__put(after);
708 } 710 }
709put_map: 711put_map:
710 map__put(pos); 712 map__put(pos);
@@ -742,6 +744,7 @@ int map_groups__clone(struct map_groups *mg,
742 if (new == NULL) 744 if (new == NULL)
743 goto out_unlock; 745 goto out_unlock;
744 map_groups__insert(mg, new); 746 map_groups__insert(mg, new);
747 map__put(new);
745 } 748 }
746 749
747 err = 0; 750 err = 0;
diff --git a/tools/perf/util/parse-branch-options.c b/tools/perf/util/parse-branch-options.c
index 355eecf6bf59..afc088dd7d20 100644
--- a/tools/perf/util/parse-branch-options.c
+++ b/tools/perf/util/parse-branch-options.c
@@ -1,7 +1,7 @@
1#include "perf.h" 1#include "perf.h"
2#include "util/util.h" 2#include "util/util.h"
3#include "util/debug.h" 3#include "util/debug.h"
4#include "util/parse-options.h" 4#include <subcmd/parse-options.h>
5#include "util/parse-branch-options.h" 5#include "util/parse-branch-options.h"
6 6
7#define BRANCH_OPT(n, m) \ 7#define BRANCH_OPT(n, m) \
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 6fc8cd753e1a..4f7b0efdde2f 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -4,9 +4,9 @@
4#include "../perf.h" 4#include "../perf.h"
5#include "evlist.h" 5#include "evlist.h"
6#include "evsel.h" 6#include "evsel.h"
7#include "parse-options.h" 7#include <subcmd/parse-options.h>
8#include "parse-events.h" 8#include "parse-events.h"
9#include "exec_cmd.h" 9#include <subcmd/exec-cmd.h>
10#include "string.h" 10#include "string.h"
11#include "symbol.h" 11#include "symbol.h"
12#include "cache.h" 12#include "cache.h"
diff --git a/tools/perf/util/parse-regs-options.c b/tools/perf/util/parse-regs-options.c
index 4f2c1c255d81..646ecf736aad 100644
--- a/tools/perf/util/parse-regs-options.c
+++ b/tools/perf/util/parse-regs-options.c
@@ -1,7 +1,7 @@
1#include "perf.h" 1#include "perf.h"
2#include "util/util.h" 2#include "util/util.h"
3#include "util/debug.h" 3#include "util/debug.h"
4#include "util/parse-options.h" 4#include <subcmd/parse-options.h>
5#include "util/parse-regs-options.h" 5#include "util/parse-regs-options.h"
6 6
7int 7int
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index 5d13cb45b317..3654d964e49d 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -22,24 +22,6 @@ static const char *get_perf_dir(void)
22 return "."; 22 return ".";
23} 23}
24 24
25/*
26 * If libc has strlcpy() then that version will override this
27 * implementation:
28 */
29size_t __weak strlcpy(char *dest, const char *src, size_t size)
30{
31 size_t ret = strlen(src);
32
33 if (size) {
34 size_t len = (ret >= size) ? size - 1 : ret;
35
36 memcpy(dest, src, len);
37 dest[len] = '\0';
38 }
39
40 return ret;
41}
42
43static char *get_pathname(void) 25static char *get_pathname(void)
44{ 26{
45 static char pathname_array[4][PATH_MAX]; 27 static char pathname_array[4][PATH_MAX];
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index e4b173dec4b9..b597bcc8fc78 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -220,6 +220,7 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
220 alias->scale = 1.0; 220 alias->scale = 1.0;
221 alias->unit[0] = '\0'; 221 alias->unit[0] = '\0';
222 alias->per_pkg = false; 222 alias->per_pkg = false;
223 alias->snapshot = false;
223 224
224 ret = parse_events_terms(&alias->terms, val); 225 ret = parse_events_terms(&alias->terms, val);
225 if (ret) { 226 if (ret) {
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 03875f9154e7..93996ec4bbe3 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2326,8 +2326,11 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2326 goto out; 2326 goto out;
2327 2327
2328 if (!allow_suffix) { 2328 if (!allow_suffix) {
2329 pr_warning("Error: event \"%s\" already exists. " 2329 pr_warning("Error: event \"%s\" already exists.\n"
2330 "(Use -f to force duplicates.)\n", buf); 2330 " Hint: Remove existing event by 'perf probe -d'\n"
2331 " or force duplicates by 'perf probe -f'\n"
2332 " or set 'force=yes' in BPF source.\n",
2333 buf);
2331 ret = -EEXIST; 2334 ret = -EEXIST;
2332 goto out; 2335 goto out;
2333 } 2336 }
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 05012bb178d7..2be10fb27172 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -654,6 +654,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
654static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf) 654static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
655{ 655{
656 Dwarf_Attribute fb_attr; 656 Dwarf_Attribute fb_attr;
657 Dwarf_Frame *frame = NULL;
657 size_t nops; 658 size_t nops;
658 int ret; 659 int ret;
659 660
@@ -686,11 +687,11 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
686#if _ELFUTILS_PREREQ(0, 142) 687#if _ELFUTILS_PREREQ(0, 142)
687 } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa && 688 } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
688 pf->cfi != NULL) { 689 pf->cfi != NULL) {
689 Dwarf_Frame *frame;
690 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 || 690 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
691 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) { 691 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
692 pr_warning("Failed to get call frame on 0x%jx\n", 692 pr_warning("Failed to get call frame on 0x%jx\n",
693 (uintmax_t)pf->addr); 693 (uintmax_t)pf->addr);
694 free(frame);
694 return -ENOENT; 695 return -ENOENT;
695 } 696 }
696#endif 697#endif
@@ -699,7 +700,8 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
699 /* Call finder's callback handler */ 700 /* Call finder's callback handler */
700 ret = pf->callback(sc_die, pf); 701 ret = pf->callback(sc_die, pf);
701 702
702 /* *pf->fb_ops will be cached in libdw. Don't free it. */ 703 /* Since *pf->fb_ops can be a part of frame. we should free it here. */
704 free(frame);
703 pf->fb_ops = NULL; 705 pf->fb_ops = NULL;
704 706
705 return ret; 707 return ret;
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 51be28b1bca2..8162ba0e2e57 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -10,6 +10,8 @@ util/ctype.c
10util/evlist.c 10util/evlist.c
11util/evsel.c 11util/evsel.c
12util/cpumap.c 12util/cpumap.c
13../lib/bitmap.c
14../lib/find_bit.c
13../lib/hweight.c 15../lib/hweight.c
14util/thread_map.c 16util/thread_map.c
15util/util.c 17util/util.c
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index a8e825fca42a..d72fafc1c800 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -41,6 +41,9 @@
41#include "../thread-stack.h" 41#include "../thread-stack.h"
42#include "../trace-event.h" 42#include "../trace-event.h"
43#include "../machine.h" 43#include "../machine.h"
44#include "thread_map.h"
45#include "cpumap.h"
46#include "stat.h"
44 47
45PyMODINIT_FUNC initperf_trace_context(void); 48PyMODINIT_FUNC initperf_trace_context(void);
46 49
@@ -859,6 +862,104 @@ static void python_process_event(union perf_event *event,
859 } 862 }
860} 863}
861 864
865static void get_handler_name(char *str, size_t size,
866 struct perf_evsel *evsel)
867{
868 char *p = str;
869
870 scnprintf(str, size, "stat__%s", perf_evsel__name(evsel));
871
872 while ((p = strchr(p, ':'))) {
873 *p = '_';
874 p++;
875 }
876}
877
878static void
879process_stat(struct perf_evsel *counter, int cpu, int thread, u64 tstamp,
880 struct perf_counts_values *count)
881{
882 PyObject *handler, *t;
883 static char handler_name[256];
884 int n = 0;
885
886 t = PyTuple_New(MAX_FIELDS);
887 if (!t)
888 Py_FatalError("couldn't create Python tuple");
889
890 get_handler_name(handler_name, sizeof(handler_name),
891 counter);
892
893 handler = get_handler(handler_name);
894 if (!handler) {
895 pr_debug("can't find python handler %s\n", handler_name);
896 return;
897 }
898
899 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
900 PyTuple_SetItem(t, n++, PyInt_FromLong(thread));
901
902 tuple_set_u64(t, n++, tstamp);
903 tuple_set_u64(t, n++, count->val);
904 tuple_set_u64(t, n++, count->ena);
905 tuple_set_u64(t, n++, count->run);
906
907 if (_PyTuple_Resize(&t, n) == -1)
908 Py_FatalError("error resizing Python tuple");
909
910 call_object(handler, t, handler_name);
911
912 Py_DECREF(t);
913}
914
915static void python_process_stat(struct perf_stat_config *config,
916 struct perf_evsel *counter, u64 tstamp)
917{
918 struct thread_map *threads = counter->threads;
919 struct cpu_map *cpus = counter->cpus;
920 int cpu, thread;
921
922 if (config->aggr_mode == AGGR_GLOBAL) {
923 process_stat(counter, -1, -1, tstamp,
924 &counter->counts->aggr);
925 return;
926 }
927
928 for (thread = 0; thread < threads->nr; thread++) {
929 for (cpu = 0; cpu < cpus->nr; cpu++) {
930 process_stat(counter, cpus->map[cpu],
931 thread_map__pid(threads, thread), tstamp,
932 perf_counts(counter->counts, cpu, thread));
933 }
934 }
935}
936
937static void python_process_stat_interval(u64 tstamp)
938{
939 PyObject *handler, *t;
940 static const char handler_name[] = "stat__interval";
941 int n = 0;
942
943 t = PyTuple_New(MAX_FIELDS);
944 if (!t)
945 Py_FatalError("couldn't create Python tuple");
946
947 handler = get_handler(handler_name);
948 if (!handler) {
949 pr_debug("can't find python handler %s\n", handler_name);
950 return;
951 }
952
953 tuple_set_u64(t, n++, tstamp);
954
955 if (_PyTuple_Resize(&t, n) == -1)
956 Py_FatalError("error resizing Python tuple");
957
958 call_object(handler, t, handler_name);
959
960 Py_DECREF(t);
961}
962
862static int run_start_sub(void) 963static int run_start_sub(void)
863{ 964{
864 main_module = PyImport_AddModule("__main__"); 965 main_module = PyImport_AddModule("__main__");
@@ -1201,10 +1302,12 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
1201} 1302}
1202 1303
1203struct scripting_ops python_scripting_ops = { 1304struct scripting_ops python_scripting_ops = {
1204 .name = "Python", 1305 .name = "Python",
1205 .start_script = python_start_script, 1306 .start_script = python_start_script,
1206 .flush_script = python_flush_script, 1307 .flush_script = python_flush_script,
1207 .stop_script = python_stop_script, 1308 .stop_script = python_stop_script,
1208 .process_event = python_process_event, 1309 .process_event = python_process_event,
1209 .generate_script = python_generate_script, 1310 .process_stat = python_process_stat,
1311 .process_stat_interval = python_process_stat_interval,
1312 .generate_script = python_generate_script,
1210}; 1313};
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index c35ffdd360fe..d5636ba94b20 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -17,6 +17,7 @@
17#include "asm/bug.h" 17#include "asm/bug.h"
18#include "auxtrace.h" 18#include "auxtrace.h"
19#include "thread-stack.h" 19#include "thread-stack.h"
20#include "stat.h"
20 21
21static int perf_session__deliver_event(struct perf_session *session, 22static int perf_session__deliver_event(struct perf_session *session,
22 union perf_event *event, 23 union perf_event *event,
@@ -36,6 +37,9 @@ static int perf_session__open(struct perf_session *session)
36 if (perf_data_file__is_pipe(file)) 37 if (perf_data_file__is_pipe(file))
37 return 0; 38 return 0;
38 39
40 if (perf_header__has_feat(&session->header, HEADER_STAT))
41 return 0;
42
39 if (!perf_evlist__valid_sample_type(session->evlist)) { 43 if (!perf_evlist__valid_sample_type(session->evlist)) {
40 pr_err("non matching sample_type\n"); 44 pr_err("non matching sample_type\n");
41 return -1; 45 return -1;
@@ -205,6 +209,18 @@ static int process_event_synth_attr_stub(struct perf_tool *tool __maybe_unused,
205 return 0; 209 return 0;
206} 210}
207 211
212static int process_event_synth_event_update_stub(struct perf_tool *tool __maybe_unused,
213 union perf_event *event __maybe_unused,
214 struct perf_evlist **pevlist
215 __maybe_unused)
216{
217 if (dump_trace)
218 perf_event__fprintf_event_update(event, stdout);
219
220 dump_printf(": unhandled!\n");
221 return 0;
222}
223
208static int process_event_sample_stub(struct perf_tool *tool __maybe_unused, 224static int process_event_sample_stub(struct perf_tool *tool __maybe_unused,
209 union perf_event *event __maybe_unused, 225 union perf_event *event __maybe_unused,
210 struct perf_sample *sample __maybe_unused, 226 struct perf_sample *sample __maybe_unused,
@@ -296,6 +312,67 @@ int process_event_auxtrace_error_stub(struct perf_tool *tool __maybe_unused,
296 return 0; 312 return 0;
297} 313}
298 314
315
316static
317int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
318 union perf_event *event __maybe_unused,
319 struct perf_session *session __maybe_unused)
320{
321 if (dump_trace)
322 perf_event__fprintf_thread_map(event, stdout);
323
324 dump_printf(": unhandled!\n");
325 return 0;
326}
327
328static
329int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
330 union perf_event *event __maybe_unused,
331 struct perf_session *session __maybe_unused)
332{
333 if (dump_trace)
334 perf_event__fprintf_cpu_map(event, stdout);
335
336 dump_printf(": unhandled!\n");
337 return 0;
338}
339
340static
341int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
342 union perf_event *event __maybe_unused,
343 struct perf_session *session __maybe_unused)
344{
345 if (dump_trace)
346 perf_event__fprintf_stat_config(event, stdout);
347
348 dump_printf(": unhandled!\n");
349 return 0;
350}
351
352static int process_stat_stub(struct perf_tool *tool __maybe_unused,
353 union perf_event *event __maybe_unused,
354 struct perf_session *perf_session
355 __maybe_unused)
356{
357 if (dump_trace)
358 perf_event__fprintf_stat(event, stdout);
359
360 dump_printf(": unhandled!\n");
361 return 0;
362}
363
364static int process_stat_round_stub(struct perf_tool *tool __maybe_unused,
365 union perf_event *event __maybe_unused,
366 struct perf_session *perf_session
367 __maybe_unused)
368{
369 if (dump_trace)
370 perf_event__fprintf_stat_round(event, stdout);
371
372 dump_printf(": unhandled!\n");
373 return 0;
374}
375
299void perf_tool__fill_defaults(struct perf_tool *tool) 376void perf_tool__fill_defaults(struct perf_tool *tool)
300{ 377{
301 if (tool->sample == NULL) 378 if (tool->sample == NULL)
@@ -328,6 +405,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
328 tool->unthrottle = process_event_stub; 405 tool->unthrottle = process_event_stub;
329 if (tool->attr == NULL) 406 if (tool->attr == NULL)
330 tool->attr = process_event_synth_attr_stub; 407 tool->attr = process_event_synth_attr_stub;
408 if (tool->event_update == NULL)
409 tool->event_update = process_event_synth_event_update_stub;
331 if (tool->tracing_data == NULL) 410 if (tool->tracing_data == NULL)
332 tool->tracing_data = process_event_synth_tracing_data_stub; 411 tool->tracing_data = process_event_synth_tracing_data_stub;
333 if (tool->build_id == NULL) 412 if (tool->build_id == NULL)
@@ -346,6 +425,16 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
346 tool->auxtrace = process_event_auxtrace_stub; 425 tool->auxtrace = process_event_auxtrace_stub;
347 if (tool->auxtrace_error == NULL) 426 if (tool->auxtrace_error == NULL)
348 tool->auxtrace_error = process_event_auxtrace_error_stub; 427 tool->auxtrace_error = process_event_auxtrace_error_stub;
428 if (tool->thread_map == NULL)
429 tool->thread_map = process_event_thread_map_stub;
430 if (tool->cpu_map == NULL)
431 tool->cpu_map = process_event_cpu_map_stub;
432 if (tool->stat_config == NULL)
433 tool->stat_config = process_event_stat_config_stub;
434 if (tool->stat == NULL)
435 tool->stat = process_stat_stub;
436 if (tool->stat_round == NULL)
437 tool->stat_round = process_stat_round_stub;
349} 438}
350 439
351static void swap_sample_id_all(union perf_event *event, void *data) 440static void swap_sample_id_all(union perf_event *event, void *data)
@@ -569,6 +658,13 @@ static void perf_event__hdr_attr_swap(union perf_event *event,
569 mem_bswap_64(event->attr.id, size); 658 mem_bswap_64(event->attr.id, size);
570} 659}
571 660
661static void perf_event__event_update_swap(union perf_event *event,
662 bool sample_id_all __maybe_unused)
663{
664 event->event_update.type = bswap_64(event->event_update.type);
665 event->event_update.id = bswap_64(event->event_update.id);
666}
667
572static void perf_event__event_type_swap(union perf_event *event, 668static void perf_event__event_type_swap(union perf_event *event,
573 bool sample_id_all __maybe_unused) 669 bool sample_id_all __maybe_unused)
574{ 670{
@@ -616,6 +712,81 @@ static void perf_event__auxtrace_error_swap(union perf_event *event,
616 event->auxtrace_error.ip = bswap_64(event->auxtrace_error.ip); 712 event->auxtrace_error.ip = bswap_64(event->auxtrace_error.ip);
617} 713}
618 714
715static void perf_event__thread_map_swap(union perf_event *event,
716 bool sample_id_all __maybe_unused)
717{
718 unsigned i;
719
720 event->thread_map.nr = bswap_64(event->thread_map.nr);
721
722 for (i = 0; i < event->thread_map.nr; i++)
723 event->thread_map.entries[i].pid = bswap_64(event->thread_map.entries[i].pid);
724}
725
726static void perf_event__cpu_map_swap(union perf_event *event,
727 bool sample_id_all __maybe_unused)
728{
729 struct cpu_map_data *data = &event->cpu_map.data;
730 struct cpu_map_entries *cpus;
731 struct cpu_map_mask *mask;
732 unsigned i;
733
734 data->type = bswap_64(data->type);
735
736 switch (data->type) {
737 case PERF_CPU_MAP__CPUS:
738 cpus = (struct cpu_map_entries *)data->data;
739
740 cpus->nr = bswap_16(cpus->nr);
741
742 for (i = 0; i < cpus->nr; i++)
743 cpus->cpu[i] = bswap_16(cpus->cpu[i]);
744 break;
745 case PERF_CPU_MAP__MASK:
746 mask = (struct cpu_map_mask *) data->data;
747
748 mask->nr = bswap_16(mask->nr);
749 mask->long_size = bswap_16(mask->long_size);
750
751 switch (mask->long_size) {
752 case 4: mem_bswap_32(&mask->mask, mask->nr); break;
753 case 8: mem_bswap_64(&mask->mask, mask->nr); break;
754 default:
755 pr_err("cpu_map swap: unsupported long size\n");
756 }
757 default:
758 break;
759 }
760}
761
762static void perf_event__stat_config_swap(union perf_event *event,
763 bool sample_id_all __maybe_unused)
764{
765 u64 size;
766
767 size = event->stat_config.nr * sizeof(event->stat_config.data[0]);
768 size += 1; /* nr item itself */
769 mem_bswap_64(&event->stat_config.nr, size);
770}
771
772static void perf_event__stat_swap(union perf_event *event,
773 bool sample_id_all __maybe_unused)
774{
775 event->stat.id = bswap_64(event->stat.id);
776 event->stat.thread = bswap_32(event->stat.thread);
777 event->stat.cpu = bswap_32(event->stat.cpu);
778 event->stat.val = bswap_64(event->stat.val);
779 event->stat.ena = bswap_64(event->stat.ena);
780 event->stat.run = bswap_64(event->stat.run);
781}
782
783static void perf_event__stat_round_swap(union perf_event *event,
784 bool sample_id_all __maybe_unused)
785{
786 event->stat_round.type = bswap_64(event->stat_round.type);
787 event->stat_round.time = bswap_64(event->stat_round.time);
788}
789
619typedef void (*perf_event__swap_op)(union perf_event *event, 790typedef void (*perf_event__swap_op)(union perf_event *event,
620 bool sample_id_all); 791 bool sample_id_all);
621 792
@@ -643,6 +814,12 @@ static perf_event__swap_op perf_event__swap_ops[] = {
643 [PERF_RECORD_AUXTRACE_INFO] = perf_event__auxtrace_info_swap, 814 [PERF_RECORD_AUXTRACE_INFO] = perf_event__auxtrace_info_swap,
644 [PERF_RECORD_AUXTRACE] = perf_event__auxtrace_swap, 815 [PERF_RECORD_AUXTRACE] = perf_event__auxtrace_swap,
645 [PERF_RECORD_AUXTRACE_ERROR] = perf_event__auxtrace_error_swap, 816 [PERF_RECORD_AUXTRACE_ERROR] = perf_event__auxtrace_error_swap,
817 [PERF_RECORD_THREAD_MAP] = perf_event__thread_map_swap,
818 [PERF_RECORD_CPU_MAP] = perf_event__cpu_map_swap,
819 [PERF_RECORD_STAT_CONFIG] = perf_event__stat_config_swap,
820 [PERF_RECORD_STAT] = perf_event__stat_swap,
821 [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap,
822 [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap,
646 [PERF_RECORD_HEADER_MAX] = NULL, 823 [PERF_RECORD_HEADER_MAX] = NULL,
647}; 824};
648 825
@@ -1154,6 +1331,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
1154 perf_session__set_comm_exec(session); 1331 perf_session__set_comm_exec(session);
1155 } 1332 }
1156 return err; 1333 return err;
1334 case PERF_RECORD_EVENT_UPDATE:
1335 return tool->event_update(tool, event, &session->evlist);
1157 case PERF_RECORD_HEADER_EVENT_TYPE: 1336 case PERF_RECORD_HEADER_EVENT_TYPE:
1158 /* 1337 /*
1159 * Depreceated, but we need to handle it for sake 1338 * Depreceated, but we need to handle it for sake
@@ -1179,6 +1358,16 @@ static s64 perf_session__process_user_event(struct perf_session *session,
1179 case PERF_RECORD_AUXTRACE_ERROR: 1358 case PERF_RECORD_AUXTRACE_ERROR:
1180 perf_session__auxtrace_error_inc(session, event); 1359 perf_session__auxtrace_error_inc(session, event);
1181 return tool->auxtrace_error(tool, event, session); 1360 return tool->auxtrace_error(tool, event, session);
1361 case PERF_RECORD_THREAD_MAP:
1362 return tool->thread_map(tool, event, session);
1363 case PERF_RECORD_CPU_MAP:
1364 return tool->cpu_map(tool, event, session);
1365 case PERF_RECORD_STAT_CONFIG:
1366 return tool->stat_config(tool, event, session);
1367 case PERF_RECORD_STAT:
1368 return tool->stat(tool, event, session);
1369 case PERF_RECORD_STAT_ROUND:
1370 return tool->stat_round(tool, event, session);
1182 default: 1371 default:
1183 return -EINVAL; 1372 return -EINVAL;
1184 } 1373 }
@@ -1311,17 +1500,20 @@ struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
1311 return machine__findnew_thread(&session->machines.host, -1, pid); 1500 return machine__findnew_thread(&session->machines.host, -1, pid);
1312} 1501}
1313 1502
1314struct thread *perf_session__register_idle_thread(struct perf_session *session) 1503int perf_session__register_idle_thread(struct perf_session *session)
1315{ 1504{
1316 struct thread *thread; 1505 struct thread *thread;
1506 int err = 0;
1317 1507
1318 thread = machine__findnew_thread(&session->machines.host, 0, 0); 1508 thread = machine__findnew_thread(&session->machines.host, 0, 0);
1319 if (thread == NULL || thread__set_comm(thread, "swapper", 0)) { 1509 if (thread == NULL || thread__set_comm(thread, "swapper", 0)) {
1320 pr_err("problem inserting idle task.\n"); 1510 pr_err("problem inserting idle task.\n");
1321 thread = NULL; 1511 err = -1;
1322 } 1512 }
1323 1513
1324 return thread; 1514 /* machine__findnew_thread() got the thread, so put it */
1515 thread__put(thread);
1516 return err;
1325} 1517}
1326 1518
1327static void perf_session__warn_about_errors(const struct perf_session *session) 1519static void perf_session__warn_about_errors(const struct perf_session *session)
@@ -1676,7 +1868,7 @@ int perf_session__process_events(struct perf_session *session)
1676 u64 size = perf_data_file__size(session->file); 1868 u64 size = perf_data_file__size(session->file);
1677 int err; 1869 int err;
1678 1870
1679 if (perf_session__register_idle_thread(session) == NULL) 1871 if (perf_session__register_idle_thread(session) < 0)
1680 return -ENOMEM; 1872 return -ENOMEM;
1681 1873
1682 if (!perf_data_file__is_pipe(session->file)) 1874 if (!perf_data_file__is_pipe(session->file))
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 3e900c0efc73..5f792e35d4c1 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -89,7 +89,7 @@ struct machine *perf_session__findnew_machine(struct perf_session *session, pid_
89} 89}
90 90
91struct thread *perf_session__findnew(struct perf_session *session, pid_t pid); 91struct thread *perf_session__findnew(struct perf_session *session, pid_t pid);
92struct thread *perf_session__register_idle_thread(struct perf_session *session); 92int perf_session__register_idle_thread(struct perf_session *session);
93 93
94size_t perf_session__fprintf(struct perf_session *session, FILE *fp); 94size_t perf_session__fprintf(struct perf_session *session, FILE *fp);
95 95
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 2d8ccd4d9e1b..ec722346e6ff 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -4,6 +4,8 @@
4#include "comm.h" 4#include "comm.h"
5#include "symbol.h" 5#include "symbol.h"
6#include "evsel.h" 6#include "evsel.h"
7#include "evlist.h"
8#include <traceevent/event-parse.h>
7 9
8regex_t parent_regex; 10regex_t parent_regex;
9const char default_parent_pattern[] = "^sys_|^do_page_fault"; 11const char default_parent_pattern[] = "^sys_|^do_page_fault";
@@ -13,6 +15,7 @@ const char default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cy
13const char default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked"; 15const char default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
14const char default_top_sort_order[] = "dso,symbol"; 16const char default_top_sort_order[] = "dso,symbol";
15const char default_diff_sort_order[] = "dso,symbol"; 17const char default_diff_sort_order[] = "dso,symbol";
18const char default_tracepoint_sort_order[] = "trace";
16const char *sort_order; 19const char *sort_order;
17const char *field_order; 20const char *field_order;
18regex_t ignore_callees_regex; 21regex_t ignore_callees_regex;
@@ -443,6 +446,70 @@ struct sort_entry sort_socket = {
443 .se_width_idx = HISTC_SOCKET, 446 .se_width_idx = HISTC_SOCKET,
444}; 447};
445 448
449/* --sort trace */
450
451static char *get_trace_output(struct hist_entry *he)
452{
453 struct trace_seq seq;
454 struct perf_evsel *evsel;
455 struct pevent_record rec = {
456 .data = he->raw_data,
457 .size = he->raw_size,
458 };
459
460 evsel = hists_to_evsel(he->hists);
461
462 trace_seq_init(&seq);
463 if (symbol_conf.raw_trace) {
464 pevent_print_fields(&seq, he->raw_data, he->raw_size,
465 evsel->tp_format);
466 } else {
467 pevent_event_info(&seq, evsel->tp_format, &rec);
468 }
469 return seq.buffer;
470}
471
472static int64_t
473sort__trace_cmp(struct hist_entry *left, struct hist_entry *right)
474{
475 struct perf_evsel *evsel;
476
477 evsel = hists_to_evsel(left->hists);
478 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
479 return 0;
480
481 if (left->trace_output == NULL)
482 left->trace_output = get_trace_output(left);
483 if (right->trace_output == NULL)
484 right->trace_output = get_trace_output(right);
485
486 hists__new_col_len(left->hists, HISTC_TRACE, strlen(left->trace_output));
487 hists__new_col_len(right->hists, HISTC_TRACE, strlen(right->trace_output));
488
489 return strcmp(right->trace_output, left->trace_output);
490}
491
492static int hist_entry__trace_snprintf(struct hist_entry *he, char *bf,
493 size_t size, unsigned int width)
494{
495 struct perf_evsel *evsel;
496
497 evsel = hists_to_evsel(he->hists);
498 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
499 return scnprintf(bf, size, "%-*.*s", width, width, "N/A");
500
501 if (he->trace_output == NULL)
502 he->trace_output = get_trace_output(he);
503 return repsep_snprintf(bf, size, "%-*.*s", width, width, he->trace_output);
504}
505
506struct sort_entry sort_trace = {
507 .se_header = "Trace output",
508 .se_cmp = sort__trace_cmp,
509 .se_snprintf = hist_entry__trace_snprintf,
510 .se_width_idx = HISTC_TRACE,
511};
512
446/* sort keys for branch stacks */ 513/* sort keys for branch stacks */
447 514
448static int64_t 515static int64_t
@@ -1312,6 +1379,7 @@ static struct sort_dimension common_sort_dimensions[] = {
1312 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), 1379 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
1313 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), 1380 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
1314 DIM(SORT_TRANSACTION, "transaction", sort_transaction), 1381 DIM(SORT_TRANSACTION, "transaction", sort_transaction),
1382 DIM(SORT_TRACE, "trace", sort_trace),
1315}; 1383};
1316 1384
1317#undef DIM 1385#undef DIM
@@ -1529,6 +1597,455 @@ static int __sort_dimension__add_hpp_output(struct sort_dimension *sd)
1529 return 0; 1597 return 0;
1530} 1598}
1531 1599
1600struct hpp_dynamic_entry {
1601 struct perf_hpp_fmt hpp;
1602 struct perf_evsel *evsel;
1603 struct format_field *field;
1604 unsigned dynamic_len;
1605 bool raw_trace;
1606};
1607
1608static int hde_width(struct hpp_dynamic_entry *hde)
1609{
1610 if (!hde->hpp.len) {
1611 int len = hde->dynamic_len;
1612 int namelen = strlen(hde->field->name);
1613 int fieldlen = hde->field->size;
1614
1615 if (namelen > len)
1616 len = namelen;
1617
1618 if (!(hde->field->flags & FIELD_IS_STRING)) {
1619 /* length for print hex numbers */
1620 fieldlen = hde->field->size * 2 + 2;
1621 }
1622 if (fieldlen > len)
1623 len = fieldlen;
1624
1625 hde->hpp.len = len;
1626 }
1627 return hde->hpp.len;
1628}
1629
1630static void update_dynamic_len(struct hpp_dynamic_entry *hde,
1631 struct hist_entry *he)
1632{
1633 char *str, *pos;
1634 struct format_field *field = hde->field;
1635 size_t namelen;
1636 bool last = false;
1637
1638 if (hde->raw_trace)
1639 return;
1640
1641 /* parse pretty print result and update max length */
1642 if (!he->trace_output)
1643 he->trace_output = get_trace_output(he);
1644
1645 namelen = strlen(field->name);
1646 str = he->trace_output;
1647
1648 while (str) {
1649 pos = strchr(str, ' ');
1650 if (pos == NULL) {
1651 last = true;
1652 pos = str + strlen(str);
1653 }
1654
1655 if (!strncmp(str, field->name, namelen)) {
1656 size_t len;
1657
1658 str += namelen + 1;
1659 len = pos - str;
1660
1661 if (len > hde->dynamic_len)
1662 hde->dynamic_len = len;
1663 break;
1664 }
1665
1666 if (last)
1667 str = NULL;
1668 else
1669 str = pos + 1;
1670 }
1671}
1672
1673static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1674 struct perf_evsel *evsel __maybe_unused)
1675{
1676 struct hpp_dynamic_entry *hde;
1677 size_t len = fmt->user_len;
1678
1679 hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
1680
1681 if (!len)
1682 len = hde_width(hde);
1683
1684 return scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, hde->field->name);
1685}
1686
1687static int __sort__hde_width(struct perf_hpp_fmt *fmt,
1688 struct perf_hpp *hpp __maybe_unused,
1689 struct perf_evsel *evsel __maybe_unused)
1690{
1691 struct hpp_dynamic_entry *hde;
1692 size_t len = fmt->user_len;
1693
1694 hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
1695
1696 if (!len)
1697 len = hde_width(hde);
1698
1699 return len;
1700}
1701
1702bool perf_hpp__defined_dynamic_entry(struct perf_hpp_fmt *fmt, struct hists *hists)
1703{
1704 struct hpp_dynamic_entry *hde;
1705
1706 hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
1707
1708 return hists_to_evsel(hists) == hde->evsel;
1709}
1710
1711static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1712 struct hist_entry *he)
1713{
1714 struct hpp_dynamic_entry *hde;
1715 size_t len = fmt->user_len;
1716 char *str, *pos;
1717 struct format_field *field;
1718 size_t namelen;
1719 bool last = false;
1720 int ret;
1721
1722 hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
1723
1724 if (!len)
1725 len = hde_width(hde);
1726
1727 if (hde->raw_trace)
1728 goto raw_field;
1729
1730 field = hde->field;
1731 namelen = strlen(field->name);
1732 str = he->trace_output;
1733
1734 while (str) {
1735 pos = strchr(str, ' ');
1736 if (pos == NULL) {
1737 last = true;
1738 pos = str + strlen(str);
1739 }
1740
1741 if (!strncmp(str, field->name, namelen)) {
1742 str += namelen + 1;
1743 str = strndup(str, pos - str);
1744
1745 if (str == NULL)
1746 return scnprintf(hpp->buf, hpp->size,
1747 "%*.*s", len, len, "ERROR");
1748 break;
1749 }
1750
1751 if (last)
1752 str = NULL;
1753 else
1754 str = pos + 1;
1755 }
1756
1757 if (str == NULL) {
1758 struct trace_seq seq;
1759raw_field:
1760 trace_seq_init(&seq);
1761 pevent_print_field(&seq, he->raw_data, hde->field);
1762 str = seq.buffer;
1763 }
1764
1765 ret = scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, str);
1766 free(str);
1767 return ret;
1768}
1769
1770static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
1771 struct hist_entry *a, struct hist_entry *b)
1772{
1773 struct hpp_dynamic_entry *hde;
1774 struct format_field *field;
1775 unsigned offset, size;
1776
1777 hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
1778
1779 field = hde->field;
1780 if (field->flags & FIELD_IS_DYNAMIC) {
1781 unsigned long long dyn;
1782
1783 pevent_read_number_field(field, a->raw_data, &dyn);
1784 offset = dyn & 0xffff;
1785 size = (dyn >> 16) & 0xffff;
1786
1787 /* record max width for output */
1788 if (size > hde->dynamic_len)
1789 hde->dynamic_len = size;
1790 } else {
1791 offset = field->offset;
1792 size = field->size;
1793
1794 update_dynamic_len(hde, a);
1795 update_dynamic_len(hde, b);
1796 }
1797
1798 return memcmp(a->raw_data + offset, b->raw_data + offset, size);
1799}
1800
1801bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *fmt)
1802{
1803 return fmt->cmp == __sort__hde_cmp;
1804}
1805
1806static struct hpp_dynamic_entry *
1807__alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field)
1808{
1809 struct hpp_dynamic_entry *hde;
1810
1811 hde = malloc(sizeof(*hde));
1812 if (hde == NULL) {
1813 pr_debug("Memory allocation failed\n");
1814 return NULL;
1815 }
1816
1817 hde->evsel = evsel;
1818 hde->field = field;
1819 hde->dynamic_len = 0;
1820
1821 hde->hpp.name = field->name;
1822 hde->hpp.header = __sort__hde_header;
1823 hde->hpp.width = __sort__hde_width;
1824 hde->hpp.entry = __sort__hde_entry;
1825 hde->hpp.color = NULL;
1826
1827 hde->hpp.cmp = __sort__hde_cmp;
1828 hde->hpp.collapse = __sort__hde_cmp;
1829 hde->hpp.sort = __sort__hde_cmp;
1830
1831 INIT_LIST_HEAD(&hde->hpp.list);
1832 INIT_LIST_HEAD(&hde->hpp.sort_list);
1833 hde->hpp.elide = false;
1834 hde->hpp.len = 0;
1835 hde->hpp.user_len = 0;
1836
1837 return hde;
1838}
1839
1840static int parse_field_name(char *str, char **event, char **field, char **opt)
1841{
1842 char *event_name, *field_name, *opt_name;
1843
1844 event_name = str;
1845 field_name = strchr(str, '.');
1846
1847 if (field_name) {
1848 *field_name++ = '\0';
1849 } else {
1850 event_name = NULL;
1851 field_name = str;
1852 }
1853
1854 opt_name = strchr(field_name, '/');
1855 if (opt_name)
1856 *opt_name++ = '\0';
1857
1858 *event = event_name;
1859 *field = field_name;
1860 *opt = opt_name;
1861
1862 return 0;
1863}
1864
1865/* find match evsel using a given event name. The event name can be:
1866 * 1. '%' + event index (e.g. '%1' for first event)
1867 * 2. full event name (e.g. sched:sched_switch)
1868 * 3. partial event name (should not contain ':')
1869 */
1870static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_name)
1871{
1872 struct perf_evsel *evsel = NULL;
1873 struct perf_evsel *pos;
1874 bool full_name;
1875
1876 /* case 1 */
1877 if (event_name[0] == '%') {
1878 int nr = strtol(event_name+1, NULL, 0);
1879
1880 if (nr > evlist->nr_entries)
1881 return NULL;
1882
1883 evsel = perf_evlist__first(evlist);
1884 while (--nr > 0)
1885 evsel = perf_evsel__next(evsel);
1886
1887 return evsel;
1888 }
1889
1890 full_name = !!strchr(event_name, ':');
1891 evlist__for_each(evlist, pos) {
1892 /* case 2 */
1893 if (full_name && !strcmp(pos->name, event_name))
1894 return pos;
1895 /* case 3 */
1896 if (!full_name && strstr(pos->name, event_name)) {
1897 if (evsel) {
1898 pr_debug("'%s' event is ambiguous: it can be %s or %s\n",
1899 event_name, evsel->name, pos->name);
1900 return NULL;
1901 }
1902 evsel = pos;
1903 }
1904 }
1905
1906 return evsel;
1907}
1908
1909static int __dynamic_dimension__add(struct perf_evsel *evsel,
1910 struct format_field *field,
1911 bool raw_trace)
1912{
1913 struct hpp_dynamic_entry *hde;
1914
1915 hde = __alloc_dynamic_entry(evsel, field);
1916 if (hde == NULL)
1917 return -ENOMEM;
1918
1919 hde->raw_trace = raw_trace;
1920
1921 perf_hpp__register_sort_field(&hde->hpp);
1922 return 0;
1923}
1924
1925static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace)
1926{
1927 int ret;
1928 struct format_field *field;
1929
1930 field = evsel->tp_format->format.fields;
1931 while (field) {
1932 ret = __dynamic_dimension__add(evsel, field, raw_trace);
1933 if (ret < 0)
1934 return ret;
1935
1936 field = field->next;
1937 }
1938 return 0;
1939}
1940
1941static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
1942{
1943 int ret;
1944 struct perf_evsel *evsel;
1945
1946 evlist__for_each(evlist, evsel) {
1947 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
1948 continue;
1949
1950 ret = add_evsel_fields(evsel, raw_trace);
1951 if (ret < 0)
1952 return ret;
1953 }
1954 return 0;
1955}
1956
1957static int add_all_matching_fields(struct perf_evlist *evlist,
1958 char *field_name, bool raw_trace)
1959{
1960 int ret = -ESRCH;
1961 struct perf_evsel *evsel;
1962 struct format_field *field;
1963
1964 evlist__for_each(evlist, evsel) {
1965 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
1966 continue;
1967
1968 field = pevent_find_any_field(evsel->tp_format, field_name);
1969 if (field == NULL)
1970 continue;
1971
1972 ret = __dynamic_dimension__add(evsel, field, raw_trace);
1973 if (ret < 0)
1974 break;
1975 }
1976 return ret;
1977}
1978
1979static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
1980{
1981 char *str, *event_name, *field_name, *opt_name;
1982 struct perf_evsel *evsel;
1983 struct format_field *field;
1984 bool raw_trace = symbol_conf.raw_trace;
1985 int ret = 0;
1986
1987 if (evlist == NULL)
1988 return -ENOENT;
1989
1990 str = strdup(tok);
1991 if (str == NULL)
1992 return -ENOMEM;
1993
1994 if (parse_field_name(str, &event_name, &field_name, &opt_name) < 0) {
1995 ret = -EINVAL;
1996 goto out;
1997 }
1998
1999 if (opt_name) {
2000 if (strcmp(opt_name, "raw")) {
2001 pr_debug("unsupported field option %s\n", opt_name);
2002 ret = -EINVAL;
2003 goto out;
2004 }
2005 raw_trace = true;
2006 }
2007
2008 if (!strcmp(field_name, "trace_fields")) {
2009 ret = add_all_dynamic_fields(evlist, raw_trace);
2010 goto out;
2011 }
2012
2013 if (event_name == NULL) {
2014 ret = add_all_matching_fields(evlist, field_name, raw_trace);
2015 goto out;
2016 }
2017
2018 evsel = find_evsel(evlist, event_name);
2019 if (evsel == NULL) {
2020 pr_debug("Cannot find event: %s\n", event_name);
2021 ret = -ENOENT;
2022 goto out;
2023 }
2024
2025 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
2026 pr_debug("%s is not a tracepoint event\n", event_name);
2027 ret = -EINVAL;
2028 goto out;
2029 }
2030
2031 if (!strcmp(field_name, "*")) {
2032 ret = add_evsel_fields(evsel, raw_trace);
2033 } else {
2034 field = pevent_find_any_field(evsel->tp_format, field_name);
2035 if (field == NULL) {
2036 pr_debug("Cannot find event field for %s.%s\n",
2037 event_name, field_name);
2038 return -ENOENT;
2039 }
2040
2041 ret = __dynamic_dimension__add(evsel, field, raw_trace);
2042 }
2043
2044out:
2045 free(str);
2046 return ret;
2047}
2048
1532static int __sort_dimension__add(struct sort_dimension *sd) 2049static int __sort_dimension__add(struct sort_dimension *sd)
1533{ 2050{
1534 if (sd->taken) 2051 if (sd->taken)
@@ -1583,7 +2100,8 @@ int hpp_dimension__add_output(unsigned col)
1583 return __hpp_dimension__add_output(&hpp_sort_dimensions[col]); 2100 return __hpp_dimension__add_output(&hpp_sort_dimensions[col]);
1584} 2101}
1585 2102
1586int sort_dimension__add(const char *tok) 2103static int sort_dimension__add(const char *tok,
2104 struct perf_evlist *evlist __maybe_unused)
1587{ 2105{
1588 unsigned int i; 2106 unsigned int i;
1589 2107
@@ -1664,10 +2182,13 @@ int sort_dimension__add(const char *tok)
1664 return 0; 2182 return 0;
1665 } 2183 }
1666 2184
2185 if (!add_dynamic_entry(evlist, tok))
2186 return 0;
2187
1667 return -ESRCH; 2188 return -ESRCH;
1668} 2189}
1669 2190
1670static const char *get_default_sort_order(void) 2191static const char *get_default_sort_order(struct perf_evlist *evlist)
1671{ 2192{
1672 const char *default_sort_orders[] = { 2193 const char *default_sort_orders[] = {
1673 default_sort_order, 2194 default_sort_order,
@@ -1675,14 +2196,33 @@ static const char *get_default_sort_order(void)
1675 default_mem_sort_order, 2196 default_mem_sort_order,
1676 default_top_sort_order, 2197 default_top_sort_order,
1677 default_diff_sort_order, 2198 default_diff_sort_order,
2199 default_tracepoint_sort_order,
1678 }; 2200 };
2201 bool use_trace = true;
2202 struct perf_evsel *evsel;
1679 2203
1680 BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders)); 2204 BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders));
1681 2205
2206 if (evlist == NULL)
2207 goto out_no_evlist;
2208
2209 evlist__for_each(evlist, evsel) {
2210 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
2211 use_trace = false;
2212 break;
2213 }
2214 }
2215
2216 if (use_trace) {
2217 sort__mode = SORT_MODE__TRACEPOINT;
2218 if (symbol_conf.raw_trace)
2219 return "trace_fields";
2220 }
2221out_no_evlist:
1682 return default_sort_orders[sort__mode]; 2222 return default_sort_orders[sort__mode];
1683} 2223}
1684 2224
1685static int setup_sort_order(void) 2225static int setup_sort_order(struct perf_evlist *evlist)
1686{ 2226{
1687 char *new_sort_order; 2227 char *new_sort_order;
1688 2228
@@ -1703,7 +2243,7 @@ static int setup_sort_order(void)
1703 * because it's checked over the rest of the code. 2243 * because it's checked over the rest of the code.
1704 */ 2244 */
1705 if (asprintf(&new_sort_order, "%s,%s", 2245 if (asprintf(&new_sort_order, "%s,%s",
1706 get_default_sort_order(), sort_order + 1) < 0) { 2246 get_default_sort_order(evlist), sort_order + 1) < 0) {
1707 error("Not enough memory to set up --sort"); 2247 error("Not enough memory to set up --sort");
1708 return -ENOMEM; 2248 return -ENOMEM;
1709 } 2249 }
@@ -1712,13 +2252,41 @@ static int setup_sort_order(void)
1712 return 0; 2252 return 0;
1713} 2253}
1714 2254
1715static int __setup_sorting(void) 2255/*
2256 * Adds 'pre,' prefix into 'str' is 'pre' is
2257 * not already part of 'str'.
2258 */
2259static char *prefix_if_not_in(const char *pre, char *str)
2260{
2261 char *n;
2262
2263 if (!str || strstr(str, pre))
2264 return str;
2265
2266 if (asprintf(&n, "%s,%s", pre, str) < 0)
2267 return NULL;
2268
2269 free(str);
2270 return n;
2271}
2272
2273static char *setup_overhead(char *keys)
2274{
2275 keys = prefix_if_not_in("overhead", keys);
2276
2277 if (symbol_conf.cumulate_callchain)
2278 keys = prefix_if_not_in("overhead_children", keys);
2279
2280 return keys;
2281}
2282
2283static int __setup_sorting(struct perf_evlist *evlist)
1716{ 2284{
1717 char *tmp, *tok, *str; 2285 char *tmp, *tok, *str;
1718 const char *sort_keys; 2286 const char *sort_keys;
1719 int ret = 0; 2287 int ret = 0;
1720 2288
1721 ret = setup_sort_order(); 2289 ret = setup_sort_order(evlist);
1722 if (ret) 2290 if (ret)
1723 return ret; 2291 return ret;
1724 2292
@@ -1732,7 +2300,7 @@ static int __setup_sorting(void)
1732 return 0; 2300 return 0;
1733 } 2301 }
1734 2302
1735 sort_keys = get_default_sort_order(); 2303 sort_keys = get_default_sort_order(evlist);
1736 } 2304 }
1737 2305
1738 str = strdup(sort_keys); 2306 str = strdup(sort_keys);
@@ -1741,9 +2309,20 @@ static int __setup_sorting(void)
1741 return -ENOMEM; 2309 return -ENOMEM;
1742 } 2310 }
1743 2311
2312 /*
2313 * Prepend overhead fields for backward compatibility.
2314 */
2315 if (!is_strict_order(field_order)) {
2316 str = setup_overhead(str);
2317 if (str == NULL) {
2318 error("Not enough memory to setup overhead keys");
2319 return -ENOMEM;
2320 }
2321 }
2322
1744 for (tok = strtok_r(str, ", ", &tmp); 2323 for (tok = strtok_r(str, ", ", &tmp);
1745 tok; tok = strtok_r(NULL, ", ", &tmp)) { 2324 tok; tok = strtok_r(NULL, ", ", &tmp)) {
1746 ret = sort_dimension__add(tok); 2325 ret = sort_dimension__add(tok, evlist);
1747 if (ret == -EINVAL) { 2326 if (ret == -EINVAL) {
1748 error("Invalid --sort key: `%s'", tok); 2327 error("Invalid --sort key: `%s'", tok);
1749 break; 2328 break;
@@ -1954,16 +2533,16 @@ out:
1954 return ret; 2533 return ret;
1955} 2534}
1956 2535
1957int setup_sorting(void) 2536int setup_sorting(struct perf_evlist *evlist)
1958{ 2537{
1959 int err; 2538 int err;
1960 2539
1961 err = __setup_sorting(); 2540 err = __setup_sorting(evlist);
1962 if (err < 0) 2541 if (err < 0)
1963 return err; 2542 return err;
1964 2543
1965 if (parent_pattern != default_parent_pattern) { 2544 if (parent_pattern != default_parent_pattern) {
1966 err = sort_dimension__add("parent"); 2545 err = sort_dimension__add("parent", evlist);
1967 if (err < 0) 2546 if (err < 0)
1968 return err; 2547 return err;
1969 } 2548 }
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 31228851e397..687bbb124428 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -18,7 +18,7 @@
18#include "debug.h" 18#include "debug.h"
19#include "header.h" 19#include "header.h"
20 20
21#include "parse-options.h" 21#include <subcmd/parse-options.h>
22#include "parse-events.h" 22#include "parse-events.h"
23#include "hist.h" 23#include "hist.h"
24#include "thread.h" 24#include "thread.h"
@@ -122,6 +122,9 @@ struct hist_entry {
122 struct branch_info *branch_info; 122 struct branch_info *branch_info;
123 struct hists *hists; 123 struct hists *hists;
124 struct mem_info *mem_info; 124 struct mem_info *mem_info;
125 void *raw_data;
126 u32 raw_size;
127 void *trace_output;
125 struct callchain_root callchain[0]; /* must be last member */ 128 struct callchain_root callchain[0]; /* must be last member */
126}; 129};
127 130
@@ -164,6 +167,7 @@ enum sort_mode {
164 SORT_MODE__MEMORY, 167 SORT_MODE__MEMORY,
165 SORT_MODE__TOP, 168 SORT_MODE__TOP,
166 SORT_MODE__DIFF, 169 SORT_MODE__DIFF,
170 SORT_MODE__TRACEPOINT,
167}; 171};
168 172
169enum sort_type { 173enum sort_type {
@@ -180,6 +184,7 @@ enum sort_type {
180 SORT_LOCAL_WEIGHT, 184 SORT_LOCAL_WEIGHT,
181 SORT_GLOBAL_WEIGHT, 185 SORT_GLOBAL_WEIGHT,
182 SORT_TRANSACTION, 186 SORT_TRANSACTION,
187 SORT_TRACE,
183 188
184 /* branch stack specific sort keys */ 189 /* branch stack specific sort keys */
185 __SORT_BRANCH_STACK, 190 __SORT_BRANCH_STACK,
@@ -209,8 +214,6 @@ enum sort_type {
209 */ 214 */
210 215
211struct sort_entry { 216struct sort_entry {
212 struct list_head list;
213
214 const char *se_header; 217 const char *se_header;
215 218
216 int64_t (*se_cmp)(struct hist_entry *, struct hist_entry *); 219 int64_t (*se_cmp)(struct hist_entry *, struct hist_entry *);
@@ -224,10 +227,11 @@ struct sort_entry {
224extern struct sort_entry sort_thread; 227extern struct sort_entry sort_thread;
225extern struct list_head hist_entry__sort_list; 228extern struct list_head hist_entry__sort_list;
226 229
227int setup_sorting(void); 230struct perf_evlist;
231struct pevent;
232int setup_sorting(struct perf_evlist *evlist);
228int setup_output_field(void); 233int setup_output_field(void);
229void reset_output_field(void); 234void reset_output_field(void);
230extern int sort_dimension__add(const char *);
231void sort__setup_elide(FILE *fp); 235void sort__setup_elide(FILE *fp);
232void perf_hpp__set_elide(int idx, bool elide); 236void perf_hpp__set_elide(int idx, bool elide);
233 237
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 2d9d8306dbd3..2f901d15e063 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -341,3 +341,65 @@ int perf_stat_process_counter(struct perf_stat_config *config,
341 341
342 return 0; 342 return 0;
343} 343}
344
345int perf_event__process_stat_event(struct perf_tool *tool __maybe_unused,
346 union perf_event *event,
347 struct perf_session *session)
348{
349 struct perf_counts_values count;
350 struct stat_event *st = &event->stat;
351 struct perf_evsel *counter;
352
353 count.val = st->val;
354 count.ena = st->ena;
355 count.run = st->run;
356
357 counter = perf_evlist__id2evsel(session->evlist, st->id);
358 if (!counter) {
359 pr_err("Failed to resolve counter for stat event.\n");
360 return -EINVAL;
361 }
362
363 *perf_counts(counter->counts, st->cpu, st->thread) = count;
364 counter->supported = true;
365 return 0;
366}
367
368size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp)
369{
370 struct stat_event *st = (struct stat_event *) event;
371 size_t ret;
372
373 ret = fprintf(fp, "\n... id %" PRIu64 ", cpu %d, thread %d\n",
374 st->id, st->cpu, st->thread);
375 ret += fprintf(fp, "... value %" PRIu64 ", enabled %" PRIu64 ", running %" PRIu64 "\n",
376 st->val, st->ena, st->run);
377
378 return ret;
379}
380
381size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp)
382{
383 struct stat_round_event *rd = (struct stat_round_event *)event;
384 size_t ret;
385
386 ret = fprintf(fp, "\n... time %" PRIu64 ", type %s\n", rd->time,
387 rd->type == PERF_STAT_ROUND_TYPE__FINAL ? "FINAL" : "INTERVAL");
388
389 return ret;
390}
391
392size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
393{
394 struct perf_stat_config sc;
395 size_t ret;
396
397 perf_event__read_stat_config(&sc, &event->stat_config);
398
399 ret = fprintf(fp, "\n");
400 ret += fprintf(fp, "... aggr_mode %d\n", sc.aggr_mode);
401 ret += fprintf(fp, "... scale %d\n", sc.scale);
402 ret += fprintf(fp, "... interval %u\n", sc.interval);
403
404 return ret;
405}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index da1d11c4f8c1..086f4e128d63 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -90,4 +90,14 @@ void perf_evlist__reset_stats(struct perf_evlist *evlist);
90 90
91int perf_stat_process_counter(struct perf_stat_config *config, 91int perf_stat_process_counter(struct perf_stat_config *config,
92 struct perf_evsel *counter); 92 struct perf_evsel *counter);
93struct perf_tool;
94union perf_event;
95struct perf_session;
96int perf_event__process_stat_event(struct perf_tool *tool,
97 union perf_event *event,
98 struct perf_session *session);
99
100size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp);
101size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp);
102size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp);
93#endif 103#endif
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index fc8781de62db..7f7e072be746 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -342,22 +342,6 @@ char *rtrim(char *s)
342 return s; 342 return s;
343} 343}
344 344
345/**
346 * memdup - duplicate region of memory
347 * @src: memory region to duplicate
348 * @len: memory region length
349 */
350void *memdup(const void *src, size_t len)
351{
352 void *p;
353
354 p = malloc(len);
355 if (p)
356 memcpy(p, src, len);
357
358 return p;
359}
360
361char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints) 345char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints)
362{ 346{
363 /* 347 /*
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 475d88d0a1c9..562b8ebeae5b 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -1026,8 +1026,8 @@ int dso__load_sym(struct dso *dso, struct map *map,
1026 curr_dso->long_name_len = dso->long_name_len; 1026 curr_dso->long_name_len = dso->long_name_len;
1027 curr_map = map__new2(start, curr_dso, 1027 curr_map = map__new2(start, curr_dso,
1028 map->type); 1028 map->type);
1029 dso__put(curr_dso);
1029 if (curr_map == NULL) { 1030 if (curr_map == NULL) {
1030 dso__put(curr_dso);
1031 goto out_elf_end; 1031 goto out_elf_end;
1032 } 1032 }
1033 if (adjust_kernel_syms) { 1033 if (adjust_kernel_syms) {
@@ -1042,7 +1042,14 @@ int dso__load_sym(struct dso *dso, struct map *map,
1042 } 1042 }
1043 curr_dso->symtab_type = dso->symtab_type; 1043 curr_dso->symtab_type = dso->symtab_type;
1044 map_groups__insert(kmaps, curr_map); 1044 map_groups__insert(kmaps, curr_map);
1045 /*
1046 * Add it before we drop the referece to curr_map,
1047 * i.e. while we still are sure to have a reference
1048 * to this DSO via curr_map->dso.
1049 */
1045 dsos__add(&map->groups->machine->dsos, curr_dso); 1050 dsos__add(&map->groups->machine->dsos, curr_dso);
1051 /* kmaps already got it */
1052 map__put(curr_map);
1046 dso__set_loaded(curr_dso, map->type); 1053 dso__set_loaded(curr_dso, map->type);
1047 } else 1054 } else
1048 curr_dso = curr_map->dso; 1055 curr_dso = curr_map->dso;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index cd08027a6d2c..3b2de6eb3376 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -39,6 +39,7 @@ struct symbol_conf symbol_conf = {
39 .cumulate_callchain = true, 39 .cumulate_callchain = true,
40 .show_hist_headers = true, 40 .show_hist_headers = true,
41 .symfs = "", 41 .symfs = "",
42 .event_group = true,
42}; 43};
43 44
44static enum dso_binary_type binary_type_symtab[] = { 45static enum dso_binary_type binary_type_symtab[] = {
@@ -1860,24 +1861,44 @@ static void vmlinux_path__exit(void)
1860 zfree(&vmlinux_path); 1861 zfree(&vmlinux_path);
1861} 1862}
1862 1863
1864static const char * const vmlinux_paths[] = {
1865 "vmlinux",
1866 "/boot/vmlinux"
1867};
1868
1869static const char * const vmlinux_paths_upd[] = {
1870 "/boot/vmlinux-%s",
1871 "/usr/lib/debug/boot/vmlinux-%s",
1872 "/lib/modules/%s/build/vmlinux",
1873 "/usr/lib/debug/lib/modules/%s/vmlinux",
1874 "/usr/lib/debug/boot/vmlinux-%s.debug"
1875};
1876
1877static int vmlinux_path__add(const char *new_entry)
1878{
1879 vmlinux_path[vmlinux_path__nr_entries] = strdup(new_entry);
1880 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1881 return -1;
1882 ++vmlinux_path__nr_entries;
1883
1884 return 0;
1885}
1886
1863static int vmlinux_path__init(struct perf_env *env) 1887static int vmlinux_path__init(struct perf_env *env)
1864{ 1888{
1865 struct utsname uts; 1889 struct utsname uts;
1866 char bf[PATH_MAX]; 1890 char bf[PATH_MAX];
1867 char *kernel_version; 1891 char *kernel_version;
1892 unsigned int i;
1868 1893
1869 vmlinux_path = malloc(sizeof(char *) * 6); 1894 vmlinux_path = malloc(sizeof(char *) * (ARRAY_SIZE(vmlinux_paths) +
1895 ARRAY_SIZE(vmlinux_paths_upd)));
1870 if (vmlinux_path == NULL) 1896 if (vmlinux_path == NULL)
1871 return -1; 1897 return -1;
1872 1898
1873 vmlinux_path[vmlinux_path__nr_entries] = strdup("vmlinux"); 1899 for (i = 0; i < ARRAY_SIZE(vmlinux_paths); i++)
1874 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1900 if (vmlinux_path__add(vmlinux_paths[i]) < 0)
1875 goto out_fail; 1901 goto out_fail;
1876 ++vmlinux_path__nr_entries;
1877 vmlinux_path[vmlinux_path__nr_entries] = strdup("/boot/vmlinux");
1878 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1879 goto out_fail;
1880 ++vmlinux_path__nr_entries;
1881 1902
1882 /* only try kernel version if no symfs was given */ 1903 /* only try kernel version if no symfs was given */
1883 if (symbol_conf.symfs[0] != 0) 1904 if (symbol_conf.symfs[0] != 0)
@@ -1892,28 +1913,11 @@ static int vmlinux_path__init(struct perf_env *env)
1892 kernel_version = uts.release; 1913 kernel_version = uts.release;
1893 } 1914 }
1894 1915
1895 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", kernel_version); 1916 for (i = 0; i < ARRAY_SIZE(vmlinux_paths_upd); i++) {
1896 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1917 snprintf(bf, sizeof(bf), vmlinux_paths_upd[i], kernel_version);
1897 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1918 if (vmlinux_path__add(bf) < 0)
1898 goto out_fail; 1919 goto out_fail;
1899 ++vmlinux_path__nr_entries; 1920 }
1900 snprintf(bf, sizeof(bf), "/usr/lib/debug/boot/vmlinux-%s",
1901 kernel_version);
1902 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1903 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1904 goto out_fail;
1905 ++vmlinux_path__nr_entries;
1906 snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", kernel_version);
1907 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1908 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1909 goto out_fail;
1910 ++vmlinux_path__nr_entries;
1911 snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux",
1912 kernel_version);
1913 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1914 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1915 goto out_fail;
1916 ++vmlinux_path__nr_entries;
1917 1921
1918 return 0; 1922 return 0;
1919 1923
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index dcd786e364f2..ccd1caa40e11 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -108,7 +108,9 @@ struct symbol_conf {
108 show_hist_headers, 108 show_hist_headers,
109 branch_callstack, 109 branch_callstack,
110 has_filter, 110 has_filter,
111 show_ref_callgraph; 111 show_ref_callgraph,
112 hide_unresolved,
113 raw_trace;
112 const char *vmlinux_name, 114 const char *vmlinux_name,
113 *kallsyms_name, 115 *kallsyms_name,
114 *source_prefix, 116 *source_prefix,
diff --git a/tools/perf/util/term.c b/tools/perf/util/term.c
new file mode 100644
index 000000000000..90b47d8aa19c
--- /dev/null
+++ b/tools/perf/util/term.c
@@ -0,0 +1,35 @@
1#include "util.h"
2
3void get_term_dimensions(struct winsize *ws)
4{
5 char *s = getenv("LINES");
6
7 if (s != NULL) {
8 ws->ws_row = atoi(s);
9 s = getenv("COLUMNS");
10 if (s != NULL) {
11 ws->ws_col = atoi(s);
12 if (ws->ws_row && ws->ws_col)
13 return;
14 }
15 }
16#ifdef TIOCGWINSZ
17 if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
18 ws->ws_row && ws->ws_col)
19 return;
20#endif
21 ws->ws_row = 25;
22 ws->ws_col = 80;
23}
24
25void set_term_quiet_input(struct termios *old)
26{
27 struct termios tc;
28
29 tcgetattr(0, old);
30 tc = *old;
31 tc.c_lflag &= ~(ICANON | ECHO);
32 tc.c_cc[VMIN] = 0;
33 tc.c_cc[VTIME] = 0;
34 tcsetattr(0, TCSANOW, &tc);
35}
diff --git a/tools/perf/util/term.h b/tools/perf/util/term.h
new file mode 100644
index 000000000000..2c06a61846a1
--- /dev/null
+++ b/tools/perf/util/term.h
@@ -0,0 +1,10 @@
1#ifndef __PERF_TERM_H
2#define __PERF_TERM_H
3
4struct termios;
5struct winsize;
6
7void get_term_dimensions(struct winsize *ws);
8void set_term_quiet_input(struct termios *old);
9
10#endif /* __PERF_TERM_H */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 0a9ae8014729..dfd00c6dad6e 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -19,8 +19,10 @@ int thread__init_map_groups(struct thread *thread, struct machine *machine)
19 thread->mg = map_groups__new(machine); 19 thread->mg = map_groups__new(machine);
20 } else { 20 } else {
21 leader = __machine__findnew_thread(machine, pid, pid); 21 leader = __machine__findnew_thread(machine, pid, pid);
22 if (leader) 22 if (leader) {
23 thread->mg = map_groups__get(leader->mg); 23 thread->mg = map_groups__get(leader->mg);
24 thread__put(leader);
25 }
24 } 26 }
25 27
26 return thread->mg ? 0 : -1; 28 return thread->mg ? 0 : -1;
@@ -53,7 +55,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
53 goto err_thread; 55 goto err_thread;
54 56
55 list_add(&comm->list, &thread->comm_list); 57 list_add(&comm->list, &thread->comm_list);
56 atomic_set(&thread->refcnt, 0); 58 atomic_set(&thread->refcnt, 1);
57 RB_CLEAR_NODE(&thread->rb_node); 59 RB_CLEAR_NODE(&thread->rb_node);
58 } 60 }
59 61
@@ -95,6 +97,10 @@ struct thread *thread__get(struct thread *thread)
95void thread__put(struct thread *thread) 97void thread__put(struct thread *thread)
96{ 98{
97 if (thread && atomic_dec_and_test(&thread->refcnt)) { 99 if (thread && atomic_dec_and_test(&thread->refcnt)) {
100 /*
101 * Remove it from the dead_threads list, as last reference
102 * is gone.
103 */
98 list_del_init(&thread->node); 104 list_del_init(&thread->node);
99 thread__delete(thread); 105 thread__delete(thread);
100 } 106 }
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 6ec3c5ca438f..08afc6909953 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -13,6 +13,7 @@
13#include "thread_map.h" 13#include "thread_map.h"
14#include "util.h" 14#include "util.h"
15#include "debug.h" 15#include "debug.h"
16#include "event.h"
16 17
17/* Skip "." and ".." directories */ 18/* Skip "." and ".." directories */
18static int filter(const struct dirent *dir) 19static int filter(const struct dirent *dir)
@@ -304,6 +305,7 @@ out:
304 305
305out_free_threads: 306out_free_threads:
306 zfree(&threads); 307 zfree(&threads);
308 strlist__delete(slist);
307 goto out; 309 goto out;
308} 310}
309 311
@@ -408,3 +410,29 @@ void thread_map__read_comms(struct thread_map *threads)
408 for (i = 0; i < threads->nr; ++i) 410 for (i = 0; i < threads->nr; ++i)
409 comm_init(threads, i); 411 comm_init(threads, i);
410} 412}
413
414static void thread_map__copy_event(struct thread_map *threads,
415 struct thread_map_event *event)
416{
417 unsigned i;
418
419 threads->nr = (int) event->nr;
420
421 for (i = 0; i < event->nr; i++) {
422 thread_map__set_pid(threads, i, (pid_t) event->entries[i].pid);
423 threads->map[i].comm = strndup(event->entries[i].comm, 16);
424 }
425
426 atomic_set(&threads->refcnt, 1);
427}
428
429struct thread_map *thread_map__new_event(struct thread_map_event *event)
430{
431 struct thread_map *threads;
432
433 threads = thread_map__alloc(event->nr);
434 if (threads)
435 thread_map__copy_event(threads, event);
436
437 return threads;
438}
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index af679d8a50f8..85e4c7c4fbde 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -16,11 +16,14 @@ struct thread_map {
16 struct thread_map_data map[]; 16 struct thread_map_data map[];
17}; 17};
18 18
19struct thread_map_event;
20
19struct thread_map *thread_map__new_dummy(void); 21struct thread_map *thread_map__new_dummy(void);
20struct thread_map *thread_map__new_by_pid(pid_t pid); 22struct thread_map *thread_map__new_by_pid(pid_t pid);
21struct thread_map *thread_map__new_by_tid(pid_t tid); 23struct thread_map *thread_map__new_by_tid(pid_t tid);
22struct thread_map *thread_map__new_by_uid(uid_t uid); 24struct thread_map *thread_map__new_by_uid(uid_t uid);
23struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid); 25struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid);
26struct thread_map *thread_map__new_event(struct thread_map_event *event);
24 27
25struct thread_map *thread_map__get(struct thread_map *map); 28struct thread_map *thread_map__get(struct thread_map *map);
26void thread_map__put(struct thread_map *map); 29void thread_map__put(struct thread_map *map);
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index cab8cc24831b..55de4cffcd4e 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -50,12 +50,18 @@ struct perf_tool {
50 throttle, 50 throttle,
51 unthrottle; 51 unthrottle;
52 event_attr_op attr; 52 event_attr_op attr;
53 event_attr_op event_update;
53 event_op2 tracing_data; 54 event_op2 tracing_data;
54 event_oe finished_round; 55 event_oe finished_round;
55 event_op2 build_id, 56 event_op2 build_id,
56 id_index, 57 id_index,
57 auxtrace_info, 58 auxtrace_info,
58 auxtrace_error; 59 auxtrace_error,
60 thread_map,
61 cpu_map,
62 stat_config,
63 stat,
64 stat_round;
59 event_op3 auxtrace; 65 event_op3 auxtrace;
60 bool ordered_events; 66 bool ordered_events;
61 bool ordering_requires_timestamps; 67 bool ordering_requires_timestamps;
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index b85ee55cca0c..bce5b1dac268 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -65,6 +65,7 @@ int tracing_data_put(struct tracing_data *tdata);
65struct addr_location; 65struct addr_location;
66 66
67struct perf_session; 67struct perf_session;
68struct perf_stat_config;
68 69
69struct scripting_ops { 70struct scripting_ops {
70 const char *name; 71 const char *name;
@@ -75,6 +76,9 @@ struct scripting_ops {
75 struct perf_sample *sample, 76 struct perf_sample *sample,
76 struct perf_evsel *evsel, 77 struct perf_evsel *evsel,
77 struct addr_location *al); 78 struct addr_location *al);
79 void (*process_stat)(struct perf_stat_config *config,
80 struct perf_evsel *evsel, u64 tstamp);
81 void (*process_stat_interval)(u64 tstamp);
78 int (*generate_script) (struct pevent *pevent, const char *outfile); 82 int (*generate_script) (struct pevent *pevent, const char *outfile);
79}; 83};
80 84
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index 2dcfe9a7c8d0..cf5e250bc78e 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -11,6 +11,7 @@
11#include <linux/types.h> 11#include <linux/types.h>
12#include "event.h" 12#include "event.h"
13#include "perf_regs.h" 13#include "perf_regs.h"
14#include "callchain.h"
14 15
15static char *debuginfo_path; 16static char *debuginfo_path;
16 17
@@ -52,25 +53,28 @@ static int report_module(u64 ip, struct unwind_info *ui)
52 return __report_module(&al, ip, ui); 53 return __report_module(&al, ip, ui);
53} 54}
54 55
56/*
57 * Store all entries within entries array,
58 * we will process it after we finish unwind.
59 */
55static int entry(u64 ip, struct unwind_info *ui) 60static int entry(u64 ip, struct unwind_info *ui)
56 61
57{ 62{
58 struct unwind_entry e; 63 struct unwind_entry *e = &ui->entries[ui->idx++];
59 struct addr_location al; 64 struct addr_location al;
60 65
61 if (__report_module(&al, ip, ui)) 66 if (__report_module(&al, ip, ui))
62 return -1; 67 return -1;
63 68
64 e.ip = ip; 69 e->ip = ip;
65 e.map = al.map; 70 e->map = al.map;
66 e.sym = al.sym; 71 e->sym = al.sym;
67 72
68 pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n", 73 pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
69 al.sym ? al.sym->name : "''", 74 al.sym ? al.sym->name : "''",
70 ip, 75 ip,
71 al.map ? al.map->map_ip(al.map, ip) : (u64) 0); 76 al.map ? al.map->map_ip(al.map, ip) : (u64) 0);
72 77 return 0;
73 return ui->cb(&e, ui->arg);
74} 78}
75 79
76static pid_t next_thread(Dwfl *dwfl, void *arg, void **thread_argp) 80static pid_t next_thread(Dwfl *dwfl, void *arg, void **thread_argp)
@@ -92,6 +96,16 @@ static int access_dso_mem(struct unwind_info *ui, Dwarf_Addr addr,
92 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER, 96 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
93 MAP__FUNCTION, addr, &al); 97 MAP__FUNCTION, addr, &al);
94 if (!al.map) { 98 if (!al.map) {
99 /*
100 * We've seen cases (softice) where DWARF unwinder went
101 * through non executable mmaps, which we need to lookup
102 * in MAP__VARIABLE tree.
103 */
104 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
105 MAP__VARIABLE, addr, &al);
106 }
107
108 if (!al.map) {
95 pr_debug("unwind: no map for %lx\n", (unsigned long)addr); 109 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
96 return -1; 110 return -1;
97 } 111 }
@@ -168,7 +182,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
168 struct perf_sample *data, 182 struct perf_sample *data,
169 int max_stack) 183 int max_stack)
170{ 184{
171 struct unwind_info ui = { 185 struct unwind_info *ui, ui_buf = {
172 .sample = data, 186 .sample = data,
173 .thread = thread, 187 .thread = thread,
174 .machine = thread->mg->machine, 188 .machine = thread->mg->machine,
@@ -177,35 +191,54 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
177 .max_stack = max_stack, 191 .max_stack = max_stack,
178 }; 192 };
179 Dwarf_Word ip; 193 Dwarf_Word ip;
180 int err = -EINVAL; 194 int err = -EINVAL, i;
181 195
182 if (!data->user_regs.regs) 196 if (!data->user_regs.regs)
183 return -EINVAL; 197 return -EINVAL;
184 198
185 ui.dwfl = dwfl_begin(&offline_callbacks); 199 ui = zalloc(sizeof(ui_buf) + sizeof(ui_buf.entries[0]) * max_stack);
186 if (!ui.dwfl) 200 if (!ui)
201 return -ENOMEM;
202
203 *ui = ui_buf;
204
205 ui->dwfl = dwfl_begin(&offline_callbacks);
206 if (!ui->dwfl)
187 goto out; 207 goto out;
188 208
189 err = perf_reg_value(&ip, &data->user_regs, PERF_REG_IP); 209 err = perf_reg_value(&ip, &data->user_regs, PERF_REG_IP);
190 if (err) 210 if (err)
191 goto out; 211 goto out;
192 212
193 err = report_module(ip, &ui); 213 err = report_module(ip, ui);
194 if (err) 214 if (err)
195 goto out; 215 goto out;
196 216
197 if (!dwfl_attach_state(ui.dwfl, EM_NONE, thread->tid, &callbacks, &ui)) 217 if (!dwfl_attach_state(ui->dwfl, EM_NONE, thread->tid, &callbacks, ui))
198 goto out; 218 goto out;
199 219
200 err = dwfl_getthread_frames(ui.dwfl, thread->tid, frame_callback, &ui); 220 err = dwfl_getthread_frames(ui->dwfl, thread->tid, frame_callback, ui);
201 221
202 if (err && !ui.max_stack) 222 if (err && !ui->max_stack)
203 err = 0; 223 err = 0;
204 224
225 /*
226 * Display what we got based on the order setup.
227 */
228 for (i = 0; i < ui->idx && !err; i++) {
229 int j = i;
230
231 if (callchain_param.order == ORDER_CALLER)
232 j = ui->idx - i - 1;
233
234 err = ui->entries[j].ip ? ui->cb(&ui->entries[j], ui->arg) : 0;
235 }
236
205 out: 237 out:
206 if (err) 238 if (err)
207 pr_debug("unwind: failed with '%s'\n", dwfl_errmsg(-1)); 239 pr_debug("unwind: failed with '%s'\n", dwfl_errmsg(-1));
208 240
209 dwfl_end(ui.dwfl); 241 dwfl_end(ui->dwfl);
242 free(ui);
210 return 0; 243 return 0;
211} 244}
diff --git a/tools/perf/util/unwind-libdw.h b/tools/perf/util/unwind-libdw.h
index 417a1426f3ad..58328669ed16 100644
--- a/tools/perf/util/unwind-libdw.h
+++ b/tools/perf/util/unwind-libdw.h
@@ -16,6 +16,8 @@ struct unwind_info {
16 unwind_entry_cb_t cb; 16 unwind_entry_cb_t cb;
17 void *arg; 17 void *arg;
18 int max_stack; 18 int max_stack;
19 int idx;
20 struct unwind_entry entries[];
19}; 21};
20 22
21#endif /* __PERF_UNWIND_LIBDW_H */ 23#endif /* __PERF_UNWIND_LIBDW_H */
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index c83832b555e5..ee7e372297e5 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -319,6 +319,15 @@ static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
319 319
320 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER, 320 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
321 MAP__FUNCTION, ip, &al); 321 MAP__FUNCTION, ip, &al);
322 if (!al.map) {
323 /*
324 * We've seen cases (softice) where DWARF unwinder went
325 * through non executable mmaps, which we need to lookup
326 * in MAP__VARIABLE tree.
327 */
328 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
329 MAP__VARIABLE, ip, &al);
330 }
322 return al.map; 331 return al.map;
323} 332}
324 333
@@ -416,20 +425,19 @@ get_proc_name(unw_addr_space_t __maybe_unused as,
416static int access_dso_mem(struct unwind_info *ui, unw_word_t addr, 425static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
417 unw_word_t *data) 426 unw_word_t *data)
418{ 427{
419 struct addr_location al; 428 struct map *map;
420 ssize_t size; 429 ssize_t size;
421 430
422 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER, 431 map = find_map(addr, ui);
423 MAP__FUNCTION, addr, &al); 432 if (!map) {
424 if (!al.map) {
425 pr_debug("unwind: no map for %lx\n", (unsigned long)addr); 433 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
426 return -1; 434 return -1;
427 } 435 }
428 436
429 if (!al.map->dso) 437 if (!map->dso)
430 return -1; 438 return -1;
431 439
432 size = dso__data_read_addr(al.map->dso, al.map, ui->machine, 440 size = dso__data_read_addr(map->dso, map, ui->machine,
433 addr, (u8 *) data, sizeof(*data)); 441 addr, (u8 *) data, sizeof(*data));
434 442
435 return !(size == sizeof(*data)); 443 return !(size == sizeof(*data));
@@ -614,23 +622,48 @@ void unwind__finish_access(struct thread *thread)
614static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, 622static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
615 void *arg, int max_stack) 623 void *arg, int max_stack)
616{ 624{
625 u64 val;
626 unw_word_t ips[max_stack];
617 unw_addr_space_t addr_space; 627 unw_addr_space_t addr_space;
618 unw_cursor_t c; 628 unw_cursor_t c;
619 int ret; 629 int ret, i = 0;
620
621 addr_space = thread__priv(ui->thread);
622 if (addr_space == NULL)
623 return -1;
624 630
625 ret = unw_init_remote(&c, addr_space, ui); 631 ret = perf_reg_value(&val, &ui->sample->user_regs, PERF_REG_IP);
626 if (ret) 632 if (ret)
627 display_error(ret); 633 return ret;
628 634
629 while (!ret && (unw_step(&c) > 0) && max_stack--) { 635 ips[i++] = (unw_word_t) val;
630 unw_word_t ip;
631 636
632 unw_get_reg(&c, UNW_REG_IP, &ip); 637 /*
633 ret = ip ? entry(ip, ui->thread, cb, arg) : 0; 638 * If we need more than one entry, do the DWARF
639 * unwind itself.
640 */
641 if (max_stack - 1 > 0) {
642 addr_space = thread__priv(ui->thread);
643 if (addr_space == NULL)
644 return -1;
645
646 ret = unw_init_remote(&c, addr_space, ui);
647 if (ret)
648 display_error(ret);
649
650 while (!ret && (unw_step(&c) > 0) && i < max_stack) {
651 unw_get_reg(&c, UNW_REG_IP, &ips[i]);
652 ++i;
653 }
654
655 max_stack = i;
656 }
657
658 /*
659 * Display what we got based on the order setup.
660 */
661 for (i = 0; i < max_stack && !ret; i++) {
662 int j = i;
663
664 if (callchain_param.order == ORDER_CALLER)
665 j = max_stack - i - 1;
666 ret = ips[j] ? entry(ips[j], ui->thread, cb, arg) : 0;
634 } 667 }
635 668
636 return ret; 669 return ret;
@@ -640,24 +673,17 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
640 struct thread *thread, 673 struct thread *thread,
641 struct perf_sample *data, int max_stack) 674 struct perf_sample *data, int max_stack)
642{ 675{
643 u64 ip;
644 struct unwind_info ui = { 676 struct unwind_info ui = {
645 .sample = data, 677 .sample = data,
646 .thread = thread, 678 .thread = thread,
647 .machine = thread->mg->machine, 679 .machine = thread->mg->machine,
648 }; 680 };
649 int ret;
650 681
651 if (!data->user_regs.regs) 682 if (!data->user_regs.regs)
652 return -EINVAL; 683 return -EINVAL;
653 684
654 ret = perf_reg_value(&ip, &data->user_regs, PERF_REG_IP); 685 if (max_stack <= 0)
655 if (ret) 686 return -EINVAL;
656 return ret;
657
658 ret = entry(ip, thread, cb, arg);
659 if (ret)
660 return -ENOMEM;
661 687
662 return --max_stack > 0 ? get_entries(&ui, cb, arg, max_stack) : 0; 688 return get_entries(&ui, cb, arg, max_stack);
663} 689}
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 47b1e36c7ea0..88b8f8d21f58 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -16,12 +16,15 @@
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <unistd.h> 17#include <unistd.h>
18#include "callchain.h" 18#include "callchain.h"
19#include "strlist.h"
20#include <subcmd/exec-cmd.h>
19 21
20struct callchain_param callchain_param = { 22struct callchain_param callchain_param = {
21 .mode = CHAIN_GRAPH_ABS, 23 .mode = CHAIN_GRAPH_ABS,
22 .min_percent = 0.5, 24 .min_percent = 0.5,
23 .order = ORDER_CALLEE, 25 .order = ORDER_CALLEE,
24 .key = CCKEY_FUNCTION 26 .key = CCKEY_FUNCTION,
27 .value = CCVAL_PERCENT,
25}; 28};
26 29
27/* 30/*
@@ -351,41 +354,8 @@ void sighandler_dump_stack(int sig)
351{ 354{
352 psignal(sig, "perf"); 355 psignal(sig, "perf");
353 dump_stack(); 356 dump_stack();
354 exit(sig); 357 signal(sig, SIG_DFL);
355} 358 raise(sig);
356
357void get_term_dimensions(struct winsize *ws)
358{
359 char *s = getenv("LINES");
360
361 if (s != NULL) {
362 ws->ws_row = atoi(s);
363 s = getenv("COLUMNS");
364 if (s != NULL) {
365 ws->ws_col = atoi(s);
366 if (ws->ws_row && ws->ws_col)
367 return;
368 }
369 }
370#ifdef TIOCGWINSZ
371 if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
372 ws->ws_row && ws->ws_col)
373 return;
374#endif
375 ws->ws_row = 25;
376 ws->ws_col = 80;
377}
378
379void set_term_quiet_input(struct termios *old)
380{
381 struct termios tc;
382
383 tcgetattr(0, old);
384 tc = *old;
385 tc.c_lflag &= ~(ICANON | ECHO);
386 tc.c_cc[VMIN] = 0;
387 tc.c_cc[VTIME] = 0;
388 tcsetattr(0, TCSANOW, &tc);
389} 359}
390 360
391int parse_nsec_time(const char *str, u64 *ptime) 361int parse_nsec_time(const char *str, u64 *ptime)
@@ -695,3 +665,28 @@ fetch_kernel_version(unsigned int *puint, char *str,
695 *puint = (version << 16) + (patchlevel << 8) + sublevel; 665 *puint = (version << 16) + (patchlevel << 8) + sublevel;
696 return 0; 666 return 0;
697} 667}
668
669const char *perf_tip(const char *dirpath)
670{
671 struct strlist *tips;
672 struct str_node *node;
673 char *tip = NULL;
674 struct strlist_config conf = {
675 .dirname = system_path(dirpath) ,
676 };
677
678 tips = strlist__new("tips.txt", &conf);
679 if (tips == NULL || strlist__nr_entries(tips) == 1) {
680 tip = (char *)"Cannot find tips.txt file";
681 goto out;
682 }
683
684 node = strlist__entry(tips, random() % strlist__nr_entries(tips));
685 if (asprintf(&tip, "Tip: %s", node->s) < 0)
686 tip = (char *)"Tip: get more memory! ;-)";
687
688out:
689 strlist__delete(tips);
690
691 return tip;
692}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index dcc659017976..fe915e616f9b 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -53,6 +53,7 @@
53#include <stdlib.h> 53#include <stdlib.h>
54#include <stdarg.h> 54#include <stdarg.h>
55#include <string.h> 55#include <string.h>
56#include <term.h>
56#include <errno.h> 57#include <errno.h>
57#include <limits.h> 58#include <limits.h>
58#include <sys/param.h> 59#include <sys/param.h>
@@ -150,12 +151,6 @@ extern void set_warning_routine(void (*routine)(const char *err, va_list params)
150extern int prefixcmp(const char *str, const char *prefix); 151extern int prefixcmp(const char *str, const char *prefix);
151extern void set_buildid_dir(const char *dir); 152extern void set_buildid_dir(const char *dir);
152 153
153static inline const char *skip_prefix(const char *str, const char *prefix)
154{
155 size_t len = strlen(prefix);
156 return strncmp(str, prefix, len) ? NULL : str + len;
157}
158
159#ifdef __GLIBC_PREREQ 154#ifdef __GLIBC_PREREQ
160#if __GLIBC_PREREQ(2, 1) 155#if __GLIBC_PREREQ(2, 1)
161#define HAVE_STRCHRNUL 156#define HAVE_STRCHRNUL
@@ -186,14 +181,6 @@ static inline void *zalloc(size_t size)
186 181
187#define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) 182#define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
188 183
189static inline int has_extension(const char *filename, const char *ext)
190{
191 size_t len = strlen(filename);
192 size_t extlen = strlen(ext);
193
194 return len > extlen && !memcmp(filename + len - extlen, ext, extlen);
195}
196
197/* Sane ctype - no locale, and works with signed chars */ 184/* Sane ctype - no locale, and works with signed chars */
198#undef isascii 185#undef isascii
199#undef isspace 186#undef isspace
@@ -282,9 +269,6 @@ void sighandler_dump_stack(int sig);
282extern unsigned int page_size; 269extern unsigned int page_size;
283extern int cacheline_size; 270extern int cacheline_size;
284 271
285void get_term_dimensions(struct winsize *ws);
286void set_term_quiet_input(struct termios *old);
287
288struct parse_tag { 272struct parse_tag {
289 char tag; 273 char tag;
290 int mult; 274 int mult;
@@ -358,4 +342,6 @@ int fetch_kernel_version(unsigned int *puint,
358#define KVER_FMT "%d.%d.%d" 342#define KVER_FMT "%d.%d.%d"
359#define KVER_PARAM(x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x) 343#define KVER_PARAM(x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x)
360 344
345const char *perf_tip(const char *dirpath);
346
361#endif /* GIT_COMPAT_UTIL_H */ 347#endif /* GIT_COMPAT_UTIL_H */