aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-06-22 18:19:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-22 18:19:21 -0400
commitc58267e9fa7b0345dd9006939254701e3622ca6a (patch)
tree9a96adabaa1c61ecbb9e5e8653d5085dad27ef07
parent1bf7067c6e173dc10411704db48338ed69c05565 (diff)
parenta9a3cd900fbbcbf837d65653105e7bfc583ced09 (diff)
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar: "Kernel side changes mostly consist of work on x86 PMU drivers: - x86 Intel PT (hardware CPU tracer) improvements (Alexander Shishkin) - x86 Intel CQM (cache quality monitoring) improvements (Thomas Gleixner) - x86 Intel PEBSv3 support (Peter Zijlstra) - x86 Intel PEBS interrupt batching support for lower overhead sampling (Zheng Yan, Kan Liang) - x86 PMU scheduler fixes and improvements (Peter Zijlstra) There's too many tooling improvements to list them all - here are a few select highlights: 'perf bench': - Introduce new 'perf bench futex' benchmark: 'wake-parallel', to measure parallel waker threads generating contention for kernel locks (hb->lock). (Davidlohr Bueso) 'perf top', 'perf report': - Allow disabling/enabling events dynamicaly in 'perf top': a 'perf top' session can instantly become a 'perf report' one, i.e. going from dynamic analysis to a static one, returning to a dynamic one is possible, to toogle the modes, just press 'f' to 'freeze/unfreeze' the sampling. (Arnaldo Carvalho de Melo) - Make Ctrl-C stop processing on TUI, allowing interrupting the load of big perf.data files (Namhyung Kim) 'perf probe': (Masami Hiramatsu) - Support glob wildcards for function name - Support $params special probe argument: Collect all function arguments - Make --line checks validate C-style function name. - Add --no-inlines option to avoid searching inline functions - Greatly speed up 'perf probe --list' by caching debuginfo. - Improve --filter support for 'perf probe', allowing using its arguments on other commands, as --add, --del, etc. 'perf sched': - Add option in 'perf sched' to merge like comms to lat output (Josef Bacik) Plus tons of infrastructure work - in particular preparation for upcoming threaded perf report support, but also lots of other work - and fixes and other improvements. See (much) more details in the shortlog and in the git log" * 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (305 commits) perf tools: Configurable per thread proc map processing time out perf tools: Add time out to force stop proc map processing perf report: Fix sort__sym_cmp to also compare end of symbol perf hists browser: React to unassigned hotkey pressing perf top: Tell the user how to unfreeze events after pressing 'f' perf hists browser: Honour the help line provided by builtin-{top,report}.c perf hists browser: Do not exit when 'f' is pressed in 'report' mode perf top: Replace CTRL+z with 'f' as hotkey for enable/disable events perf annotate: Rename source_line_percent to source_line_samples perf annotate: Display total number of samples with --show-total-period perf tools: Ensure thread-stack is flushed perf top: Allow disabling/enabling events dynamicly perf evlist: Add toggle_enable() method perf trace: Fix race condition at the end of started workloads perf probe: Speed up perf probe --list by caching debuginfo perf probe: Show usage even if the last event is skipped perf tools: Move libtraceevent dynamic list to separated LDFLAGS variable perf tools: Fix a problem when opening old perf.data with different byte order perf tools: Ignore .config-detected in .gitignore perf probe: Fix to return error if no probe is added ...
-rw-r--r--MAINTAINERS1
-rw-r--r--Makefile5
-rw-r--r--arch/x86/kernel/cpu/perf_event.c20
-rw-r--r--arch/x86/kernel/cpu/perf_event.h21
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c224
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_cqm.c108
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_ds.c317
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_lbr.c13
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_pt.c38
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore.c3
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore.h1
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore_snb.c20
-rw-r--r--include/linux/perf_event.h42
-rw-r--r--include/linux/sched.h7
-rw-r--r--include/uapi/linux/perf_event.h18
-rw-r--r--init/Kconfig2
-rw-r--r--kernel/events/core.c39
-rw-r--r--kernel/events/internal.h9
-rw-r--r--kernel/sched/core.c2
-rw-r--r--tools/Makefile20
-rw-r--r--tools/arch/alpha/include/asm/barrier.h8
-rw-r--r--tools/arch/arm/include/asm/barrier.h12
-rw-r--r--tools/arch/arm64/include/asm/barrier.h16
-rw-r--r--tools/arch/ia64/include/asm/barrier.h48
-rw-r--r--tools/arch/mips/include/asm/barrier.h20
-rw-r--r--tools/arch/powerpc/include/asm/barrier.h29
-rw-r--r--tools/arch/s390/include/asm/barrier.h30
-rw-r--r--tools/arch/sh/include/asm/barrier.h32
-rw-r--r--tools/arch/sparc/include/asm/barrier.h8
-rw-r--r--tools/arch/sparc/include/asm/barrier_32.h6
-rw-r--r--tools/arch/sparc/include/asm/barrier_64.h42
-rw-r--r--tools/arch/tile/include/asm/barrier.h15
-rw-r--r--tools/arch/x86/include/asm/atomic.h65
-rw-r--r--tools/arch/x86/include/asm/barrier.h28
-rw-r--r--tools/arch/x86/include/asm/rmwcc.h41
-rw-r--r--tools/arch/xtensa/include/asm/barrier.h18
-rw-r--r--tools/build/Makefile.build2
-rw-r--r--tools/build/Makefile.feature4
-rw-r--r--tools/build/tests/ex/Build1
-rw-r--r--tools/build/tests/ex/empty2/README2
-rw-r--r--tools/include/asm-generic/atomic-gcc.h63
-rw-r--r--tools/include/asm-generic/barrier.h44
-rw-r--r--tools/include/asm/atomic.h10
-rw-r--r--tools/include/asm/barrier.h27
-rw-r--r--tools/include/linux/atomic.h6
-rw-r--r--tools/include/linux/compiler.h4
-rw-r--r--tools/include/linux/kernel.h (renamed from tools/perf/util/include/linux/kernel.h)4
-rw-r--r--tools/include/linux/list.h (renamed from tools/perf/util/include/linux/list.h)6
-rw-r--r--tools/include/linux/poison.h1
-rw-r--r--tools/include/linux/types.h8
-rw-r--r--tools/lib/traceevent/.gitignore1
-rw-r--r--tools/lib/traceevent/Makefile34
-rw-r--r--tools/lib/traceevent/event-parse.c6
-rw-r--r--tools/lib/traceevent/event-parse.h1
-rw-r--r--tools/lib/traceevent/plugin_cfg80211.c13
-rw-r--r--tools/perf/.gitignore1
-rw-r--r--tools/perf/Documentation/callchain-overhead-calculation.txt108
-rw-r--r--tools/perf/Documentation/perf-bench.txt3
-rw-r--r--tools/perf/Documentation/perf-inject.txt27
-rw-r--r--tools/perf/Documentation/perf-kmem.txt11
-rw-r--r--tools/perf/Documentation/perf-kvm.txt6
-rw-r--r--tools/perf/Documentation/perf-probe.txt17
-rw-r--r--tools/perf/Documentation/perf-record.txt27
-rw-r--r--tools/perf/Documentation/perf-report.txt35
-rw-r--r--tools/perf/Documentation/perf-script.txt37
-rw-r--r--tools/perf/Documentation/perf-top.txt9
-rw-r--r--tools/perf/Documentation/perf-trace.txt7
-rw-r--r--tools/perf/MANIFEST26
-rw-r--r--tools/perf/Makefile.perf30
-rw-r--r--tools/perf/arch/arm64/Build1
-rw-r--r--tools/perf/arch/arm64/include/perf_regs.h3
-rw-r--r--tools/perf/arch/arm64/tests/Build2
-rw-r--r--tools/perf/arch/arm64/tests/dwarf-unwind.c61
-rw-r--r--tools/perf/arch/arm64/tests/regs_load.S46
-rw-r--r--tools/perf/arch/common.c2
-rw-r--r--tools/perf/arch/powerpc/util/Build1
-rw-r--r--tools/perf/arch/powerpc/util/sym-handling.c82
-rw-r--r--tools/perf/bench/Build1
-rw-r--r--tools/perf/bench/bench.h2
-rw-r--r--tools/perf/bench/futex-wake-parallel.c294
-rw-r--r--tools/perf/bench/futex-wake.c7
-rw-r--r--tools/perf/bench/numa.c33
-rw-r--r--tools/perf/builtin-annotate.c19
-rw-r--r--tools/perf/builtin-bench.c1
-rw-r--r--tools/perf/builtin-buildid-list.c9
-rw-r--r--tools/perf/builtin-diff.c9
-rw-r--r--tools/perf/builtin-inject.c175
-rw-r--r--tools/perf/builtin-kmem.c988
-rw-r--r--tools/perf/builtin-kvm.c11
-rw-r--r--tools/perf/builtin-lock.c8
-rw-r--r--tools/perf/builtin-mem.c5
-rw-r--r--tools/perf/builtin-probe.c195
-rw-r--r--tools/perf/builtin-record.c382
-rw-r--r--tools/perf/builtin-report.c47
-rw-r--r--tools/perf/builtin-sched.c159
-rw-r--r--tools/perf/builtin-script.c94
-rw-r--r--tools/perf/builtin-stat.c490
-rw-r--r--tools/perf/builtin-timechart.c9
-rw-r--r--tools/perf/builtin-top.c72
-rw-r--r--tools/perf/builtin-trace.c139
-rw-r--r--tools/perf/config/Makefile13
-rw-r--r--tools/perf/config/utilities.mak19
-rw-r--r--tools/perf/perf-sys.h73
-rw-r--r--tools/perf/perf.h6
-rw-r--r--tools/perf/tests/Build8
-rw-r--r--tools/perf/tests/builtin-test.c16
-rw-r--r--tools/perf/tests/code-reading.c26
-rw-r--r--tools/perf/tests/dso-data.c15
-rw-r--r--tools/perf/tests/dwarf-unwind.c3
-rw-r--r--tools/perf/tests/evsel-roundtrip-name.c4
-rw-r--r--tools/perf/tests/hists_common.c10
-rw-r--r--tools/perf/tests/hists_cumulate.c10
-rw-r--r--tools/perf/tests/hists_filter.c12
-rw-r--r--tools/perf/tests/hists_link.c12
-rw-r--r--tools/perf/tests/hists_output.c10
-rw-r--r--tools/perf/tests/keep-tracking.c4
-rw-r--r--tools/perf/tests/kmod-path.c72
-rw-r--r--tools/perf/tests/make18
-rw-r--r--tools/perf/tests/mmap-basic.c6
-rw-r--r--tools/perf/tests/mmap-thread-lookup.c6
-rw-r--r--tools/perf/tests/openat-syscall-all-cpus.c (renamed from tools/perf/tests/open-syscall-all-cpus.c)13
-rw-r--r--tools/perf/tests/openat-syscall-tp-fields.c (renamed from tools/perf/tests/open-syscall-tp-fields.c)6
-rw-r--r--tools/perf/tests/openat-syscall.c (renamed from tools/perf/tests/open-syscall.c)14
-rw-r--r--tools/perf/tests/parse-events.c14
-rw-r--r--tools/perf/tests/perf-time-to-tsc.c2
-rw-r--r--tools/perf/tests/pmu.c3
-rw-r--r--tools/perf/tests/switch-tracking.c8
-rw-r--r--tools/perf/tests/tests.h17
-rw-r--r--tools/perf/tests/thread-mg-share.c41
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c34
-rw-r--r--tools/perf/ui/browsers/annotate.c64
-rw-r--r--tools/perf/ui/browsers/hists.c646
-rw-r--r--tools/perf/ui/tui/setup.c2
-rw-r--r--tools/perf/util/Build13
-rw-r--r--tools/perf/util/annotate.c73
-rw-r--r--tools/perf/util/annotate.h7
-rw-r--r--tools/perf/util/auxtrace.c1352
-rw-r--r--tools/perf/util/auxtrace.h643
-rw-r--r--tools/perf/util/build-id.c64
-rw-r--r--tools/perf/util/cache.h1
-rw-r--r--tools/perf/util/callchain.h4
-rw-r--r--tools/perf/util/cgroup.c10
-rw-r--r--tools/perf/util/cgroup.h4
-rw-r--r--tools/perf/util/comm.c13
-rw-r--r--tools/perf/util/data-convert-bt.c410
-rw-r--r--tools/perf/util/db-export.c31
-rw-r--r--tools/perf/util/dso.c334
-rw-r--r--tools/perf/util/dso.h47
-rw-r--r--tools/perf/util/dwarf-aux.c220
-rw-r--r--tools/perf/util/dwarf-aux.h13
-rw-r--r--tools/perf/util/environment.c1
-rw-r--r--tools/perf/util/event.c119
-rw-r--r--tools/perf/util/event.h99
-rw-r--r--tools/perf/util/evlist.c103
-rw-r--r--tools/perf/util/evlist.h13
-rw-r--r--tools/perf/util/evsel.c26
-rw-r--r--tools/perf/util/evsel.h7
-rw-r--r--tools/perf/util/header.c52
-rw-r--r--tools/perf/util/header.h1
-rw-r--r--tools/perf/util/hist.c63
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/include/linux/poison.h1
-rw-r--r--tools/perf/util/include/linux/rbtree.h14
-rw-r--r--tools/perf/util/machine.c281
-rw-r--r--tools/perf/util/machine.h32
-rw-r--r--tools/perf/util/map.c267
-rw-r--r--tools/perf/util/map.h52
-rw-r--r--tools/perf/util/pager.c5
-rw-r--r--tools/perf/util/parse-branch-options.c94
-rw-r--r--tools/perf/util/parse-branch-options.h5
-rw-r--r--tools/perf/util/parse-events.c196
-rw-r--r--tools/perf/util/parse-events.h42
-rw-r--r--tools/perf/util/parse-events.l41
-rw-r--r--tools/perf/util/parse-events.y50
-rw-r--r--tools/perf/util/parse-options.h4
-rw-r--r--tools/perf/util/pmu.c72
-rw-r--r--tools/perf/util/pmu.h6
-rw-r--r--tools/perf/util/probe-event.c662
-rw-r--r--tools/perf/util/probe-event.h26
-rw-r--r--tools/perf/util/probe-finder.c165
-rw-r--r--tools/perf/util/probe-finder.h10
-rw-r--r--tools/perf/util/pstack.c7
-rw-r--r--tools/perf/util/pstack.h1
-rw-r--r--tools/perf/util/python-ext-sources1
-rw-r--r--tools/perf/util/record.c15
-rw-r--r--tools/perf/util/session.c288
-rw-r--r--tools/perf/util/session.h6
-rw-r--r--tools/perf/util/sort.c12
-rw-r--r--tools/perf/util/sort.h38
-rw-r--r--tools/perf/util/stat-shadow.c434
-rw-r--r--tools/perf/util/stat.c71
-rw-r--r--tools/perf/util/stat.h46
-rw-r--r--tools/perf/util/strfilter.c107
-rw-r--r--tools/perf/util/strfilter.h35
-rw-r--r--tools/perf/util/symbol-elf.c23
-rw-r--r--tools/perf/util/symbol.c117
-rw-r--r--tools/perf/util/symbol.h12
-rw-r--r--tools/perf/util/thread-stack.c18
-rw-r--r--tools/perf/util/thread-stack.h1
-rw-r--r--tools/perf/util/thread.c12
-rw-r--r--tools/perf/util/thread.h5
-rw-r--r--tools/perf/util/thread_map.c24
-rw-r--r--tools/perf/util/tool.h13
-rw-r--r--tools/perf/util/trace-event-parse.c2
-rw-r--r--tools/perf/util/unwind-libunwind.c11
-rw-r--r--tools/perf/util/util.c121
-rw-r--r--tools/perf/util/util.h6
-rw-r--r--tools/perf/util/vdso.c60
-rw-r--r--tools/perf/util/vdso.h4
-rw-r--r--tools/perf/util/xyarray.c8
-rw-r--r--tools/perf/util/xyarray.h2
211 files changed, 10821 insertions, 2891 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index d8afd2953678..4303a642a2e5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7634,7 +7634,6 @@ F: kernel/delayacct.c
7634 7634
7635PERFORMANCE EVENTS SUBSYSTEM 7635PERFORMANCE EVENTS SUBSYSTEM
7636M: Peter Zijlstra <a.p.zijlstra@chello.nl> 7636M: Peter Zijlstra <a.p.zijlstra@chello.nl>
7637M: Paul Mackerras <paulus@samba.org>
7638M: Ingo Molnar <mingo@redhat.com> 7637M: Ingo Molnar <mingo@redhat.com>
7639M: Arnaldo Carvalho de Melo <acme@kernel.org> 7638M: Arnaldo Carvalho de Melo <acme@kernel.org>
7640L: linux-kernel@vger.kernel.org 7639L: linux-kernel@vger.kernel.org
diff --git a/Makefile b/Makefile
index f5c8983aeeb7..6c6f14628f32 100644
--- a/Makefile
+++ b/Makefile
@@ -215,7 +215,6 @@ VPATH := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))
215 215
216export srctree objtree VPATH 216export srctree objtree VPATH
217 217
218
219# SUBARCH tells the usermode build what the underlying arch is. That is set 218# SUBARCH tells the usermode build what the underlying arch is. That is set
220# first, and if a usermode build is happening, the "ARCH=um" on the command 219# first, and if a usermode build is happening, the "ARCH=um" on the command
221# line overrides the setting of ARCH below. If a native build is happening, 220# line overrides the setting of ARCH below. If a native build is happening,
@@ -1497,11 +1496,11 @@ image_name:
1497# Clear a bunch of variables before executing the submake 1496# Clear a bunch of variables before executing the submake
1498tools/: FORCE 1497tools/: FORCE
1499 $(Q)mkdir -p $(objtree)/tools 1498 $(Q)mkdir -p $(objtree)/tools
1500 $(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(objtree) subdir=tools -C $(src)/tools/ 1499 $(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(O) subdir=tools -C $(src)/tools/
1501 1500
1502tools/%: FORCE 1501tools/%: FORCE
1503 $(Q)mkdir -p $(objtree)/tools 1502 $(Q)mkdir -p $(objtree)/tools
1504 $(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(objtree) subdir=tools -C $(src)/tools/ $* 1503 $(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(O) subdir=tools -C $(src)/tools/ $*
1505 1504
1506# Single targets 1505# Single targets
1507# --------------------------------------------------------------------------- 1506# ---------------------------------------------------------------------------
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 4f7001f28936..9560d0fc6fa6 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -881,10 +881,7 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
881 if (x86_pmu.commit_scheduling) 881 if (x86_pmu.commit_scheduling)
882 x86_pmu.commit_scheduling(cpuc, i, assign[i]); 882 x86_pmu.commit_scheduling(cpuc, i, assign[i]);
883 } 883 }
884 } 884 } else {
885
886 if (!assign || unsched) {
887
888 for (i = 0; i < n; i++) { 885 for (i = 0; i < n; i++) {
889 e = cpuc->event_list[i]; 886 e = cpuc->event_list[i];
890 /* 887 /*
@@ -1097,13 +1094,16 @@ int x86_perf_event_set_period(struct perf_event *event)
1097 1094
1098 per_cpu(pmc_prev_left[idx], smp_processor_id()) = left; 1095 per_cpu(pmc_prev_left[idx], smp_processor_id()) = left;
1099 1096
1100 /* 1097 if (!(hwc->flags & PERF_X86_EVENT_AUTO_RELOAD) ||
1101 * The hw event starts counting from this event offset, 1098 local64_read(&hwc->prev_count) != (u64)-left) {
1102 * mark it to be able to extra future deltas: 1099 /*
1103 */ 1100 * The hw event starts counting from this event offset,
1104 local64_set(&hwc->prev_count, (u64)-left); 1101 * mark it to be able to extra future deltas:
1102 */
1103 local64_set(&hwc->prev_count, (u64)-left);
1105 1104
1106 wrmsrl(hwc->event_base, (u64)(-left) & x86_pmu.cntval_mask); 1105 wrmsrl(hwc->event_base, (u64)(-left) & x86_pmu.cntval_mask);
1106 }
1107 1107
1108 /* 1108 /*
1109 * Due to erratum on certan cpu we need 1109 * Due to erratum on certan cpu we need
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index ef78516850fb..74089bcb6d74 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -75,6 +75,8 @@ struct event_constraint {
75#define PERF_X86_EVENT_DYNAMIC 0x0080 /* dynamic alloc'd constraint */ 75#define PERF_X86_EVENT_DYNAMIC 0x0080 /* dynamic alloc'd constraint */
76#define PERF_X86_EVENT_RDPMC_ALLOWED 0x0100 /* grant rdpmc permission */ 76#define PERF_X86_EVENT_RDPMC_ALLOWED 0x0100 /* grant rdpmc permission */
77#define PERF_X86_EVENT_EXCL_ACCT 0x0200 /* accounted EXCL event */ 77#define PERF_X86_EVENT_EXCL_ACCT 0x0200 /* accounted EXCL event */
78#define PERF_X86_EVENT_AUTO_RELOAD 0x0400 /* use PEBS auto-reload */
79#define PERF_X86_EVENT_FREERUNNING 0x0800 /* use freerunning PEBS */
78 80
79 81
80struct amd_nb { 82struct amd_nb {
@@ -88,6 +90,18 @@ struct amd_nb {
88#define MAX_PEBS_EVENTS 8 90#define MAX_PEBS_EVENTS 8
89 91
90/* 92/*
93 * Flags PEBS can handle without an PMI.
94 *
95 * TID can only be handled by flushing at context switch.
96 *
97 */
98#define PEBS_FREERUNNING_FLAGS \
99 (PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_ADDR | \
100 PERF_SAMPLE_ID | PERF_SAMPLE_CPU | PERF_SAMPLE_STREAM_ID | \
101 PERF_SAMPLE_DATA_SRC | PERF_SAMPLE_IDENTIFIER | \
102 PERF_SAMPLE_TRANSACTION)
103
104/*
91 * A debug store configuration. 105 * A debug store configuration.
92 * 106 *
93 * We only support architectures that use 64bit fields. 107 * We only support architectures that use 64bit fields.
@@ -133,7 +147,6 @@ enum intel_excl_state_type {
133}; 147};
134 148
135struct intel_excl_states { 149struct intel_excl_states {
136 enum intel_excl_state_type init_state[X86_PMC_IDX_MAX];
137 enum intel_excl_state_type state[X86_PMC_IDX_MAX]; 150 enum intel_excl_state_type state[X86_PMC_IDX_MAX];
138 bool sched_started; /* true if scheduling has started */ 151 bool sched_started; /* true if scheduling has started */
139}; 152};
@@ -527,10 +540,10 @@ struct x86_pmu {
527 void (*put_event_constraints)(struct cpu_hw_events *cpuc, 540 void (*put_event_constraints)(struct cpu_hw_events *cpuc,
528 struct perf_event *event); 541 struct perf_event *event);
529 542
530 void (*commit_scheduling)(struct cpu_hw_events *cpuc, int idx, int cntr);
531
532 void (*start_scheduling)(struct cpu_hw_events *cpuc); 543 void (*start_scheduling)(struct cpu_hw_events *cpuc);
533 544
545 void (*commit_scheduling)(struct cpu_hw_events *cpuc, int idx, int cntr);
546
534 void (*stop_scheduling)(struct cpu_hw_events *cpuc); 547 void (*stop_scheduling)(struct cpu_hw_events *cpuc);
535 548
536 struct event_constraint *event_constraints; 549 struct event_constraint *event_constraints;
@@ -866,6 +879,8 @@ void intel_pmu_pebs_enable_all(void);
866 879
867void intel_pmu_pebs_disable_all(void); 880void intel_pmu_pebs_disable_all(void);
868 881
882void intel_pmu_pebs_sched_task(struct perf_event_context *ctx, bool sched_in);
883
869void intel_ds_init(void); 884void intel_ds_init(void);
870 885
871void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in); 886void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in);
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index a1e35c9f06b9..d455e2a61287 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -1903,9 +1903,8 @@ static void
1903intel_start_scheduling(struct cpu_hw_events *cpuc) 1903intel_start_scheduling(struct cpu_hw_events *cpuc)
1904{ 1904{
1905 struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs; 1905 struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
1906 struct intel_excl_states *xl, *xlo; 1906 struct intel_excl_states *xl;
1907 int tid = cpuc->excl_thread_id; 1907 int tid = cpuc->excl_thread_id;
1908 int o_tid = 1 - tid; /* sibling thread */
1909 1908
1910 /* 1909 /*
1911 * nothing needed if in group validation mode 1910 * nothing needed if in group validation mode
@@ -1916,10 +1915,9 @@ intel_start_scheduling(struct cpu_hw_events *cpuc)
1916 /* 1915 /*
1917 * no exclusion needed 1916 * no exclusion needed
1918 */ 1917 */
1919 if (!excl_cntrs) 1918 if (WARN_ON_ONCE(!excl_cntrs))
1920 return; 1919 return;
1921 1920
1922 xlo = &excl_cntrs->states[o_tid];
1923 xl = &excl_cntrs->states[tid]; 1921 xl = &excl_cntrs->states[tid];
1924 1922
1925 xl->sched_started = true; 1923 xl->sched_started = true;
@@ -1928,22 +1926,41 @@ intel_start_scheduling(struct cpu_hw_events *cpuc)
1928 * in stop_event_scheduling() 1926 * in stop_event_scheduling()
1929 * makes scheduling appear as a transaction 1927 * makes scheduling appear as a transaction
1930 */ 1928 */
1931 WARN_ON_ONCE(!irqs_disabled());
1932 raw_spin_lock(&excl_cntrs->lock); 1929 raw_spin_lock(&excl_cntrs->lock);
1930}
1933 1931
1934 /* 1932static void intel_commit_scheduling(struct cpu_hw_events *cpuc, int idx, int cntr)
1935 * save initial state of sibling thread 1933{
1936 */ 1934 struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
1937 memcpy(xlo->init_state, xlo->state, sizeof(xlo->init_state)); 1935 struct event_constraint *c = cpuc->event_constraint[idx];
1936 struct intel_excl_states *xl;
1937 int tid = cpuc->excl_thread_id;
1938
1939 if (cpuc->is_fake || !is_ht_workaround_enabled())
1940 return;
1941
1942 if (WARN_ON_ONCE(!excl_cntrs))
1943 return;
1944
1945 if (!(c->flags & PERF_X86_EVENT_DYNAMIC))
1946 return;
1947
1948 xl = &excl_cntrs->states[tid];
1949
1950 lockdep_assert_held(&excl_cntrs->lock);
1951
1952 if (c->flags & PERF_X86_EVENT_EXCL)
1953 xl->state[cntr] = INTEL_EXCL_EXCLUSIVE;
1954 else
1955 xl->state[cntr] = INTEL_EXCL_SHARED;
1938} 1956}
1939 1957
1940static void 1958static void
1941intel_stop_scheduling(struct cpu_hw_events *cpuc) 1959intel_stop_scheduling(struct cpu_hw_events *cpuc)
1942{ 1960{
1943 struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs; 1961 struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
1944 struct intel_excl_states *xl, *xlo; 1962 struct intel_excl_states *xl;
1945 int tid = cpuc->excl_thread_id; 1963 int tid = cpuc->excl_thread_id;
1946 int o_tid = 1 - tid; /* sibling thread */
1947 1964
1948 /* 1965 /*
1949 * nothing needed if in group validation mode 1966 * nothing needed if in group validation mode
@@ -1953,17 +1970,11 @@ intel_stop_scheduling(struct cpu_hw_events *cpuc)
1953 /* 1970 /*
1954 * no exclusion needed 1971 * no exclusion needed
1955 */ 1972 */
1956 if (!excl_cntrs) 1973 if (WARN_ON_ONCE(!excl_cntrs))
1957 return; 1974 return;
1958 1975
1959 xlo = &excl_cntrs->states[o_tid];
1960 xl = &excl_cntrs->states[tid]; 1976 xl = &excl_cntrs->states[tid];
1961 1977
1962 /*
1963 * make new sibling thread state visible
1964 */
1965 memcpy(xlo->state, xlo->init_state, sizeof(xlo->state));
1966
1967 xl->sched_started = false; 1978 xl->sched_started = false;
1968 /* 1979 /*
1969 * release shared state lock (acquired in intel_start_scheduling()) 1980 * release shared state lock (acquired in intel_start_scheduling())
@@ -1975,12 +1986,10 @@ static struct event_constraint *
1975intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event, 1986intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
1976 int idx, struct event_constraint *c) 1987 int idx, struct event_constraint *c)
1977{ 1988{
1978 struct event_constraint *cx;
1979 struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs; 1989 struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
1980 struct intel_excl_states *xl, *xlo; 1990 struct intel_excl_states *xlo;
1981 int is_excl, i;
1982 int tid = cpuc->excl_thread_id; 1991 int tid = cpuc->excl_thread_id;
1983 int o_tid = 1 - tid; /* alternate */ 1992 int is_excl, i;
1984 1993
1985 /* 1994 /*
1986 * validating a group does not require 1995 * validating a group does not require
@@ -1992,27 +2001,8 @@ intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
1992 /* 2001 /*
1993 * no exclusion needed 2002 * no exclusion needed
1994 */ 2003 */
1995 if (!excl_cntrs) 2004 if (WARN_ON_ONCE(!excl_cntrs))
1996 return c; 2005 return c;
1997 /*
1998 * event requires exclusive counter access
1999 * across HT threads
2000 */
2001 is_excl = c->flags & PERF_X86_EVENT_EXCL;
2002 if (is_excl && !(event->hw.flags & PERF_X86_EVENT_EXCL_ACCT)) {
2003 event->hw.flags |= PERF_X86_EVENT_EXCL_ACCT;
2004 if (!cpuc->n_excl++)
2005 WRITE_ONCE(excl_cntrs->has_exclusive[tid], 1);
2006 }
2007
2008 /*
2009 * xl = state of current HT
2010 * xlo = state of sibling HT
2011 */
2012 xl = &excl_cntrs->states[tid];
2013 xlo = &excl_cntrs->states[o_tid];
2014
2015 cx = c;
2016 2006
2017 /* 2007 /*
2018 * because we modify the constraint, we need 2008 * because we modify the constraint, we need
@@ -2023,10 +2013,7 @@ intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
2023 * been cloned (marked dynamic) 2013 * been cloned (marked dynamic)
2024 */ 2014 */
2025 if (!(c->flags & PERF_X86_EVENT_DYNAMIC)) { 2015 if (!(c->flags & PERF_X86_EVENT_DYNAMIC)) {
2026 2016 struct event_constraint *cx;
2027 /* sanity check */
2028 if (idx < 0)
2029 return &emptyconstraint;
2030 2017
2031 /* 2018 /*
2032 * grab pre-allocated constraint entry 2019 * grab pre-allocated constraint entry
@@ -2037,13 +2024,14 @@ intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
2037 * initialize dynamic constraint 2024 * initialize dynamic constraint
2038 * with static constraint 2025 * with static constraint
2039 */ 2026 */
2040 memcpy(cx, c, sizeof(*cx)); 2027 *cx = *c;
2041 2028
2042 /* 2029 /*
2043 * mark constraint as dynamic, so we 2030 * mark constraint as dynamic, so we
2044 * can free it later on 2031 * can free it later on
2045 */ 2032 */
2046 cx->flags |= PERF_X86_EVENT_DYNAMIC; 2033 cx->flags |= PERF_X86_EVENT_DYNAMIC;
2034 c = cx;
2047 } 2035 }
2048 2036
2049 /* 2037 /*
@@ -2054,6 +2042,22 @@ intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
2054 */ 2042 */
2055 2043
2056 /* 2044 /*
2045 * state of sibling HT
2046 */
2047 xlo = &excl_cntrs->states[tid ^ 1];
2048
2049 /*
2050 * event requires exclusive counter access
2051 * across HT threads
2052 */
2053 is_excl = c->flags & PERF_X86_EVENT_EXCL;
2054 if (is_excl && !(event->hw.flags & PERF_X86_EVENT_EXCL_ACCT)) {
2055 event->hw.flags |= PERF_X86_EVENT_EXCL_ACCT;
2056 if (!cpuc->n_excl++)
2057 WRITE_ONCE(excl_cntrs->has_exclusive[tid], 1);
2058 }
2059
2060 /*
2057 * Modify static constraint with current dynamic 2061 * Modify static constraint with current dynamic
2058 * state of thread 2062 * state of thread
2059 * 2063 *
@@ -2061,37 +2065,37 @@ intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
2061 * SHARED : sibling counter measuring non-exclusive event 2065 * SHARED : sibling counter measuring non-exclusive event
2062 * UNUSED : sibling counter unused 2066 * UNUSED : sibling counter unused
2063 */ 2067 */
2064 for_each_set_bit(i, cx->idxmsk, X86_PMC_IDX_MAX) { 2068 for_each_set_bit(i, c->idxmsk, X86_PMC_IDX_MAX) {
2065 /* 2069 /*
2066 * exclusive event in sibling counter 2070 * exclusive event in sibling counter
2067 * our corresponding counter cannot be used 2071 * our corresponding counter cannot be used
2068 * regardless of our event 2072 * regardless of our event
2069 */ 2073 */
2070 if (xl->state[i] == INTEL_EXCL_EXCLUSIVE) 2074 if (xlo->state[i] == INTEL_EXCL_EXCLUSIVE)
2071 __clear_bit(i, cx->idxmsk); 2075 __clear_bit(i, c->idxmsk);
2072 /* 2076 /*
2073 * if measuring an exclusive event, sibling 2077 * if measuring an exclusive event, sibling
2074 * measuring non-exclusive, then counter cannot 2078 * measuring non-exclusive, then counter cannot
2075 * be used 2079 * be used
2076 */ 2080 */
2077 if (is_excl && xl->state[i] == INTEL_EXCL_SHARED) 2081 if (is_excl && xlo->state[i] == INTEL_EXCL_SHARED)
2078 __clear_bit(i, cx->idxmsk); 2082 __clear_bit(i, c->idxmsk);
2079 } 2083 }
2080 2084
2081 /* 2085 /*
2082 * recompute actual bit weight for scheduling algorithm 2086 * recompute actual bit weight for scheduling algorithm
2083 */ 2087 */
2084 cx->weight = hweight64(cx->idxmsk64); 2088 c->weight = hweight64(c->idxmsk64);
2085 2089
2086 /* 2090 /*
2087 * if we return an empty mask, then switch 2091 * if we return an empty mask, then switch
2088 * back to static empty constraint to avoid 2092 * back to static empty constraint to avoid
2089 * the cost of freeing later on 2093 * the cost of freeing later on
2090 */ 2094 */
2091 if (cx->weight == 0) 2095 if (c->weight == 0)
2092 cx = &emptyconstraint; 2096 c = &emptyconstraint;
2093 2097
2094 return cx; 2098 return c;
2095} 2099}
2096 2100
2097static struct event_constraint * 2101static struct event_constraint *
@@ -2124,10 +2128,8 @@ static void intel_put_excl_constraints(struct cpu_hw_events *cpuc,
2124{ 2128{
2125 struct hw_perf_event *hwc = &event->hw; 2129 struct hw_perf_event *hwc = &event->hw;
2126 struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs; 2130 struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
2127 struct intel_excl_states *xlo, *xl;
2128 unsigned long flags = 0; /* keep compiler happy */
2129 int tid = cpuc->excl_thread_id; 2131 int tid = cpuc->excl_thread_id;
2130 int o_tid = 1 - tid; 2132 struct intel_excl_states *xl;
2131 2133
2132 /* 2134 /*
2133 * nothing needed if in group validation mode 2135 * nothing needed if in group validation mode
@@ -2135,13 +2137,9 @@ static void intel_put_excl_constraints(struct cpu_hw_events *cpuc,
2135 if (cpuc->is_fake) 2137 if (cpuc->is_fake)
2136 return; 2138 return;
2137 2139
2138 WARN_ON_ONCE(!excl_cntrs); 2140 if (WARN_ON_ONCE(!excl_cntrs))
2139
2140 if (!excl_cntrs)
2141 return; 2141 return;
2142 2142
2143 xl = &excl_cntrs->states[tid];
2144 xlo = &excl_cntrs->states[o_tid];
2145 if (hwc->flags & PERF_X86_EVENT_EXCL_ACCT) { 2143 if (hwc->flags & PERF_X86_EVENT_EXCL_ACCT) {
2146 hwc->flags &= ~PERF_X86_EVENT_EXCL_ACCT; 2144 hwc->flags &= ~PERF_X86_EVENT_EXCL_ACCT;
2147 if (!--cpuc->n_excl) 2145 if (!--cpuc->n_excl)
@@ -2149,22 +2147,25 @@ static void intel_put_excl_constraints(struct cpu_hw_events *cpuc,
2149 } 2147 }
2150 2148
2151 /* 2149 /*
2152 * put_constraint may be called from x86_schedule_events() 2150 * If event was actually assigned, then mark the counter state as
2153 * which already has the lock held so here make locking 2151 * unused now.
2154 * conditional
2155 */ 2152 */
2156 if (!xl->sched_started) 2153 if (hwc->idx >= 0) {
2157 raw_spin_lock_irqsave(&excl_cntrs->lock, flags); 2154 xl = &excl_cntrs->states[tid];
2158 2155
2159 /* 2156 /*
2160 * if event was actually assigned, then mark the 2157 * put_constraint may be called from x86_schedule_events()
2161 * counter state as unused now 2158 * which already has the lock held so here make locking
2162 */ 2159 * conditional.
2163 if (hwc->idx >= 0) 2160 */
2164 xlo->state[hwc->idx] = INTEL_EXCL_UNUSED; 2161 if (!xl->sched_started)
2162 raw_spin_lock(&excl_cntrs->lock);
2165 2163
2166 if (!xl->sched_started) 2164 xl->state[hwc->idx] = INTEL_EXCL_UNUSED;
2167 raw_spin_unlock_irqrestore(&excl_cntrs->lock, flags); 2165
2166 if (!xl->sched_started)
2167 raw_spin_unlock(&excl_cntrs->lock);
2168 }
2168} 2169}
2169 2170
2170static void 2171static void
@@ -2196,41 +2197,6 @@ static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
2196 intel_put_excl_constraints(cpuc, event); 2197 intel_put_excl_constraints(cpuc, event);
2197} 2198}
2198 2199
2199static void intel_commit_scheduling(struct cpu_hw_events *cpuc, int idx, int cntr)
2200{
2201 struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
2202 struct event_constraint *c = cpuc->event_constraint[idx];
2203 struct intel_excl_states *xlo, *xl;
2204 int tid = cpuc->excl_thread_id;
2205 int o_tid = 1 - tid;
2206 int is_excl;
2207
2208 if (cpuc->is_fake || !c)
2209 return;
2210
2211 is_excl = c->flags & PERF_X86_EVENT_EXCL;
2212
2213 if (!(c->flags & PERF_X86_EVENT_DYNAMIC))
2214 return;
2215
2216 WARN_ON_ONCE(!excl_cntrs);
2217
2218 if (!excl_cntrs)
2219 return;
2220
2221 xl = &excl_cntrs->states[tid];
2222 xlo = &excl_cntrs->states[o_tid];
2223
2224 WARN_ON_ONCE(!raw_spin_is_locked(&excl_cntrs->lock));
2225
2226 if (cntr >= 0) {
2227 if (is_excl)
2228 xlo->init_state[cntr] = INTEL_EXCL_EXCLUSIVE;
2229 else
2230 xlo->init_state[cntr] = INTEL_EXCL_SHARED;
2231 }
2232}
2233
2234static void intel_pebs_aliases_core2(struct perf_event *event) 2200static void intel_pebs_aliases_core2(struct perf_event *event)
2235{ 2201{
2236 if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) { 2202 if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) {
@@ -2294,8 +2260,15 @@ static int intel_pmu_hw_config(struct perf_event *event)
2294 if (ret) 2260 if (ret)
2295 return ret; 2261 return ret;
2296 2262
2297 if (event->attr.precise_ip && x86_pmu.pebs_aliases) 2263 if (event->attr.precise_ip) {
2298 x86_pmu.pebs_aliases(event); 2264 if (!event->attr.freq) {
2265 event->hw.flags |= PERF_X86_EVENT_AUTO_RELOAD;
2266 if (!(event->attr.sample_type & ~PEBS_FREERUNNING_FLAGS))
2267 event->hw.flags |= PERF_X86_EVENT_FREERUNNING;
2268 }
2269 if (x86_pmu.pebs_aliases)
2270 x86_pmu.pebs_aliases(event);
2271 }
2299 2272
2300 if (needs_branch_stack(event)) { 2273 if (needs_branch_stack(event)) {
2301 ret = intel_pmu_setup_lbr_filter(event); 2274 ret = intel_pmu_setup_lbr_filter(event);
@@ -2544,19 +2517,11 @@ struct intel_shared_regs *allocate_shared_regs(int cpu)
2544static struct intel_excl_cntrs *allocate_excl_cntrs(int cpu) 2517static struct intel_excl_cntrs *allocate_excl_cntrs(int cpu)
2545{ 2518{
2546 struct intel_excl_cntrs *c; 2519 struct intel_excl_cntrs *c;
2547 int i;
2548 2520
2549 c = kzalloc_node(sizeof(struct intel_excl_cntrs), 2521 c = kzalloc_node(sizeof(struct intel_excl_cntrs),
2550 GFP_KERNEL, cpu_to_node(cpu)); 2522 GFP_KERNEL, cpu_to_node(cpu));
2551 if (c) { 2523 if (c) {
2552 raw_spin_lock_init(&c->lock); 2524 raw_spin_lock_init(&c->lock);
2553 for (i = 0; i < X86_PMC_IDX_MAX; i++) {
2554 c->states[0].state[i] = INTEL_EXCL_UNUSED;
2555 c->states[0].init_state[i] = INTEL_EXCL_UNUSED;
2556
2557 c->states[1].state[i] = INTEL_EXCL_UNUSED;
2558 c->states[1].init_state[i] = INTEL_EXCL_UNUSED;
2559 }
2560 c->core_id = -1; 2525 c->core_id = -1;
2561 } 2526 }
2562 return c; 2527 return c;
@@ -2677,6 +2642,15 @@ static void intel_pmu_cpu_dying(int cpu)
2677 fini_debug_store_on_cpu(cpu); 2642 fini_debug_store_on_cpu(cpu);
2678} 2643}
2679 2644
2645static void intel_pmu_sched_task(struct perf_event_context *ctx,
2646 bool sched_in)
2647{
2648 if (x86_pmu.pebs_active)
2649 intel_pmu_pebs_sched_task(ctx, sched_in);
2650 if (x86_pmu.lbr_nr)
2651 intel_pmu_lbr_sched_task(ctx, sched_in);
2652}
2653
2680PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63"); 2654PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63");
2681 2655
2682PMU_FORMAT_ATTR(ldlat, "config1:0-15"); 2656PMU_FORMAT_ATTR(ldlat, "config1:0-15");
@@ -2766,7 +2740,7 @@ static __initconst const struct x86_pmu intel_pmu = {
2766 .cpu_starting = intel_pmu_cpu_starting, 2740 .cpu_starting = intel_pmu_cpu_starting,
2767 .cpu_dying = intel_pmu_cpu_dying, 2741 .cpu_dying = intel_pmu_cpu_dying,
2768 .guest_get_msrs = intel_guest_get_msrs, 2742 .guest_get_msrs = intel_guest_get_msrs,
2769 .sched_task = intel_pmu_lbr_sched_task, 2743 .sched_task = intel_pmu_sched_task,
2770}; 2744};
2771 2745
2772static __init void intel_clovertown_quirk(void) 2746static __init void intel_clovertown_quirk(void)
@@ -2939,8 +2913,8 @@ static __init void intel_ht_bug(void)
2939{ 2913{
2940 x86_pmu.flags |= PMU_FL_EXCL_CNTRS | PMU_FL_EXCL_ENABLED; 2914 x86_pmu.flags |= PMU_FL_EXCL_CNTRS | PMU_FL_EXCL_ENABLED;
2941 2915
2942 x86_pmu.commit_scheduling = intel_commit_scheduling;
2943 x86_pmu.start_scheduling = intel_start_scheduling; 2916 x86_pmu.start_scheduling = intel_start_scheduling;
2917 x86_pmu.commit_scheduling = intel_commit_scheduling;
2944 x86_pmu.stop_scheduling = intel_stop_scheduling; 2918 x86_pmu.stop_scheduling = intel_stop_scheduling;
2945} 2919}
2946 2920
@@ -3396,8 +3370,8 @@ static __init int fixup_ht_bug(void)
3396 3370
3397 x86_pmu.flags &= ~(PMU_FL_EXCL_CNTRS | PMU_FL_EXCL_ENABLED); 3371 x86_pmu.flags &= ~(PMU_FL_EXCL_CNTRS | PMU_FL_EXCL_ENABLED);
3398 3372
3399 x86_pmu.commit_scheduling = NULL;
3400 x86_pmu.start_scheduling = NULL; 3373 x86_pmu.start_scheduling = NULL;
3374 x86_pmu.commit_scheduling = NULL;
3401 x86_pmu.stop_scheduling = NULL; 3375 x86_pmu.stop_scheduling = NULL;
3402 3376
3403 watchdog_nmi_enable_all(); 3377 watchdog_nmi_enable_all();
diff --git a/arch/x86/kernel/cpu/perf_event_intel_cqm.c b/arch/x86/kernel/cpu/perf_event_intel_cqm.c
index e4d1b8b738fa..188076161c1b 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_cqm.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_cqm.c
@@ -13,16 +13,35 @@
13#define MSR_IA32_QM_CTR 0x0c8e 13#define MSR_IA32_QM_CTR 0x0c8e
14#define MSR_IA32_QM_EVTSEL 0x0c8d 14#define MSR_IA32_QM_EVTSEL 0x0c8d
15 15
16static unsigned int cqm_max_rmid = -1; 16static u32 cqm_max_rmid = -1;
17static unsigned int cqm_l3_scale; /* supposedly cacheline size */ 17static unsigned int cqm_l3_scale; /* supposedly cacheline size */
18 18
19struct intel_cqm_state { 19/**
20 raw_spinlock_t lock; 20 * struct intel_pqr_state - State cache for the PQR MSR
21 int rmid; 21 * @rmid: The cached Resource Monitoring ID
22 int cnt; 22 * @closid: The cached Class Of Service ID
23 * @rmid_usecnt: The usage counter for rmid
24 *
25 * The upper 32 bits of MSR_IA32_PQR_ASSOC contain closid and the
26 * lower 10 bits rmid. The update to MSR_IA32_PQR_ASSOC always
27 * contains both parts, so we need to cache them.
28 *
29 * The cache also helps to avoid pointless updates if the value does
30 * not change.
31 */
32struct intel_pqr_state {
33 u32 rmid;
34 u32 closid;
35 int rmid_usecnt;
23}; 36};
24 37
25static DEFINE_PER_CPU(struct intel_cqm_state, cqm_state); 38/*
39 * The cached intel_pqr_state is strictly per CPU and can never be
40 * updated from a remote CPU. Both functions which modify the state
41 * (intel_cqm_event_start and intel_cqm_event_stop) are called with
42 * interrupts disabled, which is sufficient for the protection.
43 */
44static DEFINE_PER_CPU(struct intel_pqr_state, pqr_state);
26 45
27/* 46/*
28 * Protects cache_cgroups and cqm_rmid_free_lru and cqm_rmid_limbo_lru. 47 * Protects cache_cgroups and cqm_rmid_free_lru and cqm_rmid_limbo_lru.
@@ -57,7 +76,7 @@ static cpumask_t cqm_cpumask;
57 * near-zero occupancy value, i.e. no cachelines are tagged with this 76 * near-zero occupancy value, i.e. no cachelines are tagged with this
58 * RMID, once __intel_cqm_rmid_rotate() returns. 77 * RMID, once __intel_cqm_rmid_rotate() returns.
59 */ 78 */
60static unsigned int intel_cqm_rotation_rmid; 79static u32 intel_cqm_rotation_rmid;
61 80
62#define INVALID_RMID (-1) 81#define INVALID_RMID (-1)
63 82
@@ -69,7 +88,7 @@ static unsigned int intel_cqm_rotation_rmid;
69 * Likewise, an rmid value of -1 is used to indicate "no rmid currently 88 * Likewise, an rmid value of -1 is used to indicate "no rmid currently
70 * assigned" and is used as part of the rotation code. 89 * assigned" and is used as part of the rotation code.
71 */ 90 */
72static inline bool __rmid_valid(unsigned int rmid) 91static inline bool __rmid_valid(u32 rmid)
73{ 92{
74 if (!rmid || rmid == INVALID_RMID) 93 if (!rmid || rmid == INVALID_RMID)
75 return false; 94 return false;
@@ -77,7 +96,7 @@ static inline bool __rmid_valid(unsigned int rmid)
77 return true; 96 return true;
78} 97}
79 98
80static u64 __rmid_read(unsigned int rmid) 99static u64 __rmid_read(u32 rmid)
81{ 100{
82 u64 val; 101 u64 val;
83 102
@@ -102,7 +121,7 @@ enum rmid_recycle_state {
102}; 121};
103 122
104struct cqm_rmid_entry { 123struct cqm_rmid_entry {
105 unsigned int rmid; 124 u32 rmid;
106 enum rmid_recycle_state state; 125 enum rmid_recycle_state state;
107 struct list_head list; 126 struct list_head list;
108 unsigned long queue_time; 127 unsigned long queue_time;
@@ -147,7 +166,7 @@ static LIST_HEAD(cqm_rmid_limbo_lru);
147 */ 166 */
148static struct cqm_rmid_entry **cqm_rmid_ptrs; 167static struct cqm_rmid_entry **cqm_rmid_ptrs;
149 168
150static inline struct cqm_rmid_entry *__rmid_entry(int rmid) 169static inline struct cqm_rmid_entry *__rmid_entry(u32 rmid)
151{ 170{
152 struct cqm_rmid_entry *entry; 171 struct cqm_rmid_entry *entry;
153 172
@@ -162,7 +181,7 @@ static inline struct cqm_rmid_entry *__rmid_entry(int rmid)
162 * 181 *
163 * We expect to be called with cache_mutex held. 182 * We expect to be called with cache_mutex held.
164 */ 183 */
165static int __get_rmid(void) 184static u32 __get_rmid(void)
166{ 185{
167 struct cqm_rmid_entry *entry; 186 struct cqm_rmid_entry *entry;
168 187
@@ -177,7 +196,7 @@ static int __get_rmid(void)
177 return entry->rmid; 196 return entry->rmid;
178} 197}
179 198
180static void __put_rmid(unsigned int rmid) 199static void __put_rmid(u32 rmid)
181{ 200{
182 struct cqm_rmid_entry *entry; 201 struct cqm_rmid_entry *entry;
183 202
@@ -372,7 +391,7 @@ static bool __conflict_event(struct perf_event *a, struct perf_event *b)
372} 391}
373 392
374struct rmid_read { 393struct rmid_read {
375 unsigned int rmid; 394 u32 rmid;
376 atomic64_t value; 395 atomic64_t value;
377}; 396};
378 397
@@ -381,12 +400,11 @@ static void __intel_cqm_event_count(void *info);
381/* 400/*
382 * Exchange the RMID of a group of events. 401 * Exchange the RMID of a group of events.
383 */ 402 */
384static unsigned int 403static u32 intel_cqm_xchg_rmid(struct perf_event *group, u32 rmid)
385intel_cqm_xchg_rmid(struct perf_event *group, unsigned int rmid)
386{ 404{
387 struct perf_event *event; 405 struct perf_event *event;
388 unsigned int old_rmid = group->hw.cqm_rmid;
389 struct list_head *head = &group->hw.cqm_group_entry; 406 struct list_head *head = &group->hw.cqm_group_entry;
407 u32 old_rmid = group->hw.cqm_rmid;
390 408
391 lockdep_assert_held(&cache_mutex); 409 lockdep_assert_held(&cache_mutex);
392 410
@@ -451,7 +469,7 @@ static void intel_cqm_stable(void *arg)
451 * If we have group events waiting for an RMID that don't conflict with 469 * If we have group events waiting for an RMID that don't conflict with
452 * events already running, assign @rmid. 470 * events already running, assign @rmid.
453 */ 471 */
454static bool intel_cqm_sched_in_event(unsigned int rmid) 472static bool intel_cqm_sched_in_event(u32 rmid)
455{ 473{
456 struct perf_event *leader, *event; 474 struct perf_event *leader, *event;
457 475
@@ -598,7 +616,7 @@ static bool intel_cqm_rmid_stabilize(unsigned int *available)
598static void __intel_cqm_pick_and_rotate(struct perf_event *next) 616static void __intel_cqm_pick_and_rotate(struct perf_event *next)
599{ 617{
600 struct perf_event *rotor; 618 struct perf_event *rotor;
601 unsigned int rmid; 619 u32 rmid;
602 620
603 lockdep_assert_held(&cache_mutex); 621 lockdep_assert_held(&cache_mutex);
604 622
@@ -626,7 +644,7 @@ static void __intel_cqm_pick_and_rotate(struct perf_event *next)
626static void intel_cqm_sched_out_conflicting_events(struct perf_event *event) 644static void intel_cqm_sched_out_conflicting_events(struct perf_event *event)
627{ 645{
628 struct perf_event *group, *g; 646 struct perf_event *group, *g;
629 unsigned int rmid; 647 u32 rmid;
630 648
631 lockdep_assert_held(&cache_mutex); 649 lockdep_assert_held(&cache_mutex);
632 650
@@ -828,8 +846,8 @@ static void intel_cqm_setup_event(struct perf_event *event,
828 struct perf_event **group) 846 struct perf_event **group)
829{ 847{
830 struct perf_event *iter; 848 struct perf_event *iter;
831 unsigned int rmid;
832 bool conflict = false; 849 bool conflict = false;
850 u32 rmid;
833 851
834 list_for_each_entry(iter, &cache_groups, hw.cqm_groups_entry) { 852 list_for_each_entry(iter, &cache_groups, hw.cqm_groups_entry) {
835 rmid = iter->hw.cqm_rmid; 853 rmid = iter->hw.cqm_rmid;
@@ -860,7 +878,7 @@ static void intel_cqm_setup_event(struct perf_event *event,
860static void intel_cqm_event_read(struct perf_event *event) 878static void intel_cqm_event_read(struct perf_event *event)
861{ 879{
862 unsigned long flags; 880 unsigned long flags;
863 unsigned int rmid; 881 u32 rmid;
864 u64 val; 882 u64 val;
865 883
866 /* 884 /*
@@ -961,55 +979,48 @@ out:
961 979
962static void intel_cqm_event_start(struct perf_event *event, int mode) 980static void intel_cqm_event_start(struct perf_event *event, int mode)
963{ 981{
964 struct intel_cqm_state *state = this_cpu_ptr(&cqm_state); 982 struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
965 unsigned int rmid = event->hw.cqm_rmid; 983 u32 rmid = event->hw.cqm_rmid;
966 unsigned long flags;
967 984
968 if (!(event->hw.cqm_state & PERF_HES_STOPPED)) 985 if (!(event->hw.cqm_state & PERF_HES_STOPPED))
969 return; 986 return;
970 987
971 event->hw.cqm_state &= ~PERF_HES_STOPPED; 988 event->hw.cqm_state &= ~PERF_HES_STOPPED;
972 989
973 raw_spin_lock_irqsave(&state->lock, flags); 990 if (state->rmid_usecnt++) {
974 991 if (!WARN_ON_ONCE(state->rmid != rmid))
975 if (state->cnt++) 992 return;
976 WARN_ON_ONCE(state->rmid != rmid); 993 } else {
977 else
978 WARN_ON_ONCE(state->rmid); 994 WARN_ON_ONCE(state->rmid);
995 }
979 996
980 state->rmid = rmid; 997 state->rmid = rmid;
981 wrmsrl(MSR_IA32_PQR_ASSOC, state->rmid); 998 wrmsr(MSR_IA32_PQR_ASSOC, rmid, state->closid);
982
983 raw_spin_unlock_irqrestore(&state->lock, flags);
984} 999}
985 1000
986static void intel_cqm_event_stop(struct perf_event *event, int mode) 1001static void intel_cqm_event_stop(struct perf_event *event, int mode)
987{ 1002{
988 struct intel_cqm_state *state = this_cpu_ptr(&cqm_state); 1003 struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
989 unsigned long flags;
990 1004
991 if (event->hw.cqm_state & PERF_HES_STOPPED) 1005 if (event->hw.cqm_state & PERF_HES_STOPPED)
992 return; 1006 return;
993 1007
994 event->hw.cqm_state |= PERF_HES_STOPPED; 1008 event->hw.cqm_state |= PERF_HES_STOPPED;
995 1009
996 raw_spin_lock_irqsave(&state->lock, flags);
997 intel_cqm_event_read(event); 1010 intel_cqm_event_read(event);
998 1011
999 if (!--state->cnt) { 1012 if (!--state->rmid_usecnt) {
1000 state->rmid = 0; 1013 state->rmid = 0;
1001 wrmsrl(MSR_IA32_PQR_ASSOC, 0); 1014 wrmsr(MSR_IA32_PQR_ASSOC, 0, state->closid);
1002 } else { 1015 } else {
1003 WARN_ON_ONCE(!state->rmid); 1016 WARN_ON_ONCE(!state->rmid);
1004 } 1017 }
1005
1006 raw_spin_unlock_irqrestore(&state->lock, flags);
1007} 1018}
1008 1019
1009static int intel_cqm_event_add(struct perf_event *event, int mode) 1020static int intel_cqm_event_add(struct perf_event *event, int mode)
1010{ 1021{
1011 unsigned long flags; 1022 unsigned long flags;
1012 unsigned int rmid; 1023 u32 rmid;
1013 1024
1014 raw_spin_lock_irqsave(&cache_lock, flags); 1025 raw_spin_lock_irqsave(&cache_lock, flags);
1015 1026
@@ -1024,11 +1035,6 @@ static int intel_cqm_event_add(struct perf_event *event, int mode)
1024 return 0; 1035 return 0;
1025} 1036}
1026 1037
1027static void intel_cqm_event_del(struct perf_event *event, int mode)
1028{
1029 intel_cqm_event_stop(event, mode);
1030}
1031
1032static void intel_cqm_event_destroy(struct perf_event *event) 1038static void intel_cqm_event_destroy(struct perf_event *event)
1033{ 1039{
1034 struct perf_event *group_other = NULL; 1040 struct perf_event *group_other = NULL;
@@ -1057,7 +1063,7 @@ static void intel_cqm_event_destroy(struct perf_event *event)
1057 list_replace(&event->hw.cqm_groups_entry, 1063 list_replace(&event->hw.cqm_groups_entry,
1058 &group_other->hw.cqm_groups_entry); 1064 &group_other->hw.cqm_groups_entry);
1059 } else { 1065 } else {
1060 unsigned int rmid = event->hw.cqm_rmid; 1066 u32 rmid = event->hw.cqm_rmid;
1061 1067
1062 if (__rmid_valid(rmid)) 1068 if (__rmid_valid(rmid))
1063 __put_rmid(rmid); 1069 __put_rmid(rmid);
@@ -1221,7 +1227,7 @@ static struct pmu intel_cqm_pmu = {
1221 .task_ctx_nr = perf_sw_context, 1227 .task_ctx_nr = perf_sw_context,
1222 .event_init = intel_cqm_event_init, 1228 .event_init = intel_cqm_event_init,
1223 .add = intel_cqm_event_add, 1229 .add = intel_cqm_event_add,
1224 .del = intel_cqm_event_del, 1230 .del = intel_cqm_event_stop,
1225 .start = intel_cqm_event_start, 1231 .start = intel_cqm_event_start,
1226 .stop = intel_cqm_event_stop, 1232 .stop = intel_cqm_event_stop,
1227 .read = intel_cqm_event_read, 1233 .read = intel_cqm_event_read,
@@ -1243,12 +1249,12 @@ static inline void cqm_pick_event_reader(int cpu)
1243 1249
1244static void intel_cqm_cpu_prepare(unsigned int cpu) 1250static void intel_cqm_cpu_prepare(unsigned int cpu)
1245{ 1251{
1246 struct intel_cqm_state *state = &per_cpu(cqm_state, cpu); 1252 struct intel_pqr_state *state = &per_cpu(pqr_state, cpu);
1247 struct cpuinfo_x86 *c = &cpu_data(cpu); 1253 struct cpuinfo_x86 *c = &cpu_data(cpu);
1248 1254
1249 raw_spin_lock_init(&state->lock);
1250 state->rmid = 0; 1255 state->rmid = 0;
1251 state->cnt = 0; 1256 state->closid = 0;
1257 state->rmid_usecnt = 0;
1252 1258
1253 WARN_ON(c->x86_cache_max_rmid != cqm_max_rmid); 1259 WARN_ON(c->x86_cache_max_rmid != cqm_max_rmid);
1254 WARN_ON(c->x86_cache_occ_scale != cqm_l3_scale); 1260 WARN_ON(c->x86_cache_occ_scale != cqm_l3_scale);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index 7f73b3553e2e..71fc40238843 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -11,7 +11,7 @@
11#define BTS_RECORD_SIZE 24 11#define BTS_RECORD_SIZE 24
12 12
13#define BTS_BUFFER_SIZE (PAGE_SIZE << 4) 13#define BTS_BUFFER_SIZE (PAGE_SIZE << 4)
14#define PEBS_BUFFER_SIZE PAGE_SIZE 14#define PEBS_BUFFER_SIZE (PAGE_SIZE << 4)
15#define PEBS_FIXUP_SIZE PAGE_SIZE 15#define PEBS_FIXUP_SIZE PAGE_SIZE
16 16
17/* 17/*
@@ -250,7 +250,7 @@ static int alloc_pebs_buffer(int cpu)
250{ 250{
251 struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; 251 struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
252 int node = cpu_to_node(cpu); 252 int node = cpu_to_node(cpu);
253 int max, thresh = 1; /* always use a single PEBS record */ 253 int max;
254 void *buffer, *ibuffer; 254 void *buffer, *ibuffer;
255 255
256 if (!x86_pmu.pebs) 256 if (!x86_pmu.pebs)
@@ -280,9 +280,6 @@ static int alloc_pebs_buffer(int cpu)
280 ds->pebs_absolute_maximum = ds->pebs_buffer_base + 280 ds->pebs_absolute_maximum = ds->pebs_buffer_base +
281 max * x86_pmu.pebs_record_size; 281 max * x86_pmu.pebs_record_size;
282 282
283 ds->pebs_interrupt_threshold = ds->pebs_buffer_base +
284 thresh * x86_pmu.pebs_record_size;
285
286 return 0; 283 return 0;
287} 284}
288 285
@@ -549,6 +546,19 @@ int intel_pmu_drain_bts_buffer(void)
549 return 1; 546 return 1;
550} 547}
551 548
549static inline void intel_pmu_drain_pebs_buffer(void)
550{
551 struct pt_regs regs;
552
553 x86_pmu.drain_pebs(&regs);
554}
555
556void intel_pmu_pebs_sched_task(struct perf_event_context *ctx, bool sched_in)
557{
558 if (!sched_in)
559 intel_pmu_drain_pebs_buffer();
560}
561
552/* 562/*
553 * PEBS 563 * PEBS
554 */ 564 */
@@ -684,25 +694,66 @@ struct event_constraint *intel_pebs_constraints(struct perf_event *event)
684 return &emptyconstraint; 694 return &emptyconstraint;
685} 695}
686 696
697static inline bool pebs_is_enabled(struct cpu_hw_events *cpuc)
698{
699 return (cpuc->pebs_enabled & ((1ULL << MAX_PEBS_EVENTS) - 1));
700}
701
687void intel_pmu_pebs_enable(struct perf_event *event) 702void intel_pmu_pebs_enable(struct perf_event *event)
688{ 703{
689 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 704 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
690 struct hw_perf_event *hwc = &event->hw; 705 struct hw_perf_event *hwc = &event->hw;
706 struct debug_store *ds = cpuc->ds;
707 bool first_pebs;
708 u64 threshold;
691 709
692 hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT; 710 hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT;
693 711
712 first_pebs = !pebs_is_enabled(cpuc);
694 cpuc->pebs_enabled |= 1ULL << hwc->idx; 713 cpuc->pebs_enabled |= 1ULL << hwc->idx;
695 714
696 if (event->hw.flags & PERF_X86_EVENT_PEBS_LDLAT) 715 if (event->hw.flags & PERF_X86_EVENT_PEBS_LDLAT)
697 cpuc->pebs_enabled |= 1ULL << (hwc->idx + 32); 716 cpuc->pebs_enabled |= 1ULL << (hwc->idx + 32);
698 else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST) 717 else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST)
699 cpuc->pebs_enabled |= 1ULL << 63; 718 cpuc->pebs_enabled |= 1ULL << 63;
719
720 /*
721 * When the event is constrained enough we can use a larger
722 * threshold and run the event with less frequent PMI.
723 */
724 if (hwc->flags & PERF_X86_EVENT_FREERUNNING) {
725 threshold = ds->pebs_absolute_maximum -
726 x86_pmu.max_pebs_events * x86_pmu.pebs_record_size;
727
728 if (first_pebs)
729 perf_sched_cb_inc(event->ctx->pmu);
730 } else {
731 threshold = ds->pebs_buffer_base + x86_pmu.pebs_record_size;
732
733 /*
734 * If not all events can use larger buffer,
735 * roll back to threshold = 1
736 */
737 if (!first_pebs &&
738 (ds->pebs_interrupt_threshold > threshold))
739 perf_sched_cb_dec(event->ctx->pmu);
740 }
741
742 /* Use auto-reload if possible to save a MSR write in the PMI */
743 if (hwc->flags & PERF_X86_EVENT_AUTO_RELOAD) {
744 ds->pebs_event_reset[hwc->idx] =
745 (u64)(-hwc->sample_period) & x86_pmu.cntval_mask;
746 }
747
748 if (first_pebs || ds->pebs_interrupt_threshold > threshold)
749 ds->pebs_interrupt_threshold = threshold;
700} 750}
701 751
702void intel_pmu_pebs_disable(struct perf_event *event) 752void intel_pmu_pebs_disable(struct perf_event *event)
703{ 753{
704 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 754 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
705 struct hw_perf_event *hwc = &event->hw; 755 struct hw_perf_event *hwc = &event->hw;
756 struct debug_store *ds = cpuc->ds;
706 757
707 cpuc->pebs_enabled &= ~(1ULL << hwc->idx); 758 cpuc->pebs_enabled &= ~(1ULL << hwc->idx);
708 759
@@ -711,6 +762,13 @@ void intel_pmu_pebs_disable(struct perf_event *event)
711 else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST) 762 else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST)
712 cpuc->pebs_enabled &= ~(1ULL << 63); 763 cpuc->pebs_enabled &= ~(1ULL << 63);
713 764
765 if (ds->pebs_interrupt_threshold >
766 ds->pebs_buffer_base + x86_pmu.pebs_record_size) {
767 intel_pmu_drain_pebs_buffer();
768 if (!pebs_is_enabled(cpuc))
769 perf_sched_cb_dec(event->ctx->pmu);
770 }
771
714 if (cpuc->enabled) 772 if (cpuc->enabled)
715 wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled); 773 wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled);
716 774
@@ -846,8 +904,10 @@ static inline u64 intel_hsw_transaction(struct pebs_record_hsw *pebs)
846 return txn; 904 return txn;
847} 905}
848 906
849static void __intel_pmu_pebs_event(struct perf_event *event, 907static void setup_pebs_sample_data(struct perf_event *event,
850 struct pt_regs *iregs, void *__pebs) 908 struct pt_regs *iregs, void *__pebs,
909 struct perf_sample_data *data,
910 struct pt_regs *regs)
851{ 911{
852#define PERF_X86_EVENT_PEBS_HSW_PREC \ 912#define PERF_X86_EVENT_PEBS_HSW_PREC \
853 (PERF_X86_EVENT_PEBS_ST_HSW | \ 913 (PERF_X86_EVENT_PEBS_ST_HSW | \
@@ -859,13 +919,11 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
859 */ 919 */
860 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 920 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
861 struct pebs_record_hsw *pebs = __pebs; 921 struct pebs_record_hsw *pebs = __pebs;
862 struct perf_sample_data data;
863 struct pt_regs regs;
864 u64 sample_type; 922 u64 sample_type;
865 int fll, fst, dsrc; 923 int fll, fst, dsrc;
866 int fl = event->hw.flags; 924 int fl = event->hw.flags;
867 925
868 if (!intel_pmu_save_and_restart(event)) 926 if (pebs == NULL)
869 return; 927 return;
870 928
871 sample_type = event->attr.sample_type; 929 sample_type = event->attr.sample_type;
@@ -874,15 +932,15 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
874 fll = fl & PERF_X86_EVENT_PEBS_LDLAT; 932 fll = fl & PERF_X86_EVENT_PEBS_LDLAT;
875 fst = fl & (PERF_X86_EVENT_PEBS_ST | PERF_X86_EVENT_PEBS_HSW_PREC); 933 fst = fl & (PERF_X86_EVENT_PEBS_ST | PERF_X86_EVENT_PEBS_HSW_PREC);
876 934
877 perf_sample_data_init(&data, 0, event->hw.last_period); 935 perf_sample_data_init(data, 0, event->hw.last_period);
878 936
879 data.period = event->hw.last_period; 937 data->period = event->hw.last_period;
880 938
881 /* 939 /*
882 * Use latency for weight (only avail with PEBS-LL) 940 * Use latency for weight (only avail with PEBS-LL)
883 */ 941 */
884 if (fll && (sample_type & PERF_SAMPLE_WEIGHT)) 942 if (fll && (sample_type & PERF_SAMPLE_WEIGHT))
885 data.weight = pebs->lat; 943 data->weight = pebs->lat;
886 944
887 /* 945 /*
888 * data.data_src encodes the data source 946 * data.data_src encodes the data source
@@ -895,7 +953,7 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
895 val = precise_datala_hsw(event, pebs->dse); 953 val = precise_datala_hsw(event, pebs->dse);
896 else if (fst) 954 else if (fst)
897 val = precise_store_data(pebs->dse); 955 val = precise_store_data(pebs->dse);
898 data.data_src.val = val; 956 data->data_src.val = val;
899 } 957 }
900 958
901 /* 959 /*
@@ -908,61 +966,123 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
908 * PERF_SAMPLE_IP and PERF_SAMPLE_CALLCHAIN to function properly. 966 * PERF_SAMPLE_IP and PERF_SAMPLE_CALLCHAIN to function properly.
909 * A possible PERF_SAMPLE_REGS will have to transfer all regs. 967 * A possible PERF_SAMPLE_REGS will have to transfer all regs.
910 */ 968 */
911 regs = *iregs; 969 *regs = *iregs;
912 regs.flags = pebs->flags; 970 regs->flags = pebs->flags;
913 set_linear_ip(&regs, pebs->ip); 971 set_linear_ip(regs, pebs->ip);
914 regs.bp = pebs->bp; 972 regs->bp = pebs->bp;
915 regs.sp = pebs->sp; 973 regs->sp = pebs->sp;
916 974
917 if (sample_type & PERF_SAMPLE_REGS_INTR) { 975 if (sample_type & PERF_SAMPLE_REGS_INTR) {
918 regs.ax = pebs->ax; 976 regs->ax = pebs->ax;
919 regs.bx = pebs->bx; 977 regs->bx = pebs->bx;
920 regs.cx = pebs->cx; 978 regs->cx = pebs->cx;
921 regs.dx = pebs->dx; 979 regs->dx = pebs->dx;
922 regs.si = pebs->si; 980 regs->si = pebs->si;
923 regs.di = pebs->di; 981 regs->di = pebs->di;
924 regs.bp = pebs->bp; 982 regs->bp = pebs->bp;
925 regs.sp = pebs->sp; 983 regs->sp = pebs->sp;
926 984
927 regs.flags = pebs->flags; 985 regs->flags = pebs->flags;
928#ifndef CONFIG_X86_32 986#ifndef CONFIG_X86_32
929 regs.r8 = pebs->r8; 987 regs->r8 = pebs->r8;
930 regs.r9 = pebs->r9; 988 regs->r9 = pebs->r9;
931 regs.r10 = pebs->r10; 989 regs->r10 = pebs->r10;
932 regs.r11 = pebs->r11; 990 regs->r11 = pebs->r11;
933 regs.r12 = pebs->r12; 991 regs->r12 = pebs->r12;
934 regs.r13 = pebs->r13; 992 regs->r13 = pebs->r13;
935 regs.r14 = pebs->r14; 993 regs->r14 = pebs->r14;
936 regs.r15 = pebs->r15; 994 regs->r15 = pebs->r15;
937#endif 995#endif
938 } 996 }
939 997
940 if (event->attr.precise_ip > 1 && x86_pmu.intel_cap.pebs_format >= 2) { 998 if (event->attr.precise_ip > 1 && x86_pmu.intel_cap.pebs_format >= 2) {
941 regs.ip = pebs->real_ip; 999 regs->ip = pebs->real_ip;
942 regs.flags |= PERF_EFLAGS_EXACT; 1000 regs->flags |= PERF_EFLAGS_EXACT;
943 } else if (event->attr.precise_ip > 1 && intel_pmu_pebs_fixup_ip(&regs)) 1001 } else if (event->attr.precise_ip > 1 && intel_pmu_pebs_fixup_ip(regs))
944 regs.flags |= PERF_EFLAGS_EXACT; 1002 regs->flags |= PERF_EFLAGS_EXACT;
945 else 1003 else
946 regs.flags &= ~PERF_EFLAGS_EXACT; 1004 regs->flags &= ~PERF_EFLAGS_EXACT;
947 1005
948 if ((sample_type & PERF_SAMPLE_ADDR) && 1006 if ((sample_type & PERF_SAMPLE_ADDR) &&
949 x86_pmu.intel_cap.pebs_format >= 1) 1007 x86_pmu.intel_cap.pebs_format >= 1)
950 data.addr = pebs->dla; 1008 data->addr = pebs->dla;
951 1009
952 if (x86_pmu.intel_cap.pebs_format >= 2) { 1010 if (x86_pmu.intel_cap.pebs_format >= 2) {
953 /* Only set the TSX weight when no memory weight. */ 1011 /* Only set the TSX weight when no memory weight. */
954 if ((sample_type & PERF_SAMPLE_WEIGHT) && !fll) 1012 if ((sample_type & PERF_SAMPLE_WEIGHT) && !fll)
955 data.weight = intel_hsw_weight(pebs); 1013 data->weight = intel_hsw_weight(pebs);
956 1014
957 if (sample_type & PERF_SAMPLE_TRANSACTION) 1015 if (sample_type & PERF_SAMPLE_TRANSACTION)
958 data.txn = intel_hsw_transaction(pebs); 1016 data->txn = intel_hsw_transaction(pebs);
959 } 1017 }
960 1018
961 if (has_branch_stack(event)) 1019 if (has_branch_stack(event))
962 data.br_stack = &cpuc->lbr_stack; 1020 data->br_stack = &cpuc->lbr_stack;
1021}
1022
1023static inline void *
1024get_next_pebs_record_by_bit(void *base, void *top, int bit)
1025{
1026 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
1027 void *at;
1028 u64 pebs_status;
1029
1030 if (base == NULL)
1031 return NULL;
1032
1033 for (at = base; at < top; at += x86_pmu.pebs_record_size) {
1034 struct pebs_record_nhm *p = at;
1035
1036 if (test_bit(bit, (unsigned long *)&p->status)) {
1037 /* PEBS v3 has accurate status bits */
1038 if (x86_pmu.intel_cap.pebs_format >= 3)
1039 return at;
963 1040
964 if (perf_event_overflow(event, &data, &regs)) 1041 if (p->status == (1 << bit))
1042 return at;
1043
1044 /* clear non-PEBS bit and re-check */
1045 pebs_status = p->status & cpuc->pebs_enabled;
1046 pebs_status &= (1ULL << MAX_PEBS_EVENTS) - 1;
1047 if (pebs_status == (1 << bit))
1048 return at;
1049 }
1050 }
1051 return NULL;
1052}
1053
1054static void __intel_pmu_pebs_event(struct perf_event *event,
1055 struct pt_regs *iregs,
1056 void *base, void *top,
1057 int bit, int count)
1058{
1059 struct perf_sample_data data;
1060 struct pt_regs regs;
1061 void *at = get_next_pebs_record_by_bit(base, top, bit);
1062
1063 if (!intel_pmu_save_and_restart(event) &&
1064 !(event->hw.flags & PERF_X86_EVENT_AUTO_RELOAD))
1065 return;
1066
1067 while (count > 1) {
1068 setup_pebs_sample_data(event, iregs, at, &data, &regs);
1069 perf_event_output(event, &data, &regs);
1070 at += x86_pmu.pebs_record_size;
1071 at = get_next_pebs_record_by_bit(at, top, bit);
1072 count--;
1073 }
1074
1075 setup_pebs_sample_data(event, iregs, at, &data, &regs);
1076
1077 /*
1078 * All but the last records are processed.
1079 * The last one is left to be able to call the overflow handler.
1080 */
1081 if (perf_event_overflow(event, &data, &regs)) {
965 x86_pmu_stop(event, 0); 1082 x86_pmu_stop(event, 0);
1083 return;
1084 }
1085
966} 1086}
967 1087
968static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) 1088static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
@@ -992,72 +1112,99 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
992 if (!event->attr.precise_ip) 1112 if (!event->attr.precise_ip)
993 return; 1113 return;
994 1114
995 n = top - at; 1115 n = (top - at) / x86_pmu.pebs_record_size;
996 if (n <= 0) 1116 if (n <= 0)
997 return; 1117 return;
998 1118
999 /* 1119 __intel_pmu_pebs_event(event, iregs, at, top, 0, n);
1000 * Should not happen, we program the threshold at 1 and do not
1001 * set a reset value.
1002 */
1003 WARN_ONCE(n > 1, "bad leftover pebs %d\n", n);
1004 at += n - 1;
1005
1006 __intel_pmu_pebs_event(event, iregs, at);
1007} 1120}
1008 1121
1009static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) 1122static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
1010{ 1123{
1011 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 1124 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
1012 struct debug_store *ds = cpuc->ds; 1125 struct debug_store *ds = cpuc->ds;
1013 struct perf_event *event = NULL; 1126 struct perf_event *event;
1014 void *at, *top; 1127 void *base, *at, *top;
1015 u64 status = 0; 1128 short counts[MAX_PEBS_EVENTS] = {};
1016 int bit; 1129 short error[MAX_PEBS_EVENTS] = {};
1130 int bit, i;
1017 1131
1018 if (!x86_pmu.pebs_active) 1132 if (!x86_pmu.pebs_active)
1019 return; 1133 return;
1020 1134
1021 at = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base; 1135 base = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base;
1022 top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index; 1136 top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index;
1023 1137
1024 ds->pebs_index = ds->pebs_buffer_base; 1138 ds->pebs_index = ds->pebs_buffer_base;
1025 1139
1026 if (unlikely(at > top)) 1140 if (unlikely(base >= top))
1027 return; 1141 return;
1028 1142
1029 /* 1143 for (at = base; at < top; at += x86_pmu.pebs_record_size) {
1030 * Should not happen, we program the threshold at 1 and do not
1031 * set a reset value.
1032 */
1033 WARN_ONCE(top - at > x86_pmu.max_pebs_events * x86_pmu.pebs_record_size,
1034 "Unexpected number of pebs records %ld\n",
1035 (long)(top - at) / x86_pmu.pebs_record_size);
1036
1037 for (; at < top; at += x86_pmu.pebs_record_size) {
1038 struct pebs_record_nhm *p = at; 1144 struct pebs_record_nhm *p = at;
1039 1145
1040 for_each_set_bit(bit, (unsigned long *)&p->status, 1146 /* PEBS v3 has accurate status bits */
1041 x86_pmu.max_pebs_events) { 1147 if (x86_pmu.intel_cap.pebs_format >= 3) {
1042 event = cpuc->events[bit]; 1148 for_each_set_bit(bit, (unsigned long *)&p->status,
1043 if (!test_bit(bit, cpuc->active_mask)) 1149 MAX_PEBS_EVENTS)
1044 continue; 1150 counts[bit]++;
1045
1046 WARN_ON_ONCE(!event);
1047 1151
1048 if (!event->attr.precise_ip) 1152 continue;
1049 continue; 1153 }
1050 1154
1051 if (__test_and_set_bit(bit, (unsigned long *)&status)) 1155 bit = find_first_bit((unsigned long *)&p->status,
1156 x86_pmu.max_pebs_events);
1157 if (bit >= x86_pmu.max_pebs_events)
1158 continue;
1159 if (!test_bit(bit, cpuc->active_mask))
1160 continue;
1161 /*
1162 * The PEBS hardware does not deal well with the situation
1163 * when events happen near to each other and multiple bits
1164 * are set. But it should happen rarely.
1165 *
1166 * If these events include one PEBS and multiple non-PEBS
1167 * events, it doesn't impact PEBS record. The record will
1168 * be handled normally. (slow path)
1169 *
1170 * If these events include two or more PEBS events, the
1171 * records for the events can be collapsed into a single
1172 * one, and it's not possible to reconstruct all events
1173 * that caused the PEBS record. It's called collision.
1174 * If collision happened, the record will be dropped.
1175 *
1176 */
1177 if (p->status != (1 << bit)) {
1178 u64 pebs_status;
1179
1180 /* slow path */
1181 pebs_status = p->status & cpuc->pebs_enabled;
1182 pebs_status &= (1ULL << MAX_PEBS_EVENTS) - 1;
1183 if (pebs_status != (1 << bit)) {
1184 for_each_set_bit(i, (unsigned long *)&pebs_status,
1185 MAX_PEBS_EVENTS)
1186 error[i]++;
1052 continue; 1187 continue;
1053 1188 }
1054 break;
1055 } 1189 }
1190 counts[bit]++;
1191 }
1056 1192
1057 if (!event || bit >= x86_pmu.max_pebs_events) 1193 for (bit = 0; bit < x86_pmu.max_pebs_events; bit++) {
1194 if ((counts[bit] == 0) && (error[bit] == 0))
1058 continue; 1195 continue;
1196 event = cpuc->events[bit];
1197 WARN_ON_ONCE(!event);
1198 WARN_ON_ONCE(!event->attr.precise_ip);
1059 1199
1060 __intel_pmu_pebs_event(event, iregs, at); 1200 /* log dropped samples number */
1201 if (error[bit])
1202 perf_log_lost_samples(event, error[bit]);
1203
1204 if (counts[bit]) {
1205 __intel_pmu_pebs_event(event, iregs, base,
1206 top, bit, counts[bit]);
1207 }
1061 } 1208 }
1062} 1209}
1063 1210
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
index 94e5b506caa6..452a7bd2dedb 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
@@ -96,6 +96,7 @@ enum {
96 X86_BR_NO_TX = 1 << 14,/* not in transaction */ 96 X86_BR_NO_TX = 1 << 14,/* not in transaction */
97 X86_BR_ZERO_CALL = 1 << 15,/* zero length call */ 97 X86_BR_ZERO_CALL = 1 << 15,/* zero length call */
98 X86_BR_CALL_STACK = 1 << 16,/* call stack */ 98 X86_BR_CALL_STACK = 1 << 16,/* call stack */
99 X86_BR_IND_JMP = 1 << 17,/* indirect jump */
99}; 100};
100 101
101#define X86_BR_PLM (X86_BR_USER | X86_BR_KERNEL) 102#define X86_BR_PLM (X86_BR_USER | X86_BR_KERNEL)
@@ -113,6 +114,7 @@ enum {
113 X86_BR_IRQ |\ 114 X86_BR_IRQ |\
114 X86_BR_ABORT |\ 115 X86_BR_ABORT |\
115 X86_BR_IND_CALL |\ 116 X86_BR_IND_CALL |\
117 X86_BR_IND_JMP |\
116 X86_BR_ZERO_CALL) 118 X86_BR_ZERO_CALL)
117 119
118#define X86_BR_ALL (X86_BR_PLM | X86_BR_ANY) 120#define X86_BR_ALL (X86_BR_PLM | X86_BR_ANY)
@@ -262,9 +264,6 @@ void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in)
262 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 264 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
263 struct x86_perf_task_context *task_ctx; 265 struct x86_perf_task_context *task_ctx;
264 266
265 if (!x86_pmu.lbr_nr)
266 return;
267
268 /* 267 /*
269 * If LBR callstack feature is enabled and the stack was saved when 268 * If LBR callstack feature is enabled and the stack was saved when
270 * the task was scheduled out, restore the stack. Otherwise flush 269 * the task was scheduled out, restore the stack. Otherwise flush
@@ -523,6 +522,9 @@ static int intel_pmu_setup_sw_lbr_filter(struct perf_event *event)
523 X86_BR_CALL_STACK; 522 X86_BR_CALL_STACK;
524 } 523 }
525 524
525 if (br_type & PERF_SAMPLE_BRANCH_IND_JUMP)
526 mask |= X86_BR_IND_JMP;
527
526 /* 528 /*
527 * stash actual user request into reg, it may 529 * stash actual user request into reg, it may
528 * be used by fixup code for some CPU 530 * be used by fixup code for some CPU
@@ -736,7 +738,7 @@ static int branch_type(unsigned long from, unsigned long to, int abort)
736 break; 738 break;
737 case 4: 739 case 4:
738 case 5: 740 case 5:
739 ret = X86_BR_JMP; 741 ret = X86_BR_IND_JMP;
740 break; 742 break;
741 } 743 }
742 break; 744 break;
@@ -844,6 +846,7 @@ static const int nhm_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
844 */ 846 */
845 [PERF_SAMPLE_BRANCH_IND_CALL_SHIFT] = LBR_IND_CALL | LBR_IND_JMP, 847 [PERF_SAMPLE_BRANCH_IND_CALL_SHIFT] = LBR_IND_CALL | LBR_IND_JMP,
846 [PERF_SAMPLE_BRANCH_COND_SHIFT] = LBR_JCC, 848 [PERF_SAMPLE_BRANCH_COND_SHIFT] = LBR_JCC,
849 [PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT] = LBR_IND_JMP,
847}; 850};
848 851
849static const int snb_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = { 852static const int snb_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
@@ -856,6 +859,7 @@ static const int snb_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
856 | LBR_FAR, 859 | LBR_FAR,
857 [PERF_SAMPLE_BRANCH_IND_CALL_SHIFT] = LBR_IND_CALL, 860 [PERF_SAMPLE_BRANCH_IND_CALL_SHIFT] = LBR_IND_CALL,
858 [PERF_SAMPLE_BRANCH_COND_SHIFT] = LBR_JCC, 861 [PERF_SAMPLE_BRANCH_COND_SHIFT] = LBR_JCC,
862 [PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT] = LBR_IND_JMP,
859}; 863};
860 864
861static const int hsw_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = { 865static const int hsw_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
@@ -870,6 +874,7 @@ static const int hsw_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
870 [PERF_SAMPLE_BRANCH_COND_SHIFT] = LBR_JCC, 874 [PERF_SAMPLE_BRANCH_COND_SHIFT] = LBR_JCC,
871 [PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT] = LBR_REL_CALL | LBR_IND_CALL 875 [PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT] = LBR_REL_CALL | LBR_IND_CALL
872 | LBR_RETURN | LBR_CALL_STACK, 876 | LBR_RETURN | LBR_CALL_STACK,
877 [PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT] = LBR_IND_JMP,
873}; 878};
874 879
875/* core */ 880/* core */
diff --git a/arch/x86/kernel/cpu/perf_event_intel_pt.c b/arch/x86/kernel/cpu/perf_event_intel_pt.c
index 123ff1bb2f60..159887c3a89d 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_pt.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_pt.c
@@ -187,15 +187,6 @@ static bool pt_event_valid(struct perf_event *event)
187 * These all are cpu affine and operate on a local PT 187 * These all are cpu affine and operate on a local PT
188 */ 188 */
189 189
190static bool pt_is_running(void)
191{
192 u64 ctl;
193
194 rdmsrl(MSR_IA32_RTIT_CTL, ctl);
195
196 return !!(ctl & RTIT_CTL_TRACEEN);
197}
198
199static void pt_config(struct perf_event *event) 190static void pt_config(struct perf_event *event)
200{ 191{
201 u64 reg; 192 u64 reg;
@@ -609,7 +600,12 @@ static unsigned int pt_topa_next_entry(struct pt_buffer *buf, unsigned int pg)
609 * @handle: Current output handle. 600 * @handle: Current output handle.
610 * 601 *
611 * Place INT and STOP marks to prevent overwriting old data that the consumer 602 * Place INT and STOP marks to prevent overwriting old data that the consumer
612 * hasn't yet collected. 603 * hasn't yet collected and waking up the consumer after a certain fraction of
604 * the buffer has filled up. Only needed and sensible for non-snapshot counters.
605 *
606 * This obviously relies on buf::head to figure out buffer markers, so it has
607 * to be called after pt_buffer_reset_offsets() and before the hardware tracing
608 * is enabled.
613 */ 609 */
614static int pt_buffer_reset_markers(struct pt_buffer *buf, 610static int pt_buffer_reset_markers(struct pt_buffer *buf,
615 struct perf_output_handle *handle) 611 struct perf_output_handle *handle)
@@ -618,9 +614,6 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
618 unsigned long head = local64_read(&buf->head); 614 unsigned long head = local64_read(&buf->head);
619 unsigned long idx, npages, wakeup; 615 unsigned long idx, npages, wakeup;
620 616
621 if (buf->snapshot)
622 return 0;
623
624 /* can't stop in the middle of an output region */ 617 /* can't stop in the middle of an output region */
625 if (buf->output_off + handle->size + 1 < 618 if (buf->output_off + handle->size + 1 <
626 sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) 619 sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size))
@@ -674,7 +667,7 @@ static void pt_buffer_setup_topa_index(struct pt_buffer *buf)
674 struct topa *cur = buf->first, *prev = buf->last; 667 struct topa *cur = buf->first, *prev = buf->last;
675 struct topa_entry *te_cur = TOPA_ENTRY(cur, 0), 668 struct topa_entry *te_cur = TOPA_ENTRY(cur, 0),
676 *te_prev = TOPA_ENTRY(prev, prev->last - 1); 669 *te_prev = TOPA_ENTRY(prev, prev->last - 1);
677 int pg = 0, idx = 0, ntopa = 0; 670 int pg = 0, idx = 0;
678 671
679 while (pg < buf->nr_pages) { 672 while (pg < buf->nr_pages) {
680 int tidx; 673 int tidx;
@@ -689,9 +682,9 @@ static void pt_buffer_setup_topa_index(struct pt_buffer *buf)
689 /* advance to next topa table */ 682 /* advance to next topa table */
690 idx = 0; 683 idx = 0;
691 cur = list_entry(cur->list.next, struct topa, list); 684 cur = list_entry(cur->list.next, struct topa, list);
692 ntopa++; 685 } else {
693 } else
694 idx++; 686 idx++;
687 }
695 te_cur = TOPA_ENTRY(cur, idx); 688 te_cur = TOPA_ENTRY(cur, idx);
696 } 689 }
697 690
@@ -703,7 +696,14 @@ static void pt_buffer_setup_topa_index(struct pt_buffer *buf)
703 * @head: Write pointer (aux_head) from AUX buffer. 696 * @head: Write pointer (aux_head) from AUX buffer.
704 * 697 *
705 * Find the ToPA table and entry corresponding to given @head and set buffer's 698 * Find the ToPA table and entry corresponding to given @head and set buffer's
706 * "current" pointers accordingly. 699 * "current" pointers accordingly. This is done after we have obtained the
700 * current aux_head position from a successful call to perf_aux_output_begin()
701 * to make sure the hardware is writing to the right place.
702 *
703 * This function modifies buf::{cur,cur_idx,output_off} that will be programmed
704 * into PT msrs when the tracing is enabled and buf::head and buf::data_size,
705 * which are used to determine INT and STOP markers' locations by a subsequent
706 * call to pt_buffer_reset_markers().
707 */ 707 */
708static void pt_buffer_reset_offsets(struct pt_buffer *buf, unsigned long head) 708static void pt_buffer_reset_offsets(struct pt_buffer *buf, unsigned long head)
709{ 709{
@@ -901,6 +901,7 @@ void intel_pt_interrupt(void)
901 } 901 }
902 902
903 pt_buffer_reset_offsets(buf, pt->handle.head); 903 pt_buffer_reset_offsets(buf, pt->handle.head);
904 /* snapshot counters don't use PMI, so it's safe */
904 ret = pt_buffer_reset_markers(buf, &pt->handle); 905 ret = pt_buffer_reset_markers(buf, &pt->handle);
905 if (ret) { 906 if (ret) {
906 perf_aux_output_end(&pt->handle, 0, true); 907 perf_aux_output_end(&pt->handle, 0, true);
@@ -923,7 +924,7 @@ static void pt_event_start(struct perf_event *event, int mode)
923 struct pt *pt = this_cpu_ptr(&pt_ctx); 924 struct pt *pt = this_cpu_ptr(&pt_ctx);
924 struct pt_buffer *buf = perf_get_aux(&pt->handle); 925 struct pt_buffer *buf = perf_get_aux(&pt->handle);
925 926
926 if (pt_is_running() || !buf || pt_buffer_is_full(buf, pt)) { 927 if (!buf || pt_buffer_is_full(buf, pt)) {
927 event->hw.state = PERF_HES_STOPPED; 928 event->hw.state = PERF_HES_STOPPED;
928 return; 929 return;
929 } 930 }
@@ -954,7 +955,6 @@ static void pt_event_stop(struct perf_event *event, int mode)
954 event->hw.state = PERF_HES_STOPPED; 955 event->hw.state = PERF_HES_STOPPED;
955 956
956 if (mode & PERF_EF_UPDATE) { 957 if (mode & PERF_EF_UPDATE) {
957 struct pt *pt = this_cpu_ptr(&pt_ctx);
958 struct pt_buffer *buf = perf_get_aux(&pt->handle); 958 struct pt_buffer *buf = perf_get_aux(&pt->handle);
959 959
960 if (!buf) 960 if (!buf)
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
index 90b7c501c95b..7c1de1610178 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
@@ -922,6 +922,9 @@ static int __init uncore_pci_init(void)
922 case 69: /* Haswell Celeron */ 922 case 69: /* Haswell Celeron */
923 ret = hsw_uncore_pci_init(); 923 ret = hsw_uncore_pci_init();
924 break; 924 break;
925 case 61: /* Broadwell */
926 ret = bdw_uncore_pci_init();
927 break;
925 default: 928 default:
926 return 0; 929 return 0;
927 } 930 }
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
index ceac8f5dc018..0f77f0a196e4 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
@@ -325,6 +325,7 @@ extern struct event_constraint uncore_constraint_empty;
325int snb_uncore_pci_init(void); 325int snb_uncore_pci_init(void);
326int ivb_uncore_pci_init(void); 326int ivb_uncore_pci_init(void);
327int hsw_uncore_pci_init(void); 327int hsw_uncore_pci_init(void);
328int bdw_uncore_pci_init(void);
328void snb_uncore_cpu_init(void); 329void snb_uncore_cpu_init(void);
329void nhm_uncore_cpu_init(void); 330void nhm_uncore_cpu_init(void);
330 331
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 4562e9e22c60..b005a78c7012 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore_snb.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore_snb.c
@@ -7,6 +7,7 @@
7#define PCI_DEVICE_ID_INTEL_IVB_E3_IMC 0x0150 7#define PCI_DEVICE_ID_INTEL_IVB_E3_IMC 0x0150
8#define PCI_DEVICE_ID_INTEL_HSW_IMC 0x0c00 8#define PCI_DEVICE_ID_INTEL_HSW_IMC 0x0c00
9#define PCI_DEVICE_ID_INTEL_HSW_U_IMC 0x0a04 9#define PCI_DEVICE_ID_INTEL_HSW_U_IMC 0x0a04
10#define PCI_DEVICE_ID_INTEL_BDW_IMC 0x1604
10 11
11/* SNB event control */ 12/* SNB event control */
12#define SNB_UNC_CTL_EV_SEL_MASK 0x000000ff 13#define SNB_UNC_CTL_EV_SEL_MASK 0x000000ff
@@ -486,6 +487,14 @@ static const struct pci_device_id hsw_uncore_pci_ids[] = {
486 { /* end: all zeroes */ }, 487 { /* end: all zeroes */ },
487}; 488};
488 489
490static const struct pci_device_id bdw_uncore_pci_ids[] = {
491 { /* IMC */
492 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BDW_IMC),
493 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
494 },
495 { /* end: all zeroes */ },
496};
497
489static struct pci_driver snb_uncore_pci_driver = { 498static struct pci_driver snb_uncore_pci_driver = {
490 .name = "snb_uncore", 499 .name = "snb_uncore",
491 .id_table = snb_uncore_pci_ids, 500 .id_table = snb_uncore_pci_ids,
@@ -501,6 +510,11 @@ static struct pci_driver hsw_uncore_pci_driver = {
501 .id_table = hsw_uncore_pci_ids, 510 .id_table = hsw_uncore_pci_ids,
502}; 511};
503 512
513static struct pci_driver bdw_uncore_pci_driver = {
514 .name = "bdw_uncore",
515 .id_table = bdw_uncore_pci_ids,
516};
517
504struct imc_uncore_pci_dev { 518struct imc_uncore_pci_dev {
505 __u32 pci_id; 519 __u32 pci_id;
506 struct pci_driver *driver; 520 struct pci_driver *driver;
@@ -514,6 +528,7 @@ static const struct imc_uncore_pci_dev desktop_imc_pci_ids[] = {
514 IMC_DEV(IVB_E3_IMC, &ivb_uncore_pci_driver), /* Xeon E3-1200 v2/3rd Gen Core processor */ 528 IMC_DEV(IVB_E3_IMC, &ivb_uncore_pci_driver), /* Xeon E3-1200 v2/3rd Gen Core processor */
515 IMC_DEV(HSW_IMC, &hsw_uncore_pci_driver), /* 4th Gen Core Processor */ 529 IMC_DEV(HSW_IMC, &hsw_uncore_pci_driver), /* 4th Gen Core Processor */
516 IMC_DEV(HSW_U_IMC, &hsw_uncore_pci_driver), /* 4th Gen Core ULT Mobile Processor */ 530 IMC_DEV(HSW_U_IMC, &hsw_uncore_pci_driver), /* 4th Gen Core ULT Mobile Processor */
531 IMC_DEV(BDW_IMC, &bdw_uncore_pci_driver), /* 5th Gen Core U */
517 { /* end marker */ } 532 { /* end marker */ }
518}; 533};
519 534
@@ -561,6 +576,11 @@ int hsw_uncore_pci_init(void)
561 return imc_uncore_pci_init(); 576 return imc_uncore_pci_init();
562} 577}
563 578
579int bdw_uncore_pci_init(void)
580{
581 return imc_uncore_pci_init();
582}
583
564/* end of Sandy Bridge uncore support */ 584/* end of Sandy Bridge uncore support */
565 585
566/* Nehalem uncore support */ 586/* Nehalem uncore support */
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index d8a82a89f35a..a204d5266f5f 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -120,7 +120,7 @@ struct hw_perf_event {
120 }; 120 };
121 struct { /* intel_cqm */ 121 struct { /* intel_cqm */
122 int cqm_state; 122 int cqm_state;
123 int cqm_rmid; 123 u32 cqm_rmid;
124 struct list_head cqm_events_entry; 124 struct list_head cqm_events_entry;
125 struct list_head cqm_groups_entry; 125 struct list_head cqm_groups_entry;
126 struct list_head cqm_group_entry; 126 struct list_head cqm_group_entry;
@@ -730,6 +730,22 @@ extern int perf_event_overflow(struct perf_event *event,
730 struct perf_sample_data *data, 730 struct perf_sample_data *data,
731 struct pt_regs *regs); 731 struct pt_regs *regs);
732 732
733extern void perf_event_output(struct perf_event *event,
734 struct perf_sample_data *data,
735 struct pt_regs *regs);
736
737extern void
738perf_event_header__init_id(struct perf_event_header *header,
739 struct perf_sample_data *data,
740 struct perf_event *event);
741extern void
742perf_event__output_id_sample(struct perf_event *event,
743 struct perf_output_handle *handle,
744 struct perf_sample_data *sample);
745
746extern void
747perf_log_lost_samples(struct perf_event *event, u64 lost);
748
733static inline bool is_sampling_event(struct perf_event *event) 749static inline bool is_sampling_event(struct perf_event *event)
734{ 750{
735 return event->attr.sample_period != 0; 751 return event->attr.sample_period != 0;
@@ -794,11 +810,33 @@ perf_sw_event_sched(u32 event_id, u64 nr, u64 addr)
794 810
795extern struct static_key_deferred perf_sched_events; 811extern struct static_key_deferred perf_sched_events;
796 812
813static __always_inline bool
814perf_sw_migrate_enabled(void)
815{
816 if (static_key_false(&perf_swevent_enabled[PERF_COUNT_SW_CPU_MIGRATIONS]))
817 return true;
818 return false;
819}
820
821static inline void perf_event_task_migrate(struct task_struct *task)
822{
823 if (perf_sw_migrate_enabled())
824 task->sched_migrated = 1;
825}
826
797static inline void perf_event_task_sched_in(struct task_struct *prev, 827static inline void perf_event_task_sched_in(struct task_struct *prev,
798 struct task_struct *task) 828 struct task_struct *task)
799{ 829{
800 if (static_key_false(&perf_sched_events.key)) 830 if (static_key_false(&perf_sched_events.key))
801 __perf_event_task_sched_in(prev, task); 831 __perf_event_task_sched_in(prev, task);
832
833 if (perf_sw_migrate_enabled() && task->sched_migrated) {
834 struct pt_regs *regs = this_cpu_ptr(&__perf_regs[0]);
835
836 perf_fetch_caller_regs(regs);
837 ___perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS, 1, regs, 0);
838 task->sched_migrated = 0;
839 }
802} 840}
803 841
804static inline void perf_event_task_sched_out(struct task_struct *prev, 842static inline void perf_event_task_sched_out(struct task_struct *prev,
@@ -921,6 +959,8 @@ perf_aux_output_skip(struct perf_output_handle *handle,
921static inline void * 959static inline void *
922perf_get_aux(struct perf_output_handle *handle) { return NULL; } 960perf_get_aux(struct perf_output_handle *handle) { return NULL; }
923static inline void 961static inline void
962perf_event_task_migrate(struct task_struct *task) { }
963static inline void
924perf_event_task_sched_in(struct task_struct *prev, 964perf_event_task_sched_in(struct task_struct *prev,
925 struct task_struct *task) { } 965 struct task_struct *task) { }
926static inline void 966static inline void
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 8ca95f6a9395..659f5729cacc 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1357,9 +1357,6 @@ struct task_struct {
1357#endif 1357#endif
1358 1358
1359 struct mm_struct *mm, *active_mm; 1359 struct mm_struct *mm, *active_mm;
1360#ifdef CONFIG_COMPAT_BRK
1361 unsigned brk_randomized:1;
1362#endif
1363 /* per-thread vma caching */ 1360 /* per-thread vma caching */
1364 u32 vmacache_seqnum; 1361 u32 vmacache_seqnum;
1365 struct vm_area_struct *vmacache[VMACACHE_SIZE]; 1362 struct vm_area_struct *vmacache[VMACACHE_SIZE];
@@ -1382,10 +1379,14 @@ struct task_struct {
1382 /* Revert to default priority/policy when forking */ 1379 /* Revert to default priority/policy when forking */
1383 unsigned sched_reset_on_fork:1; 1380 unsigned sched_reset_on_fork:1;
1384 unsigned sched_contributes_to_load:1; 1381 unsigned sched_contributes_to_load:1;
1382 unsigned sched_migrated:1;
1385 1383
1386#ifdef CONFIG_MEMCG_KMEM 1384#ifdef CONFIG_MEMCG_KMEM
1387 unsigned memcg_kmem_skip_account:1; 1385 unsigned memcg_kmem_skip_account:1;
1388#endif 1386#endif
1387#ifdef CONFIG_COMPAT_BRK
1388 unsigned brk_randomized:1;
1389#endif
1389 1390
1390 unsigned long atomic_flags; /* Flags needing atomic access. */ 1391 unsigned long atomic_flags; /* Flags needing atomic access. */
1391 1392
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 309211b3eb67..d97f84c080da 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -167,6 +167,7 @@ enum perf_branch_sample_type_shift {
167 PERF_SAMPLE_BRANCH_COND_SHIFT = 10, /* conditional branches */ 167 PERF_SAMPLE_BRANCH_COND_SHIFT = 10, /* conditional branches */
168 168
169 PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT = 11, /* call/ret stack */ 169 PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT = 11, /* call/ret stack */
170 PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT = 12, /* indirect jumps */
170 171
171 PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */ 172 PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */
172}; 173};
@@ -186,6 +187,7 @@ enum perf_branch_sample_type {
186 PERF_SAMPLE_BRANCH_COND = 1U << PERF_SAMPLE_BRANCH_COND_SHIFT, 187 PERF_SAMPLE_BRANCH_COND = 1U << PERF_SAMPLE_BRANCH_COND_SHIFT,
187 188
188 PERF_SAMPLE_BRANCH_CALL_STACK = 1U << PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT, 189 PERF_SAMPLE_BRANCH_CALL_STACK = 1U << PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT,
190 PERF_SAMPLE_BRANCH_IND_JUMP = 1U << PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT,
189 191
190 PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT, 192 PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT,
191}; 193};
@@ -564,6 +566,10 @@ struct perf_event_mmap_page {
564#define PERF_RECORD_MISC_GUEST_USER (5 << 0) 566#define PERF_RECORD_MISC_GUEST_USER (5 << 0)
565 567
566/* 568/*
569 * Indicates that /proc/PID/maps parsing are truncated by time out.
570 */
571#define PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT (1 << 12)
572/*
567 * PERF_RECORD_MISC_MMAP_DATA and PERF_RECORD_MISC_COMM_EXEC are used on 573 * PERF_RECORD_MISC_MMAP_DATA and PERF_RECORD_MISC_COMM_EXEC are used on
568 * different events so can reuse the same bit position. 574 * different events so can reuse the same bit position.
569 */ 575 */
@@ -800,6 +806,18 @@ enum perf_event_type {
800 */ 806 */
801 PERF_RECORD_ITRACE_START = 12, 807 PERF_RECORD_ITRACE_START = 12,
802 808
809 /*
810 * Records the dropped/lost sample number.
811 *
812 * struct {
813 * struct perf_event_header header;
814 *
815 * u64 lost;
816 * struct sample_id sample_id;
817 * };
818 */
819 PERF_RECORD_LOST_SAMPLES = 13,
820
803 PERF_RECORD_MAX, /* non-ABI */ 821 PERF_RECORD_MAX, /* non-ABI */
804}; 822};
805 823
diff --git a/init/Kconfig b/init/Kconfig
index 4c08197044f1..b999fa381bf9 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1623,7 +1623,7 @@ config PERF_EVENTS
1623config DEBUG_PERF_USE_VMALLOC 1623config DEBUG_PERF_USE_VMALLOC
1624 default n 1624 default n
1625 bool "Debug: use vmalloc to back perf mmap() buffers" 1625 bool "Debug: use vmalloc to back perf mmap() buffers"
1626 depends on PERF_EVENTS && DEBUG_KERNEL 1626 depends on PERF_EVENTS && DEBUG_KERNEL && !PPC
1627 select PERF_USE_VMALLOC 1627 select PERF_USE_VMALLOC
1628 help 1628 help
1629 Use vmalloc memory to back perf mmap() buffers. 1629 Use vmalloc memory to back perf mmap() buffers.
diff --git a/kernel/events/core.c b/kernel/events/core.c
index eddf1ed4155e..9e0773d5d110 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5381,9 +5381,9 @@ void perf_prepare_sample(struct perf_event_header *header,
5381 } 5381 }
5382} 5382}
5383 5383
5384static void perf_event_output(struct perf_event *event, 5384void perf_event_output(struct perf_event *event,
5385 struct perf_sample_data *data, 5385 struct perf_sample_data *data,
5386 struct pt_regs *regs) 5386 struct pt_regs *regs)
5387{ 5387{
5388 struct perf_output_handle handle; 5388 struct perf_output_handle handle;
5389 struct perf_event_header header; 5389 struct perf_event_header header;
@@ -5975,6 +5975,39 @@ void perf_event_aux_event(struct perf_event *event, unsigned long head,
5975} 5975}
5976 5976
5977/* 5977/*
5978 * Lost/dropped samples logging
5979 */
5980void perf_log_lost_samples(struct perf_event *event, u64 lost)
5981{
5982 struct perf_output_handle handle;
5983 struct perf_sample_data sample;
5984 int ret;
5985
5986 struct {
5987 struct perf_event_header header;
5988 u64 lost;
5989 } lost_samples_event = {
5990 .header = {
5991 .type = PERF_RECORD_LOST_SAMPLES,
5992 .misc = 0,
5993 .size = sizeof(lost_samples_event),
5994 },
5995 .lost = lost,
5996 };
5997
5998 perf_event_header__init_id(&lost_samples_event.header, &sample, event);
5999
6000 ret = perf_output_begin(&handle, event,
6001 lost_samples_event.header.size);
6002 if (ret)
6003 return;
6004
6005 perf_output_put(&handle, lost_samples_event);
6006 perf_event__output_id_sample(event, &handle, &sample);
6007 perf_output_end(&handle);
6008}
6009
6010/*
5978 * IRQ throttle logging 6011 * IRQ throttle logging
5979 */ 6012 */
5980 6013
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index 9f6ce9ba4a04..2deb24c7a40d 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -72,15 +72,6 @@ static inline bool rb_has_aux(struct ring_buffer *rb)
72void perf_event_aux_event(struct perf_event *event, unsigned long head, 72void perf_event_aux_event(struct perf_event *event, unsigned long head,
73 unsigned long size, u64 flags); 73 unsigned long size, u64 flags);
74 74
75extern void
76perf_event_header__init_id(struct perf_event_header *header,
77 struct perf_sample_data *data,
78 struct perf_event *event);
79extern void
80perf_event__output_id_sample(struct perf_event *event,
81 struct perf_output_handle *handle,
82 struct perf_sample_data *sample);
83
84extern struct page * 75extern struct page *
85perf_mmap_to_page(struct ring_buffer *rb, unsigned long pgoff); 76perf_mmap_to_page(struct ring_buffer *rb, unsigned long pgoff);
86 77
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 123673291ffb..db9b10a78d74 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1049,7 +1049,7 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
1049 if (p->sched_class->migrate_task_rq) 1049 if (p->sched_class->migrate_task_rq)
1050 p->sched_class->migrate_task_rq(p, new_cpu); 1050 p->sched_class->migrate_task_rq(p, new_cpu);
1051 p->se.nr_migrations++; 1051 p->se.nr_migrations++;
1052 perf_sw_event_sched(PERF_COUNT_SW_CPU_MIGRATIONS, 1, 0); 1052 perf_event_task_migrate(p);
1053 } 1053 }
1054 1054
1055 __set_task_cpu(p, new_cpu); 1055 __set_task_cpu(p, new_cpu);
diff --git a/tools/Makefile b/tools/Makefile
index 9a617adc6675..b35102721cbb 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -1,3 +1,8 @@
1# Some of the tools (perf) use same make variables
2# as in kernel build.
3export srctree=
4export objtree=
5
1include scripts/Makefile.include 6include scripts/Makefile.include
2 7
3help: 8help:
@@ -47,11 +52,16 @@ cgroup firewire hv guest usb virtio vm net: FORCE
47liblockdep: FORCE 52liblockdep: FORCE
48 $(call descend,lib/lockdep) 53 $(call descend,lib/lockdep)
49 54
50libapikfs: FORCE 55libapi: FORCE
51 $(call descend,lib/api) 56 $(call descend,lib/api)
52 57
53perf: libapikfs FORCE 58# The perf build does not follow the descend function setup,
54 $(call descend,$@) 59# invoking it via it's own make rule.
60PERF_O = $(if $(O),$(O)/tools/perf,)
61
62perf: FORCE
63 $(Q)mkdir -p $(PERF_O) .
64 $(Q)$(MAKE) --no-print-directory -C perf O=$(PERF_O) subdir=
55 65
56selftests: FORCE 66selftests: FORCE
57 $(call descend,testing/$@) 67 $(call descend,testing/$@)
@@ -97,10 +107,10 @@ cgroup_clean hv_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clea
97liblockdep_clean: 107liblockdep_clean:
98 $(call descend,lib/lockdep,clean) 108 $(call descend,lib/lockdep,clean)
99 109
100libapikfs_clean: 110libapi_clean:
101 $(call descend,lib/api,clean) 111 $(call descend,lib/api,clean)
102 112
103perf_clean: libapikfs_clean 113perf_clean:
104 $(call descend,$(@:_clean=),clean) 114 $(call descend,$(@:_clean=),clean)
105 115
106selftests_clean: 116selftests_clean:
diff --git a/tools/arch/alpha/include/asm/barrier.h b/tools/arch/alpha/include/asm/barrier.h
new file mode 100644
index 000000000000..95df19c95482
--- /dev/null
+++ b/tools/arch/alpha/include/asm/barrier.h
@@ -0,0 +1,8 @@
1#ifndef __TOOLS_LINUX_ASM_ALPHA_BARRIER_H
2#define __TOOLS_LINUX_ASM_ALPHA_BARRIER_H
3
4#define mb() __asm__ __volatile__("mb": : :"memory")
5#define rmb() __asm__ __volatile__("mb": : :"memory")
6#define wmb() __asm__ __volatile__("wmb": : :"memory")
7
8#endif /* __TOOLS_LINUX_ASM_ALPHA_BARRIER_H */
diff --git a/tools/arch/arm/include/asm/barrier.h b/tools/arch/arm/include/asm/barrier.h
new file mode 100644
index 000000000000..005c618a0ab0
--- /dev/null
+++ b/tools/arch/arm/include/asm/barrier.h
@@ -0,0 +1,12 @@
1#ifndef _TOOLS_LINUX_ASM_ARM_BARRIER_H
2#define _TOOLS_LINUX_ASM_ARM_BARRIER_H
3
4/*
5 * Use the __kuser_memory_barrier helper in the CPU helper page. See
6 * arch/arm/kernel/entry-armv.S in the kernel source for details.
7 */
8#define mb() ((void(*)(void))0xffff0fa0)()
9#define wmb() ((void(*)(void))0xffff0fa0)()
10#define rmb() ((void(*)(void))0xffff0fa0)()
11
12#endif /* _TOOLS_LINUX_ASM_ARM_BARRIER_H */
diff --git a/tools/arch/arm64/include/asm/barrier.h b/tools/arch/arm64/include/asm/barrier.h
new file mode 100644
index 000000000000..a0483c8e0142
--- /dev/null
+++ b/tools/arch/arm64/include/asm/barrier.h
@@ -0,0 +1,16 @@
1#ifndef _TOOLS_LINUX_ASM_AARCH64_BARRIER_H
2#define _TOOLS_LINUX_ASM_AARCH64_BARRIER_H
3
4/*
5 * From tools/perf/perf-sys.h, last modified in:
6 * f428ebd184c82a7914b2aa7e9f868918aaf7ea78 perf tools: Fix AAAAARGH64 memory barriers
7 *
8 * XXX: arch/arm64/include/asm/barrier.h in the kernel sources use dsb, is this
9 * a case like for arm32 where we do things differently in userspace?
10 */
11
12#define mb() asm volatile("dmb ish" ::: "memory")
13#define wmb() asm volatile("dmb ishst" ::: "memory")
14#define rmb() asm volatile("dmb ishld" ::: "memory")
15
16#endif /* _TOOLS_LINUX_ASM_AARCH64_BARRIER_H */
diff --git a/tools/arch/ia64/include/asm/barrier.h b/tools/arch/ia64/include/asm/barrier.h
new file mode 100644
index 000000000000..e4422b4b634e
--- /dev/null
+++ b/tools/arch/ia64/include/asm/barrier.h
@@ -0,0 +1,48 @@
1/*
2 * Copied from the kernel sources to tools/:
3 *
4 * Memory barrier definitions. This is based on information published
5 * in the Processor Abstraction Layer and the System Abstraction Layer
6 * manual.
7 *
8 * Copyright (C) 1998-2003 Hewlett-Packard Co
9 * David Mosberger-Tang <davidm@hpl.hp.com>
10 * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
11 * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
12 */
13#ifndef _TOOLS_LINUX_ASM_IA64_BARRIER_H
14#define _TOOLS_LINUX_ASM_IA64_BARRIER_H
15
16#include <linux/compiler.h>
17
18/*
19 * Macros to force memory ordering. In these descriptions, "previous"
20 * and "subsequent" refer to program order; "visible" means that all
21 * architecturally visible effects of a memory access have occurred
22 * (at a minimum, this means the memory has been read or written).
23 *
24 * wmb(): Guarantees that all preceding stores to memory-
25 * like regions are visible before any subsequent
26 * stores and that all following stores will be
27 * visible only after all previous stores.
28 * rmb(): Like wmb(), but for reads.
29 * mb(): wmb()/rmb() combo, i.e., all previous memory
30 * accesses are visible before all subsequent
31 * accesses and vice versa. This is also known as
32 * a "fence."
33 *
34 * Note: "mb()" and its variants cannot be used as a fence to order
35 * accesses to memory mapped I/O registers. For that, mf.a needs to
36 * be used. However, we don't want to always use mf.a because (a)
37 * it's (presumably) much slower than mf and (b) mf.a is supported for
38 * sequential memory pages only.
39 */
40
41/* XXX From arch/ia64/include/uapi/asm/gcc_intrin.h */
42#define ia64_mf() asm volatile ("mf" ::: "memory")
43
44#define mb() ia64_mf()
45#define rmb() mb()
46#define wmb() mb()
47
48#endif /* _TOOLS_LINUX_ASM_IA64_BARRIER_H */
diff --git a/tools/arch/mips/include/asm/barrier.h b/tools/arch/mips/include/asm/barrier.h
new file mode 100644
index 000000000000..80f96f7556e3
--- /dev/null
+++ b/tools/arch/mips/include/asm/barrier.h
@@ -0,0 +1,20 @@
1#ifndef _TOOLS_LINUX_ASM_MIPS_BARRIER_H
2#define _TOOLS_LINUX_ASM_MIPS_BARRIER_H
3/*
4 * FIXME: This came from tools/perf/perf-sys.h, where it was first introduced
5 * in c1e028ef40b8d6943b767028ba17d4f2ba020edb, more work needed to make it
6 * more closely follow the Linux kernel arch/mips/include/asm/barrier.h file.
7 * Probably when we continue work on tools/ Kconfig support to have all the
8 * CONFIG_ needed for properly doing that.
9 */
10#define mb() asm volatile( \
11 ".set mips2\n\t" \
12 "sync\n\t" \
13 ".set mips0" \
14 : /* no output */ \
15 : /* no input */ \
16 : "memory")
17#define wmb() mb()
18#define rmb() mb()
19
20#endif /* _TOOLS_LINUX_ASM_MIPS_BARRIER_H */
diff --git a/tools/arch/powerpc/include/asm/barrier.h b/tools/arch/powerpc/include/asm/barrier.h
new file mode 100644
index 000000000000..b23aee8e6d90
--- /dev/null
+++ b/tools/arch/powerpc/include/asm/barrier.h
@@ -0,0 +1,29 @@
1/*
2 * Copied from the kernel sources:
3 *
4 * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
5 */
6#ifndef _TOOLS_LINUX_ASM_POWERPC_BARRIER_H
7#define _TOOLS_LINUX_ASM_POWERPC_BARRIER_H
8
9/*
10 * Memory barrier.
11 * The sync instruction guarantees that all memory accesses initiated
12 * by this processor have been performed (with respect to all other
13 * mechanisms that access memory). The eieio instruction is a barrier
14 * providing an ordering (separately) for (a) cacheable stores and (b)
15 * loads and stores to non-cacheable memory (e.g. I/O devices).
16 *
17 * mb() prevents loads and stores being reordered across this point.
18 * rmb() prevents loads being reordered across this point.
19 * wmb() prevents stores being reordered across this point.
20 *
21 * *mb() variants without smp_ prefix must order all types of memory
22 * operations with one another. sync is the only instruction sufficient
23 * to do this.
24 */
25#define mb() __asm__ __volatile__ ("sync" : : : "memory")
26#define rmb() __asm__ __volatile__ ("sync" : : : "memory")
27#define wmb() __asm__ __volatile__ ("sync" : : : "memory")
28
29#endif /* _TOOLS_LINUX_ASM_POWERPC_BARRIER_H */
diff --git a/tools/arch/s390/include/asm/barrier.h b/tools/arch/s390/include/asm/barrier.h
new file mode 100644
index 000000000000..f85141266b92
--- /dev/null
+++ b/tools/arch/s390/include/asm/barrier.h
@@ -0,0 +1,30 @@
1/*
2 * Copied from the kernel sources:
3 *
4 * Copyright IBM Corp. 1999, 2009
5 *
6 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
7 */
8
9#ifndef __TOOLS_LINUX_ASM_BARRIER_H
10#define __TOOLS_LINUX_ASM_BARRIER_H
11
12/*
13 * Force strict CPU ordering.
14 * And yes, this is required on UP too when we're talking
15 * to devices.
16 */
17
18#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
19/* Fast-BCR without checkpoint synchronization */
20#define __ASM_BARRIER "bcr 14,0\n"
21#else
22#define __ASM_BARRIER "bcr 15,0\n"
23#endif
24
25#define mb() do { asm volatile(__ASM_BARRIER : : : "memory"); } while (0)
26
27#define rmb() mb()
28#define wmb() mb()
29
30#endif /* __TOOLS_LIB_ASM_BARRIER_H */
diff --git a/tools/arch/sh/include/asm/barrier.h b/tools/arch/sh/include/asm/barrier.h
new file mode 100644
index 000000000000..c18fd7599b97
--- /dev/null
+++ b/tools/arch/sh/include/asm/barrier.h
@@ -0,0 +1,32 @@
1/*
2 * Copied from the kernel sources:
3 *
4 * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima
5 * Copyright (C) 2002 Paul Mundt
6 */
7#ifndef __TOOLS_LINUX_ASM_SH_BARRIER_H
8#define __TOOLS_LINUX_ASM_SH_BARRIER_H
9
10/*
11 * A brief note on ctrl_barrier(), the control register write barrier.
12 *
13 * Legacy SH cores typically require a sequence of 8 nops after
14 * modification of a control register in order for the changes to take
15 * effect. On newer cores (like the sh4a and sh5) this is accomplished
16 * with icbi.
17 *
18 * Also note that on sh4a in the icbi case we can forego a synco for the
19 * write barrier, as it's not necessary for control registers.
20 *
21 * Historically we have only done this type of barrier for the MMUCR, but
22 * it's also necessary for the CCR, so we make it generic here instead.
23 */
24#if defined(__SH4A__) || defined(__SH5__)
25#define mb() __asm__ __volatile__ ("synco": : :"memory")
26#define rmb() mb()
27#define wmb() mb()
28#endif
29
30#include <asm-generic/barrier.h>
31
32#endif /* __TOOLS_LINUX_ASM_SH_BARRIER_H */
diff --git a/tools/arch/sparc/include/asm/barrier.h b/tools/arch/sparc/include/asm/barrier.h
new file mode 100644
index 000000000000..8c017b3b1391
--- /dev/null
+++ b/tools/arch/sparc/include/asm/barrier.h
@@ -0,0 +1,8 @@
1#ifndef ___TOOLS_LINUX_ASM_SPARC_BARRIER_H
2#define ___TOOLS_LINUX_ASM_SPARC_BARRIER_H
3#if defined(__sparc__) && defined(__arch64__)
4#include "barrier_64.h"
5#else
6#include "barrier_32.h"
7#endif
8#endif
diff --git a/tools/arch/sparc/include/asm/barrier_32.h b/tools/arch/sparc/include/asm/barrier_32.h
new file mode 100644
index 000000000000..c5eadd0a7233
--- /dev/null
+++ b/tools/arch/sparc/include/asm/barrier_32.h
@@ -0,0 +1,6 @@
1#ifndef __TOOLS_PERF_SPARC_BARRIER_H
2#define __TOOLS_PERF_SPARC_BARRIER_H
3
4#include <asm-generic/barrier.h>
5
6#endif /* !(__TOOLS_PERF_SPARC_BARRIER_H) */
diff --git a/tools/arch/sparc/include/asm/barrier_64.h b/tools/arch/sparc/include/asm/barrier_64.h
new file mode 100644
index 000000000000..9a7d7322c3f7
--- /dev/null
+++ b/tools/arch/sparc/include/asm/barrier_64.h
@@ -0,0 +1,42 @@
1#ifndef __TOOLS_LINUX_SPARC64_BARRIER_H
2#define __TOOLS_LINUX_SPARC64_BARRIER_H
3
4/* Copied from the kernel sources to tools/:
5 *
6 * These are here in an effort to more fully work around Spitfire Errata
7 * #51. Essentially, if a memory barrier occurs soon after a mispredicted
8 * branch, the chip can stop executing instructions until a trap occurs.
9 * Therefore, if interrupts are disabled, the chip can hang forever.
10 *
11 * It used to be believed that the memory barrier had to be right in the
12 * delay slot, but a case has been traced recently wherein the memory barrier
13 * was one instruction after the branch delay slot and the chip still hung.
14 * The offending sequence was the following in sym_wakeup_done() of the
15 * sym53c8xx_2 driver:
16 *
17 * call sym_ccb_from_dsa, 0
18 * movge %icc, 0, %l0
19 * brz,pn %o0, .LL1303
20 * mov %o0, %l2
21 * membar #LoadLoad
22 *
23 * The branch has to be mispredicted for the bug to occur. Therefore, we put
24 * the memory barrier explicitly into a "branch always, predicted taken"
25 * delay slot to avoid the problem case.
26 */
27#define membar_safe(type) \
28do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \
29 " membar " type "\n" \
30 "1:\n" \
31 : : : "memory"); \
32} while (0)
33
34/* The kernel always executes in TSO memory model these days,
35 * and furthermore most sparc64 chips implement more stringent
36 * memory ordering than required by the specifications.
37 */
38#define mb() membar_safe("#StoreLoad")
39#define rmb() __asm__ __volatile__("":::"memory")
40#define wmb() __asm__ __volatile__("":::"memory")
41
42#endif /* !(__TOOLS_LINUX_SPARC64_BARRIER_H) */
diff --git a/tools/arch/tile/include/asm/barrier.h b/tools/arch/tile/include/asm/barrier.h
new file mode 100644
index 000000000000..7d3692c3d4ac
--- /dev/null
+++ b/tools/arch/tile/include/asm/barrier.h
@@ -0,0 +1,15 @@
1#ifndef _TOOLS_LINUX_ASM_TILE_BARRIER_H
2#define _TOOLS_LINUX_ASM_TILE_BARRIER_H
3/*
4 * FIXME: This came from tools/perf/perf-sys.h, where it was first introduced
5 * in 620830b6954913647b7c7f68920cf48eddf6ad92, more work needed to make it
6 * more closely follow the Linux kernel arch/tile/include/asm/barrier.h file.
7 * Probably when we continue work on tools/ Kconfig support to have all the
8 * CONFIG_ needed for properly doing that.
9 */
10
11#define mb() asm volatile ("mf" ::: "memory")
12#define wmb() mb()
13#define rmb() mb()
14
15#endif /* _TOOLS_LINUX_ASM_TILE_BARRIER_H */
diff --git a/tools/arch/x86/include/asm/atomic.h b/tools/arch/x86/include/asm/atomic.h
new file mode 100644
index 000000000000..059e33e94260
--- /dev/null
+++ b/tools/arch/x86/include/asm/atomic.h
@@ -0,0 +1,65 @@
1#ifndef _TOOLS_LINUX_ASM_X86_ATOMIC_H
2#define _TOOLS_LINUX_ASM_X86_ATOMIC_H
3
4#include <linux/compiler.h>
5#include <linux/types.h>
6#include "rmwcc.h"
7
8#define LOCK_PREFIX "\n\tlock; "
9
10/*
11 * Atomic operations that C can't guarantee us. Useful for
12 * resource counting etc..
13 */
14
15#define ATOMIC_INIT(i) { (i) }
16
17/**
18 * atomic_read - read atomic variable
19 * @v: pointer of type atomic_t
20 *
21 * Atomically reads the value of @v.
22 */
23static inline int atomic_read(const atomic_t *v)
24{
25 return ACCESS_ONCE((v)->counter);
26}
27
28/**
29 * atomic_set - set atomic variable
30 * @v: pointer of type atomic_t
31 * @i: required value
32 *
33 * Atomically sets the value of @v to @i.
34 */
35static inline void atomic_set(atomic_t *v, int i)
36{
37 v->counter = i;
38}
39
40/**
41 * atomic_inc - increment atomic variable
42 * @v: pointer of type atomic_t
43 *
44 * Atomically increments @v by 1.
45 */
46static inline void atomic_inc(atomic_t *v)
47{
48 asm volatile(LOCK_PREFIX "incl %0"
49 : "+m" (v->counter));
50}
51
52/**
53 * atomic_dec_and_test - decrement and test
54 * @v: pointer of type atomic_t
55 *
56 * Atomically decrements @v by 1 and
57 * returns true if the result is 0, or false for all other
58 * cases.
59 */
60static inline int atomic_dec_and_test(atomic_t *v)
61{
62 GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", "e");
63}
64
65#endif /* _TOOLS_LINUX_ASM_X86_ATOMIC_H */
diff --git a/tools/arch/x86/include/asm/barrier.h b/tools/arch/x86/include/asm/barrier.h
new file mode 100644
index 000000000000..f366d8e550e4
--- /dev/null
+++ b/tools/arch/x86/include/asm/barrier.h
@@ -0,0 +1,28 @@
1#ifndef _TOOLS_LINUX_ASM_X86_BARRIER_H
2#define _TOOLS_LINUX_ASM_X86_BARRIER_H
3
4/*
5 * Copied from the Linux kernel sources, and also moving code
6 * out from tools/perf/perf-sys.h so as to make it be located
7 * in a place similar as in the kernel sources.
8 *
9 * Force strict CPU ordering.
10 * And yes, this is required on UP too when we're talking
11 * to devices.
12 */
13
14#if defined(__i386__)
15/*
16 * Some non-Intel clones support out of order store. wmb() ceases to be a
17 * nop for these.
18 */
19#define mb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
20#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
21#define wmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
22#elif defined(__x86_64__)
23#define mb() asm volatile("mfence":::"memory")
24#define rmb() asm volatile("lfence":::"memory")
25#define wmb() asm volatile("sfence" ::: "memory")
26#endif
27
28#endif /* _TOOLS_LINUX_ASM_X86_BARRIER_H */
diff --git a/tools/arch/x86/include/asm/rmwcc.h b/tools/arch/x86/include/asm/rmwcc.h
new file mode 100644
index 000000000000..a6669bc06939
--- /dev/null
+++ b/tools/arch/x86/include/asm/rmwcc.h
@@ -0,0 +1,41 @@
1#ifndef _TOOLS_LINUX_ASM_X86_RMWcc
2#define _TOOLS_LINUX_ASM_X86_RMWcc
3
4#ifdef CC_HAVE_ASM_GOTO
5
6#define __GEN_RMWcc(fullop, var, cc, ...) \
7do { \
8 asm_volatile_goto (fullop "; j" cc " %l[cc_label]" \
9 : : "m" (var), ## __VA_ARGS__ \
10 : "memory" : cc_label); \
11 return 0; \
12cc_label: \
13 return 1; \
14} while (0)
15
16#define GEN_UNARY_RMWcc(op, var, arg0, cc) \
17 __GEN_RMWcc(op " " arg0, var, cc)
18
19#define GEN_BINARY_RMWcc(op, var, vcon, val, arg0, cc) \
20 __GEN_RMWcc(op " %1, " arg0, var, cc, vcon (val))
21
22#else /* !CC_HAVE_ASM_GOTO */
23
24#define __GEN_RMWcc(fullop, var, cc, ...) \
25do { \
26 char c; \
27 asm volatile (fullop "; set" cc " %1" \
28 : "+m" (var), "=qm" (c) \
29 : __VA_ARGS__ : "memory"); \
30 return c != 0; \
31} while (0)
32
33#define GEN_UNARY_RMWcc(op, var, arg0, cc) \
34 __GEN_RMWcc(op " " arg0, var, cc)
35
36#define GEN_BINARY_RMWcc(op, var, vcon, val, arg0, cc) \
37 __GEN_RMWcc(op " %2, " arg0, var, cc, vcon (val))
38
39#endif /* CC_HAVE_ASM_GOTO */
40
41#endif /* _TOOLS_LINUX_ASM_X86_RMWcc */
diff --git a/tools/arch/xtensa/include/asm/barrier.h b/tools/arch/xtensa/include/asm/barrier.h
new file mode 100644
index 000000000000..583800bd7259
--- /dev/null
+++ b/tools/arch/xtensa/include/asm/barrier.h
@@ -0,0 +1,18 @@
1/*
2 * Copied from the kernel sources to tools/:
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2012 Tensilica Inc.
9 */
10
11#ifndef _TOOLS_LINUX_XTENSA_SYSTEM_H
12#define _TOOLS_LINUX_XTENSA_SYSTEM_H
13
14#define mb() ({ __asm__ __volatile__("memw" : : : "memory"); })
15#define rmb() barrier()
16#define wmb() mb()
17
18#endif /* _TOOLS_LINUX_XTENSA_SYSTEM_H */
diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build
index 10df57237a66..69c35cf09cad 100644
--- a/tools/build/Makefile.build
+++ b/tools/build/Makefile.build
@@ -37,7 +37,7 @@ subdir-obj-y :=
37 37
38# Build definitions 38# Build definitions
39build-file := $(dir)/Build 39build-file := $(dir)/Build
40include $(build-file) 40-include $(build-file)
41 41
42quiet_cmd_flex = FLEX $@ 42quiet_cmd_flex = FLEX $@
43quiet_cmd_bison = BISON $@ 43quiet_cmd_bison = BISON $@
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index 3a0b0ca2a28c..2975632d51e2 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -27,7 +27,7 @@ endef
27# the rule that uses them - an example for that is the 'bionic' 27# the rule that uses them - an example for that is the 'bionic'
28# feature check. ] 28# feature check. ]
29# 29#
30FEATURE_TESTS = \ 30FEATURE_TESTS ?= \
31 backtrace \ 31 backtrace \
32 dwarf \ 32 dwarf \
33 fortify-source \ 33 fortify-source \
@@ -53,7 +53,7 @@ FEATURE_TESTS = \
53 zlib \ 53 zlib \
54 lzma 54 lzma
55 55
56FEATURE_DISPLAY = \ 56FEATURE_DISPLAY ?= \
57 dwarf \ 57 dwarf \
58 glibc \ 58 glibc \
59 gtk2 \ 59 gtk2 \
diff --git a/tools/build/tests/ex/Build b/tools/build/tests/ex/Build
index 0e6c3e6767e6..70d876237c57 100644
--- a/tools/build/tests/ex/Build
+++ b/tools/build/tests/ex/Build
@@ -2,6 +2,7 @@ ex-y += ex.o
2ex-y += a.o 2ex-y += a.o
3ex-y += b.o 3ex-y += b.o
4ex-y += empty/ 4ex-y += empty/
5ex-y += empty2/
5 6
6libex-y += c.o 7libex-y += c.o
7libex-y += d.o 8libex-y += d.o
diff --git a/tools/build/tests/ex/empty2/README b/tools/build/tests/ex/empty2/README
new file mode 100644
index 000000000000..2107cc5bf5a9
--- /dev/null
+++ b/tools/build/tests/ex/empty2/README
@@ -0,0 +1,2 @@
1This directory is left intentionally without Build file
2to test proper nesting into Build-less directories.
diff --git a/tools/include/asm-generic/atomic-gcc.h b/tools/include/asm-generic/atomic-gcc.h
new file mode 100644
index 000000000000..2ba78c9f5701
--- /dev/null
+++ b/tools/include/asm-generic/atomic-gcc.h
@@ -0,0 +1,63 @@
1#ifndef __TOOLS_ASM_GENERIC_ATOMIC_H
2#define __TOOLS_ASM_GENERIC_ATOMIC_H
3
4#include <linux/compiler.h>
5#include <linux/types.h>
6
7/*
8 * Atomic operations that C can't guarantee us. Useful for
9 * resource counting etc..
10 *
11 * Excerpts obtained from the Linux kernel sources.
12 */
13
14#define ATOMIC_INIT(i) { (i) }
15
16/**
17 * atomic_read - read atomic variable
18 * @v: pointer of type atomic_t
19 *
20 * Atomically reads the value of @v.
21 */
22static inline int atomic_read(const atomic_t *v)
23{
24 return ACCESS_ONCE((v)->counter);
25}
26
27/**
28 * atomic_set - set atomic variable
29 * @v: pointer of type atomic_t
30 * @i: required value
31 *
32 * Atomically sets the value of @v to @i.
33 */
34static inline void atomic_set(atomic_t *v, int i)
35{
36 v->counter = i;
37}
38
39/**
40 * atomic_inc - increment atomic variable
41 * @v: pointer of type atomic_t
42 *
43 * Atomically increments @v by 1.
44 */
45static inline void atomic_inc(atomic_t *v)
46{
47 __sync_add_and_fetch(&v->counter, 1);
48}
49
50/**
51 * atomic_dec_and_test - decrement and test
52 * @v: pointer of type atomic_t
53 *
54 * Atomically decrements @v by 1 and
55 * returns true if the result is 0, or false for all other
56 * cases.
57 */
58static inline int atomic_dec_and_test(atomic_t *v)
59{
60 return __sync_sub_and_fetch(&v->counter, 1) == 0;
61}
62
63#endif /* __TOOLS_ASM_GENERIC_ATOMIC_H */
diff --git a/tools/include/asm-generic/barrier.h b/tools/include/asm-generic/barrier.h
new file mode 100644
index 000000000000..47b933903eaf
--- /dev/null
+++ b/tools/include/asm-generic/barrier.h
@@ -0,0 +1,44 @@
1/*
2 * Copied from the kernel sources to tools/perf/:
3 *
4 * Generic barrier definitions, originally based on MN10300 definitions.
5 *
6 * It should be possible to use these on really simple architectures,
7 * but it serves more as a starting point for new ports.
8 *
9 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
10 * Written by David Howells (dhowells@redhat.com)
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public Licence
14 * as published by the Free Software Foundation; either version
15 * 2 of the Licence, or (at your option) any later version.
16 */
17#ifndef __TOOLS_LINUX_ASM_GENERIC_BARRIER_H
18#define __TOOLS_LINUX_ASM_GENERIC_BARRIER_H
19
20#ifndef __ASSEMBLY__
21
22#include <linux/compiler.h>
23
24/*
25 * Force strict CPU ordering. And yes, this is required on UP too when we're
26 * talking to devices.
27 *
28 * Fall back to compiler barriers if nothing better is provided.
29 */
30
31#ifndef mb
32#define mb() barrier()
33#endif
34
35#ifndef rmb
36#define rmb() mb()
37#endif
38
39#ifndef wmb
40#define wmb() mb()
41#endif
42
43#endif /* !__ASSEMBLY__ */
44#endif /* __TOOLS_LINUX_ASM_GENERIC_BARRIER_H */
diff --git a/tools/include/asm/atomic.h b/tools/include/asm/atomic.h
new file mode 100644
index 000000000000..70794f538a86
--- /dev/null
+++ b/tools/include/asm/atomic.h
@@ -0,0 +1,10 @@
1#ifndef __TOOLS_LINUX_ASM_ATOMIC_H
2#define __TOOLS_LINUX_ASM_ATOMIC_H
3
4#if defined(__i386__) || defined(__x86_64__)
5#include "../../arch/x86/include/asm/atomic.h"
6#else
7#include <asm-generic/atomic-gcc.h>
8#endif
9
10#endif /* __TOOLS_LINUX_ASM_ATOMIC_H */
diff --git a/tools/include/asm/barrier.h b/tools/include/asm/barrier.h
new file mode 100644
index 000000000000..ac66ac594685
--- /dev/null
+++ b/tools/include/asm/barrier.h
@@ -0,0 +1,27 @@
1#if defined(__i386__) || defined(__x86_64__)
2#include "../../arch/x86/include/asm/barrier.h"
3#elif defined(__arm__)
4#include "../../arch/arm/include/asm/barrier.h"
5#elif defined(__aarch64__)
6#include "../../arch/arm64/include/asm/barrier.h"
7#elif defined(__powerpc__)
8#include "../../arch/powerpc/include/asm/barrier.h"
9#elif defined(__s390__)
10#include "../../arch/s390/include/asm/barrier.h"
11#elif defined(__sh__)
12#include "../../arch/sh/include/asm/barrier.h"
13#elif defined(__sparc__)
14#include "../../arch/sparc/include/asm/barrier.h"
15#elif defined(__tile__)
16#include "../../arch/tile/include/asm/barrier.h"
17#elif defined(__alpha__)
18#include "../../arch/alpha/include/asm/barrier.h"
19#elif defined(__mips__)
20#include "../../arch/mips/include/asm/barrier.h"
21#elif defined(__ia64__)
22#include "../../arch/ia64/include/asm/barrier.h"
23#elif defined(__xtensa__)
24#include "../../arch/xtensa/include/asm/barrier.h"
25#else
26#include <asm-generic/barrier.h>
27#endif
diff --git a/tools/include/linux/atomic.h b/tools/include/linux/atomic.h
new file mode 100644
index 000000000000..4e3d3d18ebab
--- /dev/null
+++ b/tools/include/linux/atomic.h
@@ -0,0 +1,6 @@
1#ifndef __TOOLS_LINUX_ATOMIC_H
2#define __TOOLS_LINUX_ATOMIC_H
3
4#include <asm/atomic.h>
5
6#endif /* __TOOLS_LINUX_ATOMIC_H */
diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 88461f09cc86..f0e72674c52d 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -1,6 +1,10 @@
1#ifndef _TOOLS_LINUX_COMPILER_H_ 1#ifndef _TOOLS_LINUX_COMPILER_H_
2#define _TOOLS_LINUX_COMPILER_H_ 2#define _TOOLS_LINUX_COMPILER_H_
3 3
4/* Optimization barrier */
5/* The "volatile" is due to gcc bugs */
6#define barrier() __asm__ __volatile__("": : :"memory")
7
4#ifndef __always_inline 8#ifndef __always_inline
5# define __always_inline inline __attribute__((always_inline)) 9# define __always_inline inline __attribute__((always_inline))
6#endif 10#endif
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/include/linux/kernel.h
index 09e8e7aea7c6..76df53539c2a 100644
--- a/tools/perf/util/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -1,5 +1,5 @@
1#ifndef PERF_LINUX_KERNEL_H_ 1#ifndef __TOOLS_LINUX_KERNEL_H
2#define PERF_LINUX_KERNEL_H_ 2#define __TOOLS_LINUX_KERNEL_H
3 3
4#include <stdarg.h> 4#include <stdarg.h>
5#include <stdio.h> 5#include <stdio.h>
diff --git a/tools/perf/util/include/linux/list.h b/tools/include/linux/list.h
index 76ddbc726343..76b014c96893 100644
--- a/tools/perf/util/include/linux/list.h
+++ b/tools/include/linux/list.h
@@ -1,10 +1,10 @@
1#include <linux/kernel.h> 1#include <linux/kernel.h>
2#include <linux/types.h> 2#include <linux/types.h>
3 3
4#include "../../../../include/linux/list.h" 4#include "../../../include/linux/list.h"
5 5
6#ifndef PERF_LIST_H 6#ifndef TOOLS_LIST_H
7#define PERF_LIST_H 7#define TOOLS_LIST_H
8/** 8/**
9 * list_del_range - deletes range of entries from list. 9 * list_del_range - deletes range of entries from list.
10 * @begin: first element in the range to delete from the list. 10 * @begin: first element in the range to delete from the list.
diff --git a/tools/include/linux/poison.h b/tools/include/linux/poison.h
new file mode 100644
index 000000000000..0c27bdf14233
--- /dev/null
+++ b/tools/include/linux/poison.h
@@ -0,0 +1 @@
#include "../../../include/linux/poison.h"
diff --git a/tools/include/linux/types.h b/tools/include/linux/types.h
index b5cf25e05df2..8ebf6278b2ef 100644
--- a/tools/include/linux/types.h
+++ b/tools/include/linux/types.h
@@ -60,6 +60,14 @@ typedef __u32 __bitwise __be32;
60typedef __u64 __bitwise __le64; 60typedef __u64 __bitwise __le64;
61typedef __u64 __bitwise __be64; 61typedef __u64 __bitwise __be64;
62 62
63typedef struct {
64 int counter;
65} atomic_t;
66
67#ifndef __aligned_u64
68# define __aligned_u64 __u64 __attribute__((aligned(8)))
69#endif
70
63struct list_head { 71struct list_head {
64 struct list_head *next, *prev; 72 struct list_head *next, *prev;
65}; 73};
diff --git a/tools/lib/traceevent/.gitignore b/tools/lib/traceevent/.gitignore
index 35f56be5a4cd..3c60335fe7be 100644
--- a/tools/lib/traceevent/.gitignore
+++ b/tools/lib/traceevent/.gitignore
@@ -1 +1,2 @@
1TRACEEVENT-CFLAGS 1TRACEEVENT-CFLAGS
2libtraceevent-dynamic-list
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index d410da335e3d..6daaff652aff 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -23,6 +23,7 @@ endef
23# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix. 23# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix.
24$(call allow-override,CC,$(CROSS_COMPILE)gcc) 24$(call allow-override,CC,$(CROSS_COMPILE)gcc)
25$(call allow-override,AR,$(CROSS_COMPILE)ar) 25$(call allow-override,AR,$(CROSS_COMPILE)ar)
26$(call allow-override,NM,$(CROSS_COMPILE)nm)
26 27
27EXT = -std=gnu99 28EXT = -std=gnu99
28INSTALL = install 29INSTALL = install
@@ -34,9 +35,15 @@ INSTALL = install
34DESTDIR ?= 35DESTDIR ?=
35DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))' 36DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
36 37
38LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
39ifeq ($(LP64), 1)
40 libdir_relative = lib64
41else
42 libdir_relative = lib
43endif
44
37prefix ?= /usr/local 45prefix ?= /usr/local
38bindir_relative = bin 46libdir = $(prefix)/$(libdir_relative)
39bindir = $(prefix)/$(bindir_relative)
40man_dir = $(prefix)/share/man 47man_dir = $(prefix)/share/man
41man_dir_SQ = '$(subst ','\'',$(man_dir))' 48man_dir_SQ = '$(subst ','\'',$(man_dir))'
42 49
@@ -58,7 +65,7 @@ ifeq ($(prefix),$(HOME))
58override plugin_dir = $(HOME)/.traceevent/plugins 65override plugin_dir = $(HOME)/.traceevent/plugins
59set_plugin_dir := 0 66set_plugin_dir := 0
60else 67else
61override plugin_dir = $(prefix)/lib/traceevent/plugins 68override plugin_dir = $(libdir)/traceevent/plugins
62endif 69endif
63endif 70endif
64 71
@@ -85,11 +92,11 @@ srctree := $(patsubst %/,%,$(dir $(srctree)))
85#$(info Determined 'srctree' to be $(srctree)) 92#$(info Determined 'srctree' to be $(srctree))
86endif 93endif
87 94
88export prefix bindir src obj 95export prefix libdir src obj
89 96
90# Shell quotes 97# Shell quotes
91bindir_SQ = $(subst ','\'',$(bindir)) 98libdir_SQ = $(subst ','\'',$(libdir))
92bindir_relative_SQ = $(subst ','\'',$(bindir_relative)) 99libdir_relative_SQ = $(subst ','\'',$(libdir_relative))
93plugin_dir_SQ = $(subst ','\'',$(plugin_dir)) 100plugin_dir_SQ = $(subst ','\'',$(plugin_dir))
94 101
95LIB_FILE = libtraceevent.a libtraceevent.so 102LIB_FILE = libtraceevent.a libtraceevent.so
@@ -151,8 +158,9 @@ PLUGINS_IN := $(PLUGINS:.so=-in.o)
151 158
152TE_IN := $(OUTPUT)libtraceevent-in.o 159TE_IN := $(OUTPUT)libtraceevent-in.o
153LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE)) 160LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))
161DYNAMIC_LIST_FILE := $(OUTPUT)libtraceevent-dynamic-list
154 162
155CMD_TARGETS = $(LIB_FILE) $(PLUGINS) 163CMD_TARGETS = $(LIB_FILE) $(PLUGINS) $(DYNAMIC_LIST_FILE)
156 164
157TARGETS = $(CMD_TARGETS) 165TARGETS = $(CMD_TARGETS)
158 166
@@ -169,6 +177,9 @@ $(OUTPUT)libtraceevent.so: $(TE_IN)
169$(OUTPUT)libtraceevent.a: $(TE_IN) 177$(OUTPUT)libtraceevent.a: $(TE_IN)
170 $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^ 178 $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^
171 179
180$(OUTPUT)libtraceevent-dynamic-list: $(PLUGINS)
181 $(QUIET_GEN)$(call do_generate_dynamic_list_file, $(PLUGINS), $@)
182
172plugins: $(PLUGINS) 183plugins: $(PLUGINS)
173 184
174__plugin_obj = $(notdir $@) 185__plugin_obj = $(notdir $@)
@@ -238,9 +249,16 @@ define do_install_plugins
238 done 249 done
239endef 250endef
240 251
252define do_generate_dynamic_list_file
253 (echo '{'; \
254 $(NM) -u -D $1 | awk 'NF>1 {print "\t"$$2";"}' | sort -u; \
255 echo '};'; \
256 ) > $2
257endef
258
241install_lib: all_cmd install_plugins 259install_lib: all_cmd install_plugins
242 $(call QUIET_INSTALL, $(LIB_FILE)) \ 260 $(call QUIET_INSTALL, $(LIB_FILE)) \
243 $(call do_install,$(LIB_FILE),$(bindir_SQ)) 261 $(call do_install,$(LIB_FILE),$(libdir_SQ))
244 262
245install_plugins: $(PLUGINS) 263install_plugins: $(PLUGINS)
246 $(call QUIET_INSTALL, trace_plugins) \ 264 $(call QUIET_INSTALL, trace_plugins) \
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 29f94f6f0d9e..cc25f059ab3d 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -1387,7 +1387,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f
1387 do_warning_event(event, "%s: no type found", __func__); 1387 do_warning_event(event, "%s: no type found", __func__);
1388 goto fail; 1388 goto fail;
1389 } 1389 }
1390 field->name = last_token; 1390 field->name = field->alias = last_token;
1391 1391
1392 if (test_type(type, EVENT_OP)) 1392 if (test_type(type, EVENT_OP))
1393 goto fail; 1393 goto fail;
@@ -1469,7 +1469,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f
1469 size_dynamic = type_size(field->name); 1469 size_dynamic = type_size(field->name);
1470 free_token(field->name); 1470 free_token(field->name);
1471 strcat(field->type, brackets); 1471 strcat(field->type, brackets);
1472 field->name = token; 1472 field->name = field->alias = token;
1473 type = read_token(&token); 1473 type = read_token(&token);
1474 } else { 1474 } else {
1475 char *new_type; 1475 char *new_type;
@@ -6444,6 +6444,8 @@ void pevent_ref(struct pevent *pevent)
6444void pevent_free_format_field(struct format_field *field) 6444void pevent_free_format_field(struct format_field *field)
6445{ 6445{
6446 free(field->type); 6446 free(field->type);
6447 if (field->alias != field->name)
6448 free(field->alias);
6447 free(field->name); 6449 free(field->name);
6448 free(field); 6450 free(field);
6449} 6451}
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 86a5839fb048..063b1971eb35 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -191,6 +191,7 @@ struct format_field {
191 struct event_format *event; 191 struct event_format *event;
192 char *type; 192 char *type;
193 char *name; 193 char *name;
194 char *alias;
194 int offset; 195 int offset;
195 int size; 196 int size;
196 unsigned int arraylen; 197 unsigned int arraylen;
diff --git a/tools/lib/traceevent/plugin_cfg80211.c b/tools/lib/traceevent/plugin_cfg80211.c
index 4592d8438318..ec57d0c1fbc2 100644
--- a/tools/lib/traceevent/plugin_cfg80211.c
+++ b/tools/lib/traceevent/plugin_cfg80211.c
@@ -4,6 +4,19 @@
4#include <endian.h> 4#include <endian.h>
5#include "event-parse.h" 5#include "event-parse.h"
6 6
7/*
8 * From glibc endian.h, for older systems where it is not present, e.g.: RHEL5,
9 * Fedora6.
10 */
11#ifndef le16toh
12# if __BYTE_ORDER == __LITTLE_ENDIAN
13# define le16toh(x) (x)
14# else
15# define le16toh(x) __bswap_16 (x)
16# endif
17#endif
18
19
7static unsigned long long 20static unsigned long long
8process___le16_to_cpup(struct trace_seq *s, unsigned long long *args) 21process___le16_to_cpup(struct trace_seq *s, unsigned long long *args)
9{ 22{
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 812f904193e8..09db62ba5786 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -28,3 +28,4 @@ config.mak.autogen
28*-flex.* 28*-flex.*
29*.pyc 29*.pyc
30*.pyo 30*.pyo
31.config-detected
diff --git a/tools/perf/Documentation/callchain-overhead-calculation.txt b/tools/perf/Documentation/callchain-overhead-calculation.txt
new file mode 100644
index 000000000000..1a757927195e
--- /dev/null
+++ b/tools/perf/Documentation/callchain-overhead-calculation.txt
@@ -0,0 +1,108 @@
1Overhead calculation
2--------------------
3The overhead can be shown in two columns as 'Children' and 'Self' when
4perf collects callchains. The 'self' overhead is simply calculated by
5adding all period values of the entry - usually a function (symbol).
6This is the value that perf shows traditionally and sum of all the
7'self' overhead values should be 100%.
8
9The 'children' overhead is calculated by adding all period values of
10the child functions so that it can show the total overhead of the
11higher level functions even if they don't directly execute much.
12'Children' here means functions that are called from another (parent)
13function.
14
15It might be confusing that the sum of all the 'children' overhead
16values exceeds 100% since each of them is already an accumulation of
17'self' overhead of its child functions. But with this enabled, users
18can find which function has the most overhead even if samples are
19spread over the children.
20
21Consider the following example; there are three functions like below.
22
23-----------------------
24void foo(void) {
25 /* do something */
26}
27
28void bar(void) {
29 /* do something */
30 foo();
31}
32
33int main(void) {
34 bar()
35 return 0;
36}
37-----------------------
38
39In this case 'foo' is a child of 'bar', and 'bar' is an immediate
40child of 'main' so 'foo' also is a child of 'main'. In other words,
41'main' is a parent of 'foo' and 'bar', and 'bar' is a parent of 'foo'.
42
43Suppose all samples are recorded in 'foo' and 'bar' only. When it's
44recorded with callchains the output will show something like below
45in the usual (self-overhead-only) output of perf report:
46
47----------------------------------
48Overhead Symbol
49........ .....................
50 60.00% foo
51 |
52 --- foo
53 bar
54 main
55 __libc_start_main
56
57 40.00% bar
58 |
59 --- bar
60 main
61 __libc_start_main
62----------------------------------
63
64When the --children option is enabled, the 'self' overhead values of
65child functions (i.e. 'foo' and 'bar') are added to the parents to
66calculate the 'children' overhead. In this case the report could be
67displayed as:
68
69-------------------------------------------
70Children Self Symbol
71........ ........ ....................
72 100.00% 0.00% __libc_start_main
73 |
74 --- __libc_start_main
75
76 100.00% 0.00% main
77 |
78 --- main
79 __libc_start_main
80
81 100.00% 40.00% bar
82 |
83 --- bar
84 main
85 __libc_start_main
86
87 60.00% 60.00% foo
88 |
89 --- foo
90 bar
91 main
92 __libc_start_main
93-------------------------------------------
94
95In the above output, the 'self' overhead of 'foo' (60%) was add to the
96'children' overhead of 'bar', 'main' and '\_\_libc_start_main'.
97Likewise, the 'self' overhead of 'bar' (40%) was added to the
98'children' overhead of 'main' and '\_\_libc_start_main'.
99
100So '\_\_libc_start_main' and 'main' are shown first since they have
101same (100%) 'children' overhead (even though they have zero 'self'
102overhead) and they are the parents of 'foo' and 'bar'.
103
104Since v3.16 the 'children' overhead is shown by default and the output
105is sorted by its values. The 'children' overhead is disabled by
106specifying --no-children option on the command line or by adding
107'report.children = false' or 'top.children = false' in the perf config
108file.
diff --git a/tools/perf/Documentation/perf-bench.txt b/tools/perf/Documentation/perf-bench.txt
index f6480cbf309b..bf3d0644bf10 100644
--- a/tools/perf/Documentation/perf-bench.txt
+++ b/tools/perf/Documentation/perf-bench.txt
@@ -210,6 +210,9 @@ Suite for evaluating hash tables.
210*wake*:: 210*wake*::
211Suite for evaluating wake calls. 211Suite for evaluating wake calls.
212 212
213*wake-parallel*::
214Suite for evaluating parallel wake calls.
215
213*requeue*:: 216*requeue*::
214Suite for evaluating requeue calls. 217Suite for evaluating requeue calls.
215 218
diff --git a/tools/perf/Documentation/perf-inject.txt b/tools/perf/Documentation/perf-inject.txt
index dc7442cf3d7f..b876ae312699 100644
--- a/tools/perf/Documentation/perf-inject.txt
+++ b/tools/perf/Documentation/perf-inject.txt
@@ -44,6 +44,33 @@ OPTIONS
44--kallsyms=<file>:: 44--kallsyms=<file>::
45 kallsyms pathname 45 kallsyms pathname
46 46
47--itrace::
48 Decode Instruction Tracing data, replacing it with synthesized events.
49 Options are:
50
51 i synthesize instructions events
52 b synthesize branches events
53 c synthesize branches events (calls only)
54 r synthesize branches events (returns only)
55 x synthesize transactions events
56 e synthesize error events
57 d create a debug log
58 g synthesize a call chain (use with i or x)
59
60 The default is all events i.e. the same as --itrace=ibxe
61
62 In addition, the period (default 100000) for instructions events
63 can be specified in units of:
64
65 i instructions
66 t ticks
67 ms milliseconds
68 us microseconds
69 ns nanoseconds (default)
70
71 Also the call chain size (default 16, max. 1024) for instructions or
72 transactions events can be specified.
73
47SEE ALSO 74SEE ALSO
48-------- 75--------
49linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1] 76linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1]
diff --git a/tools/perf/Documentation/perf-kmem.txt b/tools/perf/Documentation/perf-kmem.txt
index 23219c65c16f..ff0f433b3fce 100644
--- a/tools/perf/Documentation/perf-kmem.txt
+++ b/tools/perf/Documentation/perf-kmem.txt
@@ -37,7 +37,11 @@ OPTIONS
37 37
38-s <key[,key2...]>:: 38-s <key[,key2...]>::
39--sort=<key[,key2...]>:: 39--sort=<key[,key2...]>::
40 Sort the output (default: frag,hit,bytes) 40 Sort the output (default: 'frag,hit,bytes' for slab and 'bytes,hit'
41 for page). Available sort keys are 'ptr, callsite, bytes, hit,
42 pingpong, frag' for slab and 'page, callsite, bytes, hit, order,
43 migtype, gfp' for page. This option should be preceded by one of the
44 mode selection options - i.e. --slab, --page, --alloc and/or --caller.
41 45
42-l <num>:: 46-l <num>::
43--line=<num>:: 47--line=<num>::
@@ -52,6 +56,11 @@ OPTIONS
52--page:: 56--page::
53 Analyze page allocator events 57 Analyze page allocator events
54 58
59--live::
60 Show live page stat. The perf kmem shows total allocation stat by
61 default, but this option shows live (currently allocated) pages
62 instead. (This option works with --page option only)
63
55SEE ALSO 64SEE ALSO
56-------- 65--------
57linkperf:perf-record[1] 66linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index 6252e776009c..6a5bb2b17039 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -151,6 +151,12 @@ STAT LIVE OPTIONS
151 Show events other than HLT (x86 only) or Wait state (s390 only) 151 Show events other than HLT (x86 only) or Wait state (s390 only)
152 that take longer than duration usecs. 152 that take longer than duration usecs.
153 153
154--proc-map-timeout::
155 When processing pre-existing threads /proc/XXX/mmap, it may take
156 a long time, because the file may be huge. A time out is needed
157 in such cases.
158 This option sets the time out limit. The default value is 500 ms.
159
154SEE ALSO 160SEE ALSO
155-------- 161--------
156linkperf:perf-top[1], linkperf:perf-record[1], linkperf:perf-report[1], 162linkperf:perf-top[1], linkperf:perf-record[1], linkperf:perf-report[1],
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 239609c09f83..3a8a9ba2b041 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -14,11 +14,13 @@ or
14or 14or
15'perf probe' [options] --del='[GROUP:]EVENT' [...] 15'perf probe' [options] --del='[GROUP:]EVENT' [...]
16or 16or
17'perf probe' --list 17'perf probe' --list[=[GROUP:]EVENT]
18or 18or
19'perf probe' [options] --line='LINE' 19'perf probe' [options] --line='LINE'
20or 20or
21'perf probe' [options] --vars='PROBEPOINT' 21'perf probe' [options] --vars='PROBEPOINT'
22or
23'perf probe' [options] --funcs
22 24
23DESCRIPTION 25DESCRIPTION
24----------- 26-----------
@@ -64,8 +66,8 @@ OPTIONS
64 classes(e.g. [a-z], [!A-Z]). 66 classes(e.g. [a-z], [!A-Z]).
65 67
66-l:: 68-l::
67--list:: 69--list[=[GROUP:]EVENT]::
68 List up current probe events. 70 List up current probe events. This can also accept filtering patterns of event names.
69 71
70-L:: 72-L::
71--line=:: 73--line=::
@@ -81,10 +83,15 @@ OPTIONS
81 (Only for --vars) Show external defined variables in addition to local 83 (Only for --vars) Show external defined variables in addition to local
82 variables. 84 variables.
83 85
86--no-inlines::
87 (Only for --add) Search only for non-inlined functions. The functions
88 which do not have instances are ignored.
89
84-F:: 90-F::
85--funcs:: 91--funcs[=FILTER]::
86 Show available functions in given module or kernel. With -x/--exec, 92 Show available functions in given module or kernel. With -x/--exec,
87 can also list functions in a user space executable / shared library. 93 can also list functions in a user space executable / shared library.
94 This also can accept a FILTER rule argument.
88 95
89--filter=FILTER:: 96--filter=FILTER::
90 (Only for --vars and --funcs) Set filter. FILTER is a combination of glob 97 (Only for --vars and --funcs) Set filter. FILTER is a combination of glob
@@ -148,7 +155,7 @@ Each probe argument follows below syntax.
148 [NAME=]LOCALVAR|$retval|%REG|@SYMBOL[:TYPE] 155 [NAME=]LOCALVAR|$retval|%REG|@SYMBOL[:TYPE]
149 156
150'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.) 157'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.)
151'$vars' special argument is also available for NAME, it is expanded to the local variables which can access at given probe point. 158'$vars' and '$params' special arguments are also available for NAME, '$vars' is expanded to the local variables (including function parameters) which can access at given probe point. '$params' is expanded to only the function parameters.
152'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type. 159'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type.
153 160
154On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid. 161On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid.
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 4847a793de65..9b9d9d086680 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -108,6 +108,8 @@ OPTIONS
108 Number of mmap data pages (must be a power of two) or size 108 Number of mmap data pages (must be a power of two) or size
109 specification with appended unit character - B/K/M/G. The 109 specification with appended unit character - B/K/M/G. The
110 size is rounded up to have nearest pages power of two value. 110 size is rounded up to have nearest pages power of two value.
111 Also, by adding a comma, the number of mmap pages for AUX
112 area tracing can be specified.
111 113
112--group:: 114--group::
113 Put all events in a single event group. This precedes the --event 115 Put all events in a single event group. This precedes the --event
@@ -145,16 +147,21 @@ OPTIONS
145 147
146-s:: 148-s::
147--stat:: 149--stat::
148 Per thread counts. 150 Record per-thread event counts. Use it with 'perf report -T' to see
151 the values.
149 152
150-d:: 153-d::
151--data:: 154--data::
152 Sample addresses. 155 Record the sample addresses.
153 156
154-T:: 157-T::
155--timestamp:: 158--timestamp::
156 Sample timestamps. Use it with 'perf report -D' to see the timestamps, 159 Record the sample timestamps. Use it with 'perf report -D' to see the
157 for instance. 160 timestamps, for instance.
161
162-P::
163--period::
164 Record the sample period.
158 165
159-n:: 166-n::
160--no-samples:: 167--no-samples::
@@ -257,6 +264,18 @@ records. See clock_gettime(). In particular CLOCK_MONOTONIC and
257CLOCK_MONOTONIC_RAW are supported, some events might also allow 264CLOCK_MONOTONIC_RAW are supported, some events might also allow
258CLOCK_BOOTTIME, CLOCK_REALTIME and CLOCK_TAI. 265CLOCK_BOOTTIME, CLOCK_REALTIME and CLOCK_TAI.
259 266
267-S::
268--snapshot::
269Select AUX area tracing Snapshot Mode. This option is valid only with an
270AUX area tracing event. Optionally the number of bytes to capture per
271snapshot can be specified. In Snapshot Mode, trace data is captured only when
272signal SIGUSR2 is received.
273
274--proc-map-timeout::
275When processing pre-existing threads /proc/XXX/mmap, it may take a long time,
276because the file may be huge. A time out is needed in such cases.
277This option sets the time out limit. The default value is 500 ms.
278
260SEE ALSO 279SEE ALSO
261-------- 280--------
262linkperf:perf-stat[1], linkperf:perf-list[1] 281linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 4879cf638824..c33b69f3374f 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -34,7 +34,8 @@ OPTIONS
34 34
35-T:: 35-T::
36--threads:: 36--threads::
37 Show per-thread event counters 37 Show per-thread event counters. The input data file should be recorded
38 with -s option.
38-c:: 39-c::
39--comms=:: 40--comms=::
40 Only consider symbols in these comms. CSV that understands 41 Only consider symbols in these comms. CSV that understands
@@ -193,6 +194,7 @@ OPTIONS
193 Accumulate callchain of children to parent entry so that then can 194 Accumulate callchain of children to parent entry so that then can
194 show up in the output. The output will have a new "Children" column 195 show up in the output. The output will have a new "Children" column
195 and will be sorted on the data. It requires callchains are recorded. 196 and will be sorted on the data. It requires callchains are recorded.
197 See the `overhead calculation' section for more details.
196 198
197--max-stack:: 199--max-stack::
198 Set the stack depth limit when parsing the callchain, anything 200 Set the stack depth limit when parsing the callchain, anything
@@ -323,6 +325,37 @@ OPTIONS
323--header-only:: 325--header-only::
324 Show only perf.data header (forces --stdio). 326 Show only perf.data header (forces --stdio).
325 327
328--itrace::
329 Options for decoding instruction tracing data. The options are:
330
331 i synthesize instructions events
332 b synthesize branches events
333 c synthesize branches events (calls only)
334 r synthesize branches events (returns only)
335 x synthesize transactions events
336 e synthesize error events
337 d create a debug log
338 g synthesize a call chain (use with i or x)
339
340 The default is all events i.e. the same as --itrace=ibxe
341
342 In addition, the period (default 100000) for instructions events
343 can be specified in units of:
344
345 i instructions
346 t ticks
347 ms milliseconds
348 us microseconds
349 ns nanoseconds (default)
350
351 Also the call chain size (default 16, max. 1024) for instructions or
352 transactions events can be specified.
353
354 To disable decoding entirely, use --no-itrace.
355
356
357include::callchain-overhead-calculation.txt[]
358
326SEE ALSO 359SEE ALSO
327-------- 360--------
328linkperf:perf-stat[1], linkperf:perf-annotate[1] 361linkperf:perf-stat[1], linkperf:perf-annotate[1]
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 79445750fcb3..c82df572fac2 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -115,7 +115,8 @@ OPTIONS
115-f:: 115-f::
116--fields:: 116--fields::
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, srcline, period. 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
119 srcline, period, flags.
119 Field list can be prepended with the type, trace, sw or hw, 120 Field list can be prepended with the type, trace, sw or hw,
120 to indicate to which event type the field list applies. 121 to indicate to which event type the field list applies.
121 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace 122 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
@@ -165,6 +166,12 @@ OPTIONS
165 166
166 At this point usage is displayed, and perf-script exits. 167 At this point usage is displayed, and perf-script exits.
167 168
169 The flags field is synthesized and may have a value when Instruction
170 Trace decoding. The flags are "bcrosyiABEx" which stand for branch,
171 call, return, conditional, system, asynchronous, interrupt,
172 transaction abort, trace begin, trace end, and in transaction,
173 respectively.
174
168 Finally, a user may not set fields to none for all event types. 175 Finally, a user may not set fields to none for all event types.
169 i.e., -f "" is not allowed. 176 i.e., -f "" is not allowed.
170 177
@@ -221,6 +228,34 @@ OPTIONS
221--header-only 228--header-only
222 Show only perf.data header. 229 Show only perf.data header.
223 230
231--itrace::
232 Options for decoding instruction tracing data. The options are:
233
234 i synthesize instructions events
235 b synthesize branches events
236 c synthesize branches events (calls only)
237 r synthesize branches events (returns only)
238 x synthesize transactions events
239 e synthesize error events
240 d create a debug log
241 g synthesize a call chain (use with i or x)
242
243 The default is all events i.e. the same as --itrace=ibxe
244
245 In addition, the period (default 100000) for instructions events
246 can be specified in units of:
247
248 i instructions
249 t ticks
250 ms milliseconds
251 us microseconds
252 ns nanoseconds (default)
253
254 Also the call chain size (default 16, max. 1024) for instructions or
255 transactions events can be specified.
256
257 To disable decoding entirely, use --no-itrace.
258
224SEE ALSO 259SEE ALSO
225-------- 260--------
226linkperf:perf-record[1], linkperf:perf-script-perl[1], 261linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 3265b1070518..776aec4d0927 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -168,7 +168,7 @@ Default is to monitor all CPUS.
168 Accumulate callchain of children to parent entry so that then can 168 Accumulate callchain of children to parent entry so that then can
169 show up in the output. The output will have a new "Children" column 169 show up in the output. The output will have a new "Children" column
170 and will be sorted on the data. It requires -g/--call-graph option 170 and will be sorted on the data. It requires -g/--call-graph option
171 enabled. 171 enabled. See the `overhead calculation' section for more details.
172 172
173--max-stack:: 173--max-stack::
174 Set the stack depth limit when parsing the callchain, anything 174 Set the stack depth limit when parsing the callchain, anything
@@ -201,6 +201,12 @@ Default is to monitor all CPUS.
201 Force each column width to the provided list, for large terminal 201 Force each column width to the provided list, for large terminal
202 readability. 0 means no limit (default behavior). 202 readability. 0 means no limit (default behavior).
203 203
204--proc-map-timeout::
205 When processing pre-existing threads /proc/XXX/mmap, it may take
206 a long time, because the file may be huge. A time out is needed
207 in such cases.
208 This option sets the time out limit. The default value is 500 ms.
209
204 210
205INTERACTIVE PROMPTING KEYS 211INTERACTIVE PROMPTING KEYS
206-------------------------- 212--------------------------
@@ -234,6 +240,7 @@ INTERACTIVE PROMPTING KEYS
234 240
235Pressing any unmapped key displays a menu, and prompts for input. 241Pressing any unmapped key displays a menu, and prompts for input.
236 242
243include::callchain-overhead-calculation.txt[]
237 244
238SEE ALSO 245SEE ALSO
239-------- 246--------
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index ba03fd5d1a54..7ea078658a87 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -35,7 +35,7 @@ OPTIONS
35 35
36-e:: 36-e::
37--expr:: 37--expr::
38 List of events to show, currently only syscall names. 38 List of syscalls to show, currently only syscall names.
39 Prefixing with ! shows all syscalls but the ones specified. You may 39 Prefixing with ! shows all syscalls but the ones specified. You may
40 need to escape it. 40 need to escape it.
41 41
@@ -121,6 +121,11 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
121--event:: 121--event::
122 Trace other events, see 'perf list' for a complete list. 122 Trace other events, see 'perf list' for a complete list.
123 123
124--proc-map-timeout::
125 When processing pre-existing threads /proc/XXX/mmap, it may take a long time,
126 because the file may be huge. A time out is needed in such cases.
127 This option sets the time out limit. The default value is 500 ms.
128
124PAGEFAULTS 129PAGEFAULTS
125---------- 130----------
126 131
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 11ccbb22ea2b..fe50a1b34aa0 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -1,12 +1,30 @@
1tools/perf 1tools/perf
2tools/arch/alpha/include/asm/barrier.h
3tools/arch/arm/include/asm/barrier.h
4tools/arch/ia64/include/asm/barrier.h
5tools/arch/mips/include/asm/barrier.h
6tools/arch/powerpc/include/asm/barrier.h
7tools/arch/s390/include/asm/barrier.h
8tools/arch/sh/include/asm/barrier.h
9tools/arch/sparc/include/asm/barrier.h
10tools/arch/sparc/include/asm/barrier_32.h
11tools/arch/sparc/include/asm/barrier_64.h
12tools/arch/tile/include/asm/barrier.h
13tools/arch/x86/include/asm/barrier.h
14tools/arch/xtensa/include/asm/barrier.h
2tools/scripts 15tools/scripts
3tools/build 16tools/build
17tools/arch/x86/include/asm/atomic.h
18tools/arch/x86/include/asm/rmwcc.h
4tools/lib/traceevent 19tools/lib/traceevent
5tools/lib/api 20tools/lib/api
6tools/lib/symbol/kallsyms.c 21tools/lib/symbol/kallsyms.c
7tools/lib/symbol/kallsyms.h 22tools/lib/symbol/kallsyms.h
8tools/lib/util/find_next_bit.c 23tools/lib/util/find_next_bit.c
24tools/include/asm/atomic.h
25tools/include/asm/barrier.h
9tools/include/asm/bug.h 26tools/include/asm/bug.h
27tools/include/asm-generic/barrier.h
10tools/include/asm-generic/bitops/arch_hweight.h 28tools/include/asm-generic/bitops/arch_hweight.h
11tools/include/asm-generic/bitops/atomic.h 29tools/include/asm-generic/bitops/atomic.h
12tools/include/asm-generic/bitops/const_hweight.h 30tools/include/asm-generic/bitops/const_hweight.h
@@ -17,35 +35,35 @@ tools/include/asm-generic/bitops/fls64.h
17tools/include/asm-generic/bitops/fls.h 35tools/include/asm-generic/bitops/fls.h
18tools/include/asm-generic/bitops/hweight.h 36tools/include/asm-generic/bitops/hweight.h
19tools/include/asm-generic/bitops.h 37tools/include/asm-generic/bitops.h
38tools/include/linux/atomic.h
20tools/include/linux/bitops.h 39tools/include/linux/bitops.h
21tools/include/linux/compiler.h 40tools/include/linux/compiler.h
22tools/include/linux/export.h 41tools/include/linux/export.h
23tools/include/linux/hash.h 42tools/include/linux/hash.h
43tools/include/linux/kernel.h
44tools/include/linux/list.h
24tools/include/linux/log2.h 45tools/include/linux/log2.h
46tools/include/linux/poison.h
25tools/include/linux/types.h 47tools/include/linux/types.h
26include/asm-generic/bitops/arch_hweight.h 48include/asm-generic/bitops/arch_hweight.h
27include/asm-generic/bitops/const_hweight.h 49include/asm-generic/bitops/const_hweight.h
28include/asm-generic/bitops/fls64.h 50include/asm-generic/bitops/fls64.h
29include/asm-generic/bitops/__fls.h 51include/asm-generic/bitops/__fls.h
30include/asm-generic/bitops/fls.h 52include/asm-generic/bitops/fls.h
31include/linux/const.h
32include/linux/perf_event.h 53include/linux/perf_event.h
33include/linux/rbtree.h 54include/linux/rbtree.h
34include/linux/list.h 55include/linux/list.h
35include/linux/hash.h 56include/linux/hash.h
36include/linux/stringify.h 57include/linux/stringify.h
37lib/find_next_bit.c
38lib/hweight.c 58lib/hweight.c
39lib/rbtree.c 59lib/rbtree.c
40include/linux/swab.h 60include/linux/swab.h
41arch/*/include/asm/unistd*.h 61arch/*/include/asm/unistd*.h
42arch/*/include/asm/perf_regs.h
43arch/*/include/uapi/asm/unistd*.h 62arch/*/include/uapi/asm/unistd*.h
44arch/*/include/uapi/asm/perf_regs.h 63arch/*/include/uapi/asm/perf_regs.h
45arch/*/lib/memcpy*.S 64arch/*/lib/memcpy*.S
46arch/*/lib/memset*.S 65arch/*/lib/memset*.S
47include/linux/poison.h 66include/linux/poison.h
48include/linux/magic.h
49include/linux/hw_breakpoint.h 67include/linux/hw_breakpoint.h
50include/linux/rbtree_augmented.h 68include/linux/rbtree_augmented.h
51include/uapi/linux/perf_event.h 69include/uapi/linux/perf_event.h
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index c43a20517591..1af0cfeb7a57 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -73,6 +73,8 @@ include config/utilities.mak
73# for CTF data format. 73# for CTF data format.
74# 74#
75# Define NO_LZMA if you do not want to support compressed (xz) kernel modules 75# Define NO_LZMA if you do not want to support compressed (xz) kernel modules
76#
77# Define NO_AUXTRACE if you do not want AUX area tracing support
76 78
77ifeq ($(srctree),) 79ifeq ($(srctree),)
78srctree := $(patsubst %/,%,$(dir $(shell pwd))) 80srctree := $(patsubst %/,%,$(dir $(shell pwd)))
@@ -171,6 +173,9 @@ endif
171LIBTRACEEVENT = $(TE_PATH)libtraceevent.a 173LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
172export LIBTRACEEVENT 174export LIBTRACEEVENT
173 175
176LIBTRACEEVENT_DYNAMIC_LIST = $(TE_PATH)libtraceevent-dynamic-list
177LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS = -Xlinker --dynamic-list=$(LIBTRACEEVENT_DYNAMIC_LIST)
178
174LIBAPI = $(LIB_PATH)libapi.a 179LIBAPI = $(LIB_PATH)libapi.a
175export LIBAPI 180export LIBAPI
176 181
@@ -185,8 +190,9 @@ python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT
185PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) 190PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
186PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI) 191PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI)
187 192
188$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) 193$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
189 $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \ 194 $(QUIET_GEN)CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \
195 $(PYTHON_WORD) util/setup.py \
190 --quiet build_ext; \ 196 --quiet build_ext; \
191 mkdir -p $(OUTPUT)python && \ 197 mkdir -p $(OUTPUT)python && \
192 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/ 198 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
@@ -276,8 +282,9 @@ build := -f $(srctree)/tools/build/Makefile.build dir=. obj
276$(PERF_IN): $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h FORCE 282$(PERF_IN): $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h FORCE
277 $(Q)$(MAKE) $(build)=perf 283 $(Q)$(MAKE) $(build)=perf
278 284
279$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) 285$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST)
280 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(PERF_IN) $(LIBS) -o $@ 286 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS) \
287 $(PERF_IN) $(LIBS) -o $@
281 288
282$(GTK_IN): FORCE 289$(GTK_IN): FORCE
283 $(Q)$(MAKE) $(build)=gtk 290 $(Q)$(MAKE) $(build)=gtk
@@ -371,7 +378,13 @@ $(LIB_FILE): $(LIBPERF_IN)
371LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ) 378LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ)
372 379
373$(LIBTRACEEVENT): FORCE 380$(LIBTRACEEVENT): FORCE
374 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a plugins 381 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a
382
383libtraceevent_plugins: FORCE
384 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) plugins
385
386$(LIBTRACEEVENT_DYNAMIC_LIST): libtraceevent_plugins
387 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent-dynamic-list
375 388
376$(LIBTRACEEVENT)-clean: 389$(LIBTRACEEVENT)-clean:
377 $(call QUIET_CLEAN, libtraceevent) 390 $(call QUIET_CLEAN, libtraceevent)
@@ -462,7 +475,7 @@ check: $(OUTPUT)common-cmds.h
462 475
463install-gtk: 476install-gtk:
464 477
465install-bin: all install-gtk 478install-tools: all install-gtk
466 $(call QUIET_INSTALL, binaries) \ 479 $(call QUIET_INSTALL, binaries) \
467 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \ 480 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \
468 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \ 481 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \
@@ -500,12 +513,16 @@ endif
500 $(call QUIET_INSTALL, perf_completion-script) \ 513 $(call QUIET_INSTALL, perf_completion-script) \
501 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \ 514 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \
502 $(INSTALL) perf-completion.sh '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf' 515 $(INSTALL) perf-completion.sh '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
516
517install-tests: all install-gtk
503 $(call QUIET_INSTALL, tests) \ 518 $(call QUIET_INSTALL, tests) \
504 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ 519 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
505 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ 520 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
506 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \ 521 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
507 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' 522 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
508 523
524install-bin: install-tools install-tests
525
509install: install-bin try-install-man install-traceevent-plugins 526install: install-bin try-install-man install-traceevent-plugins
510 527
511install-python_ext: 528install-python_ext:
@@ -549,4 +566,5 @@ FORCE:
549.PHONY: all install clean config-clean strip install-gtk 566.PHONY: all install clean config-clean strip install-gtk
550.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell 567.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
551.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE single_dep 568.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE single_dep
569.PHONY: libtraceevent_plugins
552 570
diff --git a/tools/perf/arch/arm64/Build b/tools/perf/arch/arm64/Build
index 54afe4a467e7..41bf61da476a 100644
--- a/tools/perf/arch/arm64/Build
+++ b/tools/perf/arch/arm64/Build
@@ -1 +1,2 @@
1libperf-y += util/ 1libperf-y += util/
2libperf-$(CONFIG_DWARF_UNWIND) += tests/
diff --git a/tools/perf/arch/arm64/include/perf_regs.h b/tools/perf/arch/arm64/include/perf_regs.h
index 1d3f39c3aa56..4e5af27e3fbf 100644
--- a/tools/perf/arch/arm64/include/perf_regs.h
+++ b/tools/perf/arch/arm64/include/perf_regs.h
@@ -5,8 +5,11 @@
5#include <linux/types.h> 5#include <linux/types.h>
6#include <asm/perf_regs.h> 6#include <asm/perf_regs.h>
7 7
8void perf_regs_load(u64 *regs);
9
8#define PERF_REGS_MASK ((1ULL << PERF_REG_ARM64_MAX) - 1) 10#define PERF_REGS_MASK ((1ULL << PERF_REG_ARM64_MAX) - 1)
9#define PERF_REGS_MAX PERF_REG_ARM64_MAX 11#define PERF_REGS_MAX PERF_REG_ARM64_MAX
12#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64
10 13
11#define PERF_REG_IP PERF_REG_ARM64_PC 14#define PERF_REG_IP PERF_REG_ARM64_PC
12#define PERF_REG_SP PERF_REG_ARM64_SP 15#define PERF_REG_SP PERF_REG_ARM64_SP
diff --git a/tools/perf/arch/arm64/tests/Build b/tools/perf/arch/arm64/tests/Build
new file mode 100644
index 000000000000..b30eff9bcc83
--- /dev/null
+++ b/tools/perf/arch/arm64/tests/Build
@@ -0,0 +1,2 @@
1libperf-y += regs_load.o
2libperf-y += dwarf-unwind.o
diff --git a/tools/perf/arch/arm64/tests/dwarf-unwind.c b/tools/perf/arch/arm64/tests/dwarf-unwind.c
new file mode 100644
index 000000000000..cf04a4c91c59
--- /dev/null
+++ b/tools/perf/arch/arm64/tests/dwarf-unwind.c
@@ -0,0 +1,61 @@
1#include <string.h>
2#include "perf_regs.h"
3#include "thread.h"
4#include "map.h"
5#include "event.h"
6#include "debug.h"
7#include "tests/tests.h"
8
9#define STACK_SIZE 8192
10
11static int sample_ustack(struct perf_sample *sample,
12 struct thread *thread, u64 *regs)
13{
14 struct stack_dump *stack = &sample->user_stack;
15 struct map *map;
16 unsigned long sp;
17 u64 stack_size, *buf;
18
19 buf = malloc(STACK_SIZE);
20 if (!buf) {
21 pr_debug("failed to allocate sample uregs data\n");
22 return -1;
23 }
24
25 sp = (unsigned long) regs[PERF_REG_ARM64_SP];
26
27 map = map_groups__find(thread->mg, MAP__VARIABLE, (u64) sp);
28 if (!map) {
29 pr_debug("failed to get stack map\n");
30 free(buf);
31 return -1;
32 }
33
34 stack_size = map->end - sp;
35 stack_size = stack_size > STACK_SIZE ? STACK_SIZE : stack_size;
36
37 memcpy(buf, (void *) sp, stack_size);
38 stack->data = (char *) buf;
39 stack->size = stack_size;
40 return 0;
41}
42
43int test__arch_unwind_sample(struct perf_sample *sample,
44 struct thread *thread)
45{
46 struct regs_dump *regs = &sample->user_regs;
47 u64 *buf;
48
49 buf = calloc(1, sizeof(u64) * PERF_REGS_MAX);
50 if (!buf) {
51 pr_debug("failed to allocate sample uregs data\n");
52 return -1;
53 }
54
55 perf_regs_load(buf);
56 regs->abi = PERF_SAMPLE_REGS_ABI;
57 regs->regs = buf;
58 regs->mask = PERF_REGS_MASK;
59
60 return sample_ustack(sample, thread, buf);
61}
diff --git a/tools/perf/arch/arm64/tests/regs_load.S b/tools/perf/arch/arm64/tests/regs_load.S
new file mode 100644
index 000000000000..025b46e579a6
--- /dev/null
+++ b/tools/perf/arch/arm64/tests/regs_load.S
@@ -0,0 +1,46 @@
1#include <linux/linkage.h>
2
3.text
4.type perf_regs_load,%function
5#define STR_REG(r) str x##r, [x0, 8 * r]
6#define LDR_REG(r) ldr x##r, [x0, 8 * r]
7#define SP (8 * 31)
8#define PC (8 * 32)
9ENTRY(perf_regs_load)
10 STR_REG(0)
11 STR_REG(1)
12 STR_REG(2)
13 STR_REG(3)
14 STR_REG(4)
15 STR_REG(5)
16 STR_REG(6)
17 STR_REG(7)
18 STR_REG(8)
19 STR_REG(9)
20 STR_REG(10)
21 STR_REG(11)
22 STR_REG(12)
23 STR_REG(13)
24 STR_REG(14)
25 STR_REG(15)
26 STR_REG(16)
27 STR_REG(17)
28 STR_REG(18)
29 STR_REG(19)
30 STR_REG(20)
31 STR_REG(21)
32 STR_REG(22)
33 STR_REG(23)
34 STR_REG(24)
35 STR_REG(25)
36 STR_REG(26)
37 STR_REG(27)
38 STR_REG(28)
39 STR_REG(29)
40 STR_REG(30)
41 mov x1, sp
42 str x1, [x0, #SP]
43 str x30, [x0, #PC]
44 LDR_REG(1)
45 ret
46ENDPROC(perf_regs_load)
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index 49776f190abf..b7bb42c44694 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -61,7 +61,7 @@ const char *const mips_triplets[] = {
61static bool lookup_path(char *name) 61static bool lookup_path(char *name)
62{ 62{
63 bool found = false; 63 bool found = false;
64 char *path, *tmp; 64 char *path, *tmp = NULL;
65 char buf[PATH_MAX]; 65 char buf[PATH_MAX];
66 char *env = getenv("PATH"); 66 char *env = getenv("PATH");
67 67
diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build
index 0af6e9b3f728..7b8b0d1a1b62 100644
--- a/tools/perf/arch/powerpc/util/Build
+++ b/tools/perf/arch/powerpc/util/Build
@@ -1,4 +1,5 @@
1libperf-y += header.o 1libperf-y += header.o
2libperf-y += sym-handling.o
2 3
3libperf-$(CONFIG_DWARF) += dwarf-regs.o 4libperf-$(CONFIG_DWARF) += dwarf-regs.o
4libperf-$(CONFIG_DWARF) += skip-callchain-idx.o 5libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
new file mode 100644
index 000000000000..bbc1a50768dd
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -0,0 +1,82 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2, as
4 * published by the Free Software Foundation.
5 *
6 * Copyright (C) 2015 Naveen N. Rao, IBM Corporation
7 */
8
9#include "debug.h"
10#include "symbol.h"
11#include "map.h"
12#include "probe-event.h"
13
14#ifdef HAVE_LIBELF_SUPPORT
15bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
16{
17 return ehdr.e_type == ET_EXEC ||
18 ehdr.e_type == ET_REL ||
19 ehdr.e_type == ET_DYN;
20}
21
22#if defined(_CALL_ELF) && _CALL_ELF == 2
23void arch__elf_sym_adjust(GElf_Sym *sym)
24{
25 sym->st_value += PPC64_LOCAL_ENTRY_OFFSET(sym->st_other);
26}
27#endif
28#endif
29
30#if !defined(_CALL_ELF) || _CALL_ELF != 2
31int arch__choose_best_symbol(struct symbol *syma,
32 struct symbol *symb __maybe_unused)
33{
34 char *sym = syma->name;
35
36 /* Skip over any initial dot */
37 if (*sym == '.')
38 sym++;
39
40 /* Avoid "SyS" kernel syscall aliases */
41 if (strlen(sym) >= 3 && !strncmp(sym, "SyS", 3))
42 return SYMBOL_B;
43 if (strlen(sym) >= 10 && !strncmp(sym, "compat_SyS", 10))
44 return SYMBOL_B;
45
46 return SYMBOL_A;
47}
48
49/* Allow matching against dot variants */
50int arch__compare_symbol_names(const char *namea, const char *nameb)
51{
52 /* Skip over initial dot */
53 if (*namea == '.')
54 namea++;
55 if (*nameb == '.')
56 nameb++;
57
58 return strcmp(namea, nameb);
59}
60#endif
61
62#if defined(_CALL_ELF) && _CALL_ELF == 2
63bool arch__prefers_symtab(void)
64{
65 return true;
66}
67
68#define PPC64LE_LEP_OFFSET 8
69
70void arch__fix_tev_from_maps(struct perf_probe_event *pev,
71 struct probe_trace_event *tev, struct map *map)
72{
73 /*
74 * ppc64 ABIv2 local entry point is currently always 2 instructions
75 * (8 bytes) after the global entry point.
76 */
77 if (!pev->uprobes && map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) {
78 tev->point.address += PPC64LE_LEP_OFFSET;
79 tev->point.offset += PPC64LE_LEP_OFFSET;
80 }
81}
82#endif
diff --git a/tools/perf/bench/Build b/tools/perf/bench/Build
index 5ce98023d518..c3ab760e06b4 100644
--- a/tools/perf/bench/Build
+++ b/tools/perf/bench/Build
@@ -3,6 +3,7 @@ perf-y += sched-pipe.o
3perf-y += mem-memcpy.o 3perf-y += mem-memcpy.o
4perf-y += futex-hash.o 4perf-y += futex-hash.o
5perf-y += futex-wake.o 5perf-y += futex-wake.o
6perf-y += futex-wake-parallel.o
6perf-y += futex-requeue.o 7perf-y += futex-requeue.o
7 8
8perf-$(CONFIG_X86_64) += mem-memcpy-x86-64-asm.o 9perf-$(CONFIG_X86_64) += mem-memcpy-x86-64-asm.o
diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h
index 3c4dd44d45cb..70b2f718cc21 100644
--- a/tools/perf/bench/bench.h
+++ b/tools/perf/bench/bench.h
@@ -33,6 +33,8 @@ extern int bench_mem_memcpy(int argc, const char **argv,
33extern int bench_mem_memset(int argc, const char **argv, const char *prefix); 33extern int bench_mem_memset(int argc, const char **argv, const char *prefix);
34extern int bench_futex_hash(int argc, const char **argv, const char *prefix); 34extern int bench_futex_hash(int argc, const char **argv, const char *prefix);
35extern int bench_futex_wake(int argc, const char **argv, const char *prefix); 35extern int bench_futex_wake(int argc, const char **argv, const char *prefix);
36extern int bench_futex_wake_parallel(int argc, const char **argv,
37 const char *prefix);
36extern int bench_futex_requeue(int argc, const char **argv, const char *prefix); 38extern int bench_futex_requeue(int argc, const char **argv, const char *prefix);
37 39
38#define BENCH_FORMAT_DEFAULT_STR "default" 40#define BENCH_FORMAT_DEFAULT_STR "default"
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
new file mode 100644
index 000000000000..6d8c9fa2a16c
--- /dev/null
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -0,0 +1,294 @@
1/*
2 * Copyright (C) 2015 Davidlohr Bueso.
3 *
4 * Block a bunch of threads and let parallel waker threads wakeup an
5 * equal amount of them. The program output reflects the avg latency
6 * for each individual thread to service its share of work. Ultimately
7 * it can be used to measure futex_wake() changes.
8 */
9
10#include "../perf.h"
11#include "../util/util.h"
12#include "../util/stat.h"
13#include "../util/parse-options.h"
14#include "../util/header.h"
15#include "bench.h"
16#include "futex.h"
17
18#include <err.h>
19#include <stdlib.h>
20#include <sys/time.h>
21#include <pthread.h>
22
23struct thread_data {
24 pthread_t worker;
25 unsigned int nwoken;
26 struct timeval runtime;
27};
28
29static unsigned int nwakes = 1;
30
31/* all threads will block on the same futex -- hash bucket chaos ;) */
32static u_int32_t futex = 0;
33
34static pthread_t *blocked_worker;
35static bool done = false, silent = false, fshared = false;
36static unsigned int nblocked_threads = 0, nwaking_threads = 0;
37static pthread_mutex_t thread_lock;
38static pthread_cond_t thread_parent, thread_worker;
39static struct stats waketime_stats, wakeup_stats;
40static unsigned int ncpus, threads_starting;
41static int futex_flag = 0;
42
43static const struct option options[] = {
44 OPT_UINTEGER('t', "threads", &nblocked_threads, "Specify amount of threads"),
45 OPT_UINTEGER('w', "nwakers", &nwaking_threads, "Specify amount of waking threads"),
46 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
47 OPT_BOOLEAN( 'S', "shared", &fshared, "Use shared futexes instead of private ones"),
48 OPT_END()
49};
50
51static const char * const bench_futex_wake_parallel_usage[] = {
52 "perf bench futex wake-parallel <options>",
53 NULL
54};
55
56static void *waking_workerfn(void *arg)
57{
58 struct thread_data *waker = (struct thread_data *) arg;
59 struct timeval start, end;
60
61 gettimeofday(&start, NULL);
62
63 waker->nwoken = futex_wake(&futex, nwakes, futex_flag);
64 if (waker->nwoken != nwakes)
65 warnx("couldn't wakeup all tasks (%d/%d)",
66 waker->nwoken, nwakes);
67
68 gettimeofday(&end, NULL);
69 timersub(&end, &start, &waker->runtime);
70
71 pthread_exit(NULL);
72 return NULL;
73}
74
75static void wakeup_threads(struct thread_data *td, pthread_attr_t thread_attr)
76{
77 unsigned int i;
78
79 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
80
81 /* create and block all threads */
82 for (i = 0; i < nwaking_threads; i++) {
83 /*
84 * Thread creation order will impact per-thread latency
85 * as it will affect the order to acquire the hb spinlock.
86 * For now let the scheduler decide.
87 */
88 if (pthread_create(&td[i].worker, &thread_attr,
89 waking_workerfn, (void *)&td[i]))
90 err(EXIT_FAILURE, "pthread_create");
91 }
92
93 for (i = 0; i < nwaking_threads; i++)
94 if (pthread_join(td[i].worker, NULL))
95 err(EXIT_FAILURE, "pthread_join");
96}
97
98static void *blocked_workerfn(void *arg __maybe_unused)
99{
100 pthread_mutex_lock(&thread_lock);
101 threads_starting--;
102 if (!threads_starting)
103 pthread_cond_signal(&thread_parent);
104 pthread_cond_wait(&thread_worker, &thread_lock);
105 pthread_mutex_unlock(&thread_lock);
106
107 while (1) { /* handle spurious wakeups */
108 if (futex_wait(&futex, 0, NULL, futex_flag) != EINTR)
109 break;
110 }
111
112 pthread_exit(NULL);
113 return NULL;
114}
115
116static void block_threads(pthread_t *w, pthread_attr_t thread_attr)
117{
118 cpu_set_t cpu;
119 unsigned int i;
120
121 threads_starting = nblocked_threads;
122
123 /* create and block all threads */
124 for (i = 0; i < nblocked_threads; i++) {
125 CPU_ZERO(&cpu);
126 CPU_SET(i % ncpus, &cpu);
127
128 if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu))
129 err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
130
131 if (pthread_create(&w[i], &thread_attr, blocked_workerfn, NULL))
132 err(EXIT_FAILURE, "pthread_create");
133 }
134}
135
136static void print_run(struct thread_data *waking_worker, unsigned int run_num)
137{
138 unsigned int i, wakeup_avg;
139 double waketime_avg, waketime_stddev;
140 struct stats __waketime_stats, __wakeup_stats;
141
142 init_stats(&__wakeup_stats);
143 init_stats(&__waketime_stats);
144
145 for (i = 0; i < nwaking_threads; i++) {
146 update_stats(&__waketime_stats, waking_worker[i].runtime.tv_usec);
147 update_stats(&__wakeup_stats, waking_worker[i].nwoken);
148 }
149
150 waketime_avg = avg_stats(&__waketime_stats);
151 waketime_stddev = stddev_stats(&__waketime_stats);
152 wakeup_avg = avg_stats(&__wakeup_stats);
153
154 printf("[Run %d]: Avg per-thread latency (waking %d/%d threads) "
155 "in %.4f ms (+-%.2f%%)\n", run_num + 1, wakeup_avg,
156 nblocked_threads, waketime_avg/1e3,
157 rel_stddev_stats(waketime_stddev, waketime_avg));
158}
159
160static void print_summary(void)
161{
162 unsigned int wakeup_avg;
163 double waketime_avg, waketime_stddev;
164
165 waketime_avg = avg_stats(&waketime_stats);
166 waketime_stddev = stddev_stats(&waketime_stats);
167 wakeup_avg = avg_stats(&wakeup_stats);
168
169 printf("Avg per-thread latency (waking %d/%d threads) in %.4f ms (+-%.2f%%)\n",
170 wakeup_avg,
171 nblocked_threads,
172 waketime_avg/1e3,
173 rel_stddev_stats(waketime_stddev, waketime_avg));
174}
175
176
177static void do_run_stats(struct thread_data *waking_worker)
178{
179 unsigned int i;
180
181 for (i = 0; i < nwaking_threads; i++) {
182 update_stats(&waketime_stats, waking_worker[i].runtime.tv_usec);
183 update_stats(&wakeup_stats, waking_worker[i].nwoken);
184 }
185
186}
187
188static void toggle_done(int sig __maybe_unused,
189 siginfo_t *info __maybe_unused,
190 void *uc __maybe_unused)
191{
192 done = true;
193}
194
195int bench_futex_wake_parallel(int argc, const char **argv,
196 const char *prefix __maybe_unused)
197{
198 int ret = 0;
199 unsigned int i, j;
200 struct sigaction act;
201 pthread_attr_t thread_attr;
202 struct thread_data *waking_worker;
203
204 argc = parse_options(argc, argv, options,
205 bench_futex_wake_parallel_usage, 0);
206 if (argc) {
207 usage_with_options(bench_futex_wake_parallel_usage, options);
208 exit(EXIT_FAILURE);
209 }
210
211 sigfillset(&act.sa_mask);
212 act.sa_sigaction = toggle_done;
213 sigaction(SIGINT, &act, NULL);
214
215 ncpus = sysconf(_SC_NPROCESSORS_ONLN);
216 if (!nblocked_threads)
217 nblocked_threads = ncpus;
218
219 /* some sanity checks */
220 if (nwaking_threads > nblocked_threads || !nwaking_threads)
221 nwaking_threads = nblocked_threads;
222
223 if (nblocked_threads % nwaking_threads)
224 errx(EXIT_FAILURE, "Must be perfectly divisible");
225 /*
226 * Each thread will wakeup nwakes tasks in
227 * a single futex_wait call.
228 */
229 nwakes = nblocked_threads/nwaking_threads;
230
231 blocked_worker = calloc(nblocked_threads, sizeof(*blocked_worker));
232 if (!blocked_worker)
233 err(EXIT_FAILURE, "calloc");
234
235 if (!fshared)
236 futex_flag = FUTEX_PRIVATE_FLAG;
237
238 printf("Run summary [PID %d]: blocking on %d threads (at [%s] "
239 "futex %p), %d threads waking up %d at a time.\n\n",
240 getpid(), nblocked_threads, fshared ? "shared":"private",
241 &futex, nwaking_threads, nwakes);
242
243 init_stats(&wakeup_stats);
244 init_stats(&waketime_stats);
245
246 pthread_attr_init(&thread_attr);
247 pthread_mutex_init(&thread_lock, NULL);
248 pthread_cond_init(&thread_parent, NULL);
249 pthread_cond_init(&thread_worker, NULL);
250
251 for (j = 0; j < bench_repeat && !done; j++) {
252 waking_worker = calloc(nwaking_threads, sizeof(*waking_worker));
253 if (!waking_worker)
254 err(EXIT_FAILURE, "calloc");
255
256 /* create, launch & block all threads */
257 block_threads(blocked_worker, thread_attr);
258
259 /* make sure all threads are already blocked */
260 pthread_mutex_lock(&thread_lock);
261 while (threads_starting)
262 pthread_cond_wait(&thread_parent, &thread_lock);
263 pthread_cond_broadcast(&thread_worker);
264 pthread_mutex_unlock(&thread_lock);
265
266 usleep(100000);
267
268 /* Ok, all threads are patiently blocked, start waking folks up */
269 wakeup_threads(waking_worker, thread_attr);
270
271 for (i = 0; i < nblocked_threads; i++) {
272 ret = pthread_join(blocked_worker[i], NULL);
273 if (ret)
274 err(EXIT_FAILURE, "pthread_join");
275 }
276
277 do_run_stats(waking_worker);
278 if (!silent)
279 print_run(waking_worker, j);
280
281 free(waking_worker);
282 }
283
284 /* cleanup & report results */
285 pthread_cond_destroy(&thread_parent);
286 pthread_cond_destroy(&thread_worker);
287 pthread_mutex_destroy(&thread_lock);
288 pthread_attr_destroy(&thread_attr);
289
290 print_summary();
291
292 free(blocked_worker);
293 return ret;
294}
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index 929f762be47e..e5e41d3bdce7 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -60,7 +60,12 @@ static void *workerfn(void *arg __maybe_unused)
60 pthread_cond_wait(&thread_worker, &thread_lock); 60 pthread_cond_wait(&thread_worker, &thread_lock);
61 pthread_mutex_unlock(&thread_lock); 61 pthread_mutex_unlock(&thread_lock);
62 62
63 futex_wait(&futex1, 0, NULL, futex_flag); 63 while (1) {
64 if (futex_wait(&futex1, 0, NULL, futex_flag) != EINTR)
65 break;
66 }
67
68 pthread_exit(NULL);
64 return NULL; 69 return NULL;
65} 70}
66 71
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index ba5efa4710b5..870b7e665a20 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -8,6 +8,7 @@
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 "../util/parse-options.h"
11#include "../util/cloexec.h"
11 12
12#include "bench.h" 13#include "bench.h"
13 14
@@ -23,6 +24,7 @@
23#include <pthread.h> 24#include <pthread.h>
24#include <sys/mman.h> 25#include <sys/mman.h>
25#include <sys/time.h> 26#include <sys/time.h>
27#include <sys/resource.h>
26#include <sys/wait.h> 28#include <sys/wait.h>
27#include <sys/prctl.h> 29#include <sys/prctl.h>
28#include <sys/types.h> 30#include <sys/types.h>
@@ -51,6 +53,9 @@ struct thread_data {
51 unsigned int loops_done; 53 unsigned int loops_done;
52 u64 val; 54 u64 val;
53 u64 runtime_ns; 55 u64 runtime_ns;
56 u64 system_time_ns;
57 u64 user_time_ns;
58 double speed_gbs;
54 pthread_mutex_t *process_lock; 59 pthread_mutex_t *process_lock;
55}; 60};
56 61
@@ -1042,6 +1047,7 @@ static void *worker_thread(void *__tdata)
1042 u64 bytes_done; 1047 u64 bytes_done;
1043 long work_done; 1048 long work_done;
1044 u32 l; 1049 u32 l;
1050 struct rusage rusage;
1045 1051
1046 bind_to_cpumask(td->bind_cpumask); 1052 bind_to_cpumask(td->bind_cpumask);
1047 bind_to_memnode(td->bind_node); 1053 bind_to_memnode(td->bind_node);
@@ -1194,6 +1200,13 @@ static void *worker_thread(void *__tdata)
1194 timersub(&stop, &start0, &diff); 1200 timersub(&stop, &start0, &diff);
1195 td->runtime_ns = diff.tv_sec * 1000000000ULL; 1201 td->runtime_ns = diff.tv_sec * 1000000000ULL;
1196 td->runtime_ns += diff.tv_usec * 1000ULL; 1202 td->runtime_ns += diff.tv_usec * 1000ULL;
1203 td->speed_gbs = bytes_done / (td->runtime_ns / 1e9) / 1e9;
1204
1205 getrusage(RUSAGE_THREAD, &rusage);
1206 td->system_time_ns = rusage.ru_stime.tv_sec * 1000000000ULL;
1207 td->system_time_ns += rusage.ru_stime.tv_usec * 1000ULL;
1208 td->user_time_ns = rusage.ru_utime.tv_sec * 1000000000ULL;
1209 td->user_time_ns += rusage.ru_utime.tv_usec * 1000ULL;
1197 1210
1198 free_data(thread_data, g->p.bytes_thread); 1211 free_data(thread_data, g->p.bytes_thread);
1199 1212
@@ -1420,7 +1433,7 @@ static int __bench_numa(const char *name)
1420 double runtime_sec_min; 1433 double runtime_sec_min;
1421 int wait_stat; 1434 int wait_stat;
1422 double bytes; 1435 double bytes;
1423 int i, t; 1436 int i, t, p;
1424 1437
1425 if (init()) 1438 if (init())
1426 return -1; 1439 return -1;
@@ -1556,6 +1569,24 @@ static int __bench_numa(const char *name)
1556 print_res(name, bytes / runtime_sec_max / 1e9, 1569 print_res(name, bytes / runtime_sec_max / 1e9,
1557 "GB/sec,", "total-speed", "GB/sec total speed"); 1570 "GB/sec,", "total-speed", "GB/sec total speed");
1558 1571
1572 if (g->p.show_details >= 2) {
1573 char tname[32];
1574 struct thread_data *td;
1575 for (p = 0; p < g->p.nr_proc; p++) {
1576 for (t = 0; t < g->p.nr_threads; t++) {
1577 memset(tname, 0, 32);
1578 td = g->threads + p*g->p.nr_threads + t;
1579 snprintf(tname, 32, "process%d:thread%d", p, t);
1580 print_res(tname, td->speed_gbs,
1581 "GB/sec", "thread-speed", "GB/sec/thread speed");
1582 print_res(tname, td->system_time_ns / 1e9,
1583 "secs", "thread-system-time", "system CPU time/thread");
1584 print_res(tname, td->user_time_ns / 1e9,
1585 "secs", "thread-user-time", "user CPU time/thread");
1586 }
1587 }
1588 }
1589
1559 free(pids); 1590 free(pids);
1560 1591
1561 deinit(); 1592 deinit();
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 71bf7451c0ca..2c1bec39c30e 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -59,6 +59,10 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
59 (al->sym == NULL || 59 (al->sym == NULL ||
60 strcmp(ann->sym_hist_filter, al->sym->name) != 0)) { 60 strcmp(ann->sym_hist_filter, al->sym->name) != 0)) {
61 /* We're only interested in a symbol named sym_hist_filter */ 61 /* We're only interested in a symbol named sym_hist_filter */
62 /*
63 * FIXME: why isn't this done in the symbol_filter when loading
64 * the DSO?
65 */
62 if (al->sym != NULL) { 66 if (al->sym != NULL) {
63 rb_erase(&al->sym->rb_node, 67 rb_erase(&al->sym->rb_node,
64 &al->map->dso->symbols[al->map->type]); 68 &al->map->dso->symbols[al->map->type]);
@@ -84,6 +88,7 @@ static int process_sample_event(struct perf_tool *tool,
84{ 88{
85 struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool); 89 struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool);
86 struct addr_location al; 90 struct addr_location al;
91 int ret = 0;
87 92
88 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { 93 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
89 pr_warning("problem processing %d event, skipping it.\n", 94 pr_warning("problem processing %d event, skipping it.\n",
@@ -92,15 +97,16 @@ static int process_sample_event(struct perf_tool *tool,
92 } 97 }
93 98
94 if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap)) 99 if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap))
95 return 0; 100 goto out_put;
96 101
97 if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al, ann)) { 102 if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al, ann)) {
98 pr_warning("problem incrementing symbol count, " 103 pr_warning("problem incrementing symbol count, "
99 "skipping event\n"); 104 "skipping event\n");
100 return -1; 105 ret = -1;
101 } 106 }
102 107out_put:
103 return 0; 108 addr_location__put(&al);
109 return ret;
104} 110}
105 111
106static int hist_entry__tty_annotate(struct hist_entry *he, 112static int hist_entry__tty_annotate(struct hist_entry *he,
@@ -283,7 +289,6 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
283 }, 289 },
284 }; 290 };
285 struct perf_data_file file = { 291 struct perf_data_file file = {
286 .path = input_name,
287 .mode = PERF_DATA_MODE_READ, 292 .mode = PERF_DATA_MODE_READ,
288 }; 293 };
289 const struct option options[] = { 294 const struct option options[] = {
@@ -324,6 +329,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
324 "objdump binary to use for disassembly and annotations"), 329 "objdump binary to use for disassembly and annotations"),
325 OPT_BOOLEAN(0, "group", &symbol_conf.event_group, 330 OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
326 "Show event group information together"), 331 "Show event group information together"),
332 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
333 "Show a column with the sum of periods"),
327 OPT_END() 334 OPT_END()
328 }; 335 };
329 int ret = hists__init(); 336 int ret = hists__init();
@@ -340,6 +347,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
340 else if (annotate.use_gtk) 347 else if (annotate.use_gtk)
341 use_browser = 2; 348 use_browser = 2;
342 349
350 file.path = input_name;
351
343 setup_browser(true); 352 setup_browser(true);
344 353
345 annotate.session = perf_session__new(&file, false, &annotate.tool); 354 annotate.session = perf_session__new(&file, false, &annotate.tool);
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index b9a56fa83330..b5314e452ec7 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -58,6 +58,7 @@ static struct bench mem_benchmarks[] = {
58static struct bench futex_benchmarks[] = { 58static struct bench futex_benchmarks[] = {
59 { "hash", "Benchmark for futex hash table", bench_futex_hash }, 59 { "hash", "Benchmark for futex hash table", bench_futex_hash },
60 { "wake", "Benchmark for futex wake calls", bench_futex_wake }, 60 { "wake", "Benchmark for futex wake calls", bench_futex_wake },
61 { "wake-parallel", "Benchmark for parallel futex wake calls", bench_futex_wake_parallel },
61 { "requeue", "Benchmark for futex requeue calls", bench_futex_requeue }, 62 { "requeue", "Benchmark for futex requeue calls", bench_futex_requeue },
62 { "all", "Test all futex benchmarks", NULL }, 63 { "all", "Test all futex benchmarks", NULL },
63 { NULL, NULL, NULL } 64 { NULL, NULL, NULL }
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index feb420f74c2d..9fe93c8d4fcf 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -69,6 +69,15 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
69 session = perf_session__new(&file, false, &build_id__mark_dso_hit_ops); 69 session = perf_session__new(&file, false, &build_id__mark_dso_hit_ops);
70 if (session == NULL) 70 if (session == NULL)
71 return -1; 71 return -1;
72
73 /*
74 * We take all buildids when the file contains AUX area tracing data
75 * because we do not decode the trace because it would take too long.
76 */
77 if (!perf_data_file__is_pipe(&file) &&
78 perf_header__has_feat(&session->header, HEADER_AUXTRACE))
79 with_hits = false;
80
72 /* 81 /*
73 * in pipe-mode, the only way to get the buildids is to parse 82 * in pipe-mode, the only way to get the buildids is to parse
74 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID 83 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index df6307b4050a..daaa7dca9c3b 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -328,6 +328,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
328{ 328{
329 struct addr_location al; 329 struct addr_location al;
330 struct hists *hists = evsel__hists(evsel); 330 struct hists *hists = evsel__hists(evsel);
331 int ret = -1;
331 332
332 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { 333 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
333 pr_warning("problem processing %d event, skipping it.\n", 334 pr_warning("problem processing %d event, skipping it.\n",
@@ -338,7 +339,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
338 if (hists__add_entry(hists, &al, sample->period, 339 if (hists__add_entry(hists, &al, sample->period,
339 sample->weight, sample->transaction)) { 340 sample->weight, sample->transaction)) {
340 pr_warning("problem incrementing symbol period, skipping event\n"); 341 pr_warning("problem incrementing symbol period, skipping event\n");
341 return -1; 342 goto out_put;
342 } 343 }
343 344
344 /* 345 /*
@@ -350,8 +351,10 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
350 hists->stats.total_period += sample->period; 351 hists->stats.total_period += sample->period;
351 if (!al.filtered) 352 if (!al.filtered)
352 hists->stats.total_non_filtered_period += sample->period; 353 hists->stats.total_non_filtered_period += sample->period;
353 354 ret = 0;
354 return 0; 355out_put:
356 addr_location__put(&al);
357 return ret;
355} 358}
356 359
357static struct perf_tool tool = { 360static struct perf_tool tool = {
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 40a33d7334cc..52ec66b23607 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -16,6 +16,7 @@
16#include "util/debug.h" 16#include "util/debug.h"
17#include "util/build-id.h" 17#include "util/build-id.h"
18#include "util/data.h" 18#include "util/data.h"
19#include "util/auxtrace.h"
19 20
20#include "util/parse-options.h" 21#include "util/parse-options.h"
21 22
@@ -26,10 +27,12 @@ struct perf_inject {
26 struct perf_session *session; 27 struct perf_session *session;
27 bool build_ids; 28 bool build_ids;
28 bool sched_stat; 29 bool sched_stat;
30 bool have_auxtrace;
29 const char *input_name; 31 const char *input_name;
30 struct perf_data_file output; 32 struct perf_data_file output;
31 u64 bytes_written; 33 u64 bytes_written;
32 struct list_head samples; 34 struct list_head samples;
35 struct itrace_synth_opts itrace_synth_opts;
33}; 36};
34 37
35struct event_entry { 38struct event_entry {
@@ -38,14 +41,11 @@ struct event_entry {
38 union perf_event event[0]; 41 union perf_event event[0];
39}; 42};
40 43
41static int perf_event__repipe_synth(struct perf_tool *tool, 44static int output_bytes(struct perf_inject *inject, void *buf, size_t sz)
42 union perf_event *event)
43{ 45{
44 struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
45 ssize_t size; 46 ssize_t size;
46 47
47 size = perf_data_file__write(&inject->output, event, 48 size = perf_data_file__write(&inject->output, buf, sz);
48 event->header.size);
49 if (size < 0) 49 if (size < 0)
50 return -errno; 50 return -errno;
51 51
@@ -53,6 +53,15 @@ static int perf_event__repipe_synth(struct perf_tool *tool,
53 return 0; 53 return 0;
54} 54}
55 55
56static int perf_event__repipe_synth(struct perf_tool *tool,
57 union perf_event *event)
58{
59 struct perf_inject *inject = container_of(tool, struct perf_inject,
60 tool);
61
62 return output_bytes(inject, event, event->header.size);
63}
64
56static int perf_event__repipe_oe_synth(struct perf_tool *tool, 65static int perf_event__repipe_oe_synth(struct perf_tool *tool,
57 union perf_event *event, 66 union perf_event *event,
58 struct ordered_events *oe __maybe_unused) 67 struct ordered_events *oe __maybe_unused)
@@ -86,6 +95,79 @@ static int perf_event__repipe_attr(struct perf_tool *tool,
86 return perf_event__repipe_synth(tool, event); 95 return perf_event__repipe_synth(tool, event);
87} 96}
88 97
98#ifdef HAVE_AUXTRACE_SUPPORT
99
100static int copy_bytes(struct perf_inject *inject, int fd, off_t size)
101{
102 char buf[4096];
103 ssize_t ssz;
104 int ret;
105
106 while (size > 0) {
107 ssz = read(fd, buf, min(size, (off_t)sizeof(buf)));
108 if (ssz < 0)
109 return -errno;
110 ret = output_bytes(inject, buf, ssz);
111 if (ret)
112 return ret;
113 size -= ssz;
114 }
115
116 return 0;
117}
118
119static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
120 union perf_event *event,
121 struct perf_session *session
122 __maybe_unused)
123{
124 struct perf_inject *inject = container_of(tool, struct perf_inject,
125 tool);
126 int ret;
127
128 inject->have_auxtrace = true;
129
130 if (!inject->output.is_pipe) {
131 off_t offset;
132
133 offset = lseek(inject->output.fd, 0, SEEK_CUR);
134 if (offset == -1)
135 return -errno;
136 ret = auxtrace_index__auxtrace_event(&session->auxtrace_index,
137 event, offset);
138 if (ret < 0)
139 return ret;
140 }
141
142 if (perf_data_file__is_pipe(session->file) || !session->one_mmap) {
143 ret = output_bytes(inject, event, event->header.size);
144 if (ret < 0)
145 return ret;
146 ret = copy_bytes(inject, perf_data_file__fd(session->file),
147 event->auxtrace.size);
148 } else {
149 ret = output_bytes(inject, event,
150 event->header.size + event->auxtrace.size);
151 }
152 if (ret < 0)
153 return ret;
154
155 return event->auxtrace.size;
156}
157
158#else
159
160static s64
161perf_event__repipe_auxtrace(struct perf_tool *tool __maybe_unused,
162 union perf_event *event __maybe_unused,
163 struct perf_session *session __maybe_unused)
164{
165 pr_err("AUX area tracing not supported\n");
166 return -EINVAL;
167}
168
169#endif
170
89static int perf_event__repipe(struct perf_tool *tool, 171static int perf_event__repipe(struct perf_tool *tool,
90 union perf_event *event, 172 union perf_event *event,
91 struct perf_sample *sample __maybe_unused, 173 struct perf_sample *sample __maybe_unused,
@@ -155,6 +237,32 @@ static int perf_event__repipe_fork(struct perf_tool *tool,
155 return err; 237 return err;
156} 238}
157 239
240static int perf_event__repipe_comm(struct perf_tool *tool,
241 union perf_event *event,
242 struct perf_sample *sample,
243 struct machine *machine)
244{
245 int err;
246
247 err = perf_event__process_comm(tool, event, sample, machine);
248 perf_event__repipe(tool, event, sample, machine);
249
250 return err;
251}
252
253static int perf_event__repipe_exit(struct perf_tool *tool,
254 union perf_event *event,
255 struct perf_sample *sample,
256 struct machine *machine)
257{
258 int err;
259
260 err = perf_event__process_exit(tool, event, sample, machine);
261 perf_event__repipe(tool, event, sample, machine);
262
263 return err;
264}
265
158static int perf_event__repipe_tracing_data(struct perf_tool *tool, 266static int perf_event__repipe_tracing_data(struct perf_tool *tool,
159 union perf_event *event, 267 union perf_event *event,
160 struct perf_session *session) 268 struct perf_session *session)
@@ -167,6 +275,18 @@ static int perf_event__repipe_tracing_data(struct perf_tool *tool,
167 return err; 275 return err;
168} 276}
169 277
278static int perf_event__repipe_id_index(struct perf_tool *tool,
279 union perf_event *event,
280 struct perf_session *session)
281{
282 int err;
283
284 perf_event__repipe_synth(tool, event);
285 err = perf_event__process_id_index(tool, event, session);
286
287 return err;
288}
289
170static int dso__read_build_id(struct dso *dso) 290static int dso__read_build_id(struct dso *dso)
171{ 291{
172 if (dso->has_build_id) 292 if (dso->has_build_id)
@@ -245,6 +365,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
245 } 365 }
246 } 366 }
247 367
368 thread__put(thread);
248repipe: 369repipe:
249 perf_event__repipe(tool, event, sample, machine); 370 perf_event__repipe(tool, event, sample, machine);
250 return 0; 371 return 0;
@@ -351,16 +472,20 @@ static int __cmd_inject(struct perf_inject *inject)
351 struct perf_session *session = inject->session; 472 struct perf_session *session = inject->session;
352 struct perf_data_file *file_out = &inject->output; 473 struct perf_data_file *file_out = &inject->output;
353 int fd = perf_data_file__fd(file_out); 474 int fd = perf_data_file__fd(file_out);
475 u64 output_data_offset;
354 476
355 signal(SIGINT, sig_handler); 477 signal(SIGINT, sig_handler);
356 478
357 if (inject->build_ids || inject->sched_stat) { 479 if (inject->build_ids || inject->sched_stat ||
480 inject->itrace_synth_opts.set) {
358 inject->tool.mmap = perf_event__repipe_mmap; 481 inject->tool.mmap = perf_event__repipe_mmap;
359 inject->tool.mmap2 = perf_event__repipe_mmap2; 482 inject->tool.mmap2 = perf_event__repipe_mmap2;
360 inject->tool.fork = perf_event__repipe_fork; 483 inject->tool.fork = perf_event__repipe_fork;
361 inject->tool.tracing_data = perf_event__repipe_tracing_data; 484 inject->tool.tracing_data = perf_event__repipe_tracing_data;
362 } 485 }
363 486
487 output_data_offset = session->header.data_offset;
488
364 if (inject->build_ids) { 489 if (inject->build_ids) {
365 inject->tool.sample = perf_event__inject_buildid; 490 inject->tool.sample = perf_event__inject_buildid;
366 } else if (inject->sched_stat) { 491 } else if (inject->sched_stat) {
@@ -379,17 +504,43 @@ static int __cmd_inject(struct perf_inject *inject)
379 else if (!strncmp(name, "sched:sched_stat_", 17)) 504 else if (!strncmp(name, "sched:sched_stat_", 17))
380 evsel->handler = perf_inject__sched_stat; 505 evsel->handler = perf_inject__sched_stat;
381 } 506 }
507 } else if (inject->itrace_synth_opts.set) {
508 session->itrace_synth_opts = &inject->itrace_synth_opts;
509 inject->itrace_synth_opts.inject = true;
510 inject->tool.comm = perf_event__repipe_comm;
511 inject->tool.exit = perf_event__repipe_exit;
512 inject->tool.id_index = perf_event__repipe_id_index;
513 inject->tool.auxtrace_info = perf_event__process_auxtrace_info;
514 inject->tool.auxtrace = perf_event__process_auxtrace;
515 inject->tool.ordered_events = true;
516 inject->tool.ordering_requires_timestamps = true;
517 /* Allow space in the header for new attributes */
518 output_data_offset = 4096;
382 } 519 }
383 520
521 if (!inject->itrace_synth_opts.set)
522 auxtrace_index__free(&session->auxtrace_index);
523
384 if (!file_out->is_pipe) 524 if (!file_out->is_pipe)
385 lseek(fd, session->header.data_offset, SEEK_SET); 525 lseek(fd, output_data_offset, SEEK_SET);
386 526
387 ret = perf_session__process_events(session); 527 ret = perf_session__process_events(session);
388 528
389 if (!file_out->is_pipe) { 529 if (!file_out->is_pipe) {
390 if (inject->build_ids) 530 if (inject->build_ids) {
391 perf_header__set_feat(&session->header, 531 perf_header__set_feat(&session->header,
392 HEADER_BUILD_ID); 532 HEADER_BUILD_ID);
533 if (inject->have_auxtrace)
534 dsos__hit_all(session);
535 }
536 /*
537 * The AUX areas have been removed and replaced with
538 * synthesized hardware events, so clear the feature flag.
539 */
540 if (inject->itrace_synth_opts.set)
541 perf_header__clear_feat(&session->header,
542 HEADER_AUXTRACE);
543 session->header.data_offset = output_data_offset;
393 session->header.data_size = inject->bytes_written; 544 session->header.data_size = inject->bytes_written;
394 perf_session__write_header(session, session->evlist, fd, true); 545 perf_session__write_header(session, session->evlist, fd, true);
395 } 546 }
@@ -408,11 +559,16 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
408 .fork = perf_event__repipe, 559 .fork = perf_event__repipe,
409 .exit = perf_event__repipe, 560 .exit = perf_event__repipe,
410 .lost = perf_event__repipe, 561 .lost = perf_event__repipe,
562 .aux = perf_event__repipe,
563 .itrace_start = perf_event__repipe,
411 .read = perf_event__repipe_sample, 564 .read = perf_event__repipe_sample,
412 .throttle = perf_event__repipe, 565 .throttle = perf_event__repipe,
413 .unthrottle = perf_event__repipe, 566 .unthrottle = perf_event__repipe,
414 .attr = perf_event__repipe_attr, 567 .attr = perf_event__repipe_attr,
415 .tracing_data = perf_event__repipe_op2_synth, 568 .tracing_data = perf_event__repipe_op2_synth,
569 .auxtrace_info = perf_event__repipe_op2_synth,
570 .auxtrace = perf_event__repipe_auxtrace,
571 .auxtrace_error = perf_event__repipe_op2_synth,
416 .finished_round = perf_event__repipe_oe_synth, 572 .finished_round = perf_event__repipe_oe_synth,
417 .build_id = perf_event__repipe_op2_synth, 573 .build_id = perf_event__repipe_op2_synth,
418 .id_index = perf_event__repipe_op2_synth, 574 .id_index = perf_event__repipe_op2_synth,
@@ -444,6 +600,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
444 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", 600 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",
445 "kallsyms pathname"), 601 "kallsyms pathname"),
446 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), 602 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
603 OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts,
604 NULL, "opts", "Instruction Tracing options",
605 itrace_parse_synth_opts),
447 OPT_END() 606 OPT_END()
448 }; 607 };
449 const char * const inject_usage[] = { 608 const char * const inject_usage[] = {
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 1634186d537c..950f296dfcf7 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -10,6 +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/tool.h" 12#include "util/tool.h"
13#include "util/callchain.h"
13 14
14#include "util/parse-options.h" 15#include "util/parse-options.h"
15#include "util/trace-event.h" 16#include "util/trace-event.h"
@@ -21,14 +22,19 @@
21#include <linux/rbtree.h> 22#include <linux/rbtree.h>
22#include <linux/string.h> 23#include <linux/string.h>
23#include <locale.h> 24#include <locale.h>
25#include <regex.h>
24 26
25static int kmem_slab; 27static int kmem_slab;
26static int kmem_page; 28static int kmem_page;
27 29
28static long kmem_page_size; 30static long kmem_page_size;
31static enum {
32 KMEM_SLAB,
33 KMEM_PAGE,
34} kmem_default = KMEM_SLAB; /* for backward compatibility */
29 35
30struct alloc_stat; 36struct alloc_stat;
31typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *); 37typedef int (*sort_fn_t)(void *, void *);
32 38
33static int alloc_flag; 39static int alloc_flag;
34static int caller_flag; 40static int caller_flag;
@@ -179,8 +185,8 @@ static int perf_evsel__process_alloc_node_event(struct perf_evsel *evsel,
179 return ret; 185 return ret;
180} 186}
181 187
182static int ptr_cmp(struct alloc_stat *, struct alloc_stat *); 188static int ptr_cmp(void *, void *);
183static int callsite_cmp(struct alloc_stat *, struct alloc_stat *); 189static int slab_callsite_cmp(void *, void *);
184 190
185static struct alloc_stat *search_alloc_stat(unsigned long ptr, 191static struct alloc_stat *search_alloc_stat(unsigned long ptr,
186 unsigned long call_site, 192 unsigned long call_site,
@@ -221,7 +227,8 @@ static int perf_evsel__process_free_event(struct perf_evsel *evsel,
221 s_alloc->pingpong++; 227 s_alloc->pingpong++;
222 228
223 s_caller = search_alloc_stat(0, s_alloc->call_site, 229 s_caller = search_alloc_stat(0, s_alloc->call_site,
224 &root_caller_stat, callsite_cmp); 230 &root_caller_stat,
231 slab_callsite_cmp);
225 if (!s_caller) 232 if (!s_caller)
226 return -1; 233 return -1;
227 s_caller->pingpong++; 234 s_caller->pingpong++;
@@ -241,6 +248,8 @@ static unsigned long nr_page_fails;
241static unsigned long nr_page_nomatch; 248static unsigned long nr_page_nomatch;
242 249
243static bool use_pfn; 250static bool use_pfn;
251static bool live_page;
252static struct perf_session *kmem_session;
244 253
245#define MAX_MIGRATE_TYPES 6 254#define MAX_MIGRATE_TYPES 6
246#define MAX_PAGE_ORDER 11 255#define MAX_PAGE_ORDER 11
@@ -250,6 +259,7 @@ static int order_stats[MAX_PAGE_ORDER][MAX_MIGRATE_TYPES];
250struct page_stat { 259struct page_stat {
251 struct rb_node node; 260 struct rb_node node;
252 u64 page; 261 u64 page;
262 u64 callsite;
253 int order; 263 int order;
254 unsigned gfp_flags; 264 unsigned gfp_flags;
255 unsigned migrate_type; 265 unsigned migrate_type;
@@ -259,13 +269,158 @@ struct page_stat {
259 int nr_free; 269 int nr_free;
260}; 270};
261 271
262static struct rb_root page_tree; 272static struct rb_root page_live_tree;
263static struct rb_root page_alloc_tree; 273static struct rb_root page_alloc_tree;
264static struct rb_root page_alloc_sorted; 274static struct rb_root page_alloc_sorted;
275static struct rb_root page_caller_tree;
276static struct rb_root page_caller_sorted;
265 277
266static struct page_stat *search_page(unsigned long page, bool create) 278struct alloc_func {
279 u64 start;
280 u64 end;
281 char *name;
282};
283
284static int nr_alloc_funcs;
285static struct alloc_func *alloc_func_list;
286
287static int funcmp(const void *a, const void *b)
288{
289 const struct alloc_func *fa = a;
290 const struct alloc_func *fb = b;
291
292 if (fa->start > fb->start)
293 return 1;
294 else
295 return -1;
296}
297
298static int callcmp(const void *a, const void *b)
299{
300 const struct alloc_func *fa = a;
301 const struct alloc_func *fb = b;
302
303 if (fb->start <= fa->start && fa->end < fb->end)
304 return 0;
305
306 if (fa->start > fb->start)
307 return 1;
308 else
309 return -1;
310}
311
312static int build_alloc_func_list(void)
267{ 313{
268 struct rb_node **node = &page_tree.rb_node; 314 int ret;
315 struct map *kernel_map;
316 struct symbol *sym;
317 struct rb_node *node;
318 struct alloc_func *func;
319 struct machine *machine = &kmem_session->machines.host;
320 regex_t alloc_func_regex;
321 const char pattern[] = "^_?_?(alloc|get_free|get_zeroed)_pages?";
322
323 ret = regcomp(&alloc_func_regex, pattern, REG_EXTENDED);
324 if (ret) {
325 char err[BUFSIZ];
326
327 regerror(ret, &alloc_func_regex, err, sizeof(err));
328 pr_err("Invalid regex: %s\n%s", pattern, err);
329 return -EINVAL;
330 }
331
332 kernel_map = machine->vmlinux_maps[MAP__FUNCTION];
333 if (map__load(kernel_map, NULL) < 0) {
334 pr_err("cannot load kernel map\n");
335 return -ENOENT;
336 }
337
338 map__for_each_symbol(kernel_map, sym, node) {
339 if (regexec(&alloc_func_regex, sym->name, 0, NULL, 0))
340 continue;
341
342 func = realloc(alloc_func_list,
343 (nr_alloc_funcs + 1) * sizeof(*func));
344 if (func == NULL)
345 return -ENOMEM;
346
347 pr_debug("alloc func: %s\n", sym->name);
348 func[nr_alloc_funcs].start = sym->start;
349 func[nr_alloc_funcs].end = sym->end;
350 func[nr_alloc_funcs].name = sym->name;
351
352 alloc_func_list = func;
353 nr_alloc_funcs++;
354 }
355
356 qsort(alloc_func_list, nr_alloc_funcs, sizeof(*func), funcmp);
357
358 regfree(&alloc_func_regex);
359 return 0;
360}
361
362/*
363 * Find first non-memory allocation function from callchain.
364 * The allocation functions are in the 'alloc_func_list'.
365 */
366static u64 find_callsite(struct perf_evsel *evsel, struct perf_sample *sample)
367{
368 struct addr_location al;
369 struct machine *machine = &kmem_session->machines.host;
370 struct callchain_cursor_node *node;
371
372 if (alloc_func_list == NULL) {
373 if (build_alloc_func_list() < 0)
374 goto out;
375 }
376
377 al.thread = machine__findnew_thread(machine, sample->pid, sample->tid);
378 sample__resolve_callchain(sample, NULL, evsel, &al, 16);
379
380 callchain_cursor_commit(&callchain_cursor);
381 while (true) {
382 struct alloc_func key, *caller;
383 u64 addr;
384
385 node = callchain_cursor_current(&callchain_cursor);
386 if (node == NULL)
387 break;
388
389 key.start = key.end = node->ip;
390 caller = bsearch(&key, alloc_func_list, nr_alloc_funcs,
391 sizeof(key), callcmp);
392 if (!caller) {
393 /* found */
394 if (node->map)
395 addr = map__unmap_ip(node->map, node->ip);
396 else
397 addr = node->ip;
398
399 return addr;
400 } else
401 pr_debug3("skipping alloc function: %s\n", caller->name);
402
403 callchain_cursor_advance(&callchain_cursor);
404 }
405
406out:
407 pr_debug2("unknown callsite: %"PRIx64 "\n", sample->ip);
408 return sample->ip;
409}
410
411struct sort_dimension {
412 const char name[20];
413 sort_fn_t cmp;
414 struct list_head list;
415};
416
417static LIST_HEAD(page_alloc_sort_input);
418static LIST_HEAD(page_caller_sort_input);
419
420static struct page_stat *
421__page_stat__findnew_page(struct page_stat *pstat, bool create)
422{
423 struct rb_node **node = &page_live_tree.rb_node;
269 struct rb_node *parent = NULL; 424 struct rb_node *parent = NULL;
270 struct page_stat *data; 425 struct page_stat *data;
271 426
@@ -275,7 +430,7 @@ static struct page_stat *search_page(unsigned long page, bool create)
275 parent = *node; 430 parent = *node;
276 data = rb_entry(*node, struct page_stat, node); 431 data = rb_entry(*node, struct page_stat, node);
277 432
278 cmp = data->page - page; 433 cmp = data->page - pstat->page;
279 if (cmp < 0) 434 if (cmp < 0)
280 node = &parent->rb_left; 435 node = &parent->rb_left;
281 else if (cmp > 0) 436 else if (cmp > 0)
@@ -289,49 +444,48 @@ static struct page_stat *search_page(unsigned long page, bool create)
289 444
290 data = zalloc(sizeof(*data)); 445 data = zalloc(sizeof(*data));
291 if (data != NULL) { 446 if (data != NULL) {
292 data->page = page; 447 data->page = pstat->page;
448 data->order = pstat->order;
449 data->gfp_flags = pstat->gfp_flags;
450 data->migrate_type = pstat->migrate_type;
293 451
294 rb_link_node(&data->node, parent, node); 452 rb_link_node(&data->node, parent, node);
295 rb_insert_color(&data->node, &page_tree); 453 rb_insert_color(&data->node, &page_live_tree);
296 } 454 }
297 455
298 return data; 456 return data;
299} 457}
300 458
301static int page_stat_cmp(struct page_stat *a, struct page_stat *b) 459static struct page_stat *page_stat__find_page(struct page_stat *pstat)
302{ 460{
303 if (a->page > b->page) 461 return __page_stat__findnew_page(pstat, false);
304 return -1; 462}
305 if (a->page < b->page) 463
306 return 1; 464static struct page_stat *page_stat__findnew_page(struct page_stat *pstat)
307 if (a->order > b->order) 465{
308 return -1; 466 return __page_stat__findnew_page(pstat, true);
309 if (a->order < b->order)
310 return 1;
311 if (a->migrate_type > b->migrate_type)
312 return -1;
313 if (a->migrate_type < b->migrate_type)
314 return 1;
315 if (a->gfp_flags > b->gfp_flags)
316 return -1;
317 if (a->gfp_flags < b->gfp_flags)
318 return 1;
319 return 0;
320} 467}
321 468
322static struct page_stat *search_page_alloc_stat(struct page_stat *pstat, bool create) 469static struct page_stat *
470__page_stat__findnew_alloc(struct page_stat *pstat, bool create)
323{ 471{
324 struct rb_node **node = &page_alloc_tree.rb_node; 472 struct rb_node **node = &page_alloc_tree.rb_node;
325 struct rb_node *parent = NULL; 473 struct rb_node *parent = NULL;
326 struct page_stat *data; 474 struct page_stat *data;
475 struct sort_dimension *sort;
327 476
328 while (*node) { 477 while (*node) {
329 s64 cmp; 478 int cmp = 0;
330 479
331 parent = *node; 480 parent = *node;
332 data = rb_entry(*node, struct page_stat, node); 481 data = rb_entry(*node, struct page_stat, node);
333 482
334 cmp = page_stat_cmp(data, pstat); 483 list_for_each_entry(sort, &page_alloc_sort_input, list) {
484 cmp = sort->cmp(pstat, data);
485 if (cmp)
486 break;
487 }
488
335 if (cmp < 0) 489 if (cmp < 0)
336 node = &parent->rb_left; 490 node = &parent->rb_left;
337 else if (cmp > 0) 491 else if (cmp > 0)
@@ -357,6 +511,71 @@ static struct page_stat *search_page_alloc_stat(struct page_stat *pstat, bool cr
357 return data; 511 return data;
358} 512}
359 513
514static struct page_stat *page_stat__find_alloc(struct page_stat *pstat)
515{
516 return __page_stat__findnew_alloc(pstat, false);
517}
518
519static struct page_stat *page_stat__findnew_alloc(struct page_stat *pstat)
520{
521 return __page_stat__findnew_alloc(pstat, true);
522}
523
524static struct page_stat *
525__page_stat__findnew_caller(struct page_stat *pstat, bool create)
526{
527 struct rb_node **node = &page_caller_tree.rb_node;
528 struct rb_node *parent = NULL;
529 struct page_stat *data;
530 struct sort_dimension *sort;
531
532 while (*node) {
533 int cmp = 0;
534
535 parent = *node;
536 data = rb_entry(*node, struct page_stat, node);
537
538 list_for_each_entry(sort, &page_caller_sort_input, list) {
539 cmp = sort->cmp(pstat, data);
540 if (cmp)
541 break;
542 }
543
544 if (cmp < 0)
545 node = &parent->rb_left;
546 else if (cmp > 0)
547 node = &parent->rb_right;
548 else
549 return data;
550 }
551
552 if (!create)
553 return NULL;
554
555 data = zalloc(sizeof(*data));
556 if (data != NULL) {
557 data->callsite = pstat->callsite;
558 data->order = pstat->order;
559 data->gfp_flags = pstat->gfp_flags;
560 data->migrate_type = pstat->migrate_type;
561
562 rb_link_node(&data->node, parent, node);
563 rb_insert_color(&data->node, &page_caller_tree);
564 }
565
566 return data;
567}
568
569static struct page_stat *page_stat__find_caller(struct page_stat *pstat)
570{
571 return __page_stat__findnew_caller(pstat, false);
572}
573
574static struct page_stat *page_stat__findnew_caller(struct page_stat *pstat)
575{
576 return __page_stat__findnew_caller(pstat, true);
577}
578
360static bool valid_page(u64 pfn_or_page) 579static bool valid_page(u64 pfn_or_page)
361{ 580{
362 if (use_pfn && pfn_or_page == -1UL) 581 if (use_pfn && pfn_or_page == -1UL)
@@ -366,6 +585,176 @@ static bool valid_page(u64 pfn_or_page)
366 return true; 585 return true;
367} 586}
368 587
588struct gfp_flag {
589 unsigned int flags;
590 char *compact_str;
591 char *human_readable;
592};
593
594static struct gfp_flag *gfps;
595static int nr_gfps;
596
597static int gfpcmp(const void *a, const void *b)
598{
599 const struct gfp_flag *fa = a;
600 const struct gfp_flag *fb = b;
601
602 return fa->flags - fb->flags;
603}
604
605/* see include/trace/events/gfpflags.h */
606static const struct {
607 const char *original;
608 const char *compact;
609} gfp_compact_table[] = {
610 { "GFP_TRANSHUGE", "THP" },
611 { "GFP_HIGHUSER_MOVABLE", "HUM" },
612 { "GFP_HIGHUSER", "HU" },
613 { "GFP_USER", "U" },
614 { "GFP_TEMPORARY", "TMP" },
615 { "GFP_KERNEL", "K" },
616 { "GFP_NOFS", "NF" },
617 { "GFP_ATOMIC", "A" },
618 { "GFP_NOIO", "NI" },
619 { "GFP_HIGH", "H" },
620 { "GFP_WAIT", "W" },
621 { "GFP_IO", "I" },
622 { "GFP_COLD", "CO" },
623 { "GFP_NOWARN", "NWR" },
624 { "GFP_REPEAT", "R" },
625 { "GFP_NOFAIL", "NF" },
626 { "GFP_NORETRY", "NR" },
627 { "GFP_COMP", "C" },
628 { "GFP_ZERO", "Z" },
629 { "GFP_NOMEMALLOC", "NMA" },
630 { "GFP_MEMALLOC", "MA" },
631 { "GFP_HARDWALL", "HW" },
632 { "GFP_THISNODE", "TN" },
633 { "GFP_RECLAIMABLE", "RC" },
634 { "GFP_MOVABLE", "M" },
635 { "GFP_NOTRACK", "NT" },
636 { "GFP_NO_KSWAPD", "NK" },
637 { "GFP_OTHER_NODE", "ON" },
638 { "GFP_NOWAIT", "NW" },
639};
640
641static size_t max_gfp_len;
642
643static char *compact_gfp_flags(char *gfp_flags)
644{
645 char *orig_flags = strdup(gfp_flags);
646 char *new_flags = NULL;
647 char *str, *pos = NULL;
648 size_t len = 0;
649
650 if (orig_flags == NULL)
651 return NULL;
652
653 str = strtok_r(orig_flags, "|", &pos);
654 while (str) {
655 size_t i;
656 char *new;
657 const char *cpt;
658
659 for (i = 0; i < ARRAY_SIZE(gfp_compact_table); i++) {
660 if (strcmp(gfp_compact_table[i].original, str))
661 continue;
662
663 cpt = gfp_compact_table[i].compact;
664 new = realloc(new_flags, len + strlen(cpt) + 2);
665 if (new == NULL) {
666 free(new_flags);
667 return NULL;
668 }
669
670 new_flags = new;
671
672 if (!len) {
673 strcpy(new_flags, cpt);
674 } else {
675 strcat(new_flags, "|");
676 strcat(new_flags, cpt);
677 len++;
678 }
679
680 len += strlen(cpt);
681 }
682
683 str = strtok_r(NULL, "|", &pos);
684 }
685
686 if (max_gfp_len < len)
687 max_gfp_len = len;
688
689 free(orig_flags);
690 return new_flags;
691}
692
693static char *compact_gfp_string(unsigned long gfp_flags)
694{
695 struct gfp_flag key = {
696 .flags = gfp_flags,
697 };
698 struct gfp_flag *gfp;
699
700 gfp = bsearch(&key, gfps, nr_gfps, sizeof(*gfps), gfpcmp);
701 if (gfp)
702 return gfp->compact_str;
703
704 return NULL;
705}
706
707static int parse_gfp_flags(struct perf_evsel *evsel, struct perf_sample *sample,
708 unsigned int gfp_flags)
709{
710 struct pevent_record record = {
711 .cpu = sample->cpu,
712 .data = sample->raw_data,
713 .size = sample->raw_size,
714 };
715 struct trace_seq seq;
716 char *str, *pos = NULL;
717
718 if (nr_gfps) {
719 struct gfp_flag key = {
720 .flags = gfp_flags,
721 };
722
723 if (bsearch(&key, gfps, nr_gfps, sizeof(*gfps), gfpcmp))
724 return 0;
725 }
726
727 trace_seq_init(&seq);
728 pevent_event_info(&seq, evsel->tp_format, &record);
729
730 str = strtok_r(seq.buffer, " ", &pos);
731 while (str) {
732 if (!strncmp(str, "gfp_flags=", 10)) {
733 struct gfp_flag *new;
734
735 new = realloc(gfps, (nr_gfps + 1) * sizeof(*gfps));
736 if (new == NULL)
737 return -ENOMEM;
738
739 gfps = new;
740 new += nr_gfps++;
741
742 new->flags = gfp_flags;
743 new->human_readable = strdup(str + 10);
744 new->compact_str = compact_gfp_flags(str + 10);
745 if (!new->human_readable || !new->compact_str)
746 return -ENOMEM;
747
748 qsort(gfps, nr_gfps, sizeof(*gfps), gfpcmp);
749 }
750
751 str = strtok_r(NULL, " ", &pos);
752 }
753
754 trace_seq_destroy(&seq);
755 return 0;
756}
757
369static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel, 758static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel,
370 struct perf_sample *sample) 759 struct perf_sample *sample)
371{ 760{
@@ -375,6 +764,7 @@ static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel,
375 unsigned int migrate_type = perf_evsel__intval(evsel, sample, 764 unsigned int migrate_type = perf_evsel__intval(evsel, sample,
376 "migratetype"); 765 "migratetype");
377 u64 bytes = kmem_page_size << order; 766 u64 bytes = kmem_page_size << order;
767 u64 callsite;
378 struct page_stat *pstat; 768 struct page_stat *pstat;
379 struct page_stat this = { 769 struct page_stat this = {
380 .order = order, 770 .order = order,
@@ -397,20 +787,36 @@ static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel,
397 return 0; 787 return 0;
398 } 788 }
399 789
790 if (parse_gfp_flags(evsel, sample, gfp_flags) < 0)
791 return -1;
792
793 callsite = find_callsite(evsel, sample);
794
400 /* 795 /*
401 * This is to find the current page (with correct gfp flags and 796 * This is to find the current page (with correct gfp flags and
402 * migrate type) at free event. 797 * migrate type) at free event.
403 */ 798 */
404 pstat = search_page(page, true); 799 this.page = page;
800 pstat = page_stat__findnew_page(&this);
405 if (pstat == NULL) 801 if (pstat == NULL)
406 return -ENOMEM; 802 return -ENOMEM;
407 803
408 pstat->order = order; 804 pstat->nr_alloc++;
409 pstat->gfp_flags = gfp_flags; 805 pstat->alloc_bytes += bytes;
410 pstat->migrate_type = migrate_type; 806 pstat->callsite = callsite;
807
808 if (!live_page) {
809 pstat = page_stat__findnew_alloc(&this);
810 if (pstat == NULL)
811 return -ENOMEM;
411 812
412 this.page = page; 813 pstat->nr_alloc++;
413 pstat = search_page_alloc_stat(&this, true); 814 pstat->alloc_bytes += bytes;
815 pstat->callsite = callsite;
816 }
817
818 this.callsite = callsite;
819 pstat = page_stat__findnew_caller(&this);
414 if (pstat == NULL) 820 if (pstat == NULL)
415 return -ENOMEM; 821 return -ENOMEM;
416 822
@@ -441,7 +847,8 @@ static int perf_evsel__process_page_free_event(struct perf_evsel *evsel,
441 nr_page_frees++; 847 nr_page_frees++;
442 total_page_free_bytes += bytes; 848 total_page_free_bytes += bytes;
443 849
444 pstat = search_page(page, false); 850 this.page = page;
851 pstat = page_stat__find_page(&this);
445 if (pstat == NULL) { 852 if (pstat == NULL) {
446 pr_debug2("missing free at page %"PRIx64" (order: %d)\n", 853 pr_debug2("missing free at page %"PRIx64" (order: %d)\n",
447 page, order); 854 page, order);
@@ -452,20 +859,41 @@ static int perf_evsel__process_page_free_event(struct perf_evsel *evsel,
452 return 0; 859 return 0;
453 } 860 }
454 861
455 this.page = page;
456 this.gfp_flags = pstat->gfp_flags; 862 this.gfp_flags = pstat->gfp_flags;
457 this.migrate_type = pstat->migrate_type; 863 this.migrate_type = pstat->migrate_type;
864 this.callsite = pstat->callsite;
458 865
459 rb_erase(&pstat->node, &page_tree); 866 rb_erase(&pstat->node, &page_live_tree);
460 free(pstat); 867 free(pstat);
461 868
462 pstat = search_page_alloc_stat(&this, false); 869 if (live_page) {
870 order_stats[this.order][this.migrate_type]--;
871 } else {
872 pstat = page_stat__find_alloc(&this);
873 if (pstat == NULL)
874 return -ENOMEM;
875
876 pstat->nr_free++;
877 pstat->free_bytes += bytes;
878 }
879
880 pstat = page_stat__find_caller(&this);
463 if (pstat == NULL) 881 if (pstat == NULL)
464 return -ENOENT; 882 return -ENOENT;
465 883
466 pstat->nr_free++; 884 pstat->nr_free++;
467 pstat->free_bytes += bytes; 885 pstat->free_bytes += bytes;
468 886
887 if (live_page) {
888 pstat->nr_alloc--;
889 pstat->alloc_bytes -= bytes;
890
891 if (pstat->nr_alloc == 0) {
892 rb_erase(&pstat->node, &page_caller_tree);
893 free(pstat);
894 }
895 }
896
469 return 0; 897 return 0;
470} 898}
471 899
@@ -478,6 +906,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
478 struct perf_evsel *evsel, 906 struct perf_evsel *evsel,
479 struct machine *machine) 907 struct machine *machine)
480{ 908{
909 int err = 0;
481 struct thread *thread = machine__findnew_thread(machine, sample->pid, 910 struct thread *thread = machine__findnew_thread(machine, sample->pid,
482 sample->tid); 911 sample->tid);
483 912
@@ -491,10 +920,12 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
491 920
492 if (evsel->handler != NULL) { 921 if (evsel->handler != NULL) {
493 tracepoint_handler f = evsel->handler; 922 tracepoint_handler f = evsel->handler;
494 return f(evsel, sample); 923 err = f(evsel, sample);
495 } 924 }
496 925
497 return 0; 926 thread__put(thread);
927
928 return err;
498} 929}
499 930
500static struct perf_tool perf_kmem = { 931static struct perf_tool perf_kmem = {
@@ -576,41 +1007,111 @@ static const char * const migrate_type_str[] = {
576 "UNKNOWN", 1007 "UNKNOWN",
577}; 1008};
578 1009
579static void __print_page_result(struct rb_root *root, 1010static void __print_page_alloc_result(struct perf_session *session, int n_lines)
580 struct perf_session *session __maybe_unused,
581 int n_lines)
582{ 1011{
583 struct rb_node *next = rb_first(root); 1012 struct rb_node *next = rb_first(&page_alloc_sorted);
1013 struct machine *machine = &session->machines.host;
584 const char *format; 1014 const char *format;
1015 int gfp_len = max(strlen("GFP flags"), max_gfp_len);
585 1016
586 printf("\n%.80s\n", graph_dotted_line); 1017 printf("\n%.105s\n", graph_dotted_line);
587 printf(" %-16s | Total alloc (KB) | Hits | Order | Mig.type | GFP flags\n", 1018 printf(" %-16s | %5s alloc (KB) | Hits | Order | Mig.type | %-*s | Callsite\n",
588 use_pfn ? "PFN" : "Page"); 1019 use_pfn ? "PFN" : "Page", live_page ? "Live" : "Total",
589 printf("%.80s\n", graph_dotted_line); 1020 gfp_len, "GFP flags");
1021 printf("%.105s\n", graph_dotted_line);
590 1022
591 if (use_pfn) 1023 if (use_pfn)
592 format = " %16llu | %'16llu | %'9d | %5d | %8s | %08lx\n"; 1024 format = " %16llu | %'16llu | %'9d | %5d | %8s | %-*s | %s\n";
593 else 1025 else
594 format = " %016llx | %'16llu | %'9d | %5d | %8s | %08lx\n"; 1026 format = " %016llx | %'16llu | %'9d | %5d | %8s | %-*s | %s\n";
595 1027
596 while (next && n_lines--) { 1028 while (next && n_lines--) {
597 struct page_stat *data; 1029 struct page_stat *data;
1030 struct symbol *sym;
1031 struct map *map;
1032 char buf[32];
1033 char *caller = buf;
598 1034
599 data = rb_entry(next, struct page_stat, node); 1035 data = rb_entry(next, struct page_stat, node);
1036 sym = machine__find_kernel_function(machine, data->callsite,
1037 &map, NULL);
1038 if (sym && sym->name)
1039 caller = sym->name;
1040 else
1041 scnprintf(buf, sizeof(buf), "%"PRIx64, data->callsite);
600 1042
601 printf(format, (unsigned long long)data->page, 1043 printf(format, (unsigned long long)data->page,
602 (unsigned long long)data->alloc_bytes / 1024, 1044 (unsigned long long)data->alloc_bytes / 1024,
603 data->nr_alloc, data->order, 1045 data->nr_alloc, data->order,
604 migrate_type_str[data->migrate_type], 1046 migrate_type_str[data->migrate_type],
605 (unsigned long)data->gfp_flags); 1047 gfp_len, compact_gfp_string(data->gfp_flags), caller);
606 1048
607 next = rb_next(next); 1049 next = rb_next(next);
608 } 1050 }
609 1051
610 if (n_lines == -1) 1052 if (n_lines == -1) {
611 printf(" ... | ... | ... | ... | ... | ... \n"); 1053 printf(" ... | ... | ... | ... | ... | %-*s | ...\n",
1054 gfp_len, "...");
1055 }
1056
1057 printf("%.105s\n", graph_dotted_line);
1058}
1059
1060static void __print_page_caller_result(struct perf_session *session, int n_lines)
1061{
1062 struct rb_node *next = rb_first(&page_caller_sorted);
1063 struct machine *machine = &session->machines.host;
1064 int gfp_len = max(strlen("GFP flags"), max_gfp_len);
1065
1066 printf("\n%.105s\n", graph_dotted_line);
1067 printf(" %5s alloc (KB) | Hits | Order | Mig.type | %-*s | Callsite\n",
1068 live_page ? "Live" : "Total", gfp_len, "GFP flags");
1069 printf("%.105s\n", graph_dotted_line);
1070
1071 while (next && n_lines--) {
1072 struct page_stat *data;
1073 struct symbol *sym;
1074 struct map *map;
1075 char buf[32];
1076 char *caller = buf;
1077
1078 data = rb_entry(next, struct page_stat, node);
1079 sym = machine__find_kernel_function(machine, data->callsite,
1080 &map, NULL);
1081 if (sym && sym->name)
1082 caller = sym->name;
1083 else
1084 scnprintf(buf, sizeof(buf), "%"PRIx64, data->callsite);
1085
1086 printf(" %'16llu | %'9d | %5d | %8s | %-*s | %s\n",
1087 (unsigned long long)data->alloc_bytes / 1024,
1088 data->nr_alloc, data->order,
1089 migrate_type_str[data->migrate_type],
1090 gfp_len, compact_gfp_string(data->gfp_flags), caller);
1091
1092 next = rb_next(next);
1093 }
1094
1095 if (n_lines == -1) {
1096 printf(" ... | ... | ... | ... | %-*s | ...\n",
1097 gfp_len, "...");
1098 }
612 1099
613 printf("%.80s\n", graph_dotted_line); 1100 printf("%.105s\n", graph_dotted_line);
1101}
1102
1103static void print_gfp_flags(void)
1104{
1105 int i;
1106
1107 printf("#\n");
1108 printf("# GFP flags\n");
1109 printf("# ---------\n");
1110 for (i = 0; i < nr_gfps; i++) {
1111 printf("# %08x: %*s: %s\n", gfps[i].flags,
1112 (int) max_gfp_len, gfps[i].compact_str,
1113 gfps[i].human_readable);
1114 }
614} 1115}
615 1116
616static void print_slab_summary(void) 1117static void print_slab_summary(void)
@@ -682,8 +1183,12 @@ static void print_slab_result(struct perf_session *session)
682 1183
683static void print_page_result(struct perf_session *session) 1184static void print_page_result(struct perf_session *session)
684{ 1185{
1186 if (caller_flag || alloc_flag)
1187 print_gfp_flags();
1188 if (caller_flag)
1189 __print_page_caller_result(session, caller_lines);
685 if (alloc_flag) 1190 if (alloc_flag)
686 __print_page_result(&page_alloc_sorted, session, alloc_lines); 1191 __print_page_alloc_result(session, alloc_lines);
687 print_page_summary(); 1192 print_page_summary();
688} 1193}
689 1194
@@ -695,14 +1200,10 @@ static void print_result(struct perf_session *session)
695 print_page_result(session); 1200 print_page_result(session);
696} 1201}
697 1202
698struct sort_dimension { 1203static LIST_HEAD(slab_caller_sort);
699 const char name[20]; 1204static LIST_HEAD(slab_alloc_sort);
700 sort_fn_t cmp; 1205static LIST_HEAD(page_caller_sort);
701 struct list_head list; 1206static LIST_HEAD(page_alloc_sort);
702};
703
704static LIST_HEAD(caller_sort);
705static LIST_HEAD(alloc_sort);
706 1207
707static void sort_slab_insert(struct rb_root *root, struct alloc_stat *data, 1208static void sort_slab_insert(struct rb_root *root, struct alloc_stat *data,
708 struct list_head *sort_list) 1209 struct list_head *sort_list)
@@ -751,10 +1252,12 @@ static void __sort_slab_result(struct rb_root *root, struct rb_root *root_sorted
751 } 1252 }
752} 1253}
753 1254
754static void sort_page_insert(struct rb_root *root, struct page_stat *data) 1255static void sort_page_insert(struct rb_root *root, struct page_stat *data,
1256 struct list_head *sort_list)
755{ 1257{
756 struct rb_node **new = &root->rb_node; 1258 struct rb_node **new = &root->rb_node;
757 struct rb_node *parent = NULL; 1259 struct rb_node *parent = NULL;
1260 struct sort_dimension *sort;
758 1261
759 while (*new) { 1262 while (*new) {
760 struct page_stat *this; 1263 struct page_stat *this;
@@ -763,8 +1266,11 @@ static void sort_page_insert(struct rb_root *root, struct page_stat *data)
763 this = rb_entry(*new, struct page_stat, node); 1266 this = rb_entry(*new, struct page_stat, node);
764 parent = *new; 1267 parent = *new;
765 1268
766 /* TODO: support more sort key */ 1269 list_for_each_entry(sort, sort_list, list) {
767 cmp = data->alloc_bytes - this->alloc_bytes; 1270 cmp = sort->cmp(data, this);
1271 if (cmp)
1272 break;
1273 }
768 1274
769 if (cmp > 0) 1275 if (cmp > 0)
770 new = &parent->rb_left; 1276 new = &parent->rb_left;
@@ -776,7 +1282,8 @@ static void sort_page_insert(struct rb_root *root, struct page_stat *data)
776 rb_insert_color(&data->node, root); 1282 rb_insert_color(&data->node, root);
777} 1283}
778 1284
779static void __sort_page_result(struct rb_root *root, struct rb_root *root_sorted) 1285static void __sort_page_result(struct rb_root *root, struct rb_root *root_sorted,
1286 struct list_head *sort_list)
780{ 1287{
781 struct rb_node *node; 1288 struct rb_node *node;
782 struct page_stat *data; 1289 struct page_stat *data;
@@ -788,7 +1295,7 @@ static void __sort_page_result(struct rb_root *root, struct rb_root *root_sorted
788 1295
789 rb_erase(node, root); 1296 rb_erase(node, root);
790 data = rb_entry(node, struct page_stat, node); 1297 data = rb_entry(node, struct page_stat, node);
791 sort_page_insert(root_sorted, data); 1298 sort_page_insert(root_sorted, data, sort_list);
792 } 1299 }
793} 1300}
794 1301
@@ -796,12 +1303,20 @@ static void sort_result(void)
796{ 1303{
797 if (kmem_slab) { 1304 if (kmem_slab) {
798 __sort_slab_result(&root_alloc_stat, &root_alloc_sorted, 1305 __sort_slab_result(&root_alloc_stat, &root_alloc_sorted,
799 &alloc_sort); 1306 &slab_alloc_sort);
800 __sort_slab_result(&root_caller_stat, &root_caller_sorted, 1307 __sort_slab_result(&root_caller_stat, &root_caller_sorted,
801 &caller_sort); 1308 &slab_caller_sort);
802 } 1309 }
803 if (kmem_page) { 1310 if (kmem_page) {
804 __sort_page_result(&page_alloc_tree, &page_alloc_sorted); 1311 if (live_page)
1312 __sort_page_result(&page_live_tree, &page_alloc_sorted,
1313 &page_alloc_sort);
1314 else
1315 __sort_page_result(&page_alloc_tree, &page_alloc_sorted,
1316 &page_alloc_sort);
1317
1318 __sort_page_result(&page_caller_tree, &page_caller_sorted,
1319 &page_caller_sort);
805 } 1320 }
806} 1321}
807 1322
@@ -850,8 +1365,12 @@ out:
850 return err; 1365 return err;
851} 1366}
852 1367
853static int ptr_cmp(struct alloc_stat *l, struct alloc_stat *r) 1368/* slab sort keys */
1369static int ptr_cmp(void *a, void *b)
854{ 1370{
1371 struct alloc_stat *l = a;
1372 struct alloc_stat *r = b;
1373
855 if (l->ptr < r->ptr) 1374 if (l->ptr < r->ptr)
856 return -1; 1375 return -1;
857 else if (l->ptr > r->ptr) 1376 else if (l->ptr > r->ptr)
@@ -864,8 +1383,11 @@ static struct sort_dimension ptr_sort_dimension = {
864 .cmp = ptr_cmp, 1383 .cmp = ptr_cmp,
865}; 1384};
866 1385
867static int callsite_cmp(struct alloc_stat *l, struct alloc_stat *r) 1386static int slab_callsite_cmp(void *a, void *b)
868{ 1387{
1388 struct alloc_stat *l = a;
1389 struct alloc_stat *r = b;
1390
869 if (l->call_site < r->call_site) 1391 if (l->call_site < r->call_site)
870 return -1; 1392 return -1;
871 else if (l->call_site > r->call_site) 1393 else if (l->call_site > r->call_site)
@@ -875,11 +1397,14 @@ static int callsite_cmp(struct alloc_stat *l, struct alloc_stat *r)
875 1397
876static struct sort_dimension callsite_sort_dimension = { 1398static struct sort_dimension callsite_sort_dimension = {
877 .name = "callsite", 1399 .name = "callsite",
878 .cmp = callsite_cmp, 1400 .cmp = slab_callsite_cmp,
879}; 1401};
880 1402
881static int hit_cmp(struct alloc_stat *l, struct alloc_stat *r) 1403static int hit_cmp(void *a, void *b)
882{ 1404{
1405 struct alloc_stat *l = a;
1406 struct alloc_stat *r = b;
1407
883 if (l->hit < r->hit) 1408 if (l->hit < r->hit)
884 return -1; 1409 return -1;
885 else if (l->hit > r->hit) 1410 else if (l->hit > r->hit)
@@ -892,8 +1417,11 @@ static struct sort_dimension hit_sort_dimension = {
892 .cmp = hit_cmp, 1417 .cmp = hit_cmp,
893}; 1418};
894 1419
895static int bytes_cmp(struct alloc_stat *l, struct alloc_stat *r) 1420static int bytes_cmp(void *a, void *b)
896{ 1421{
1422 struct alloc_stat *l = a;
1423 struct alloc_stat *r = b;
1424
897 if (l->bytes_alloc < r->bytes_alloc) 1425 if (l->bytes_alloc < r->bytes_alloc)
898 return -1; 1426 return -1;
899 else if (l->bytes_alloc > r->bytes_alloc) 1427 else if (l->bytes_alloc > r->bytes_alloc)
@@ -906,9 +1434,11 @@ static struct sort_dimension bytes_sort_dimension = {
906 .cmp = bytes_cmp, 1434 .cmp = bytes_cmp,
907}; 1435};
908 1436
909static int frag_cmp(struct alloc_stat *l, struct alloc_stat *r) 1437static int frag_cmp(void *a, void *b)
910{ 1438{
911 double x, y; 1439 double x, y;
1440 struct alloc_stat *l = a;
1441 struct alloc_stat *r = b;
912 1442
913 x = fragmentation(l->bytes_req, l->bytes_alloc); 1443 x = fragmentation(l->bytes_req, l->bytes_alloc);
914 y = fragmentation(r->bytes_req, r->bytes_alloc); 1444 y = fragmentation(r->bytes_req, r->bytes_alloc);
@@ -925,8 +1455,11 @@ static struct sort_dimension frag_sort_dimension = {
925 .cmp = frag_cmp, 1455 .cmp = frag_cmp,
926}; 1456};
927 1457
928static int pingpong_cmp(struct alloc_stat *l, struct alloc_stat *r) 1458static int pingpong_cmp(void *a, void *b)
929{ 1459{
1460 struct alloc_stat *l = a;
1461 struct alloc_stat *r = b;
1462
930 if (l->pingpong < r->pingpong) 1463 if (l->pingpong < r->pingpong)
931 return -1; 1464 return -1;
932 else if (l->pingpong > r->pingpong) 1465 else if (l->pingpong > r->pingpong)
@@ -939,7 +1472,135 @@ static struct sort_dimension pingpong_sort_dimension = {
939 .cmp = pingpong_cmp, 1472 .cmp = pingpong_cmp,
940}; 1473};
941 1474
942static struct sort_dimension *avail_sorts[] = { 1475/* page sort keys */
1476static int page_cmp(void *a, void *b)
1477{
1478 struct page_stat *l = a;
1479 struct page_stat *r = b;
1480
1481 if (l->page < r->page)
1482 return -1;
1483 else if (l->page > r->page)
1484 return 1;
1485 return 0;
1486}
1487
1488static struct sort_dimension page_sort_dimension = {
1489 .name = "page",
1490 .cmp = page_cmp,
1491};
1492
1493static int page_callsite_cmp(void *a, void *b)
1494{
1495 struct page_stat *l = a;
1496 struct page_stat *r = b;
1497
1498 if (l->callsite < r->callsite)
1499 return -1;
1500 else if (l->callsite > r->callsite)
1501 return 1;
1502 return 0;
1503}
1504
1505static struct sort_dimension page_callsite_sort_dimension = {
1506 .name = "callsite",
1507 .cmp = page_callsite_cmp,
1508};
1509
1510static int page_hit_cmp(void *a, void *b)
1511{
1512 struct page_stat *l = a;
1513 struct page_stat *r = b;
1514
1515 if (l->nr_alloc < r->nr_alloc)
1516 return -1;
1517 else if (l->nr_alloc > r->nr_alloc)
1518 return 1;
1519 return 0;
1520}
1521
1522static struct sort_dimension page_hit_sort_dimension = {
1523 .name = "hit",
1524 .cmp = page_hit_cmp,
1525};
1526
1527static int page_bytes_cmp(void *a, void *b)
1528{
1529 struct page_stat *l = a;
1530 struct page_stat *r = b;
1531
1532 if (l->alloc_bytes < r->alloc_bytes)
1533 return -1;
1534 else if (l->alloc_bytes > r->alloc_bytes)
1535 return 1;
1536 return 0;
1537}
1538
1539static struct sort_dimension page_bytes_sort_dimension = {
1540 .name = "bytes",
1541 .cmp = page_bytes_cmp,
1542};
1543
1544static int page_order_cmp(void *a, void *b)
1545{
1546 struct page_stat *l = a;
1547 struct page_stat *r = b;
1548
1549 if (l->order < r->order)
1550 return -1;
1551 else if (l->order > r->order)
1552 return 1;
1553 return 0;
1554}
1555
1556static struct sort_dimension page_order_sort_dimension = {
1557 .name = "order",
1558 .cmp = page_order_cmp,
1559};
1560
1561static int migrate_type_cmp(void *a, void *b)
1562{
1563 struct page_stat *l = a;
1564 struct page_stat *r = b;
1565
1566 /* for internal use to find free'd page */
1567 if (l->migrate_type == -1U)
1568 return 0;
1569
1570 if (l->migrate_type < r->migrate_type)
1571 return -1;
1572 else if (l->migrate_type > r->migrate_type)
1573 return 1;
1574 return 0;
1575}
1576
1577static struct sort_dimension migrate_type_sort_dimension = {
1578 .name = "migtype",
1579 .cmp = migrate_type_cmp,
1580};
1581
1582static int gfp_flags_cmp(void *a, void *b)
1583{
1584 struct page_stat *l = a;
1585 struct page_stat *r = b;
1586
1587 /* for internal use to find free'd page */
1588 if (l->gfp_flags == -1U)
1589 return 0;
1590
1591 if (l->gfp_flags < r->gfp_flags)
1592 return -1;
1593 else if (l->gfp_flags > r->gfp_flags)
1594 return 1;
1595 return 0;
1596}
1597
1598static struct sort_dimension gfp_flags_sort_dimension = {
1599 .name = "gfp",
1600 .cmp = gfp_flags_cmp,
1601};
1602
1603static struct sort_dimension *slab_sorts[] = {
943 &ptr_sort_dimension, 1604 &ptr_sort_dimension,
944 &callsite_sort_dimension, 1605 &callsite_sort_dimension,
945 &hit_sort_dimension, 1606 &hit_sort_dimension,
@@ -948,16 +1609,44 @@ static struct sort_dimension *avail_sorts[] = {
948 &pingpong_sort_dimension, 1609 &pingpong_sort_dimension,
949}; 1610};
950 1611
951#define NUM_AVAIL_SORTS ((int)ARRAY_SIZE(avail_sorts)) 1612static struct sort_dimension *page_sorts[] = {
1613 &page_sort_dimension,
1614 &page_callsite_sort_dimension,
1615 &page_hit_sort_dimension,
1616 &page_bytes_sort_dimension,
1617 &page_order_sort_dimension,
1618 &migrate_type_sort_dimension,
1619 &gfp_flags_sort_dimension,
1620};
1621
1622static int slab_sort_dimension__add(const char *tok, struct list_head *list)
1623{
1624 struct sort_dimension *sort;
1625 int i;
1626
1627 for (i = 0; i < (int)ARRAY_SIZE(slab_sorts); i++) {
1628 if (!strcmp(slab_sorts[i]->name, tok)) {
1629 sort = memdup(slab_sorts[i], sizeof(*slab_sorts[i]));
1630 if (!sort) {
1631 pr_err("%s: memdup failed\n", __func__);
1632 return -1;
1633 }
1634 list_add_tail(&sort->list, list);
1635 return 0;
1636 }
1637 }
1638
1639 return -1;
1640}
952 1641
953static int sort_dimension__add(const char *tok, struct list_head *list) 1642static int page_sort_dimension__add(const char *tok, struct list_head *list)
954{ 1643{
955 struct sort_dimension *sort; 1644 struct sort_dimension *sort;
956 int i; 1645 int i;
957 1646
958 for (i = 0; i < NUM_AVAIL_SORTS; i++) { 1647 for (i = 0; i < (int)ARRAY_SIZE(page_sorts); i++) {
959 if (!strcmp(avail_sorts[i]->name, tok)) { 1648 if (!strcmp(page_sorts[i]->name, tok)) {
960 sort = memdup(avail_sorts[i], sizeof(*avail_sorts[i])); 1649 sort = memdup(page_sorts[i], sizeof(*page_sorts[i]));
961 if (!sort) { 1650 if (!sort) {
962 pr_err("%s: memdup failed\n", __func__); 1651 pr_err("%s: memdup failed\n", __func__);
963 return -1; 1652 return -1;
@@ -970,7 +1659,33 @@ static int sort_dimension__add(const char *tok, struct list_head *list)
970 return -1; 1659 return -1;
971} 1660}
972 1661
973static int setup_sorting(struct list_head *sort_list, const char *arg) 1662static int setup_slab_sorting(struct list_head *sort_list, const char *arg)
1663{
1664 char *tok;
1665 char *str = strdup(arg);
1666 char *pos = str;
1667
1668 if (!str) {
1669 pr_err("%s: strdup failed\n", __func__);
1670 return -1;
1671 }
1672
1673 while (true) {
1674 tok = strsep(&pos, ",");
1675 if (!tok)
1676 break;
1677 if (slab_sort_dimension__add(tok, sort_list) < 0) {
1678 error("Unknown slab --sort key: '%s'", tok);
1679 free(str);
1680 return -1;
1681 }
1682 }
1683
1684 free(str);
1685 return 0;
1686}
1687
1688static int setup_page_sorting(struct list_head *sort_list, const char *arg)
974{ 1689{
975 char *tok; 1690 char *tok;
976 char *str = strdup(arg); 1691 char *str = strdup(arg);
@@ -985,8 +1700,8 @@ static int setup_sorting(struct list_head *sort_list, const char *arg)
985 tok = strsep(&pos, ","); 1700 tok = strsep(&pos, ",");
986 if (!tok) 1701 if (!tok)
987 break; 1702 break;
988 if (sort_dimension__add(tok, sort_list) < 0) { 1703 if (page_sort_dimension__add(tok, sort_list) < 0) {
989 error("Unknown --sort key: '%s'", tok); 1704 error("Unknown page --sort key: '%s'", tok);
990 free(str); 1705 free(str);
991 return -1; 1706 return -1;
992 } 1707 }
@@ -1002,10 +1717,18 @@ static int parse_sort_opt(const struct option *opt __maybe_unused,
1002 if (!arg) 1717 if (!arg)
1003 return -1; 1718 return -1;
1004 1719
1005 if (caller_flag > alloc_flag) 1720 if (kmem_page > kmem_slab ||
1006 return setup_sorting(&caller_sort, arg); 1721 (kmem_page == 0 && kmem_slab == 0 && kmem_default == KMEM_PAGE)) {
1007 else 1722 if (caller_flag > alloc_flag)
1008 return setup_sorting(&alloc_sort, arg); 1723 return setup_page_sorting(&page_caller_sort, arg);
1724 else
1725 return setup_page_sorting(&page_alloc_sort, arg);
1726 } else {
1727 if (caller_flag > alloc_flag)
1728 return setup_slab_sorting(&slab_caller_sort, arg);
1729 else
1730 return setup_slab_sorting(&slab_alloc_sort, arg);
1731 }
1009 1732
1010 return 0; 1733 return 0;
1011} 1734}
@@ -1084,7 +1807,7 @@ static int __cmd_record(int argc, const char **argv)
1084 if (kmem_slab) 1807 if (kmem_slab)
1085 rec_argc += ARRAY_SIZE(slab_events); 1808 rec_argc += ARRAY_SIZE(slab_events);
1086 if (kmem_page) 1809 if (kmem_page)
1087 rec_argc += ARRAY_SIZE(page_events); 1810 rec_argc += ARRAY_SIZE(page_events) + 1; /* for -g */
1088 1811
1089 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1812 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1090 1813
@@ -1099,6 +1822,8 @@ static int __cmd_record(int argc, const char **argv)
1099 rec_argv[i] = strdup(slab_events[j]); 1822 rec_argv[i] = strdup(slab_events[j]);
1100 } 1823 }
1101 if (kmem_page) { 1824 if (kmem_page) {
1825 rec_argv[i++] = strdup("-g");
1826
1102 for (j = 0; j < ARRAY_SIZE(page_events); j++, i++) 1827 for (j = 0; j < ARRAY_SIZE(page_events); j++, i++)
1103 rec_argv[i] = strdup(page_events[j]); 1828 rec_argv[i] = strdup(page_events[j]);
1104 } 1829 }
@@ -1109,9 +1834,26 @@ static int __cmd_record(int argc, const char **argv)
1109 return cmd_record(i, rec_argv, NULL); 1834 return cmd_record(i, rec_argv, NULL);
1110} 1835}
1111 1836
1837static int kmem_config(const char *var, const char *value, void *cb)
1838{
1839 if (!strcmp(var, "kmem.default")) {
1840 if (!strcmp(value, "slab"))
1841 kmem_default = KMEM_SLAB;
1842 else if (!strcmp(value, "page"))
1843 kmem_default = KMEM_PAGE;
1844 else
1845 pr_err("invalid default value ('slab' or 'page' required): %s\n",
1846 value);
1847 return 0;
1848 }
1849
1850 return perf_default_config(var, value, cb);
1851}
1852
1112int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) 1853int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
1113{ 1854{
1114 const char * const default_sort_order = "frag,hit,bytes"; 1855 const char * const default_slab_sort = "frag,hit,bytes";
1856 const char * const default_page_sort = "bytes,hit";
1115 struct perf_data_file file = { 1857 struct perf_data_file file = {
1116 .mode = PERF_DATA_MODE_READ, 1858 .mode = PERF_DATA_MODE_READ,
1117 }; 1859 };
@@ -1124,8 +1866,8 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
1124 OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL, 1866 OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
1125 "show per-allocation statistics", parse_alloc_opt), 1867 "show per-allocation statistics", parse_alloc_opt),
1126 OPT_CALLBACK('s', "sort", NULL, "key[,key2...]", 1868 OPT_CALLBACK('s', "sort", NULL, "key[,key2...]",
1127 "sort by keys: ptr, call_site, bytes, hit, pingpong, frag", 1869 "sort by keys: ptr, callsite, bytes, hit, pingpong, frag, "
1128 parse_sort_opt), 1870 "page, order, migtype, gfp", parse_sort_opt),
1129 OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt), 1871 OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt),
1130 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"), 1872 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
1131 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), 1873 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
@@ -1133,6 +1875,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
1133 parse_slab_opt), 1875 parse_slab_opt),
1134 OPT_CALLBACK_NOOPT(0, "page", NULL, NULL, "Analyze page allocator", 1876 OPT_CALLBACK_NOOPT(0, "page", NULL, NULL, "Analyze page allocator",
1135 parse_page_opt), 1877 parse_page_opt),
1878 OPT_BOOLEAN(0, "live", &live_page, "Show live page stat"),
1136 OPT_END() 1879 OPT_END()
1137 }; 1880 };
1138 const char *const kmem_subcommands[] = { "record", "stat", NULL }; 1881 const char *const kmem_subcommands[] = { "record", "stat", NULL };
@@ -1142,15 +1885,21 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
1142 }; 1885 };
1143 struct perf_session *session; 1886 struct perf_session *session;
1144 int ret = -1; 1887 int ret = -1;
1888 const char errmsg[] = "No %s allocation events found. Have you run 'perf kmem record --%s'?\n";
1145 1889
1890 perf_config(kmem_config, NULL);
1146 argc = parse_options_subcommand(argc, argv, kmem_options, 1891 argc = parse_options_subcommand(argc, argv, kmem_options,
1147 kmem_subcommands, kmem_usage, 0); 1892 kmem_subcommands, kmem_usage, 0);
1148 1893
1149 if (!argc) 1894 if (!argc)
1150 usage_with_options(kmem_usage, kmem_options); 1895 usage_with_options(kmem_usage, kmem_options);
1151 1896
1152 if (kmem_slab == 0 && kmem_page == 0) 1897 if (kmem_slab == 0 && kmem_page == 0) {
1153 kmem_slab = 1; /* for backward compatibility */ 1898 if (kmem_default == KMEM_SLAB)
1899 kmem_slab = 1;
1900 else
1901 kmem_page = 1;
1902 }
1154 1903
1155 if (!strncmp(argv[0], "rec", 3)) { 1904 if (!strncmp(argv[0], "rec", 3)) {
1156 symbol__init(NULL); 1905 symbol__init(NULL);
@@ -1159,19 +1908,30 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
1159 1908
1160 file.path = input_name; 1909 file.path = input_name;
1161 1910
1162 session = perf_session__new(&file, false, &perf_kmem); 1911 kmem_session = session = perf_session__new(&file, false, &perf_kmem);
1163 if (session == NULL) 1912 if (session == NULL)
1164 return -1; 1913 return -1;
1165 1914
1915 if (kmem_slab) {
1916 if (!perf_evlist__find_tracepoint_by_name(session->evlist,
1917 "kmem:kmalloc")) {
1918 pr_err(errmsg, "slab", "slab");
1919 return -1;
1920 }
1921 }
1922
1166 if (kmem_page) { 1923 if (kmem_page) {
1167 struct perf_evsel *evsel = perf_evlist__first(session->evlist); 1924 struct perf_evsel *evsel;
1168 1925
1169 if (evsel == NULL || evsel->tp_format == NULL) { 1926 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
1170 pr_err("invalid event found.. aborting\n"); 1927 "kmem:mm_page_alloc");
1928 if (evsel == NULL) {
1929 pr_err(errmsg, "page", "page");
1171 return -1; 1930 return -1;
1172 } 1931 }
1173 1932
1174 kmem_page_size = pevent_get_page_size(evsel->tp_format->pevent); 1933 kmem_page_size = pevent_get_page_size(evsel->tp_format->pevent);
1934 symbol_conf.use_callchain = true;
1175 } 1935 }
1176 1936
1177 symbol__init(&session->header.env); 1937 symbol__init(&session->header.env);
@@ -1182,11 +1942,21 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
1182 if (cpu__setup_cpunode_map()) 1942 if (cpu__setup_cpunode_map())
1183 goto out_delete; 1943 goto out_delete;
1184 1944
1185 if (list_empty(&caller_sort)) 1945 if (list_empty(&slab_caller_sort))
1186 setup_sorting(&caller_sort, default_sort_order); 1946 setup_slab_sorting(&slab_caller_sort, default_slab_sort);
1187 if (list_empty(&alloc_sort)) 1947 if (list_empty(&slab_alloc_sort))
1188 setup_sorting(&alloc_sort, default_sort_order); 1948 setup_slab_sorting(&slab_alloc_sort, default_slab_sort);
1189 1949 if (list_empty(&page_caller_sort))
1950 setup_page_sorting(&page_caller_sort, default_page_sort);
1951 if (list_empty(&page_alloc_sort))
1952 setup_page_sorting(&page_alloc_sort, default_page_sort);
1953
1954 if (kmem_page) {
1955 setup_page_sorting(&page_alloc_sort_input,
1956 "page,order,migtype,gfp");
1957 setup_page_sorting(&page_caller_sort_input,
1958 "callsite,order,migtype,gfp");
1959 }
1190 ret = __cmd_kmem(session); 1960 ret = __cmd_kmem(session);
1191 } else 1961 } else
1192 usage_with_options(kmem_usage, kmem_options); 1962 usage_with_options(kmem_usage, kmem_options);
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 1f9338f6109c..74878cd75078 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -651,6 +651,7 @@ static int process_sample_event(struct perf_tool *tool,
651 struct perf_evsel *evsel, 651 struct perf_evsel *evsel,
652 struct machine *machine) 652 struct machine *machine)
653{ 653{
654 int err = 0;
654 struct thread *thread; 655 struct thread *thread;
655 struct perf_kvm_stat *kvm = container_of(tool, struct perf_kvm_stat, 656 struct perf_kvm_stat *kvm = container_of(tool, struct perf_kvm_stat,
656 tool); 657 tool);
@@ -666,9 +667,10 @@ static int process_sample_event(struct perf_tool *tool,
666 } 667 }
667 668
668 if (!handle_kvm_event(kvm, thread, evsel, sample)) 669 if (!handle_kvm_event(kvm, thread, evsel, sample))
669 return -1; 670 err = -1;
670 671
671 return 0; 672 thread__put(thread);
673 return err;
672} 674}
673 675
674static int cpu_isa_config(struct perf_kvm_stat *kvm) 676static int cpu_isa_config(struct perf_kvm_stat *kvm)
@@ -1309,6 +1311,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1309 "show events other than" 1311 "show events other than"
1310 " HLT (x86 only) or Wait state (s390 only)" 1312 " HLT (x86 only) or Wait state (s390 only)"
1311 " that take longer than duration usecs"), 1313 " that take longer than duration usecs"),
1314 OPT_UINTEGER(0, "proc-map-timeout", &kvm->opts.proc_map_timeout,
1315 "per thread proc mmap processing timeout in ms"),
1312 OPT_END() 1316 OPT_END()
1313 }; 1317 };
1314 const char * const live_usage[] = { 1318 const char * const live_usage[] = {
@@ -1336,6 +1340,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1336 kvm->opts.target.uses_mmap = false; 1340 kvm->opts.target.uses_mmap = false;
1337 kvm->opts.target.uid_str = NULL; 1341 kvm->opts.target.uid_str = NULL;
1338 kvm->opts.target.uid = UINT_MAX; 1342 kvm->opts.target.uid = UINT_MAX;
1343 kvm->opts.proc_map_timeout = 500;
1339 1344
1340 symbol__init(NULL); 1345 symbol__init(NULL);
1341 disable_buildid_cache(); 1346 disable_buildid_cache();
@@ -1391,7 +1396,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1391 perf_session__set_id_hdr_size(kvm->session); 1396 perf_session__set_id_hdr_size(kvm->session);
1392 ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true); 1397 ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true);
1393 machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target, 1398 machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target,
1394 kvm->evlist->threads, false); 1399 kvm->evlist->threads, false, kvm->opts.proc_map_timeout);
1395 err = kvm_live_open_events(kvm); 1400 err = kvm_live_open_events(kvm);
1396 if (err) 1401 if (err)
1397 goto out; 1402 goto out;
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index d49c2ab85fc2..de16aaed516e 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -769,6 +769,7 @@ static void dump_threads(void)
769 t = perf_session__findnew(session, st->tid); 769 t = perf_session__findnew(session, st->tid);
770 pr_info("%10d: %s\n", st->tid, thread__comm_str(t)); 770 pr_info("%10d: %s\n", st->tid, thread__comm_str(t));
771 node = rb_next(node); 771 node = rb_next(node);
772 thread__put(t);
772 }; 773 };
773} 774}
774 775
@@ -810,6 +811,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
810 struct perf_evsel *evsel, 811 struct perf_evsel *evsel,
811 struct machine *machine) 812 struct machine *machine)
812{ 813{
814 int err = 0;
813 struct thread *thread = machine__findnew_thread(machine, sample->pid, 815 struct thread *thread = machine__findnew_thread(machine, sample->pid,
814 sample->tid); 816 sample->tid);
815 817
@@ -821,10 +823,12 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
821 823
822 if (evsel->handler != NULL) { 824 if (evsel->handler != NULL) {
823 tracepoint_handler f = evsel->handler; 825 tracepoint_handler f = evsel->handler;
824 return f(evsel, sample); 826 err = f(evsel, sample);
825 } 827 }
826 828
827 return 0; 829 thread__put(thread);
830
831 return err;
828} 832}
829 833
830static void sort_result(void) 834static void sort_result(void)
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 675216e08bfc..da2ec06f0742 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -74,7 +74,7 @@ dump_raw_samples(struct perf_tool *tool,
74 } 74 }
75 75
76 if (al.filtered || (mem->hide_unresolved && al.sym == NULL)) 76 if (al.filtered || (mem->hide_unresolved && al.sym == NULL))
77 return 0; 77 goto out_put;
78 78
79 if (al.map != NULL) 79 if (al.map != NULL)
80 al.map->dso->hit = 1; 80 al.map->dso->hit = 1;
@@ -103,7 +103,8 @@ dump_raw_samples(struct perf_tool *tool,
103 symbol_conf.field_sep, 103 symbol_conf.field_sep,
104 al.map ? (al.map->dso ? al.map->dso->long_name : "???") : "???", 104 al.map ? (al.map->dso ? al.map->dso->long_name : "???") : "???",
105 al.sym ? al.sym->name : "???"); 105 al.sym ? al.sym->name : "???");
106 106out_put:
107 addr_location__put(&al);
107 return 0; 108 return 0;
108} 109}
109 110
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index f7b1af67e9f6..1272559fa22d 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -44,25 +44,19 @@
44 44
45#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*" 45#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
46#define DEFAULT_FUNC_FILTER "!_*" 46#define DEFAULT_FUNC_FILTER "!_*"
47#define DEFAULT_LIST_FILTER "*:*"
47 48
48/* Session management structure */ 49/* Session management structure */
49static struct { 50static struct {
51 int command; /* Command short_name */
50 bool list_events; 52 bool list_events;
51 bool force_add;
52 bool show_lines;
53 bool show_vars;
54 bool show_ext_vars;
55 bool show_funcs;
56 bool mod_events;
57 bool uprobes; 53 bool uprobes;
58 bool quiet; 54 bool quiet;
59 bool target_used; 55 bool target_used;
60 int nevents; 56 int nevents;
61 struct perf_probe_event events[MAX_PROBES]; 57 struct perf_probe_event events[MAX_PROBES];
62 struct strlist *dellist;
63 struct line_range line_range; 58 struct line_range line_range;
64 char *target; 59 char *target;
65 int max_probe_points;
66 struct strfilter *filter; 60 struct strfilter *filter;
67} params; 61} params;
68 62
@@ -93,6 +87,28 @@ static int parse_probe_event(const char *str)
93 return ret; 87 return ret;
94} 88}
95 89
90static int params_add_filter(const char *str)
91{
92 const char *err = NULL;
93 int ret = 0;
94
95 pr_debug2("Add filter: %s\n", str);
96 if (!params.filter) {
97 params.filter = strfilter__new(str, &err);
98 if (!params.filter)
99 ret = err ? -EINVAL : -ENOMEM;
100 } else
101 ret = strfilter__or(params.filter, str, &err);
102
103 if (ret == -EINVAL) {
104 pr_err("Filter parse error at %td.\n", err - str + 1);
105 pr_err("Source: \"%s\"\n", str);
106 pr_err(" %*c\n", (int)(err - str + 1), '^');
107 }
108
109 return ret;
110}
111
96static int set_target(const char *ptr) 112static int set_target(const char *ptr)
97{ 113{
98 int found = 0; 114 int found = 0;
@@ -152,34 +168,11 @@ static int parse_probe_event_argv(int argc, const char **argv)
152 168
153 len += sprintf(&buf[len], "%s ", argv[i]); 169 len += sprintf(&buf[len], "%s ", argv[i]);
154 } 170 }
155 params.mod_events = true;
156 ret = parse_probe_event(buf); 171 ret = parse_probe_event(buf);
157 free(buf); 172 free(buf);
158 return ret; 173 return ret;
159} 174}
160 175
161static int opt_add_probe_event(const struct option *opt __maybe_unused,
162 const char *str, int unset __maybe_unused)
163{
164 if (str) {
165 params.mod_events = true;
166 return parse_probe_event(str);
167 } else
168 return 0;
169}
170
171static int opt_del_probe_event(const struct option *opt __maybe_unused,
172 const char *str, int unset __maybe_unused)
173{
174 if (str) {
175 params.mod_events = true;
176 if (!params.dellist)
177 params.dellist = strlist__new(true, NULL);
178 strlist__add(params.dellist, str);
179 }
180 return 0;
181}
182
183static int opt_set_target(const struct option *opt, const char *str, 176static int opt_set_target(const struct option *opt, const char *str,
184 int unset __maybe_unused) 177 int unset __maybe_unused)
185{ 178{
@@ -217,8 +210,10 @@ static int opt_set_target(const struct option *opt, const char *str,
217 return ret; 210 return ret;
218} 211}
219 212
213/* Command option callbacks */
214
220#ifdef HAVE_DWARF_SUPPORT 215#ifdef HAVE_DWARF_SUPPORT
221static int opt_show_lines(const struct option *opt __maybe_unused, 216static int opt_show_lines(const struct option *opt,
222 const char *str, int unset __maybe_unused) 217 const char *str, int unset __maybe_unused)
223{ 218{
224 int ret = 0; 219 int ret = 0;
@@ -226,19 +221,19 @@ static int opt_show_lines(const struct option *opt __maybe_unused,
226 if (!str) 221 if (!str)
227 return 0; 222 return 0;
228 223
229 if (params.show_lines) { 224 if (params.command == 'L') {
230 pr_warning("Warning: more than one --line options are" 225 pr_warning("Warning: more than one --line options are"
231 " detected. Only the first one is valid.\n"); 226 " detected. Only the first one is valid.\n");
232 return 0; 227 return 0;
233 } 228 }
234 229
235 params.show_lines = true; 230 params.command = opt->short_name;
236 ret = parse_line_range_desc(str, &params.line_range); 231 ret = parse_line_range_desc(str, &params.line_range);
237 232
238 return ret; 233 return ret;
239} 234}
240 235
241static int opt_show_vars(const struct option *opt __maybe_unused, 236static int opt_show_vars(const struct option *opt,
242 const char *str, int unset __maybe_unused) 237 const char *str, int unset __maybe_unused)
243{ 238{
244 struct perf_probe_event *pev = &params.events[params.nevents]; 239 struct perf_probe_event *pev = &params.events[params.nevents];
@@ -252,29 +247,39 @@ static int opt_show_vars(const struct option *opt __maybe_unused,
252 pr_err(" Error: '--vars' doesn't accept arguments.\n"); 247 pr_err(" Error: '--vars' doesn't accept arguments.\n");
253 return -EINVAL; 248 return -EINVAL;
254 } 249 }
255 params.show_vars = true; 250 params.command = opt->short_name;
256 251
257 return ret; 252 return ret;
258} 253}
259#endif 254#endif
255static int opt_add_probe_event(const struct option *opt,
256 const char *str, int unset __maybe_unused)
257{
258 if (str) {
259 params.command = opt->short_name;
260 return parse_probe_event(str);
261 }
262
263 return 0;
264}
265
266static int opt_set_filter_with_command(const struct option *opt,
267 const char *str, int unset)
268{
269 if (!unset)
270 params.command = opt->short_name;
271
272 if (str)
273 return params_add_filter(str);
274
275 return 0;
276}
260 277
261static int opt_set_filter(const struct option *opt __maybe_unused, 278static int opt_set_filter(const struct option *opt __maybe_unused,
262 const char *str, int unset __maybe_unused) 279 const char *str, int unset __maybe_unused)
263{ 280{
264 const char *err; 281 if (str)
265 282 return params_add_filter(str);
266 if (str) {
267 pr_debug2("Set filter: %s\n", str);
268 if (params.filter)
269 strfilter__delete(params.filter);
270 params.filter = strfilter__new(str, &err);
271 if (!params.filter) {
272 pr_err("Filter parse error at %td.\n", err - str + 1);
273 pr_err("Source: \"%s\"\n", str);
274 pr_err(" %*c\n", (int)(err - str + 1), '^');
275 return -EINVAL;
276 }
277 }
278 283
279 return 0; 284 return 0;
280} 285}
@@ -290,8 +295,6 @@ static void cleanup_params(void)
290 295
291 for (i = 0; i < params.nevents; i++) 296 for (i = 0; i < params.nevents; i++)
292 clear_perf_probe_event(params.events + i); 297 clear_perf_probe_event(params.events + i);
293 if (params.dellist)
294 strlist__delete(params.dellist);
295 line_range__clear(&params.line_range); 298 line_range__clear(&params.line_range);
296 free(params.target); 299 free(params.target);
297 if (params.filter) 300 if (params.filter)
@@ -316,22 +319,24 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
316 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]", 319 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
317 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", 320 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
318 "perf probe [<options>] --del '[GROUP:]EVENT' ...", 321 "perf probe [<options>] --del '[GROUP:]EVENT' ...",
319 "perf probe --list", 322 "perf probe --list [GROUP:]EVENT ...",
320#ifdef HAVE_DWARF_SUPPORT 323#ifdef HAVE_DWARF_SUPPORT
321 "perf probe [<options>] --line 'LINEDESC'", 324 "perf probe [<options>] --line 'LINEDESC'",
322 "perf probe [<options>] --vars 'PROBEPOINT'", 325 "perf probe [<options>] --vars 'PROBEPOINT'",
323#endif 326#endif
327 "perf probe [<options>] --funcs",
324 NULL 328 NULL
325}; 329 };
326 struct option options[] = { 330 struct option options[] = {
327 OPT_INCR('v', "verbose", &verbose, 331 OPT_INCR('v', "verbose", &verbose,
328 "be more verbose (show parsed arguments, etc)"), 332 "be more verbose (show parsed arguments, etc)"),
329 OPT_BOOLEAN('q', "quiet", &params.quiet, 333 OPT_BOOLEAN('q', "quiet", &params.quiet,
330 "be quiet (do not show any mesages)"), 334 "be quiet (do not show any mesages)"),
331 OPT_BOOLEAN('l', "list", &params.list_events, 335 OPT_CALLBACK_DEFAULT('l', "list", NULL, "[GROUP:]EVENT",
332 "list up current probe events"), 336 "list up probe events",
337 opt_set_filter_with_command, DEFAULT_LIST_FILTER),
333 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", 338 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
334 opt_del_probe_event), 339 opt_set_filter_with_command),
335 OPT_CALLBACK('a', "add", NULL, 340 OPT_CALLBACK('a', "add", NULL,
336#ifdef HAVE_DWARF_SUPPORT 341#ifdef HAVE_DWARF_SUPPORT
337 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT" 342 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
@@ -356,7 +361,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
356 "\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n", 361 "\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n",
357#endif 362#endif
358 opt_add_probe_event), 363 opt_add_probe_event),
359 OPT_BOOLEAN('f', "force", &params.force_add, "forcibly add events" 364 OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
360 " with existing name"), 365 " with existing name"),
361#ifdef HAVE_DWARF_SUPPORT 366#ifdef HAVE_DWARF_SUPPORT
362 OPT_CALLBACK('L', "line", NULL, 367 OPT_CALLBACK('L', "line", NULL,
@@ -365,8 +370,10 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
365 OPT_CALLBACK('V', "vars", NULL, 370 OPT_CALLBACK('V', "vars", NULL,
366 "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT", 371 "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT",
367 "Show accessible variables on PROBEDEF", opt_show_vars), 372 "Show accessible variables on PROBEDEF", opt_show_vars),
368 OPT_BOOLEAN('\0', "externs", &params.show_ext_vars, 373 OPT_BOOLEAN('\0', "externs", &probe_conf.show_ext_vars,
369 "Show external variables too (with --vars only)"), 374 "Show external variables too (with --vars only)"),
375 OPT_BOOLEAN('\0', "range", &probe_conf.show_location_range,
376 "Show variables location range in scope (with --vars only)"),
370 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 377 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
371 "file", "vmlinux pathname"), 378 "file", "vmlinux pathname"),
372 OPT_STRING('s', "source", &symbol_conf.source_prefix, 379 OPT_STRING('s', "source", &symbol_conf.source_prefix,
@@ -374,12 +381,15 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
374 OPT_CALLBACK('m', "module", NULL, "modname|path", 381 OPT_CALLBACK('m', "module", NULL, "modname|path",
375 "target module name (for online) or path (for offline)", 382 "target module name (for online) or path (for offline)",
376 opt_set_target), 383 opt_set_target),
384 OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines,
385 "Don't search inlined functions"),
377#endif 386#endif
378 OPT__DRY_RUN(&probe_event_dry_run), 387 OPT__DRY_RUN(&probe_event_dry_run),
379 OPT_INTEGER('\0', "max-probes", &params.max_probe_points, 388 OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
380 "Set how many probe points can be found for a probe."), 389 "Set how many probe points can be found for a probe."),
381 OPT_BOOLEAN('F', "funcs", &params.show_funcs, 390 OPT_CALLBACK_DEFAULT('F', "funcs", NULL, "[FILTER]",
382 "Show potential probe-able functions."), 391 "Show potential probe-able functions.",
392 opt_set_filter_with_command, DEFAULT_FUNC_FILTER),
383 OPT_CALLBACK('\0', "filter", NULL, 393 OPT_CALLBACK('\0', "filter", NULL,
384 "[!]FILTER", "Set a filter (with --vars/funcs only)\n" 394 "[!]FILTER", "Set a filter (with --vars/funcs only)\n"
385 "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n" 395 "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n"
@@ -402,6 +412,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
402 set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE); 412 set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
403 set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE); 413 set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE);
404#endif 414#endif
415 set_option_flag(options, 'F', "funcs", PARSE_OPT_EXCLUSIVE);
405 416
406 argc = parse_options(argc, argv, options, probe_usage, 417 argc = parse_options(argc, argv, options, probe_usage,
407 PARSE_OPT_STOP_AT_NON_OPTION); 418 PARSE_OPT_STOP_AT_NON_OPTION);
@@ -410,11 +421,16 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
410 pr_warning(" Error: '-' is not supported.\n"); 421 pr_warning(" Error: '-' is not supported.\n");
411 usage_with_options(probe_usage, options); 422 usage_with_options(probe_usage, options);
412 } 423 }
424 if (params.command && params.command != 'a') {
425 pr_warning(" Error: another command except --add is set.\n");
426 usage_with_options(probe_usage, options);
427 }
413 ret = parse_probe_event_argv(argc, argv); 428 ret = parse_probe_event_argv(argc, argv);
414 if (ret < 0) { 429 if (ret < 0) {
415 pr_err_with_code(" Error: Command Parse Error.", ret); 430 pr_err_with_code(" Error: Command Parse Error.", ret);
416 return ret; 431 return ret;
417 } 432 }
433 params.command = 'a';
418 } 434 }
419 435
420 if (params.quiet) { 436 if (params.quiet) {
@@ -425,89 +441,70 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
425 verbose = -1; 441 verbose = -1;
426 } 442 }
427 443
428 if (params.max_probe_points == 0) 444 if (probe_conf.max_probes == 0)
429 params.max_probe_points = MAX_PROBES; 445 probe_conf.max_probes = MAX_PROBES;
430
431 if ((!params.nevents && !params.dellist && !params.list_events &&
432 !params.show_lines && !params.show_funcs))
433 usage_with_options(probe_usage, options);
434 446
435 /* 447 /*
436 * Only consider the user's kernel image path if given. 448 * Only consider the user's kernel image path if given.
437 */ 449 */
438 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 450 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
439 451
440 if (params.list_events) { 452 switch (params.command) {
453 case 'l':
441 if (params.uprobes) { 454 if (params.uprobes) {
442 pr_warning(" Error: Don't use --list with --exec.\n"); 455 pr_warning(" Error: Don't use --list with --exec.\n");
443 usage_with_options(probe_usage, options); 456 usage_with_options(probe_usage, options);
444 } 457 }
445 ret = show_perf_probe_events(); 458 ret = show_perf_probe_events(params.filter);
446 if (ret < 0) 459 if (ret < 0)
447 pr_err_with_code(" Error: Failed to show event list.", ret); 460 pr_err_with_code(" Error: Failed to show event list.", ret);
448 return ret; 461 return ret;
449 } 462 case 'F':
450 if (params.show_funcs) {
451 if (!params.filter)
452 params.filter = strfilter__new(DEFAULT_FUNC_FILTER,
453 NULL);
454 ret = show_available_funcs(params.target, params.filter, 463 ret = show_available_funcs(params.target, params.filter,
455 params.uprobes); 464 params.uprobes);
456 strfilter__delete(params.filter);
457 params.filter = NULL;
458 if (ret < 0) 465 if (ret < 0)
459 pr_err_with_code(" Error: Failed to show functions.", ret); 466 pr_err_with_code(" Error: Failed to show functions.", ret);
460 return ret; 467 return ret;
461 }
462
463#ifdef HAVE_DWARF_SUPPORT 468#ifdef HAVE_DWARF_SUPPORT
464 if (params.show_lines) { 469 case 'L':
465 ret = show_line_range(&params.line_range, params.target, 470 ret = show_line_range(&params.line_range, params.target,
466 params.uprobes); 471 params.uprobes);
467 if (ret < 0) 472 if (ret < 0)
468 pr_err_with_code(" Error: Failed to show lines.", ret); 473 pr_err_with_code(" Error: Failed to show lines.", ret);
469 return ret; 474 return ret;
470 } 475 case 'V':
471 if (params.show_vars) {
472 if (!params.filter) 476 if (!params.filter)
473 params.filter = strfilter__new(DEFAULT_VAR_FILTER, 477 params.filter = strfilter__new(DEFAULT_VAR_FILTER,
474 NULL); 478 NULL);
475 479
476 ret = show_available_vars(params.events, params.nevents, 480 ret = show_available_vars(params.events, params.nevents,
477 params.max_probe_points, 481 params.filter);
478 params.target,
479 params.filter,
480 params.show_ext_vars);
481 strfilter__delete(params.filter);
482 params.filter = NULL;
483 if (ret < 0) 482 if (ret < 0)
484 pr_err_with_code(" Error: Failed to show vars.", ret); 483 pr_err_with_code(" Error: Failed to show vars.", ret);
485 return ret; 484 return ret;
486 }
487#endif 485#endif
488 486 case 'd':
489 if (params.dellist) { 487 ret = del_perf_probe_events(params.filter);
490 ret = del_perf_probe_events(params.dellist);
491 if (ret < 0) { 488 if (ret < 0) {
492 pr_err_with_code(" Error: Failed to delete events.", ret); 489 pr_err_with_code(" Error: Failed to delete events.", ret);
493 return ret; 490 return ret;
494 } 491 }
495 } 492 break;
496 493 case 'a':
497 if (params.nevents) {
498 /* Ensure the last given target is used */ 494 /* Ensure the last given target is used */
499 if (params.target && !params.target_used) { 495 if (params.target && !params.target_used) {
500 pr_warning(" Error: -x/-m must follow the probe definitions.\n"); 496 pr_warning(" Error: -x/-m must follow the probe definitions.\n");
501 usage_with_options(probe_usage, options); 497 usage_with_options(probe_usage, options);
502 } 498 }
503 499
504 ret = add_perf_probe_events(params.events, params.nevents, 500 ret = add_perf_probe_events(params.events, params.nevents);
505 params.max_probe_points,
506 params.force_add);
507 if (ret < 0) { 501 if (ret < 0) {
508 pr_err_with_code(" Error: Failed to add events.", ret); 502 pr_err_with_code(" Error: Failed to add events.", ret);
509 return ret; 503 return ret;
510 } 504 }
505 break;
506 default:
507 usage_with_options(probe_usage, options);
511 } 508 }
512 return 0; 509 return 0;
513} 510}
@@ -522,5 +519,5 @@ int cmd_probe(int argc, const char **argv, const char *prefix)
522 cleanup_params(); 519 cleanup_params();
523 } 520 }
524 521
525 return ret; 522 return ret < 0 ? ret : 0;
526} 523}
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index c3efdfb630b5..de165a1b9240 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -27,6 +27,8 @@
27#include "util/cpumap.h" 27#include "util/cpumap.h"
28#include "util/thread_map.h" 28#include "util/thread_map.h"
29#include "util/data.h" 29#include "util/data.h"
30#include "util/auxtrace.h"
31#include "util/parse-branch-options.h"
30 32
31#include <unistd.h> 33#include <unistd.h>
32#include <sched.h> 34#include <sched.h>
@@ -38,6 +40,7 @@ struct record {
38 struct record_opts opts; 40 struct record_opts opts;
39 u64 bytes_written; 41 u64 bytes_written;
40 struct perf_data_file file; 42 struct perf_data_file file;
43 struct auxtrace_record *itr;
41 struct perf_evlist *evlist; 44 struct perf_evlist *evlist;
42 struct perf_session *session; 45 struct perf_session *session;
43 const char *progname; 46 const char *progname;
@@ -110,9 +113,12 @@ out:
110 return rc; 113 return rc;
111} 114}
112 115
113static volatile int done = 0; 116static volatile int done;
114static volatile int signr = -1; 117static volatile int signr = -1;
115static volatile int child_finished = 0; 118static volatile int child_finished;
119static volatile int auxtrace_snapshot_enabled;
120static volatile int auxtrace_snapshot_err;
121static volatile int auxtrace_record__snapshot_started;
116 122
117static void sig_handler(int sig) 123static void sig_handler(int sig)
118{ 124{
@@ -133,6 +139,133 @@ static void record__sig_exit(void)
133 raise(signr); 139 raise(signr);
134} 140}
135 141
142#ifdef HAVE_AUXTRACE_SUPPORT
143
144static int record__process_auxtrace(struct perf_tool *tool,
145 union perf_event *event, void *data1,
146 size_t len1, void *data2, size_t len2)
147{
148 struct record *rec = container_of(tool, struct record, tool);
149 struct perf_data_file *file = &rec->file;
150 size_t padding;
151 u8 pad[8] = {0};
152
153 if (!perf_data_file__is_pipe(file)) {
154 off_t file_offset;
155 int fd = perf_data_file__fd(file);
156 int err;
157
158 file_offset = lseek(fd, 0, SEEK_CUR);
159 if (file_offset == -1)
160 return -1;
161 err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
162 event, file_offset);
163 if (err)
164 return err;
165 }
166
167 /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
168 padding = (len1 + len2) & 7;
169 if (padding)
170 padding = 8 - padding;
171
172 record__write(rec, event, event->header.size);
173 record__write(rec, data1, len1);
174 if (len2)
175 record__write(rec, data2, len2);
176 record__write(rec, &pad, padding);
177
178 return 0;
179}
180
181static int record__auxtrace_mmap_read(struct record *rec,
182 struct auxtrace_mmap *mm)
183{
184 int ret;
185
186 ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool,
187 record__process_auxtrace);
188 if (ret < 0)
189 return ret;
190
191 if (ret)
192 rec->samples++;
193
194 return 0;
195}
196
197static int record__auxtrace_mmap_read_snapshot(struct record *rec,
198 struct auxtrace_mmap *mm)
199{
200 int ret;
201
202 ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool,
203 record__process_auxtrace,
204 rec->opts.auxtrace_snapshot_size);
205 if (ret < 0)
206 return ret;
207
208 if (ret)
209 rec->samples++;
210
211 return 0;
212}
213
214static int record__auxtrace_read_snapshot_all(struct record *rec)
215{
216 int i;
217 int rc = 0;
218
219 for (i = 0; i < rec->evlist->nr_mmaps; i++) {
220 struct auxtrace_mmap *mm =
221 &rec->evlist->mmap[i].auxtrace_mmap;
222
223 if (!mm->base)
224 continue;
225
226 if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) {
227 rc = -1;
228 goto out;
229 }
230 }
231out:
232 return rc;
233}
234
235static void record__read_auxtrace_snapshot(struct record *rec)
236{
237 pr_debug("Recording AUX area tracing snapshot\n");
238 if (record__auxtrace_read_snapshot_all(rec) < 0) {
239 auxtrace_snapshot_err = -1;
240 } else {
241 auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr);
242 if (!auxtrace_snapshot_err)
243 auxtrace_snapshot_enabled = 1;
244 }
245}
246
247#else
248
249static inline
250int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
251 struct auxtrace_mmap *mm __maybe_unused)
252{
253 return 0;
254}
255
256static inline
257void record__read_auxtrace_snapshot(struct record *rec __maybe_unused)
258{
259}
260
261static inline
262int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
263{
264 return 0;
265}
266
267#endif
268
136static int record__open(struct record *rec) 269static int record__open(struct record *rec)
137{ 270{
138 char msg[512]; 271 char msg[512];
@@ -169,13 +302,16 @@ try_again:
169 goto out; 302 goto out;
170 } 303 }
171 304
172 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 305 if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
306 opts->auxtrace_mmap_pages,
307 opts->auxtrace_snapshot_mode) < 0) {
173 if (errno == EPERM) { 308 if (errno == EPERM) {
174 pr_err("Permission error mapping pages.\n" 309 pr_err("Permission error mapping pages.\n"
175 "Consider increasing " 310 "Consider increasing "
176 "/proc/sys/kernel/perf_event_mlock_kb,\n" 311 "/proc/sys/kernel/perf_event_mlock_kb,\n"
177 "or try again with a smaller value of -m/--mmap_pages.\n" 312 "or try again with a smaller value of -m/--mmap_pages.\n"
178 "(current value: %u)\n", opts->mmap_pages); 313 "(current value: %u,%u)\n",
314 opts->mmap_pages, opts->auxtrace_mmap_pages);
179 rc = -errno; 315 rc = -errno;
180 } else { 316 } else {
181 pr_err("failed to mmap with %d (%s)\n", errno, 317 pr_err("failed to mmap with %d (%s)\n", errno,
@@ -209,12 +345,9 @@ static int process_buildids(struct record *rec)
209 struct perf_data_file *file = &rec->file; 345 struct perf_data_file *file = &rec->file;
210 struct perf_session *session = rec->session; 346 struct perf_session *session = rec->session;
211 347
212 u64 size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 348 if (file->size == 0)
213 if (size == 0)
214 return 0; 349 return 0;
215 350
216 file->size = size;
217
218 /* 351 /*
219 * During this process, it'll load kernel map and replace the 352 * During this process, it'll load kernel map and replace the
220 * dso->long_name to a real pathname it found. In this case 353 * dso->long_name to a real pathname it found. In this case
@@ -270,12 +403,20 @@ static int record__mmap_read_all(struct record *rec)
270 int rc = 0; 403 int rc = 0;
271 404
272 for (i = 0; i < rec->evlist->nr_mmaps; i++) { 405 for (i = 0; i < rec->evlist->nr_mmaps; i++) {
406 struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap;
407
273 if (rec->evlist->mmap[i].base) { 408 if (rec->evlist->mmap[i].base) {
274 if (record__mmap_read(rec, i) != 0) { 409 if (record__mmap_read(rec, i) != 0) {
275 rc = -1; 410 rc = -1;
276 goto out; 411 goto out;
277 } 412 }
278 } 413 }
414
415 if (mm->base && !rec->opts.auxtrace_snapshot_mode &&
416 record__auxtrace_mmap_read(rec, mm) != 0) {
417 rc = -1;
418 goto out;
419 }
279 } 420 }
280 421
281 /* 422 /*
@@ -305,6 +446,9 @@ static void record__init_features(struct record *rec)
305 446
306 if (!rec->opts.branch_stack) 447 if (!rec->opts.branch_stack)
307 perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 448 perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
449
450 if (!rec->opts.full_auxtrace)
451 perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
308} 452}
309 453
310static volatile int workload_exec_errno; 454static volatile int workload_exec_errno;
@@ -323,6 +467,8 @@ static void workload_exec_failed_signal(int signo __maybe_unused,
323 child_finished = 1; 467 child_finished = 1;
324} 468}
325 469
470static void snapshot_sig_handler(int sig);
471
326static int __cmd_record(struct record *rec, int argc, const char **argv) 472static int __cmd_record(struct record *rec, int argc, const char **argv)
327{ 473{
328 int err; 474 int err;
@@ -343,6 +489,10 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
343 signal(SIGCHLD, sig_handler); 489 signal(SIGCHLD, sig_handler);
344 signal(SIGINT, sig_handler); 490 signal(SIGINT, sig_handler);
345 signal(SIGTERM, sig_handler); 491 signal(SIGTERM, sig_handler);
492 if (rec->opts.auxtrace_snapshot_mode)
493 signal(SIGUSR2, snapshot_sig_handler);
494 else
495 signal(SIGUSR2, SIG_IGN);
346 496
347 session = perf_session__new(file, false, tool); 497 session = perf_session__new(file, false, tool);
348 if (session == NULL) { 498 if (session == NULL) {
@@ -421,6 +571,13 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
421 } 571 }
422 } 572 }
423 573
574 if (rec->opts.full_auxtrace) {
575 err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
576 session, process_synthesized_event);
577 if (err)
578 goto out_delete_session;
579 }
580
424 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 581 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
425 machine); 582 machine);
426 if (err < 0) 583 if (err < 0)
@@ -441,7 +598,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
441 } 598 }
442 599
443 err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 600 err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
444 process_synthesized_event, opts->sample_address); 601 process_synthesized_event, opts->sample_address,
602 opts->proc_map_timeout);
445 if (err != 0) 603 if (err != 0)
446 goto out_child; 604 goto out_child;
447 605
@@ -475,14 +633,27 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
475 perf_evlist__enable(rec->evlist); 633 perf_evlist__enable(rec->evlist);
476 } 634 }
477 635
636 auxtrace_snapshot_enabled = 1;
478 for (;;) { 637 for (;;) {
479 int hits = rec->samples; 638 int hits = rec->samples;
480 639
481 if (record__mmap_read_all(rec) < 0) { 640 if (record__mmap_read_all(rec) < 0) {
641 auxtrace_snapshot_enabled = 0;
482 err = -1; 642 err = -1;
483 goto out_child; 643 goto out_child;
484 } 644 }
485 645
646 if (auxtrace_record__snapshot_started) {
647 auxtrace_record__snapshot_started = 0;
648 if (!auxtrace_snapshot_err)
649 record__read_auxtrace_snapshot(rec);
650 if (auxtrace_snapshot_err) {
651 pr_err("AUX area tracing snapshot failed\n");
652 err = -1;
653 goto out_child;
654 }
655 }
656
486 if (hits == rec->samples) { 657 if (hits == rec->samples) {
487 if (done || draining) 658 if (done || draining)
488 break; 659 break;
@@ -505,10 +676,12 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
505 * disable events in this case. 676 * disable events in this case.
506 */ 677 */
507 if (done && !disabled && !target__none(&opts->target)) { 678 if (done && !disabled && !target__none(&opts->target)) {
679 auxtrace_snapshot_enabled = 0;
508 perf_evlist__disable(rec->evlist); 680 perf_evlist__disable(rec->evlist);
509 disabled = true; 681 disabled = true;
510 } 682 }
511 } 683 }
684 auxtrace_snapshot_enabled = 0;
512 685
513 if (forks && workload_exec_errno) { 686 if (forks && workload_exec_errno) {
514 char msg[STRERR_BUFSIZE]; 687 char msg[STRERR_BUFSIZE];
@@ -544,16 +717,25 @@ out_child:
544 717
545 if (!err && !file->is_pipe) { 718 if (!err && !file->is_pipe) {
546 rec->session->header.data_size += rec->bytes_written; 719 rec->session->header.data_size += rec->bytes_written;
720 file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
547 721
548 if (!rec->no_buildid) 722 if (!rec->no_buildid) {
549 process_buildids(rec); 723 process_buildids(rec);
724 /*
725 * We take all buildids when the file contains
726 * AUX area tracing data because we do not decode the
727 * trace because it would take too long.
728 */
729 if (rec->opts.full_auxtrace)
730 dsos__hit_all(rec->session);
731 }
550 perf_session__write_header(rec->session, rec->evlist, fd, true); 732 perf_session__write_header(rec->session, rec->evlist, fd, true);
551 } 733 }
552 734
553 if (!err && !quiet) { 735 if (!err && !quiet) {
554 char samples[128]; 736 char samples[128];
555 737
556 if (rec->samples) 738 if (rec->samples && !rec->opts.full_auxtrace)
557 scnprintf(samples, sizeof(samples), 739 scnprintf(samples, sizeof(samples),
558 " (%" PRIu64 " samples)", rec->samples); 740 " (%" PRIu64 " samples)", rec->samples);
559 else 741 else
@@ -569,94 +751,6 @@ out_delete_session:
569 return status; 751 return status;
570} 752}
571 753
572#define BRANCH_OPT(n, m) \
573 { .name = n, .mode = (m) }
574
575#define BRANCH_END { .name = NULL }
576
577struct branch_mode {
578 const char *name;
579 int mode;
580};
581
582static const struct branch_mode branch_modes[] = {
583 BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
584 BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
585 BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
586 BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
587 BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
588 BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
589 BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
590 BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX),
591 BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX),
592 BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX),
593 BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND),
594 BRANCH_END
595};
596
597static int
598parse_branch_stack(const struct option *opt, const char *str, int unset)
599{
600#define ONLY_PLM \
601 (PERF_SAMPLE_BRANCH_USER |\
602 PERF_SAMPLE_BRANCH_KERNEL |\
603 PERF_SAMPLE_BRANCH_HV)
604
605 uint64_t *mode = (uint64_t *)opt->value;
606 const struct branch_mode *br;
607 char *s, *os = NULL, *p;
608 int ret = -1;
609
610 if (unset)
611 return 0;
612
613 /*
614 * cannot set it twice, -b + --branch-filter for instance
615 */
616 if (*mode)
617 return -1;
618
619 /* str may be NULL in case no arg is passed to -b */
620 if (str) {
621 /* because str is read-only */
622 s = os = strdup(str);
623 if (!s)
624 return -1;
625
626 for (;;) {
627 p = strchr(s, ',');
628 if (p)
629 *p = '\0';
630
631 for (br = branch_modes; br->name; br++) {
632 if (!strcasecmp(s, br->name))
633 break;
634 }
635 if (!br->name) {
636 ui__warning("unknown branch filter %s,"
637 " check man page\n", s);
638 goto error;
639 }
640
641 *mode |= br->mode;
642
643 if (!p)
644 break;
645
646 s = p + 1;
647 }
648 }
649 ret = 0;
650
651 /* default to any branch */
652 if ((*mode & ~ONLY_PLM) == 0) {
653 *mode = PERF_SAMPLE_BRANCH_ANY;
654 }
655error:
656 free(os);
657 return ret;
658}
659
660static void callchain_debug(void) 754static void callchain_debug(void)
661{ 755{
662 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 756 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
@@ -795,6 +889,49 @@ static int parse_clockid(const struct option *opt, const char *str, int unset)
795 return -1; 889 return -1;
796} 890}
797 891
892static int record__parse_mmap_pages(const struct option *opt,
893 const char *str,
894 int unset __maybe_unused)
895{
896 struct record_opts *opts = opt->value;
897 char *s, *p;
898 unsigned int mmap_pages;
899 int ret;
900
901 if (!str)
902 return -EINVAL;
903
904 s = strdup(str);
905 if (!s)
906 return -ENOMEM;
907
908 p = strchr(s, ',');
909 if (p)
910 *p = '\0';
911
912 if (*s) {
913 ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s);
914 if (ret)
915 goto out_free;
916 opts->mmap_pages = mmap_pages;
917 }
918
919 if (!p) {
920 ret = 0;
921 goto out_free;
922 }
923
924 ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1);
925 if (ret)
926 goto out_free;
927
928 opts->auxtrace_mmap_pages = mmap_pages;
929
930out_free:
931 free(s);
932 return ret;
933}
934
798static const char * const __record_usage[] = { 935static const char * const __record_usage[] = {
799 "perf record [<options>] [<command>]", 936 "perf record [<options>] [<command>]",
800 "perf record [<options>] -- <command> [<options>]", 937 "perf record [<options>] -- <command> [<options>]",
@@ -823,6 +960,7 @@ static struct record record = {
823 .uses_mmap = true, 960 .uses_mmap = true,
824 .default_per_cpu = true, 961 .default_per_cpu = true,
825 }, 962 },
963 .proc_map_timeout = 500,
826 }, 964 },
827 .tool = { 965 .tool = {
828 .sample = process_sample_event, 966 .sample = process_sample_event,
@@ -875,9 +1013,9 @@ struct option __record_options[] = {
875 &record.opts.no_inherit_set, 1013 &record.opts.no_inherit_set,
876 "child tasks do not inherit counters"), 1014 "child tasks do not inherit counters"),
877 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1015 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
878 OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages", 1016 OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
879 "number of mmap data pages", 1017 "number of mmap data pages and AUX area tracing mmap pages",
880 perf_evlist__parse_mmap_pages), 1018 record__parse_mmap_pages),
881 OPT_BOOLEAN(0, "group", &record.opts.group, 1019 OPT_BOOLEAN(0, "group", &record.opts.group,
882 "put the counters into a counter group"), 1020 "put the counters into a counter group"),
883 OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 1021 OPT_CALLBACK_NOOPT('g', NULL, &record.opts,
@@ -891,10 +1029,9 @@ struct option __record_options[] = {
891 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1029 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
892 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1030 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
893 "per thread counts"), 1031 "per thread counts"),
894 OPT_BOOLEAN('d', "data", &record.opts.sample_address, 1032 OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
895 "Sample addresses"), 1033 OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Record the sample timestamps"),
896 OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 1034 OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"),
897 OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
898 OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1035 OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
899 "don't sample"), 1036 "don't sample"),
900 OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 1037 OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
@@ -929,6 +1066,10 @@ struct option __record_options[] = {
929 OPT_CALLBACK('k', "clockid", &record.opts, 1066 OPT_CALLBACK('k', "clockid", &record.opts,
930 "clockid", "clockid to use for events, see clock_gettime()", 1067 "clockid", "clockid to use for events, see clock_gettime()",
931 parse_clockid), 1068 parse_clockid),
1069 OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
1070 "opts", "AUX area tracing Snapshot Mode", ""),
1071 OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout,
1072 "per thread proc mmap processing timeout in ms"),
932 OPT_END() 1073 OPT_END()
933}; 1074};
934 1075
@@ -936,7 +1077,7 @@ struct option *record_options = __record_options;
936 1077
937int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 1078int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
938{ 1079{
939 int err = -ENOMEM; 1080 int err;
940 struct record *rec = &record; 1081 struct record *rec = &record;
941 char errbuf[BUFSIZ]; 1082 char errbuf[BUFSIZ];
942 1083
@@ -957,6 +1098,19 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
957 usage_with_options(record_usage, record_options); 1098 usage_with_options(record_usage, record_options);
958 } 1099 }
959 1100
1101 if (!rec->itr) {
1102 rec->itr = auxtrace_record__init(rec->evlist, &err);
1103 if (err)
1104 return err;
1105 }
1106
1107 err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
1108 rec->opts.auxtrace_snapshot_opts);
1109 if (err)
1110 return err;
1111
1112 err = -ENOMEM;
1113
960 symbol__init(NULL); 1114 symbol__init(NULL);
961 1115
962 if (symbol_conf.kptr_restrict) 1116 if (symbol_conf.kptr_restrict)
@@ -1002,6 +1156,10 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1002 if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1156 if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
1003 usage_with_options(record_usage, record_options); 1157 usage_with_options(record_usage, record_options);
1004 1158
1159 err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
1160 if (err)
1161 goto out_symbol_exit;
1162
1005 if (record_opts__config(&rec->opts)) { 1163 if (record_opts__config(&rec->opts)) {
1006 err = -EINVAL; 1164 err = -EINVAL;
1007 goto out_symbol_exit; 1165 goto out_symbol_exit;
@@ -1011,5 +1169,15 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1011out_symbol_exit: 1169out_symbol_exit:
1012 perf_evlist__delete(rec->evlist); 1170 perf_evlist__delete(rec->evlist);
1013 symbol__exit(); 1171 symbol__exit();
1172 auxtrace_record__free(rec->itr);
1014 return err; 1173 return err;
1015} 1174}
1175
1176static void snapshot_sig_handler(int sig __maybe_unused)
1177{
1178 if (!auxtrace_snapshot_enabled)
1179 return;
1180 auxtrace_snapshot_enabled = 0;
1181 auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr);
1182 auxtrace_record__snapshot_started = 1;
1183}
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index b63aeda719be..32626ea3e227 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -36,6 +36,8 @@
36#include "util/data.h" 36#include "util/data.h"
37#include "arch/common.h" 37#include "arch/common.h"
38 38
39#include "util/auxtrace.h"
40
39#include <dlfcn.h> 41#include <dlfcn.h>
40#include <linux/bitmap.h> 42#include <linux/bitmap.h>
41 43
@@ -137,10 +139,12 @@ static int process_sample_event(struct perf_tool *tool,
137 struct report *rep = container_of(tool, struct report, tool); 139 struct report *rep = container_of(tool, struct report, tool);
138 struct addr_location al; 140 struct addr_location al;
139 struct hist_entry_iter iter = { 141 struct hist_entry_iter iter = {
140 .hide_unresolved = rep->hide_unresolved, 142 .evsel = evsel,
141 .add_entry_cb = hist_iter__report_callback, 143 .sample = sample,
144 .hide_unresolved = rep->hide_unresolved,
145 .add_entry_cb = hist_iter__report_callback,
142 }; 146 };
143 int ret; 147 int ret = 0;
144 148
145 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { 149 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
146 pr_debug("problem processing %d event, skipping it.\n", 150 pr_debug("problem processing %d event, skipping it.\n",
@@ -149,10 +153,10 @@ static int process_sample_event(struct perf_tool *tool,
149 } 153 }
150 154
151 if (rep->hide_unresolved && al.sym == NULL) 155 if (rep->hide_unresolved && al.sym == NULL)
152 return 0; 156 goto out_put;
153 157
154 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap)) 158 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
155 return 0; 159 goto out_put;
156 160
157 if (sort__mode == SORT_MODE__BRANCH) 161 if (sort__mode == SORT_MODE__BRANCH)
158 iter.ops = &hist_iter_branch; 162 iter.ops = &hist_iter_branch;
@@ -166,11 +170,11 @@ static int process_sample_event(struct perf_tool *tool,
166 if (al.map != NULL) 170 if (al.map != NULL)
167 al.map->dso->hit = 1; 171 al.map->dso->hit = 1;
168 172
169 ret = hist_entry_iter__add(&iter, &al, evsel, sample, rep->max_stack, 173 ret = hist_entry_iter__add(&iter, &al, rep->max_stack, rep);
170 rep);
171 if (ret < 0) 174 if (ret < 0)
172 pr_debug("problem adding hist entry, skipping event\n"); 175 pr_debug("problem adding hist entry, skipping event\n");
173 176out_put:
177 addr_location__put(&al);
174 return ret; 178 return ret;
175} 179}
176 180
@@ -316,6 +320,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
316{ 320{
317 struct perf_evsel *pos; 321 struct perf_evsel *pos;
318 322
323 fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", evlist->stats.total_lost_samples);
319 evlist__for_each(evlist, pos) { 324 evlist__for_each(evlist, pos) {
320 struct hists *hists = evsel__hists(pos); 325 struct hists *hists = evsel__hists(pos);
321 const char *evname = perf_evsel__name(pos); 326 const char *evname = perf_evsel__name(pos);
@@ -330,15 +335,14 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
330 } 335 }
331 336
332 if (sort_order == NULL && 337 if (sort_order == NULL &&
333 parent_pattern == default_parent_pattern) { 338 parent_pattern == default_parent_pattern)
334 fprintf(stdout, "#\n# (%s)\n#\n", help); 339 fprintf(stdout, "#\n# (%s)\n#\n", help);
335 340
336 if (rep->show_threads) { 341 if (rep->show_threads) {
337 bool style = !strcmp(rep->pretty_printing_style, "raw"); 342 bool style = !strcmp(rep->pretty_printing_style, "raw");
338 perf_read_values_display(stdout, &rep->show_threads_values, 343 perf_read_values_display(stdout, &rep->show_threads_values,
339 style); 344 style);
340 perf_read_values_destroy(&rep->show_threads_values); 345 perf_read_values_destroy(&rep->show_threads_values);
341 }
342 } 346 }
343 347
344 return 0; 348 return 0;
@@ -585,6 +589,7 @@ parse_percent_limit(const struct option *opt, const char *str,
585int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) 589int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
586{ 590{
587 struct perf_session *session; 591 struct perf_session *session;
592 struct itrace_synth_opts itrace_synth_opts = { .set = 0, };
588 struct stat st; 593 struct stat st;
589 bool has_br_stack = false; 594 bool has_br_stack = false;
590 int branch_mode = -1; 595 int branch_mode = -1;
@@ -607,6 +612,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
607 .attr = perf_event__process_attr, 612 .attr = perf_event__process_attr,
608 .tracing_data = perf_event__process_tracing_data, 613 .tracing_data = perf_event__process_tracing_data,
609 .build_id = perf_event__process_build_id, 614 .build_id = perf_event__process_build_id,
615 .id_index = perf_event__process_id_index,
616 .auxtrace_info = perf_event__process_auxtrace_info,
617 .auxtrace = perf_event__process_auxtrace,
610 .ordered_events = true, 618 .ordered_events = true,
611 .ordering_requires_timestamps = true, 619 .ordering_requires_timestamps = true,
612 }, 620 },
@@ -717,6 +725,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
717 "Don't show entries under that percent", parse_percent_limit), 725 "Don't show entries under that percent", parse_percent_limit),
718 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", 726 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
719 "how to display percentage of filtered entries", parse_filter_percentage), 727 "how to display percentage of filtered entries", parse_filter_percentage),
728 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
729 "Instruction Tracing options",
730 itrace_parse_synth_opts),
720 OPT_END() 731 OPT_END()
721 }; 732 };
722 struct perf_data_file file = { 733 struct perf_data_file file = {
@@ -761,6 +772,8 @@ repeat:
761 report.queue_size); 772 report.queue_size);
762 } 773 }
763 774
775 session->itrace_synth_opts = &itrace_synth_opts;
776
764 report.session = session; 777 report.session = session;
765 778
766 has_br_stack = perf_header__has_feat(&session->header, 779 has_br_stack = perf_header__has_feat(&session->header,
@@ -803,8 +816,8 @@ repeat:
803 goto error; 816 goto error;
804 } 817 }
805 818
806 /* Force tty output for header output. */ 819 /* Force tty output for header output and per-thread stat. */
807 if (report.header || report.header_only) 820 if (report.header || report.header_only || report.show_threads)
808 use_browser = 0; 821 use_browser = 0;
809 822
810 if (strcmp(input_name, "-") != 0) 823 if (strcmp(input_name, "-") != 0)
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 5275bab70313..33962612a5e9 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -95,6 +95,7 @@ struct work_atoms {
95 u64 total_lat; 95 u64 total_lat;
96 u64 nb_atoms; 96 u64 nb_atoms;
97 u64 total_runtime; 97 u64 total_runtime;
98 int num_merged;
98}; 99};
99 100
100typedef int (*sort_fn_t)(struct work_atoms *, struct work_atoms *); 101typedef int (*sort_fn_t)(struct work_atoms *, struct work_atoms *);
@@ -168,9 +169,10 @@ struct perf_sched {
168 u64 all_runtime; 169 u64 all_runtime;
169 u64 all_count; 170 u64 all_count;
170 u64 cpu_last_switched[MAX_CPUS]; 171 u64 cpu_last_switched[MAX_CPUS];
171 struct rb_root atom_root, sorted_atom_root; 172 struct rb_root atom_root, sorted_atom_root, merged_atom_root;
172 struct list_head sort_list, cmp_pid; 173 struct list_head sort_list, cmp_pid;
173 bool force; 174 bool force;
175 bool skip_merge;
174}; 176};
175 177
176static u64 get_nsecs(void) 178static u64 get_nsecs(void)
@@ -770,7 +772,7 @@ static int replay_fork_event(struct perf_sched *sched,
770 if (child == NULL || parent == NULL) { 772 if (child == NULL || parent == NULL) {
771 pr_debug("thread does not exist on fork event: child %p, parent %p\n", 773 pr_debug("thread does not exist on fork event: child %p, parent %p\n",
772 child, parent); 774 child, parent);
773 return 0; 775 goto out_put;
774 } 776 }
775 777
776 if (verbose) { 778 if (verbose) {
@@ -781,6 +783,9 @@ static int replay_fork_event(struct perf_sched *sched,
781 783
782 register_pid(sched, parent->tid, thread__comm_str(parent)); 784 register_pid(sched, parent->tid, thread__comm_str(parent));
783 register_pid(sched, child->tid, thread__comm_str(child)); 785 register_pid(sched, child->tid, thread__comm_str(child));
786out_put:
787 thread__put(child);
788 thread__put(parent);
784 return 0; 789 return 0;
785} 790}
786 791
@@ -957,7 +962,7 @@ static int latency_switch_event(struct perf_sched *sched,
957 struct work_atoms *out_events, *in_events; 962 struct work_atoms *out_events, *in_events;
958 struct thread *sched_out, *sched_in; 963 struct thread *sched_out, *sched_in;
959 u64 timestamp0, timestamp = sample->time; 964 u64 timestamp0, timestamp = sample->time;
960 int cpu = sample->cpu; 965 int cpu = sample->cpu, err = -1;
961 s64 delta; 966 s64 delta;
962 967
963 BUG_ON(cpu >= MAX_CPUS || cpu < 0); 968 BUG_ON(cpu >= MAX_CPUS || cpu < 0);
@@ -976,15 +981,17 @@ static int latency_switch_event(struct perf_sched *sched,
976 981
977 sched_out = machine__findnew_thread(machine, -1, prev_pid); 982 sched_out = machine__findnew_thread(machine, -1, prev_pid);
978 sched_in = machine__findnew_thread(machine, -1, next_pid); 983 sched_in = machine__findnew_thread(machine, -1, next_pid);
984 if (sched_out == NULL || sched_in == NULL)
985 goto out_put;
979 986
980 out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid); 987 out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid);
981 if (!out_events) { 988 if (!out_events) {
982 if (thread_atoms_insert(sched, sched_out)) 989 if (thread_atoms_insert(sched, sched_out))
983 return -1; 990 goto out_put;
984 out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid); 991 out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid);
985 if (!out_events) { 992 if (!out_events) {
986 pr_err("out-event: Internal tree error"); 993 pr_err("out-event: Internal tree error");
987 return -1; 994 goto out_put;
988 } 995 }
989 } 996 }
990 if (add_sched_out_event(out_events, sched_out_state(prev_state), timestamp)) 997 if (add_sched_out_event(out_events, sched_out_state(prev_state), timestamp))
@@ -993,22 +1000,25 @@ static int latency_switch_event(struct perf_sched *sched,
993 in_events = thread_atoms_search(&sched->atom_root, sched_in, &sched->cmp_pid); 1000 in_events = thread_atoms_search(&sched->atom_root, sched_in, &sched->cmp_pid);
994 if (!in_events) { 1001 if (!in_events) {
995 if (thread_atoms_insert(sched, sched_in)) 1002 if (thread_atoms_insert(sched, sched_in))
996 return -1; 1003 goto out_put;
997 in_events = thread_atoms_search(&sched->atom_root, sched_in, &sched->cmp_pid); 1004 in_events = thread_atoms_search(&sched->atom_root, sched_in, &sched->cmp_pid);
998 if (!in_events) { 1005 if (!in_events) {
999 pr_err("in-event: Internal tree error"); 1006 pr_err("in-event: Internal tree error");
1000 return -1; 1007 goto out_put;
1001 } 1008 }
1002 /* 1009 /*
1003 * Take came in we have not heard about yet, 1010 * Take came in we have not heard about yet,
1004 * add in an initial atom in runnable state: 1011 * add in an initial atom in runnable state:
1005 */ 1012 */
1006 if (add_sched_out_event(in_events, 'R', timestamp)) 1013 if (add_sched_out_event(in_events, 'R', timestamp))
1007 return -1; 1014 goto out_put;
1008 } 1015 }
1009 add_sched_in_event(in_events, timestamp); 1016 add_sched_in_event(in_events, timestamp);
1010 1017 err = 0;
1011 return 0; 1018out_put:
1019 thread__put(sched_out);
1020 thread__put(sched_in);
1021 return err;
1012} 1022}
1013 1023
1014static int latency_runtime_event(struct perf_sched *sched, 1024static int latency_runtime_event(struct perf_sched *sched,
@@ -1021,23 +1031,29 @@ static int latency_runtime_event(struct perf_sched *sched,
1021 struct thread *thread = machine__findnew_thread(machine, -1, pid); 1031 struct thread *thread = machine__findnew_thread(machine, -1, pid);
1022 struct work_atoms *atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid); 1032 struct work_atoms *atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid);
1023 u64 timestamp = sample->time; 1033 u64 timestamp = sample->time;
1024 int cpu = sample->cpu; 1034 int cpu = sample->cpu, err = -1;
1035
1036 if (thread == NULL)
1037 return -1;
1025 1038
1026 BUG_ON(cpu >= MAX_CPUS || cpu < 0); 1039 BUG_ON(cpu >= MAX_CPUS || cpu < 0);
1027 if (!atoms) { 1040 if (!atoms) {
1028 if (thread_atoms_insert(sched, thread)) 1041 if (thread_atoms_insert(sched, thread))
1029 return -1; 1042 goto out_put;
1030 atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid); 1043 atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid);
1031 if (!atoms) { 1044 if (!atoms) {
1032 pr_err("in-event: Internal tree error"); 1045 pr_err("in-event: Internal tree error");
1033 return -1; 1046 goto out_put;
1034 } 1047 }
1035 if (add_sched_out_event(atoms, 'R', timestamp)) 1048 if (add_sched_out_event(atoms, 'R', timestamp))
1036 return -1; 1049 goto out_put;
1037 } 1050 }
1038 1051
1039 add_runtime_event(atoms, runtime, timestamp); 1052 add_runtime_event(atoms, runtime, timestamp);
1040 return 0; 1053 err = 0;
1054out_put:
1055 thread__put(thread);
1056 return err;
1041} 1057}
1042 1058
1043static int latency_wakeup_event(struct perf_sched *sched, 1059static int latency_wakeup_event(struct perf_sched *sched,
@@ -1050,19 +1066,22 @@ static int latency_wakeup_event(struct perf_sched *sched,
1050 struct work_atom *atom; 1066 struct work_atom *atom;
1051 struct thread *wakee; 1067 struct thread *wakee;
1052 u64 timestamp = sample->time; 1068 u64 timestamp = sample->time;
1069 int err = -1;
1053 1070
1054 wakee = machine__findnew_thread(machine, -1, pid); 1071 wakee = machine__findnew_thread(machine, -1, pid);
1072 if (wakee == NULL)
1073 return -1;
1055 atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid); 1074 atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid);
1056 if (!atoms) { 1075 if (!atoms) {
1057 if (thread_atoms_insert(sched, wakee)) 1076 if (thread_atoms_insert(sched, wakee))
1058 return -1; 1077 goto out_put;
1059 atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid); 1078 atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid);
1060 if (!atoms) { 1079 if (!atoms) {
1061 pr_err("wakeup-event: Internal tree error"); 1080 pr_err("wakeup-event: Internal tree error");
1062 return -1; 1081 goto out_put;
1063 } 1082 }
1064 if (add_sched_out_event(atoms, 'S', timestamp)) 1083 if (add_sched_out_event(atoms, 'S', timestamp))
1065 return -1; 1084 goto out_put;
1066 } 1085 }
1067 1086
1068 BUG_ON(list_empty(&atoms->work_list)); 1087 BUG_ON(list_empty(&atoms->work_list));
@@ -1081,17 +1100,21 @@ static int latency_wakeup_event(struct perf_sched *sched,
1081 * skip in this case. 1100 * skip in this case.
1082 */ 1101 */
1083 if (sched->profile_cpu == -1 && atom->state != THREAD_SLEEPING) 1102 if (sched->profile_cpu == -1 && atom->state != THREAD_SLEEPING)
1084 return 0; 1103 goto out_ok;
1085 1104
1086 sched->nr_timestamps++; 1105 sched->nr_timestamps++;
1087 if (atom->sched_out_time > timestamp) { 1106 if (atom->sched_out_time > timestamp) {
1088 sched->nr_unordered_timestamps++; 1107 sched->nr_unordered_timestamps++;
1089 return 0; 1108 goto out_ok;
1090 } 1109 }
1091 1110
1092 atom->state = THREAD_WAIT_CPU; 1111 atom->state = THREAD_WAIT_CPU;
1093 atom->wake_up_time = timestamp; 1112 atom->wake_up_time = timestamp;
1094 return 0; 1113out_ok:
1114 err = 0;
1115out_put:
1116 thread__put(wakee);
1117 return err;
1095} 1118}
1096 1119
1097static int latency_migrate_task_event(struct perf_sched *sched, 1120static int latency_migrate_task_event(struct perf_sched *sched,
@@ -1104,6 +1127,7 @@ static int latency_migrate_task_event(struct perf_sched *sched,
1104 struct work_atoms *atoms; 1127 struct work_atoms *atoms;
1105 struct work_atom *atom; 1128 struct work_atom *atom;
1106 struct thread *migrant; 1129 struct thread *migrant;
1130 int err = -1;
1107 1131
1108 /* 1132 /*
1109 * Only need to worry about migration when profiling one CPU. 1133 * Only need to worry about migration when profiling one CPU.
@@ -1112,18 +1136,20 @@ static int latency_migrate_task_event(struct perf_sched *sched,
1112 return 0; 1136 return 0;
1113 1137
1114 migrant = machine__findnew_thread(machine, -1, pid); 1138 migrant = machine__findnew_thread(machine, -1, pid);
1139 if (migrant == NULL)
1140 return -1;
1115 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); 1141 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid);
1116 if (!atoms) { 1142 if (!atoms) {
1117 if (thread_atoms_insert(sched, migrant)) 1143 if (thread_atoms_insert(sched, migrant))
1118 return -1; 1144 goto out_put;
1119 register_pid(sched, migrant->tid, thread__comm_str(migrant)); 1145 register_pid(sched, migrant->tid, thread__comm_str(migrant));
1120 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); 1146 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid);
1121 if (!atoms) { 1147 if (!atoms) {
1122 pr_err("migration-event: Internal tree error"); 1148 pr_err("migration-event: Internal tree error");
1123 return -1; 1149 goto out_put;
1124 } 1150 }
1125 if (add_sched_out_event(atoms, 'R', timestamp)) 1151 if (add_sched_out_event(atoms, 'R', timestamp))
1126 return -1; 1152 goto out_put;
1127 } 1153 }
1128 1154
1129 BUG_ON(list_empty(&atoms->work_list)); 1155 BUG_ON(list_empty(&atoms->work_list));
@@ -1135,8 +1161,10 @@ static int latency_migrate_task_event(struct perf_sched *sched,
1135 1161
1136 if (atom->sched_out_time > timestamp) 1162 if (atom->sched_out_time > timestamp)
1137 sched->nr_unordered_timestamps++; 1163 sched->nr_unordered_timestamps++;
1138 1164 err = 0;
1139 return 0; 1165out_put:
1166 thread__put(migrant);
1167 return err;
1140} 1168}
1141 1169
1142static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_list) 1170static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_list)
@@ -1156,7 +1184,10 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_
1156 sched->all_runtime += work_list->total_runtime; 1184 sched->all_runtime += work_list->total_runtime;
1157 sched->all_count += work_list->nb_atoms; 1185 sched->all_count += work_list->nb_atoms;
1158 1186
1159 ret = printf(" %s:%d ", thread__comm_str(work_list->thread), work_list->thread->tid); 1187 if (work_list->num_merged > 1)
1188 ret = printf(" %s:(%d) ", thread__comm_str(work_list->thread), work_list->num_merged);
1189 else
1190 ret = printf(" %s:%d ", thread__comm_str(work_list->thread), work_list->thread->tid);
1160 1191
1161 for (i = 0; i < 24 - ret; i++) 1192 for (i = 0; i < 24 - ret; i++)
1162 printf(" "); 1193 printf(" ");
@@ -1276,17 +1307,22 @@ static int sort_dimension__add(const char *tok, struct list_head *list)
1276static void perf_sched__sort_lat(struct perf_sched *sched) 1307static void perf_sched__sort_lat(struct perf_sched *sched)
1277{ 1308{
1278 struct rb_node *node; 1309 struct rb_node *node;
1279 1310 struct rb_root *root = &sched->atom_root;
1311again:
1280 for (;;) { 1312 for (;;) {
1281 struct work_atoms *data; 1313 struct work_atoms *data;
1282 node = rb_first(&sched->atom_root); 1314 node = rb_first(root);
1283 if (!node) 1315 if (!node)
1284 break; 1316 break;
1285 1317
1286 rb_erase(node, &sched->atom_root); 1318 rb_erase(node, root);
1287 data = rb_entry(node, struct work_atoms, node); 1319 data = rb_entry(node, struct work_atoms, node);
1288 __thread_latency_insert(&sched->sorted_atom_root, data, &sched->sort_list); 1320 __thread_latency_insert(&sched->sorted_atom_root, data, &sched->sort_list);
1289 } 1321 }
1322 if (root == &sched->atom_root) {
1323 root = &sched->merged_atom_root;
1324 goto again;
1325 }
1290} 1326}
1291 1327
1292static int process_sched_wakeup_event(struct perf_tool *tool, 1328static int process_sched_wakeup_event(struct perf_tool *tool,
@@ -1330,8 +1366,10 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1330 } 1366 }
1331 1367
1332 sched_in = machine__findnew_thread(machine, -1, next_pid); 1368 sched_in = machine__findnew_thread(machine, -1, next_pid);
1369 if (sched_in == NULL)
1370 return -1;
1333 1371
1334 sched->curr_thread[this_cpu] = sched_in; 1372 sched->curr_thread[this_cpu] = thread__get(sched_in);
1335 1373
1336 printf(" "); 1374 printf(" ");
1337 1375
@@ -1381,6 +1419,8 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1381 printf("\n"); 1419 printf("\n");
1382 } 1420 }
1383 1421
1422 thread__put(sched_in);
1423
1384 return 0; 1424 return 0;
1385} 1425}
1386 1426
@@ -1542,6 +1582,59 @@ static void print_bad_events(struct perf_sched *sched)
1542 } 1582 }
1543} 1583}
1544 1584
1585static void __merge_work_atoms(struct rb_root *root, struct work_atoms *data)
1586{
1587 struct rb_node **new = &(root->rb_node), *parent = NULL;
1588 struct work_atoms *this;
1589 const char *comm = thread__comm_str(data->thread), *this_comm;
1590
1591 while (*new) {
1592 int cmp;
1593
1594 this = container_of(*new, struct work_atoms, node);
1595 parent = *new;
1596
1597 this_comm = thread__comm_str(this->thread);
1598 cmp = strcmp(comm, this_comm);
1599 if (cmp > 0) {
1600 new = &((*new)->rb_left);
1601 } else if (cmp < 0) {
1602 new = &((*new)->rb_right);
1603 } else {
1604 this->num_merged++;
1605 this->total_runtime += data->total_runtime;
1606 this->nb_atoms += data->nb_atoms;
1607 this->total_lat += data->total_lat;
1608 list_splice(&data->work_list, &this->work_list);
1609 if (this->max_lat < data->max_lat) {
1610 this->max_lat = data->max_lat;
1611 this->max_lat_at = data->max_lat_at;
1612 }
1613 zfree(&data);
1614 return;
1615 }
1616 }
1617
1618 data->num_merged++;
1619 rb_link_node(&data->node, parent, new);
1620 rb_insert_color(&data->node, root);
1621}
1622
1623static void perf_sched__merge_lat(struct perf_sched *sched)
1624{
1625 struct work_atoms *data;
1626 struct rb_node *node;
1627
1628 if (sched->skip_merge)
1629 return;
1630
1631 while ((node = rb_first(&sched->atom_root))) {
1632 rb_erase(node, &sched->atom_root);
1633 data = rb_entry(node, struct work_atoms, node);
1634 __merge_work_atoms(&sched->merged_atom_root, data);
1635 }
1636}
1637
1545static int perf_sched__lat(struct perf_sched *sched) 1638static int perf_sched__lat(struct perf_sched *sched)
1546{ 1639{
1547 struct rb_node *next; 1640 struct rb_node *next;
@@ -1551,6 +1644,7 @@ static int perf_sched__lat(struct perf_sched *sched)
1551 if (perf_sched__read_events(sched)) 1644 if (perf_sched__read_events(sched))
1552 return -1; 1645 return -1;
1553 1646
1647 perf_sched__merge_lat(sched);
1554 perf_sched__sort_lat(sched); 1648 perf_sched__sort_lat(sched);
1555 1649
1556 printf("\n -----------------------------------------------------------------------------------------------------------------\n"); 1650 printf("\n -----------------------------------------------------------------------------------------------------------------\n");
@@ -1702,6 +1796,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1702 .profile_cpu = -1, 1796 .profile_cpu = -1,
1703 .next_shortname1 = 'A', 1797 .next_shortname1 = 'A',
1704 .next_shortname2 = '0', 1798 .next_shortname2 = '0',
1799 .skip_merge = 0,
1705 }; 1800 };
1706 const struct option latency_options[] = { 1801 const struct option latency_options[] = {
1707 OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]", 1802 OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]",
@@ -1712,6 +1807,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1712 "CPU to profile on"), 1807 "CPU to profile on"),
1713 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1808 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1714 "dump raw trace in ASCII"), 1809 "dump raw trace in ASCII"),
1810 OPT_BOOLEAN('p', "pids", &sched.skip_merge,
1811 "latency stats per pid instead of per comm"),
1715 OPT_END() 1812 OPT_END()
1716 }; 1813 };
1717 const struct option replay_options[] = { 1814 const struct option replay_options[] = {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 58f10b8e6ff2..24809787369f 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -16,6 +16,7 @@
16#include "util/evsel.h" 16#include "util/evsel.h"
17#include "util/sort.h" 17#include "util/sort.h"
18#include "util/data.h" 18#include "util/data.h"
19#include "util/auxtrace.h"
19#include <linux/bitmap.h> 20#include <linux/bitmap.h>
20 21
21static char const *script_name; 22static char const *script_name;
@@ -26,6 +27,7 @@ static u64 nr_unordered;
26static bool no_callchain; 27static bool no_callchain;
27static bool latency_format; 28static bool latency_format;
28static bool system_wide; 29static bool system_wide;
30static bool print_flags;
29static const char *cpu_list; 31static const char *cpu_list;
30static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 32static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
31 33
@@ -146,9 +148,10 @@ static const char *output_field2str(enum perf_output_field field)
146 148
147#define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x) 149#define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x)
148 150
149static int perf_evsel__check_stype(struct perf_evsel *evsel, 151static int perf_evsel__do_check_stype(struct perf_evsel *evsel,
150 u64 sample_type, const char *sample_msg, 152 u64 sample_type, const char *sample_msg,
151 enum perf_output_field field) 153 enum perf_output_field field,
154 bool allow_user_set)
152{ 155{
153 struct perf_event_attr *attr = &evsel->attr; 156 struct perf_event_attr *attr = &evsel->attr;
154 int type = attr->type; 157 int type = attr->type;
@@ -158,6 +161,8 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel,
158 return 0; 161 return 0;
159 162
160 if (output[type].user_set) { 163 if (output[type].user_set) {
164 if (allow_user_set)
165 return 0;
161 evname = perf_evsel__name(evsel); 166 evname = perf_evsel__name(evsel);
162 pr_err("Samples for '%s' event do not have %s attribute set. " 167 pr_err("Samples for '%s' event do not have %s attribute set. "
163 "Cannot print '%s' field.\n", 168 "Cannot print '%s' field.\n",
@@ -175,10 +180,22 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel,
175 return 0; 180 return 0;
176} 181}
177 182
183static int perf_evsel__check_stype(struct perf_evsel *evsel,
184 u64 sample_type, const char *sample_msg,
185 enum perf_output_field field)
186{
187 return perf_evsel__do_check_stype(evsel, sample_type, sample_msg, field,
188 false);
189}
190
178static int perf_evsel__check_attr(struct perf_evsel *evsel, 191static int perf_evsel__check_attr(struct perf_evsel *evsel,
179 struct perf_session *session) 192 struct perf_session *session)
180{ 193{
181 struct perf_event_attr *attr = &evsel->attr; 194 struct perf_event_attr *attr = &evsel->attr;
195 bool allow_user_set;
196
197 allow_user_set = perf_header__has_feat(&session->header,
198 HEADER_AUXTRACE);
182 199
183 if (PRINT_FIELD(TRACE) && 200 if (PRINT_FIELD(TRACE) &&
184 !perf_session__has_traces(session, "record -R")) 201 !perf_session__has_traces(session, "record -R"))
@@ -191,8 +208,8 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
191 } 208 }
192 209
193 if (PRINT_FIELD(ADDR) && 210 if (PRINT_FIELD(ADDR) &&
194 perf_evsel__check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR", 211 perf_evsel__do_check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR",
195 PERF_OUTPUT_ADDR)) 212 PERF_OUTPUT_ADDR, allow_user_set))
196 return -EINVAL; 213 return -EINVAL;
197 214
198 if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { 215 if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
@@ -229,8 +246,8 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
229 return -EINVAL; 246 return -EINVAL;
230 247
231 if (PRINT_FIELD(CPU) && 248 if (PRINT_FIELD(CPU) &&
232 perf_evsel__check_stype(evsel, PERF_SAMPLE_CPU, "CPU", 249 perf_evsel__do_check_stype(evsel, PERF_SAMPLE_CPU, "CPU",
233 PERF_OUTPUT_CPU)) 250 PERF_OUTPUT_CPU, allow_user_set))
234 return -EINVAL; 251 return -EINVAL;
235 252
236 if (PRINT_FIELD(PERIOD) && 253 if (PRINT_FIELD(PERIOD) &&
@@ -445,6 +462,25 @@ static void print_sample_bts(union perf_event *event,
445 printf("\n"); 462 printf("\n");
446} 463}
447 464
465static void print_sample_flags(u32 flags)
466{
467 const char *chars = PERF_IP_FLAG_CHARS;
468 const int n = strlen(PERF_IP_FLAG_CHARS);
469 char str[33];
470 int i, pos = 0;
471
472 for (i = 0; i < n; i++, flags >>= 1) {
473 if (flags & 1)
474 str[pos++] = chars[i];
475 }
476 for (; i < 32; i++, flags >>= 1) {
477 if (flags & 1)
478 str[pos++] = '?';
479 }
480 str[pos] = 0;
481 printf(" %-4s ", str);
482}
483
448static void process_event(union perf_event *event, struct perf_sample *sample, 484static void process_event(union perf_event *event, struct perf_sample *sample,
449 struct perf_evsel *evsel, struct addr_location *al) 485 struct perf_evsel *evsel, struct addr_location *al)
450{ 486{
@@ -464,6 +500,9 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
464 printf("%s: ", evname ? evname : "[unknown]"); 500 printf("%s: ", evname ? evname : "[unknown]");
465 } 501 }
466 502
503 if (print_flags)
504 print_sample_flags(sample->flags);
505
467 if (is_bts_event(attr)) { 506 if (is_bts_event(attr)) {
468 print_sample_bts(event, sample, evsel, thread, al); 507 print_sample_bts(event, sample, evsel, thread, al);
469 return; 508 return;
@@ -568,13 +607,14 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
568 } 607 }
569 608
570 if (al.filtered) 609 if (al.filtered)
571 return 0; 610 goto out_put;
572 611
573 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 612 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
574 return 0; 613 goto out_put;
575 614
576 scripting_ops->process_event(event, sample, evsel, &al); 615 scripting_ops->process_event(event, sample, evsel, &al);
577 616out_put:
617 addr_location__put(&al);
578 return 0; 618 return 0;
579} 619}
580 620
@@ -642,8 +682,8 @@ static int process_comm_event(struct perf_tool *tool,
642 print_sample_start(sample, thread, evsel); 682 print_sample_start(sample, thread, evsel);
643 perf_event__fprintf(event, stdout); 683 perf_event__fprintf(event, stdout);
644 ret = 0; 684 ret = 0;
645
646out: 685out:
686 thread__put(thread);
647 return ret; 687 return ret;
648} 688}
649 689
@@ -674,6 +714,7 @@ static int process_fork_event(struct perf_tool *tool,
674 } 714 }
675 print_sample_start(sample, thread, evsel); 715 print_sample_start(sample, thread, evsel);
676 perf_event__fprintf(event, stdout); 716 perf_event__fprintf(event, stdout);
717 thread__put(thread);
677 718
678 return 0; 719 return 0;
679} 720}
@@ -682,6 +723,7 @@ static int process_exit_event(struct perf_tool *tool,
682 struct perf_sample *sample, 723 struct perf_sample *sample,
683 struct machine *machine) 724 struct machine *machine)
684{ 725{
726 int err = 0;
685 struct thread *thread; 727 struct thread *thread;
686 struct perf_script *script = container_of(tool, struct perf_script, tool); 728 struct perf_script *script = container_of(tool, struct perf_script, tool);
687 struct perf_session *session = script->session; 729 struct perf_session *session = script->session;
@@ -703,9 +745,10 @@ static int process_exit_event(struct perf_tool *tool,
703 perf_event__fprintf(event, stdout); 745 perf_event__fprintf(event, stdout);
704 746
705 if (perf_event__process_exit(tool, event, sample, machine) < 0) 747 if (perf_event__process_exit(tool, event, sample, machine) < 0)
706 return -1; 748 err = -1;
707 749
708 return 0; 750 thread__put(thread);
751 return err;
709} 752}
710 753
711static int process_mmap_event(struct perf_tool *tool, 754static int process_mmap_event(struct perf_tool *tool,
@@ -735,7 +778,7 @@ static int process_mmap_event(struct perf_tool *tool,
735 } 778 }
736 print_sample_start(sample, thread, evsel); 779 print_sample_start(sample, thread, evsel);
737 perf_event__fprintf(event, stdout); 780 perf_event__fprintf(event, stdout);
738 781 thread__put(thread);
739 return 0; 782 return 0;
740} 783}
741 784
@@ -766,7 +809,7 @@ static int process_mmap2_event(struct perf_tool *tool,
766 } 809 }
767 print_sample_start(sample, thread, evsel); 810 print_sample_start(sample, thread, evsel);
768 perf_event__fprintf(event, stdout); 811 perf_event__fprintf(event, stdout);
769 812 thread__put(thread);
770 return 0; 813 return 0;
771} 814}
772 815
@@ -999,12 +1042,15 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
999 } 1042 }
1000 } 1043 }
1001 1044
1002 tok = strtok(tok, ","); 1045 for (tok = strtok(tok, ","); tok; tok = strtok(NULL, ",")) {
1003 while (tok) {
1004 for (i = 0; i < imax; ++i) { 1046 for (i = 0; i < imax; ++i) {
1005 if (strcmp(tok, all_output_options[i].str) == 0) 1047 if (strcmp(tok, all_output_options[i].str) == 0)
1006 break; 1048 break;
1007 } 1049 }
1050 if (i == imax && strcmp(tok, "flags") == 0) {
1051 print_flags = true;
1052 continue;
1053 }
1008 if (i == imax) { 1054 if (i == imax) {
1009 fprintf(stderr, "Invalid field requested.\n"); 1055 fprintf(stderr, "Invalid field requested.\n");
1010 rc = -EINVAL; 1056 rc = -EINVAL;
@@ -1032,8 +1078,6 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
1032 } 1078 }
1033 output[type].fields |= all_output_options[i].field; 1079 output[type].fields |= all_output_options[i].field;
1034 } 1080 }
1035
1036 tok = strtok(NULL, ",");
1037 } 1081 }
1038 1082
1039 if (type >= 0) { 1083 if (type >= 0) {
@@ -1497,6 +1541,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1497 char *rec_script_path = NULL; 1541 char *rec_script_path = NULL;
1498 char *rep_script_path = NULL; 1542 char *rep_script_path = NULL;
1499 struct perf_session *session; 1543 struct perf_session *session;
1544 struct itrace_synth_opts itrace_synth_opts = { .set = false, };
1500 char *script_path = NULL; 1545 char *script_path = NULL;
1501 const char **__argv; 1546 const char **__argv;
1502 int i, j, err = 0; 1547 int i, j, err = 0;
@@ -1511,6 +1556,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1511 .attr = process_attr, 1556 .attr = process_attr,
1512 .tracing_data = perf_event__process_tracing_data, 1557 .tracing_data = perf_event__process_tracing_data,
1513 .build_id = perf_event__process_build_id, 1558 .build_id = perf_event__process_build_id,
1559 .id_index = perf_event__process_id_index,
1560 .auxtrace_info = perf_event__process_auxtrace_info,
1561 .auxtrace = perf_event__process_auxtrace,
1562 .auxtrace_error = perf_event__process_auxtrace_error,
1514 .ordered_events = true, 1563 .ordered_events = true,
1515 .ordering_requires_timestamps = true, 1564 .ordering_requires_timestamps = true,
1516 }, 1565 },
@@ -1549,7 +1598,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1549 "comma separated output fields prepend with 'type:'. " 1598 "comma separated output fields prepend with 'type:'. "
1550 "Valid types: hw,sw,trace,raw. " 1599 "Valid types: hw,sw,trace,raw. "
1551 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 1600 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
1552 "addr,symoff,period", parse_output_fields), 1601 "addr,symoff,period,flags", parse_output_fields),
1553 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1602 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1554 "system-wide collection from all CPUs"), 1603 "system-wide collection from all CPUs"),
1555 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 1604 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
@@ -1570,6 +1619,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1570 OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events, 1619 OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events,
1571 "Show the mmap events"), 1620 "Show the mmap events"),
1572 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), 1621 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
1622 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
1623 "Instruction Tracing options",
1624 itrace_parse_synth_opts),
1573 OPT_END() 1625 OPT_END()
1574 }; 1626 };
1575 const char * const script_subcommands[] = { "record", "report", NULL }; 1627 const char * const script_subcommands[] = { "record", "report", NULL };
@@ -1765,6 +1817,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1765 1817
1766 script.session = session; 1818 script.session = session;
1767 1819
1820 session->itrace_synth_opts = &itrace_synth_opts;
1821
1768 if (cpu_list) { 1822 if (cpu_list) {
1769 err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap); 1823 err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
1770 if (err < 0) 1824 if (err < 0)
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f7b8218785f6..fcf99bdeb19e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -73,8 +73,8 @@ static void print_counter(struct perf_evsel *counter, char *prefix);
73static void print_aggr(char *prefix); 73static void print_aggr(char *prefix);
74 74
75/* Default events used for perf stat -T */ 75/* Default events used for perf stat -T */
76static const char * const transaction_attrs[] = { 76static const char *transaction_attrs = {
77 "task-clock", 77 "task-clock,"
78 "{" 78 "{"
79 "instructions," 79 "instructions,"
80 "cycles," 80 "cycles,"
@@ -86,8 +86,8 @@ static const char * const transaction_attrs[] = {
86}; 86};
87 87
88/* More limited version when the CPU does not have all events. */ 88/* More limited version when the CPU does not have all events. */
89static const char * const transaction_limited_attrs[] = { 89static const char * transaction_limited_attrs = {
90 "task-clock", 90 "task-clock,"
91 "{" 91 "{"
92 "instructions," 92 "instructions,"
93 "cycles," 93 "cycles,"
@@ -96,30 +96,12 @@ static const char * const transaction_limited_attrs[] = {
96 "}" 96 "}"
97}; 97};
98 98
99/* must match transaction_attrs and the beginning limited_attrs */
100enum {
101 T_TASK_CLOCK,
102 T_INSTRUCTIONS,
103 T_CYCLES,
104 T_CYCLES_IN_TX,
105 T_TRANSACTION_START,
106 T_ELISION_START,
107 T_CYCLES_IN_TX_CP,
108};
109
110static struct perf_evlist *evsel_list; 99static struct perf_evlist *evsel_list;
111 100
112static struct target target = { 101static struct target target = {
113 .uid = UINT_MAX, 102 .uid = UINT_MAX,
114}; 103};
115 104
116enum aggr_mode {
117 AGGR_NONE,
118 AGGR_GLOBAL,
119 AGGR_SOCKET,
120 AGGR_CORE,
121};
122
123static int run_count = 1; 105static int run_count = 1;
124static bool no_inherit = false; 106static bool no_inherit = false;
125static bool scale = true; 107static bool scale = true;
@@ -147,10 +129,6 @@ static int (*aggr_get_id)(struct cpu_map *m, int cpu);
147 129
148static volatile int done = 0; 130static volatile int done = 0;
149 131
150struct perf_stat {
151 struct stats res_stats[3];
152};
153
154static inline void diff_timespec(struct timespec *r, struct timespec *a, 132static inline void diff_timespec(struct timespec *r, struct timespec *a,
155 struct timespec *b) 133 struct timespec *b)
156{ 134{
@@ -180,6 +158,8 @@ static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
180 158
181 for (i = 0; i < 3; i++) 159 for (i = 0; i < 3; i++)
182 init_stats(&ps->res_stats[i]); 160 init_stats(&ps->res_stats[i]);
161
162 perf_stat_evsel_id_init(evsel);
183} 163}
184 164
185static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) 165static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
@@ -198,24 +178,19 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
198 178
199static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel) 179static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel)
200{ 180{
201 void *addr; 181 struct perf_counts *counts;
202 size_t sz;
203 182
204 sz = sizeof(*evsel->counts) + 183 counts = perf_counts__new(perf_evsel__nr_cpus(evsel));
205 (perf_evsel__nr_cpus(evsel) * sizeof(struct perf_counts_values)); 184 if (counts)
185 evsel->prev_raw_counts = counts;
206 186
207 addr = zalloc(sz); 187 return counts ? 0 : -ENOMEM;
208 if (!addr)
209 return -ENOMEM;
210
211 evsel->prev_raw_counts = addr;
212
213 return 0;
214} 188}
215 189
216static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) 190static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
217{ 191{
218 zfree(&evsel->prev_raw_counts); 192 perf_counts__delete(evsel->prev_raw_counts);
193 evsel->prev_raw_counts = NULL;
219} 194}
220 195
221static void perf_evlist__free_stats(struct perf_evlist *evlist) 196static void perf_evlist__free_stats(struct perf_evlist *evlist)
@@ -247,22 +222,6 @@ out_free:
247 return -1; 222 return -1;
248} 223}
249 224
250static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
251static struct stats runtime_cycles_stats[MAX_NR_CPUS];
252static struct stats runtime_stalled_cycles_front_stats[MAX_NR_CPUS];
253static struct stats runtime_stalled_cycles_back_stats[MAX_NR_CPUS];
254static struct stats runtime_branches_stats[MAX_NR_CPUS];
255static struct stats runtime_cacherefs_stats[MAX_NR_CPUS];
256static struct stats runtime_l1_dcache_stats[MAX_NR_CPUS];
257static struct stats runtime_l1_icache_stats[MAX_NR_CPUS];
258static struct stats runtime_ll_cache_stats[MAX_NR_CPUS];
259static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];
260static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS];
261static struct stats runtime_cycles_in_tx_stats[MAX_NR_CPUS];
262static struct stats walltime_nsecs_stats;
263static struct stats runtime_transaction_stats[MAX_NR_CPUS];
264static struct stats runtime_elision_stats[MAX_NR_CPUS];
265
266static void perf_stat__reset_stats(struct perf_evlist *evlist) 225static void perf_stat__reset_stats(struct perf_evlist *evlist)
267{ 226{
268 struct perf_evsel *evsel; 227 struct perf_evsel *evsel;
@@ -272,23 +231,7 @@ static void perf_stat__reset_stats(struct perf_evlist *evlist)
272 perf_evsel__reset_counts(evsel, perf_evsel__nr_cpus(evsel)); 231 perf_evsel__reset_counts(evsel, perf_evsel__nr_cpus(evsel));
273 } 232 }
274 233
275 memset(runtime_nsecs_stats, 0, sizeof(runtime_nsecs_stats)); 234 perf_stat__reset_shadow_stats();
276 memset(runtime_cycles_stats, 0, sizeof(runtime_cycles_stats));
277 memset(runtime_stalled_cycles_front_stats, 0, sizeof(runtime_stalled_cycles_front_stats));
278 memset(runtime_stalled_cycles_back_stats, 0, sizeof(runtime_stalled_cycles_back_stats));
279 memset(runtime_branches_stats, 0, sizeof(runtime_branches_stats));
280 memset(runtime_cacherefs_stats, 0, sizeof(runtime_cacherefs_stats));
281 memset(runtime_l1_dcache_stats, 0, sizeof(runtime_l1_dcache_stats));
282 memset(runtime_l1_icache_stats, 0, sizeof(runtime_l1_icache_stats));
283 memset(runtime_ll_cache_stats, 0, sizeof(runtime_ll_cache_stats));
284 memset(runtime_itlb_cache_stats, 0, sizeof(runtime_itlb_cache_stats));
285 memset(runtime_dtlb_cache_stats, 0, sizeof(runtime_dtlb_cache_stats));
286 memset(runtime_cycles_in_tx_stats, 0,
287 sizeof(runtime_cycles_in_tx_stats));
288 memset(runtime_transaction_stats, 0,
289 sizeof(runtime_transaction_stats));
290 memset(runtime_elision_stats, 0, sizeof(runtime_elision_stats));
291 memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats));
292} 235}
293 236
294static int create_perf_stat_counter(struct perf_evsel *evsel) 237static int create_perf_stat_counter(struct perf_evsel *evsel)
@@ -325,70 +268,6 @@ static inline int nsec_counter(struct perf_evsel *evsel)
325 return 0; 268 return 0;
326} 269}
327 270
328static struct perf_evsel *nth_evsel(int n)
329{
330 static struct perf_evsel **array;
331 static int array_len;
332 struct perf_evsel *ev;
333 int j;
334
335 /* Assumes this only called when evsel_list does not change anymore. */
336 if (!array) {
337 evlist__for_each(evsel_list, ev)
338 array_len++;
339 array = malloc(array_len * sizeof(void *));
340 if (!array)
341 exit(ENOMEM);
342 j = 0;
343 evlist__for_each(evsel_list, ev)
344 array[j++] = ev;
345 }
346 if (n < array_len)
347 return array[n];
348 return NULL;
349}
350
351/*
352 * Update various tracking values we maintain to print
353 * more semantic information such as miss/hit ratios,
354 * instruction rates, etc:
355 */
356static void update_shadow_stats(struct perf_evsel *counter, u64 *count,
357 int cpu)
358{
359 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
360 update_stats(&runtime_nsecs_stats[cpu], count[0]);
361 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
362 update_stats(&runtime_cycles_stats[cpu], count[0]);
363 else if (transaction_run &&
364 perf_evsel__cmp(counter, nth_evsel(T_CYCLES_IN_TX)))
365 update_stats(&runtime_cycles_in_tx_stats[cpu], count[0]);
366 else if (transaction_run &&
367 perf_evsel__cmp(counter, nth_evsel(T_TRANSACTION_START)))
368 update_stats(&runtime_transaction_stats[cpu], count[0]);
369 else if (transaction_run &&
370 perf_evsel__cmp(counter, nth_evsel(T_ELISION_START)))
371 update_stats(&runtime_elision_stats[cpu], count[0]);
372 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
373 update_stats(&runtime_stalled_cycles_front_stats[cpu], count[0]);
374 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
375 update_stats(&runtime_stalled_cycles_back_stats[cpu], count[0]);
376 else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
377 update_stats(&runtime_branches_stats[cpu], count[0]);
378 else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES))
379 update_stats(&runtime_cacherefs_stats[cpu], count[0]);
380 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D))
381 update_stats(&runtime_l1_dcache_stats[cpu], count[0]);
382 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I))
383 update_stats(&runtime_l1_icache_stats[cpu], count[0]);
384 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL))
385 update_stats(&runtime_ll_cache_stats[cpu], count[0]);
386 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB))
387 update_stats(&runtime_dtlb_cache_stats[cpu], count[0]);
388 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB))
389 update_stats(&runtime_itlb_cache_stats[cpu], count[0]);
390}
391
392static void zero_per_pkg(struct perf_evsel *counter) 271static void zero_per_pkg(struct perf_evsel *counter)
393{ 272{
394 if (counter->per_pkg_mask) 273 if (counter->per_pkg_mask)
@@ -449,7 +328,7 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused,
449 perf_counts_values__scale(count, scale, NULL); 328 perf_counts_values__scale(count, scale, NULL);
450 evsel->counts->cpu[cpu] = *count; 329 evsel->counts->cpu[cpu] = *count;
451 if (aggr_mode == AGGR_NONE) 330 if (aggr_mode == AGGR_NONE)
452 update_shadow_stats(evsel, count->values, cpu); 331 perf_stat__update_shadow_stats(evsel, count->values, cpu);
453 break; 332 break;
454 case AGGR_GLOBAL: 333 case AGGR_GLOBAL:
455 aggr->val += count->val; 334 aggr->val += count->val;
@@ -497,7 +376,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
497 /* 376 /*
498 * Save the full runtime - to allow normalization during printout: 377 * Save the full runtime - to allow normalization during printout:
499 */ 378 */
500 update_shadow_stats(counter, count, 0); 379 perf_stat__update_shadow_stats(counter, count, 0);
501 380
502 return 0; 381 return 0;
503} 382}
@@ -665,7 +544,10 @@ static int __run_perf_stat(int argc, const char **argv)
665 ui__warning("%s event is not supported by the kernel.\n", 544 ui__warning("%s event is not supported by the kernel.\n",
666 perf_evsel__name(counter)); 545 perf_evsel__name(counter));
667 counter->supported = false; 546 counter->supported = false;
668 continue; 547
548 if ((counter->leader != counter) ||
549 !(counter->leader->nr_members > 1))
550 continue;
669 } 551 }
670 552
671 perf_evsel__open_strerror(counter, &target, 553 perf_evsel__open_strerror(counter, &target,
@@ -875,188 +757,8 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
875 fprintf(output, " "); 757 fprintf(output, " ");
876} 758}
877 759
878/* used for get_ratio_color() */
879enum grc_type {
880 GRC_STALLED_CYCLES_FE,
881 GRC_STALLED_CYCLES_BE,
882 GRC_CACHE_MISSES,
883 GRC_MAX_NR
884};
885
886static const char *get_ratio_color(enum grc_type type, double ratio)
887{
888 static const double grc_table[GRC_MAX_NR][3] = {
889 [GRC_STALLED_CYCLES_FE] = { 50.0, 30.0, 10.0 },
890 [GRC_STALLED_CYCLES_BE] = { 75.0, 50.0, 20.0 },
891 [GRC_CACHE_MISSES] = { 20.0, 10.0, 5.0 },
892 };
893 const char *color = PERF_COLOR_NORMAL;
894
895 if (ratio > grc_table[type][0])
896 color = PERF_COLOR_RED;
897 else if (ratio > grc_table[type][1])
898 color = PERF_COLOR_MAGENTA;
899 else if (ratio > grc_table[type][2])
900 color = PERF_COLOR_YELLOW;
901
902 return color;
903}
904
905static void print_stalled_cycles_frontend(int cpu,
906 struct perf_evsel *evsel
907 __maybe_unused, double avg)
908{
909 double total, ratio = 0.0;
910 const char *color;
911
912 total = avg_stats(&runtime_cycles_stats[cpu]);
913
914 if (total)
915 ratio = avg / total * 100.0;
916
917 color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio);
918
919 fprintf(output, " # ");
920 color_fprintf(output, color, "%6.2f%%", ratio);
921 fprintf(output, " frontend cycles idle ");
922}
923
924static void print_stalled_cycles_backend(int cpu,
925 struct perf_evsel *evsel
926 __maybe_unused, double avg)
927{
928 double total, ratio = 0.0;
929 const char *color;
930
931 total = avg_stats(&runtime_cycles_stats[cpu]);
932
933 if (total)
934 ratio = avg / total * 100.0;
935
936 color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio);
937
938 fprintf(output, " # ");
939 color_fprintf(output, color, "%6.2f%%", ratio);
940 fprintf(output, " backend cycles idle ");
941}
942
943static void print_branch_misses(int cpu,
944 struct perf_evsel *evsel __maybe_unused,
945 double avg)
946{
947 double total, ratio = 0.0;
948 const char *color;
949
950 total = avg_stats(&runtime_branches_stats[cpu]);
951
952 if (total)
953 ratio = avg / total * 100.0;
954
955 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
956
957 fprintf(output, " # ");
958 color_fprintf(output, color, "%6.2f%%", ratio);
959 fprintf(output, " of all branches ");
960}
961
962static void print_l1_dcache_misses(int cpu,
963 struct perf_evsel *evsel __maybe_unused,
964 double avg)
965{
966 double total, ratio = 0.0;
967 const char *color;
968
969 total = avg_stats(&runtime_l1_dcache_stats[cpu]);
970
971 if (total)
972 ratio = avg / total * 100.0;
973
974 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
975
976 fprintf(output, " # ");
977 color_fprintf(output, color, "%6.2f%%", ratio);
978 fprintf(output, " of all L1-dcache hits ");
979}
980
981static void print_l1_icache_misses(int cpu,
982 struct perf_evsel *evsel __maybe_unused,
983 double avg)
984{
985 double total, ratio = 0.0;
986 const char *color;
987
988 total = avg_stats(&runtime_l1_icache_stats[cpu]);
989
990 if (total)
991 ratio = avg / total * 100.0;
992
993 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
994
995 fprintf(output, " # ");
996 color_fprintf(output, color, "%6.2f%%", ratio);
997 fprintf(output, " of all L1-icache hits ");
998}
999
1000static void print_dtlb_cache_misses(int cpu,
1001 struct perf_evsel *evsel __maybe_unused,
1002 double avg)
1003{
1004 double total, ratio = 0.0;
1005 const char *color;
1006
1007 total = avg_stats(&runtime_dtlb_cache_stats[cpu]);
1008
1009 if (total)
1010 ratio = avg / total * 100.0;
1011
1012 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
1013
1014 fprintf(output, " # ");
1015 color_fprintf(output, color, "%6.2f%%", ratio);
1016 fprintf(output, " of all dTLB cache hits ");
1017}
1018
1019static void print_itlb_cache_misses(int cpu,
1020 struct perf_evsel *evsel __maybe_unused,
1021 double avg)
1022{
1023 double total, ratio = 0.0;
1024 const char *color;
1025
1026 total = avg_stats(&runtime_itlb_cache_stats[cpu]);
1027
1028 if (total)
1029 ratio = avg / total * 100.0;
1030
1031 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
1032
1033 fprintf(output, " # ");
1034 color_fprintf(output, color, "%6.2f%%", ratio);
1035 fprintf(output, " of all iTLB cache hits ");
1036}
1037
1038static void print_ll_cache_misses(int cpu,
1039 struct perf_evsel *evsel __maybe_unused,
1040 double avg)
1041{
1042 double total, ratio = 0.0;
1043 const char *color;
1044
1045 total = avg_stats(&runtime_ll_cache_stats[cpu]);
1046
1047 if (total)
1048 ratio = avg / total * 100.0;
1049
1050 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
1051
1052 fprintf(output, " # ");
1053 color_fprintf(output, color, "%6.2f%%", ratio);
1054 fprintf(output, " of all LL-cache hits ");
1055}
1056
1057static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg) 760static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
1058{ 761{
1059 double total, ratio = 0.0, total2;
1060 double sc = evsel->scale; 762 double sc = evsel->scale;
1061 const char *fmt; 763 const char *fmt;
1062 int cpu = cpu_map__id_to_cpu(id); 764 int cpu = cpu_map__id_to_cpu(id);
@@ -1090,138 +792,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
1090 if (csv_output || interval) 792 if (csv_output || interval)
1091 return; 793 return;
1092 794
1093 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) { 795 perf_stat__print_shadow_stats(output, evsel, avg, cpu, aggr_mode);
1094 total = avg_stats(&runtime_cycles_stats[cpu]);
1095 if (total) {
1096 ratio = avg / total;
1097 fprintf(output, " # %5.2f insns per cycle ", ratio);
1098 } else {
1099 fprintf(output, " ");
1100 }
1101 total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]);
1102 total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu]));
1103
1104 if (total && avg) {
1105 ratio = total / avg;
1106 fprintf(output, "\n");
1107 if (aggr_mode == AGGR_NONE)
1108 fprintf(output, " ");
1109 fprintf(output, " # %5.2f stalled cycles per insn", ratio);
1110 }
1111
1112 } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
1113 runtime_branches_stats[cpu].n != 0) {
1114 print_branch_misses(cpu, evsel, avg);
1115 } else if (
1116 evsel->attr.type == PERF_TYPE_HW_CACHE &&
1117 evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1D |
1118 ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
1119 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
1120 runtime_l1_dcache_stats[cpu].n != 0) {
1121 print_l1_dcache_misses(cpu, evsel, avg);
1122 } else if (
1123 evsel->attr.type == PERF_TYPE_HW_CACHE &&
1124 evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1I |
1125 ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
1126 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
1127 runtime_l1_icache_stats[cpu].n != 0) {
1128 print_l1_icache_misses(cpu, evsel, avg);
1129 } else if (
1130 evsel->attr.type == PERF_TYPE_HW_CACHE &&
1131 evsel->attr.config == ( PERF_COUNT_HW_CACHE_DTLB |
1132 ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
1133 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
1134 runtime_dtlb_cache_stats[cpu].n != 0) {
1135 print_dtlb_cache_misses(cpu, evsel, avg);
1136 } else if (
1137 evsel->attr.type == PERF_TYPE_HW_CACHE &&
1138 evsel->attr.config == ( PERF_COUNT_HW_CACHE_ITLB |
1139 ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
1140 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
1141 runtime_itlb_cache_stats[cpu].n != 0) {
1142 print_itlb_cache_misses(cpu, evsel, avg);
1143 } else if (
1144 evsel->attr.type == PERF_TYPE_HW_CACHE &&
1145 evsel->attr.config == ( PERF_COUNT_HW_CACHE_LL |
1146 ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
1147 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
1148 runtime_ll_cache_stats[cpu].n != 0) {
1149 print_ll_cache_misses(cpu, evsel, avg);
1150 } else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES) &&
1151 runtime_cacherefs_stats[cpu].n != 0) {
1152 total = avg_stats(&runtime_cacherefs_stats[cpu]);
1153
1154 if (total)
1155 ratio = avg * 100 / total;
1156
1157 fprintf(output, " # %8.3f %% of all cache refs ", ratio);
1158
1159 } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) {
1160 print_stalled_cycles_frontend(cpu, evsel, avg);
1161 } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) {
1162 print_stalled_cycles_backend(cpu, evsel, avg);
1163 } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
1164 total = avg_stats(&runtime_nsecs_stats[cpu]);
1165
1166 if (total) {
1167 ratio = avg / total;
1168 fprintf(output, " # %8.3f GHz ", ratio);
1169 } else {
1170 fprintf(output, " ");
1171 }
1172 } else if (transaction_run &&
1173 perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX))) {
1174 total = avg_stats(&runtime_cycles_stats[cpu]);
1175 if (total)
1176 fprintf(output,
1177 " # %5.2f%% transactional cycles ",
1178 100.0 * (avg / total));
1179 } else if (transaction_run &&
1180 perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX_CP))) {
1181 total = avg_stats(&runtime_cycles_stats[cpu]);
1182 total2 = avg_stats(&runtime_cycles_in_tx_stats[cpu]);
1183 if (total2 < avg)
1184 total2 = avg;
1185 if (total)
1186 fprintf(output,
1187 " # %5.2f%% aborted cycles ",
1188 100.0 * ((total2-avg) / total));
1189 } else if (transaction_run &&
1190 perf_evsel__cmp(evsel, nth_evsel(T_TRANSACTION_START)) &&
1191 avg > 0 &&
1192 runtime_cycles_in_tx_stats[cpu].n != 0) {
1193 total = avg_stats(&runtime_cycles_in_tx_stats[cpu]);
1194
1195 if (total)
1196 ratio = total / avg;
1197
1198 fprintf(output, " # %8.0f cycles / transaction ", ratio);
1199 } else if (transaction_run &&
1200 perf_evsel__cmp(evsel, nth_evsel(T_ELISION_START)) &&
1201 avg > 0 &&
1202 runtime_cycles_in_tx_stats[cpu].n != 0) {
1203 total = avg_stats(&runtime_cycles_in_tx_stats[cpu]);
1204
1205 if (total)
1206 ratio = total / avg;
1207
1208 fprintf(output, " # %8.0f cycles / elision ", ratio);
1209 } else if (runtime_nsecs_stats[cpu].n != 0) {
1210 char unit = 'M';
1211
1212 total = avg_stats(&runtime_nsecs_stats[cpu]);
1213
1214 if (total)
1215 ratio = 1000.0 * avg / total;
1216 if (ratio < 0.001) {
1217 ratio *= 1000;
1218 unit = 'K';
1219 }
1220
1221 fprintf(output, " # %8.3f %c/sec ", ratio, unit);
1222 } else {
1223 fprintf(output, " ");
1224 }
1225} 796}
1226 797
1227static void print_aggr(char *prefix) 798static void print_aggr(char *prefix)
@@ -1536,17 +1107,6 @@ static int perf_stat_init_aggr_mode(void)
1536 return 0; 1107 return 0;
1537} 1108}
1538 1109
1539static int setup_events(const char * const *attrs, unsigned len)
1540{
1541 unsigned i;
1542
1543 for (i = 0; i < len; i++) {
1544 if (parse_events(evsel_list, attrs[i]))
1545 return -1;
1546 }
1547 return 0;
1548}
1549
1550/* 1110/*
1551 * Add default attributes, if there were no attributes specified or 1111 * Add default attributes, if there were no attributes specified or
1552 * if -d/--detailed, -d -d or -d -d -d is used: 1112 * if -d/--detailed, -d -d or -d -d -d is used:
@@ -1668,12 +1228,10 @@ static int add_default_attributes(void)
1668 int err; 1228 int err;
1669 if (pmu_have_event("cpu", "cycles-ct") && 1229 if (pmu_have_event("cpu", "cycles-ct") &&
1670 pmu_have_event("cpu", "el-start")) 1230 pmu_have_event("cpu", "el-start"))
1671 err = setup_events(transaction_attrs, 1231 err = parse_events(evsel_list, transaction_attrs, NULL);
1672 ARRAY_SIZE(transaction_attrs));
1673 else 1232 else
1674 err = setup_events(transaction_limited_attrs, 1233 err = parse_events(evsel_list, transaction_limited_attrs, NULL);
1675 ARRAY_SIZE(transaction_limited_attrs)); 1234 if (err) {
1676 if (err < 0) {
1677 fprintf(stderr, "Cannot set up transaction events\n"); 1235 fprintf(stderr, "Cannot set up transaction events\n");
1678 return -1; 1236 return -1;
1679 } 1237 }
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index e50fe1187b0b..30e59620179d 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -61,13 +61,13 @@ struct timechart {
61 tasks_only, 61 tasks_only,
62 with_backtrace, 62 with_backtrace,
63 topology; 63 topology;
64 bool force;
64 /* IO related settings */ 65 /* IO related settings */
65 u64 io_events;
66 bool io_only, 66 bool io_only,
67 skip_eagain; 67 skip_eagain;
68 u64 io_events;
68 u64 min_time, 69 u64 min_time,
69 merge_dist; 70 merge_dist;
70 bool force;
71}; 71};
72 72
73struct per_pidcomm; 73struct per_pidcomm;
@@ -523,7 +523,7 @@ static const char *cat_backtrace(union perf_event *event,
523 * Discard all. 523 * Discard all.
524 */ 524 */
525 zfree(&p); 525 zfree(&p);
526 goto exit; 526 goto exit_put;
527 } 527 }
528 continue; 528 continue;
529 } 529 }
@@ -538,7 +538,8 @@ static const char *cat_backtrace(union perf_event *event,
538 else 538 else
539 fprintf(f, "..... %016" PRIx64 "\n", ip); 539 fprintf(f, "..... %016" PRIx64 "\n", ip);
540 } 540 }
541 541exit_put:
542 addr_location__put(&al);
542exit: 543exit:
543 fclose(f); 544 fclose(f);
544 545
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 6a4d5d41c671..619a8696fda7 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -235,10 +235,13 @@ static void perf_top__show_details(struct perf_top *top)
235 235
236 more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel, 236 more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel,
237 0, top->sym_pcnt_filter, top->print_entries, 4); 237 0, top->sym_pcnt_filter, top->print_entries, 4);
238 if (top->zero) 238
239 symbol__annotate_zero_histogram(symbol, top->sym_evsel->idx); 239 if (top->evlist->enabled) {
240 else 240 if (top->zero)
241 symbol__annotate_decay_histogram(symbol, top->sym_evsel->idx); 241 symbol__annotate_zero_histogram(symbol, top->sym_evsel->idx);
242 else
243 symbol__annotate_decay_histogram(symbol, top->sym_evsel->idx);
244 }
242 if (more != 0) 245 if (more != 0)
243 printf("%d lines not displayed, maybe increase display entries [e]\n", more); 246 printf("%d lines not displayed, maybe increase display entries [e]\n", more);
244out_unlock: 247out_unlock:
@@ -276,11 +279,13 @@ static void perf_top__print_sym_table(struct perf_top *top)
276 return; 279 return;
277 } 280 }
278 281
279 if (top->zero) { 282 if (top->evlist->enabled) {
280 hists__delete_entries(hists); 283 if (top->zero) {
281 } else { 284 hists__delete_entries(hists);
282 hists__decay_entries(hists, top->hide_user_symbols, 285 } else {
283 top->hide_kernel_symbols); 286 hists__decay_entries(hists, top->hide_user_symbols,
287 top->hide_kernel_symbols);
288 }
284 } 289 }
285 290
286 hists__collapse_resort(hists, NULL); 291 hists__collapse_resort(hists, NULL);
@@ -545,11 +550,13 @@ static void perf_top__sort_new_samples(void *arg)
545 550
546 hists = evsel__hists(t->sym_evsel); 551 hists = evsel__hists(t->sym_evsel);
547 552
548 if (t->zero) { 553 if (t->evlist->enabled) {
549 hists__delete_entries(hists); 554 if (t->zero) {
550 } else { 555 hists__delete_entries(hists);
551 hists__decay_entries(hists, t->hide_user_symbols, 556 } else {
552 t->hide_kernel_symbols); 557 hists__decay_entries(hists, t->hide_user_symbols,
558 t->hide_kernel_symbols);
559 }
553 } 560 }
554 561
555 hists__collapse_resort(hists, NULL); 562 hists__collapse_resort(hists, NULL);
@@ -579,8 +586,27 @@ static void *display_thread_tui(void *arg)
579 hists->uid_filter_str = top->record_opts.target.uid_str; 586 hists->uid_filter_str = top->record_opts.target.uid_str;
580 } 587 }
581 588
582 perf_evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent, 589 while (true) {
583 &top->session->header.env); 590 int key = perf_evlist__tui_browse_hists(top->evlist, help, &hbt,
591 top->min_percent,
592 &top->session->header.env);
593
594 if (key != 'f')
595 break;
596
597 perf_evlist__toggle_enable(top->evlist);
598 /*
599 * No need to refresh, resort/decay histogram entries
600 * if we are not collecting samples:
601 */
602 if (top->evlist->enabled) {
603 hbt.refresh = top->delay_secs;
604 help = "Press 'f' to disable the events or 'h' to see other hotkeys";
605 } else {
606 help = "Press 'f' again to re-enable the events";
607 hbt.refresh = 0;
608 }
609 }
584 610
585 done = 1; 611 done = 1;
586 return NULL; 612 return NULL;
@@ -775,7 +801,9 @@ static void perf_event__process_sample(struct perf_tool *tool,
775 if (al.sym == NULL || !al.sym->ignore) { 801 if (al.sym == NULL || !al.sym->ignore) {
776 struct hists *hists = evsel__hists(evsel); 802 struct hists *hists = evsel__hists(evsel);
777 struct hist_entry_iter iter = { 803 struct hist_entry_iter iter = {
778 .add_entry_cb = hist_iter__top_callback, 804 .evsel = evsel,
805 .sample = sample,
806 .add_entry_cb = hist_iter__top_callback,
779 }; 807 };
780 808
781 if (symbol_conf.cumulate_callchain) 809 if (symbol_conf.cumulate_callchain)
@@ -785,15 +813,14 @@ static void perf_event__process_sample(struct perf_tool *tool,
785 813
786 pthread_mutex_lock(&hists->lock); 814 pthread_mutex_lock(&hists->lock);
787 815
788 err = hist_entry_iter__add(&iter, &al, evsel, sample, 816 err = hist_entry_iter__add(&iter, &al, top->max_stack, top);
789 top->max_stack, top);
790 if (err < 0) 817 if (err < 0)
791 pr_err("Problem incrementing symbol period, skipping event\n"); 818 pr_err("Problem incrementing symbol period, skipping event\n");
792 819
793 pthread_mutex_unlock(&hists->lock); 820 pthread_mutex_unlock(&hists->lock);
794 } 821 }
795 822
796 return; 823 addr_location__put(&al);
797} 824}
798 825
799static void perf_top__mmap_read_idx(struct perf_top *top, int idx) 826static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
@@ -950,7 +977,7 @@ static int __cmd_top(struct perf_top *top)
950 goto out_delete; 977 goto out_delete;
951 978
952 machine__synthesize_threads(&top->session->machines.host, &opts->target, 979 machine__synthesize_threads(&top->session->machines.host, &opts->target,
953 top->evlist->threads, false); 980 top->evlist->threads, false, opts->proc_map_timeout);
954 ret = perf_top__start_counters(top); 981 ret = perf_top__start_counters(top);
955 if (ret) 982 if (ret)
956 goto out_delete; 983 goto out_delete;
@@ -1060,6 +1087,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1060 .target = { 1087 .target = {
1061 .uses_mmap = true, 1088 .uses_mmap = true,
1062 }, 1089 },
1090 .proc_map_timeout = 500,
1063 }, 1091 },
1064 .max_stack = PERF_MAX_STACK_DEPTH, 1092 .max_stack = PERF_MAX_STACK_DEPTH,
1065 .sym_pcnt_filter = 5, 1093 .sym_pcnt_filter = 5,
@@ -1159,6 +1187,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1159 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str, 1187 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
1160 "width[,width...]", 1188 "width[,width...]",
1161 "don't try to adjust column width, use these fixed values"), 1189 "don't try to adjust column width, use these fixed values"),
1190 OPT_UINTEGER(0, "proc-map-timeout", &opts->proc_map_timeout,
1191 "per thread proc mmap processing timeout in ms"),
1162 OPT_END() 1192 OPT_END()
1163 }; 1193 };
1164 const char * const top_usage[] = { 1194 const char * const top_usage[] = {
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index e122970361f2..de5d277d1ad7 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -16,7 +16,6 @@
16 16
17#include <libaudit.h> 17#include <libaudit.h>
18#include <stdlib.h> 18#include <stdlib.h>
19#include <sys/eventfd.h>
20#include <sys/mman.h> 19#include <sys/mman.h>
21#include <linux/futex.h> 20#include <linux/futex.h>
22 21
@@ -41,6 +40,51 @@
41# define EFD_SEMAPHORE 1 40# define EFD_SEMAPHORE 1
42#endif 41#endif
43 42
43#ifndef EFD_NONBLOCK
44# define EFD_NONBLOCK 00004000
45#endif
46
47#ifndef EFD_CLOEXEC
48# define EFD_CLOEXEC 02000000
49#endif
50
51#ifndef O_CLOEXEC
52# define O_CLOEXEC 02000000
53#endif
54
55#ifndef SOCK_DCCP
56# define SOCK_DCCP 6
57#endif
58
59#ifndef SOCK_CLOEXEC
60# define SOCK_CLOEXEC 02000000
61#endif
62
63#ifndef SOCK_NONBLOCK
64# define SOCK_NONBLOCK 00004000
65#endif
66
67#ifndef MSG_CMSG_CLOEXEC
68# define MSG_CMSG_CLOEXEC 0x40000000
69#endif
70
71#ifndef PERF_FLAG_FD_NO_GROUP
72# define PERF_FLAG_FD_NO_GROUP (1UL << 0)
73#endif
74
75#ifndef PERF_FLAG_FD_OUTPUT
76# define PERF_FLAG_FD_OUTPUT (1UL << 1)
77#endif
78
79#ifndef PERF_FLAG_PID_CGROUP
80# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */
81#endif
82
83#ifndef PERF_FLAG_FD_CLOEXEC
84# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */
85#endif
86
87
44struct tp_field { 88struct tp_field {
45 int offset; 89 int offset;
46 union { 90 union {
@@ -331,6 +375,14 @@ static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
331 375
332#define SCA_HEX syscall_arg__scnprintf_hex 376#define SCA_HEX syscall_arg__scnprintf_hex
333 377
378static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
379 struct syscall_arg *arg)
380{
381 return scnprintf(bf, size, "%d", arg->val);
382}
383
384#define SCA_INT syscall_arg__scnprintf_int
385
334static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, 386static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
335 struct syscall_arg *arg) 387 struct syscall_arg *arg)
336{ 388{
@@ -783,6 +835,34 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
783 835
784#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags 836#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
785 837
838static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
839 struct syscall_arg *arg)
840{
841 int printed = 0, flags = arg->val;
842
843 if (flags == 0)
844 return 0;
845
846#define P_FLAG(n) \
847 if (flags & PERF_FLAG_##n) { \
848 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
849 flags &= ~PERF_FLAG_##n; \
850 }
851
852 P_FLAG(FD_NO_GROUP);
853 P_FLAG(FD_OUTPUT);
854 P_FLAG(PID_CGROUP);
855 P_FLAG(FD_CLOEXEC);
856#undef P_FLAG
857
858 if (flags)
859 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
860
861 return printed;
862}
863
864#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
865
786static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size, 866static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
787 struct syscall_arg *arg) 867 struct syscall_arg *arg)
788{ 868{
@@ -1050,6 +1130,11 @@ static struct syscall_fmt {
1050 { .name = "openat", .errmsg = true, 1130 { .name = "openat", .errmsg = true,
1051 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 1131 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1052 [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 1132 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
1133 { .name = "perf_event_open", .errmsg = true,
1134 .arg_scnprintf = { [1] = SCA_INT, /* pid */
1135 [2] = SCA_INT, /* cpu */
1136 [3] = SCA_FD, /* group_fd */
1137 [4] = SCA_PERF_FLAGS, /* flags */ }, },
1053 { .name = "pipe2", .errmsg = true, 1138 { .name = "pipe2", .errmsg = true,
1054 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, }, 1139 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
1055 { .name = "poll", .errmsg = true, .timeout = true, }, 1140 { .name = "poll", .errmsg = true, .timeout = true, },
@@ -1433,7 +1518,8 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1433 return -ENOMEM; 1518 return -ENOMEM;
1434 1519
1435 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target, 1520 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
1436 evlist->threads, trace__tool_process, false); 1521 evlist->threads, trace__tool_process, false,
1522 trace->opts.proc_map_timeout);
1437 if (err) 1523 if (err)
1438 symbol__exit(); 1524 symbol__exit();
1439 1525
@@ -1712,7 +1798,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1712 void *args; 1798 void *args;
1713 size_t printed = 0; 1799 size_t printed = 0;
1714 struct thread *thread; 1800 struct thread *thread;
1715 int id = perf_evsel__sc_tp_uint(evsel, id, sample); 1801 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
1716 struct syscall *sc = trace__syscall_info(trace, evsel, id); 1802 struct syscall *sc = trace__syscall_info(trace, evsel, id);
1717 struct thread_trace *ttrace; 1803 struct thread_trace *ttrace;
1718 1804
@@ -1725,14 +1811,14 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1725 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); 1811 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1726 ttrace = thread__trace(thread, trace->output); 1812 ttrace = thread__trace(thread, trace->output);
1727 if (ttrace == NULL) 1813 if (ttrace == NULL)
1728 return -1; 1814 goto out_put;
1729 1815
1730 args = perf_evsel__sc_tp_ptr(evsel, args, sample); 1816 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
1731 1817
1732 if (ttrace->entry_str == NULL) { 1818 if (ttrace->entry_str == NULL) {
1733 ttrace->entry_str = malloc(1024); 1819 ttrace->entry_str = malloc(1024);
1734 if (!ttrace->entry_str) 1820 if (!ttrace->entry_str)
1735 return -1; 1821 goto out_put;
1736 } 1822 }
1737 1823
1738 if (!trace->summary_only) 1824 if (!trace->summary_only)
@@ -1757,8 +1843,10 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1757 thread__put(trace->current); 1843 thread__put(trace->current);
1758 trace->current = thread__get(thread); 1844 trace->current = thread__get(thread);
1759 } 1845 }
1760 1846 err = 0;
1761 return 0; 1847out_put:
1848 thread__put(thread);
1849 return err;
1762} 1850}
1763 1851
1764static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, 1852static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
@@ -1768,7 +1856,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1768 long ret; 1856 long ret;
1769 u64 duration = 0; 1857 u64 duration = 0;
1770 struct thread *thread; 1858 struct thread *thread;
1771 int id = perf_evsel__sc_tp_uint(evsel, id, sample); 1859 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
1772 struct syscall *sc = trace__syscall_info(trace, evsel, id); 1860 struct syscall *sc = trace__syscall_info(trace, evsel, id);
1773 struct thread_trace *ttrace; 1861 struct thread_trace *ttrace;
1774 1862
@@ -1781,7 +1869,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1781 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); 1869 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1782 ttrace = thread__trace(thread, trace->output); 1870 ttrace = thread__trace(thread, trace->output);
1783 if (ttrace == NULL) 1871 if (ttrace == NULL)
1784 return -1; 1872 goto out_put;
1785 1873
1786 if (trace->summary) 1874 if (trace->summary)
1787 thread__update_stats(ttrace, id, sample); 1875 thread__update_stats(ttrace, id, sample);
@@ -1835,8 +1923,10 @@ signed_print:
1835 fputc('\n', trace->output); 1923 fputc('\n', trace->output);
1836out: 1924out:
1837 ttrace->entry_pending = false; 1925 ttrace->entry_pending = false;
1838 1926 err = 0;
1839 return 0; 1927out_put:
1928 thread__put(thread);
1929 return err;
1840} 1930}
1841 1931
1842static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel, 1932static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
@@ -1863,6 +1953,7 @@ static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evs
1863 1953
1864 ttrace->runtime_ms += runtime_ms; 1954 ttrace->runtime_ms += runtime_ms;
1865 trace->runtime_ms += runtime_ms; 1955 trace->runtime_ms += runtime_ms;
1956 thread__put(thread);
1866 return 0; 1957 return 0;
1867 1958
1868out_dump: 1959out_dump:
@@ -1872,6 +1963,7 @@ out_dump:
1872 (pid_t)perf_evsel__intval(evsel, sample, "pid"), 1963 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
1873 runtime, 1964 runtime,
1874 perf_evsel__intval(evsel, sample, "vruntime")); 1965 perf_evsel__intval(evsel, sample, "vruntime"));
1966 thread__put(thread);
1875 return 0; 1967 return 0;
1876} 1968}
1877 1969
@@ -1924,11 +2016,12 @@ static int trace__pgfault(struct trace *trace,
1924 struct addr_location al; 2016 struct addr_location al;
1925 char map_type = 'd'; 2017 char map_type = 'd';
1926 struct thread_trace *ttrace; 2018 struct thread_trace *ttrace;
2019 int err = -1;
1927 2020
1928 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); 2021 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1929 ttrace = thread__trace(thread, trace->output); 2022 ttrace = thread__trace(thread, trace->output);
1930 if (ttrace == NULL) 2023 if (ttrace == NULL)
1931 return -1; 2024 goto out_put;
1932 2025
1933 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ) 2026 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
1934 ttrace->pfmaj++; 2027 ttrace->pfmaj++;
@@ -1936,7 +2029,7 @@ static int trace__pgfault(struct trace *trace,
1936 ttrace->pfmin++; 2029 ttrace->pfmin++;
1937 2030
1938 if (trace->summary_only) 2031 if (trace->summary_only)
1939 return 0; 2032 goto out;
1940 2033
1941 thread__find_addr_location(thread, cpumode, MAP__FUNCTION, 2034 thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
1942 sample->ip, &al); 2035 sample->ip, &al);
@@ -1967,8 +2060,11 @@ static int trace__pgfault(struct trace *trace,
1967 print_location(trace->output, sample, &al, true, false); 2060 print_location(trace->output, sample, &al, true, false);
1968 2061
1969 fprintf(trace->output, " (%c%c)\n", map_type, al.level); 2062 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
1970 2063out:
1971 return 0; 2064 err = 0;
2065out_put:
2066 thread__put(thread);
2067 return err;
1972} 2068}
1973 2069
1974static bool skip_sample(struct trace *trace, struct perf_sample *sample) 2070static bool skip_sample(struct trace *trace, struct perf_sample *sample)
@@ -2652,6 +2748,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2652 .user_interval = ULLONG_MAX, 2748 .user_interval = ULLONG_MAX,
2653 .no_buffering = true, 2749 .no_buffering = true,
2654 .mmap_pages = UINT_MAX, 2750 .mmap_pages = UINT_MAX,
2751 .proc_map_timeout = 500,
2655 }, 2752 },
2656 .output = stdout, 2753 .output = stdout,
2657 .show_comm = true, 2754 .show_comm = true,
@@ -2666,16 +2763,15 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2666 OPT_BOOLEAN(0, "comm", &trace.show_comm, 2763 OPT_BOOLEAN(0, "comm", &trace.show_comm,
2667 "show the thread COMM next to its id"), 2764 "show the thread COMM next to its id"),
2668 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"), 2765 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
2669 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", 2766 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
2670 "list of events to trace"),
2671 OPT_STRING('o', "output", &output_name, "file", "output file name"), 2767 OPT_STRING('o', "output", &output_name, "file", "output file name"),
2672 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"), 2768 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
2673 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid", 2769 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
2674 "trace events on existing process id"), 2770 "trace events on existing process id"),
2675 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid", 2771 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
2676 "trace events on existing thread id"), 2772 "trace events on existing thread id"),
2677 OPT_CALLBACK(0, "filter-pids", &trace, "float", 2773 OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
2678 "show only events with duration > N.M ms", trace__set_filter_pids), 2774 "pids to filter (by the kernel)", trace__set_filter_pids),
2679 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide, 2775 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
2680 "system-wide collection from all CPUs"), 2776 "system-wide collection from all CPUs"),
2681 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu", 2777 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
@@ -2702,6 +2798,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2702 "Trace pagefaults", parse_pagefaults, "maj"), 2798 "Trace pagefaults", parse_pagefaults, "maj"),
2703 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"), 2799 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
2704 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"), 2800 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
2801 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
2802 "per thread proc mmap processing timeout in ms"),
2705 OPT_END() 2803 OPT_END()
2706 }; 2804 };
2707 const char * const trace_subcommands[] = { "record", NULL }; 2805 const char * const trace_subcommands[] = { "record", NULL };
@@ -2712,11 +2810,10 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2712 signal(SIGFPE, sighandler_dump_stack); 2810 signal(SIGFPE, sighandler_dump_stack);
2713 2811
2714 trace.evlist = perf_evlist__new(); 2812 trace.evlist = perf_evlist__new();
2715 if (trace.evlist == NULL)
2716 return -ENOMEM;
2717 2813
2718 if (trace.evlist == NULL) { 2814 if (trace.evlist == NULL) {
2719 pr_err("Not enough memory to run!\n"); 2815 pr_err("Not enough memory to run!\n");
2816 err = -ENOMEM;
2720 goto out; 2817 goto out;
2721 } 2818 }
2722 2819
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 59a98c643240..317001c94660 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -32,7 +32,7 @@ ifeq ($(ARCH),x86)
32 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 32 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
33 $(call detected,CONFIG_X86_64) 33 $(call detected,CONFIG_X86_64)
34 else 34 else
35 LIBUNWIND_LIBS = -lunwind -lunwind-x86 35 LIBUNWIND_LIBS = -lunwind-x86 -llzma -lunwind
36 endif 36 endif
37 NO_PERF_REGS := 0 37 NO_PERF_REGS := 0
38endif 38endif
@@ -130,6 +130,8 @@ endif
130 130
131ifeq ($(DEBUG),0) 131ifeq ($(DEBUG),0)
132 CFLAGS += -O6 132 CFLAGS += -O6
133else
134 CFLAGS += $(call cc-option,-Og,-O0)
133endif 135endif
134 136
135ifdef PARSER_DEBUG 137ifdef PARSER_DEBUG
@@ -268,6 +270,10 @@ else
268 endif # libelf support 270 endif # libelf support
269endif # NO_LIBELF 271endif # NO_LIBELF
270 272
273ifdef NO_DWARF
274 NO_LIBDW_DWARF_UNWIND := 1
275endif
276
271ifndef NO_LIBELF 277ifndef NO_LIBELF
272 CFLAGS += -DHAVE_LIBELF_SUPPORT 278 CFLAGS += -DHAVE_LIBELF_SUPPORT
273 EXTLIBS += -lelf 279 EXTLIBS += -lelf
@@ -610,6 +616,11 @@ ifdef LIBBABELTRACE
610 endif 616 endif
611endif 617endif
612 618
619ifndef NO_AUXTRACE
620 $(call detected,CONFIG_AUXTRACE)
621 CFLAGS += -DHAVE_AUXTRACE_SUPPORT
622endif
623
613# Among the variables below, these: 624# Among the variables below, these:
614# perfexecdir 625# perfexecdir
615# template_dir 626# template_dir
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
index c16ce833079c..0ebef09c0842 100644
--- a/tools/perf/config/utilities.mak
+++ b/tools/perf/config/utilities.mak
@@ -177,3 +177,22 @@ $(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-sys.h b/tools/perf/perf-sys.h
index 6ef68165c9db..83a25cef82fd 100644
--- a/tools/perf/perf-sys.h
+++ b/tools/perf/perf-sys.h
@@ -6,11 +6,9 @@
6#include <sys/syscall.h> 6#include <sys/syscall.h>
7#include <linux/types.h> 7#include <linux/types.h>
8#include <linux/perf_event.h> 8#include <linux/perf_event.h>
9#include <asm/barrier.h>
9 10
10#if defined(__i386__) 11#if defined(__i386__)
11#define mb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
12#define wmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
13#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
14#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 12#define cpu_relax() asm volatile("rep; nop" ::: "memory");
15#define CPUINFO_PROC {"model name"} 13#define CPUINFO_PROC {"model name"}
16#ifndef __NR_perf_event_open 14#ifndef __NR_perf_event_open
@@ -25,9 +23,6 @@
25#endif 23#endif
26 24
27#if defined(__x86_64__) 25#if defined(__x86_64__)
28#define mb() asm volatile("mfence" ::: "memory")
29#define wmb() asm volatile("sfence" ::: "memory")
30#define rmb() asm volatile("lfence" ::: "memory")
31#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 26#define cpu_relax() asm volatile("rep; nop" ::: "memory");
32#define CPUINFO_PROC {"model name"} 27#define CPUINFO_PROC {"model name"}
33#ifndef __NR_perf_event_open 28#ifndef __NR_perf_event_open
@@ -43,129 +38,63 @@
43 38
44#ifdef __powerpc__ 39#ifdef __powerpc__
45#include "../../arch/powerpc/include/uapi/asm/unistd.h" 40#include "../../arch/powerpc/include/uapi/asm/unistd.h"
46#define mb() asm volatile ("sync" ::: "memory")
47#define wmb() asm volatile ("sync" ::: "memory")
48#define rmb() asm volatile ("sync" ::: "memory")
49#define CPUINFO_PROC {"cpu"} 41#define CPUINFO_PROC {"cpu"}
50#endif 42#endif
51 43
52#ifdef __s390__ 44#ifdef __s390__
53#define mb() asm volatile("bcr 15,0" ::: "memory")
54#define wmb() asm volatile("bcr 15,0" ::: "memory")
55#define rmb() asm volatile("bcr 15,0" ::: "memory")
56#define CPUINFO_PROC {"vendor_id"} 45#define CPUINFO_PROC {"vendor_id"}
57#endif 46#endif
58 47
59#ifdef __sh__ 48#ifdef __sh__
60#if defined(__SH4A__) || defined(__SH5__)
61# define mb() asm volatile("synco" ::: "memory")
62# define wmb() asm volatile("synco" ::: "memory")
63# define rmb() asm volatile("synco" ::: "memory")
64#else
65# define mb() asm volatile("" ::: "memory")
66# define wmb() asm volatile("" ::: "memory")
67# define rmb() asm volatile("" ::: "memory")
68#endif
69#define CPUINFO_PROC {"cpu type"} 49#define CPUINFO_PROC {"cpu type"}
70#endif 50#endif
71 51
72#ifdef __hppa__ 52#ifdef __hppa__
73#define mb() asm volatile("" ::: "memory")
74#define wmb() asm volatile("" ::: "memory")
75#define rmb() asm volatile("" ::: "memory")
76#define CPUINFO_PROC {"cpu"} 53#define CPUINFO_PROC {"cpu"}
77#endif 54#endif
78 55
79#ifdef __sparc__ 56#ifdef __sparc__
80#ifdef __LP64__
81#define mb() asm volatile("ba,pt %%xcc, 1f\n" \
82 "membar #StoreLoad\n" \
83 "1:\n":::"memory")
84#else
85#define mb() asm volatile("":::"memory")
86#endif
87#define wmb() asm volatile("":::"memory")
88#define rmb() asm volatile("":::"memory")
89#define CPUINFO_PROC {"cpu"} 57#define CPUINFO_PROC {"cpu"}
90#endif 58#endif
91 59
92#ifdef __alpha__ 60#ifdef __alpha__
93#define mb() asm volatile("mb" ::: "memory")
94#define wmb() asm volatile("wmb" ::: "memory")
95#define rmb() asm volatile("mb" ::: "memory")
96#define CPUINFO_PROC {"cpu model"} 61#define CPUINFO_PROC {"cpu model"}
97#endif 62#endif
98 63
99#ifdef __ia64__ 64#ifdef __ia64__
100#define mb() asm volatile ("mf" ::: "memory")
101#define wmb() asm volatile ("mf" ::: "memory")
102#define rmb() asm volatile ("mf" ::: "memory")
103#define cpu_relax() asm volatile ("hint @pause" ::: "memory") 65#define cpu_relax() asm volatile ("hint @pause" ::: "memory")
104#define CPUINFO_PROC {"model name"} 66#define CPUINFO_PROC {"model name"}
105#endif 67#endif
106 68
107#ifdef __arm__ 69#ifdef __arm__
108/*
109 * Use the __kuser_memory_barrier helper in the CPU helper page. See
110 * arch/arm/kernel/entry-armv.S in the kernel source for details.
111 */
112#define mb() ((void(*)(void))0xffff0fa0)()
113#define wmb() ((void(*)(void))0xffff0fa0)()
114#define rmb() ((void(*)(void))0xffff0fa0)()
115#define CPUINFO_PROC {"model name", "Processor"} 70#define CPUINFO_PROC {"model name", "Processor"}
116#endif 71#endif
117 72
118#ifdef __aarch64__ 73#ifdef __aarch64__
119#define mb() asm volatile("dmb ish" ::: "memory")
120#define wmb() asm volatile("dmb ishst" ::: "memory")
121#define rmb() asm volatile("dmb ishld" ::: "memory")
122#define cpu_relax() asm volatile("yield" ::: "memory") 74#define cpu_relax() asm volatile("yield" ::: "memory")
123#endif 75#endif
124 76
125#ifdef __mips__ 77#ifdef __mips__
126#define mb() asm volatile( \
127 ".set mips2\n\t" \
128 "sync\n\t" \
129 ".set mips0" \
130 : /* no output */ \
131 : /* no input */ \
132 : "memory")
133#define wmb() mb()
134#define rmb() mb()
135#define CPUINFO_PROC {"cpu model"} 78#define CPUINFO_PROC {"cpu model"}
136#endif 79#endif
137 80
138#ifdef __arc__ 81#ifdef __arc__
139#define mb() asm volatile("" ::: "memory")
140#define wmb() asm volatile("" ::: "memory")
141#define rmb() asm volatile("" ::: "memory")
142#define CPUINFO_PROC {"Processor"} 82#define CPUINFO_PROC {"Processor"}
143#endif 83#endif
144 84
145#ifdef __metag__ 85#ifdef __metag__
146#define mb() asm volatile("" ::: "memory")
147#define wmb() asm volatile("" ::: "memory")
148#define rmb() asm volatile("" ::: "memory")
149#define CPUINFO_PROC {"CPU"} 86#define CPUINFO_PROC {"CPU"}
150#endif 87#endif
151 88
152#ifdef __xtensa__ 89#ifdef __xtensa__
153#define mb() asm volatile("memw" ::: "memory")
154#define wmb() asm volatile("memw" ::: "memory")
155#define rmb() asm volatile("" ::: "memory")
156#define CPUINFO_PROC {"core ID"} 90#define CPUINFO_PROC {"core ID"}
157#endif 91#endif
158 92
159#ifdef __tile__ 93#ifdef __tile__
160#define mb() asm volatile ("mf" ::: "memory")
161#define wmb() asm volatile ("mf" ::: "memory")
162#define rmb() asm volatile ("mf" ::: "memory")
163#define cpu_relax() asm volatile ("mfspr zero, PASS" ::: "memory") 94#define cpu_relax() asm volatile ("mfspr zero, PASS" ::: "memory")
164#define CPUINFO_PROC {"model name"} 95#define CPUINFO_PROC {"model name"}
165#endif 96#endif
166 97
167#define barrier() asm volatile ("" ::: "memory")
168
169#ifndef cpu_relax 98#ifndef cpu_relax
170#define cpu_relax() barrier() 99#define cpu_relax() barrier()
171#endif 100#endif
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index e14bb637255c..4a5827fff799 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -54,16 +54,22 @@ struct record_opts {
54 bool period; 54 bool period;
55 bool sample_intr_regs; 55 bool sample_intr_regs;
56 bool running_time; 56 bool running_time;
57 bool full_auxtrace;
58 bool auxtrace_snapshot_mode;
57 unsigned int freq; 59 unsigned int freq;
58 unsigned int mmap_pages; 60 unsigned int mmap_pages;
61 unsigned int auxtrace_mmap_pages;
59 unsigned int user_freq; 62 unsigned int user_freq;
60 u64 branch_stack; 63 u64 branch_stack;
61 u64 default_interval; 64 u64 default_interval;
62 u64 user_interval; 65 u64 user_interval;
66 size_t auxtrace_snapshot_size;
67 const char *auxtrace_snapshot_opts;
63 bool sample_transaction; 68 bool sample_transaction;
64 unsigned initial_delay; 69 unsigned initial_delay;
65 bool use_clockid; 70 bool use_clockid;
66 clockid_t clockid; 71 clockid_t clockid;
72 unsigned int proc_map_timeout;
67}; 73};
68 74
69struct option; 75struct option;
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 6a8801b32017..ee41e705b2eb 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -3,9 +3,9 @@ perf-y += parse-events.o
3perf-y += dso-data.o 3perf-y += dso-data.o
4perf-y += attr.o 4perf-y += attr.o
5perf-y += vmlinux-kallsyms.o 5perf-y += vmlinux-kallsyms.o
6perf-y += open-syscall.o 6perf-y += openat-syscall.o
7perf-y += open-syscall-all-cpus.o 7perf-y += openat-syscall-all-cpus.o
8perf-y += open-syscall-tp-fields.o 8perf-y += openat-syscall-tp-fields.o
9perf-y += mmap-basic.o 9perf-y += mmap-basic.o
10perf-y += perf-record.o 10perf-y += perf-record.o
11perf-y += rdpmc.o 11perf-y += rdpmc.o
@@ -34,7 +34,7 @@ perf-y += kmod-path.o
34 34
35perf-$(CONFIG_X86) += perf-time-to-tsc.o 35perf-$(CONFIG_X86) += perf-time-to-tsc.o
36 36
37ifeq ($(ARCH),$(filter $(ARCH),x86 arm)) 37ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64))
38perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o 38perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
39endif 39endif
40 40
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 4f4098167112..87b9961646e4 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -23,12 +23,12 @@ static struct test {
23 .func = test__vmlinux_matches_kallsyms, 23 .func = test__vmlinux_matches_kallsyms,
24 }, 24 },
25 { 25 {
26 .desc = "detect open syscall event", 26 .desc = "detect openat syscall event",
27 .func = test__open_syscall_event, 27 .func = test__openat_syscall_event,
28 }, 28 },
29 { 29 {
30 .desc = "detect open syscall event on all cpus", 30 .desc = "detect openat syscall event on all cpus",
31 .func = test__open_syscall_event_on_all_cpus, 31 .func = test__openat_syscall_event_on_all_cpus,
32 }, 32 },
33 { 33 {
34 .desc = "read samples using the mmap interface", 34 .desc = "read samples using the mmap interface",
@@ -73,8 +73,8 @@ static struct test {
73 .func = test__perf_evsel__tp_sched_test, 73 .func = test__perf_evsel__tp_sched_test,
74 }, 74 },
75 { 75 {
76 .desc = "Generate and check syscalls:sys_enter_open event fields", 76 .desc = "Generate and check syscalls:sys_enter_openat event fields",
77 .func = test__syscall_open_tp_fields, 77 .func = test__syscall_openat_tp_fields,
78 }, 78 },
79 { 79 {
80 .desc = "struct perf_event_attr setup", 80 .desc = "struct perf_event_attr setup",
@@ -126,7 +126,7 @@ static struct test {
126 .desc = "Test parsing with no sample_id_all bit set", 126 .desc = "Test parsing with no sample_id_all bit set",
127 .func = test__parse_no_sample_id_all, 127 .func = test__parse_no_sample_id_all,
128 }, 128 },
129#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) 129#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)
130#ifdef HAVE_DWARF_UNWIND_SUPPORT 130#ifdef HAVE_DWARF_UNWIND_SUPPORT
131 { 131 {
132 .desc = "Test dwarf unwind", 132 .desc = "Test dwarf unwind",
@@ -219,7 +219,7 @@ static int run_test(struct test *test)
219 wait(&status); 219 wait(&status);
220 220
221 if (WIFEXITED(status)) { 221 if (WIFEXITED(status)) {
222 err = WEXITSTATUS(status); 222 err = (signed char)WEXITSTATUS(status);
223 pr_debug("test child finished with %d\n", err); 223 pr_debug("test child finished with %d\n", err);
224 } else if (WIFSIGNALED(status)) { 224 } else if (WIFSIGNALED(status)) {
225 err = -1; 225 err = -1;
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index f671ec37a7c4..22f8a00446e1 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -248,6 +248,7 @@ static int process_sample_event(struct machine *machine,
248 struct perf_sample sample; 248 struct perf_sample sample;
249 struct thread *thread; 249 struct thread *thread;
250 u8 cpumode; 250 u8 cpumode;
251 int ret;
251 252
252 if (perf_evlist__parse_sample(evlist, event, &sample)) { 253 if (perf_evlist__parse_sample(evlist, event, &sample)) {
253 pr_debug("perf_evlist__parse_sample failed\n"); 254 pr_debug("perf_evlist__parse_sample failed\n");
@@ -262,7 +263,9 @@ static int process_sample_event(struct machine *machine,
262 263
263 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 264 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
264 265
265 return read_object_code(sample.ip, READLEN, cpumode, thread, state); 266 ret = read_object_code(sample.ip, READLEN, cpumode, thread, state);
267 thread__put(thread);
268 return ret;
266} 269}
267 270
268static int process_event(struct machine *machine, struct perf_evlist *evlist, 271static int process_event(struct machine *machine, struct perf_evlist *evlist,
@@ -448,7 +451,7 @@ static int do_test_code_reading(bool try_kcore)
448 } 451 }
449 452
450 ret = perf_event__synthesize_thread_map(NULL, threads, 453 ret = perf_event__synthesize_thread_map(NULL, threads,
451 perf_event__process, machine, false); 454 perf_event__process, machine, false, 500);
452 if (ret < 0) { 455 if (ret < 0) {
453 pr_debug("perf_event__synthesize_thread_map failed\n"); 456 pr_debug("perf_event__synthesize_thread_map failed\n");
454 goto out_err; 457 goto out_err;
@@ -457,13 +460,13 @@ static int do_test_code_reading(bool try_kcore)
457 thread = machine__findnew_thread(machine, pid, pid); 460 thread = machine__findnew_thread(machine, pid, pid);
458 if (!thread) { 461 if (!thread) {
459 pr_debug("machine__findnew_thread failed\n"); 462 pr_debug("machine__findnew_thread failed\n");
460 goto out_err; 463 goto out_put;
461 } 464 }
462 465
463 cpus = cpu_map__new(NULL); 466 cpus = cpu_map__new(NULL);
464 if (!cpus) { 467 if (!cpus) {
465 pr_debug("cpu_map__new failed\n"); 468 pr_debug("cpu_map__new failed\n");
466 goto out_err; 469 goto out_put;
467 } 470 }
468 471
469 while (1) { 472 while (1) {
@@ -472,7 +475,7 @@ static int do_test_code_reading(bool try_kcore)
472 evlist = perf_evlist__new(); 475 evlist = perf_evlist__new();
473 if (!evlist) { 476 if (!evlist) {
474 pr_debug("perf_evlist__new failed\n"); 477 pr_debug("perf_evlist__new failed\n");
475 goto out_err; 478 goto out_put;
476 } 479 }
477 480
478 perf_evlist__set_maps(evlist, cpus, threads); 481 perf_evlist__set_maps(evlist, cpus, threads);
@@ -482,10 +485,10 @@ static int do_test_code_reading(bool try_kcore)
482 else 485 else
483 str = "cycles"; 486 str = "cycles";
484 pr_debug("Parsing event '%s'\n", str); 487 pr_debug("Parsing event '%s'\n", str);
485 ret = parse_events(evlist, str); 488 ret = parse_events(evlist, str, NULL);
486 if (ret < 0) { 489 if (ret < 0) {
487 pr_debug("parse_events failed\n"); 490 pr_debug("parse_events failed\n");
488 goto out_err; 491 goto out_put;
489 } 492 }
490 493
491 perf_evlist__config(evlist, &opts); 494 perf_evlist__config(evlist, &opts);
@@ -506,7 +509,7 @@ static int do_test_code_reading(bool try_kcore)
506 continue; 509 continue;
507 } 510 }
508 pr_debug("perf_evlist__open failed\n"); 511 pr_debug("perf_evlist__open failed\n");
509 goto out_err; 512 goto out_put;
510 } 513 }
511 break; 514 break;
512 } 515 }
@@ -514,7 +517,7 @@ static int do_test_code_reading(bool try_kcore)
514 ret = perf_evlist__mmap(evlist, UINT_MAX, false); 517 ret = perf_evlist__mmap(evlist, UINT_MAX, false);
515 if (ret < 0) { 518 if (ret < 0) {
516 pr_debug("perf_evlist__mmap failed\n"); 519 pr_debug("perf_evlist__mmap failed\n");
517 goto out_err; 520 goto out_put;
518 } 521 }
519 522
520 perf_evlist__enable(evlist); 523 perf_evlist__enable(evlist);
@@ -525,7 +528,7 @@ static int do_test_code_reading(bool try_kcore)
525 528
526 ret = process_events(machine, evlist, &state); 529 ret = process_events(machine, evlist, &state);
527 if (ret < 0) 530 if (ret < 0)
528 goto out_err; 531 goto out_put;
529 532
530 if (!have_vmlinux && !have_kcore && !try_kcore) 533 if (!have_vmlinux && !have_kcore && !try_kcore)
531 err = TEST_CODE_READING_NO_KERNEL_OBJ; 534 err = TEST_CODE_READING_NO_KERNEL_OBJ;
@@ -535,7 +538,10 @@ static int do_test_code_reading(bool try_kcore)
535 err = TEST_CODE_READING_NO_ACCESS; 538 err = TEST_CODE_READING_NO_ACCESS;
536 else 539 else
537 err = TEST_CODE_READING_OK; 540 err = TEST_CODE_READING_OK;
541out_put:
542 thread__put(thread);
538out_err: 543out_err:
544
539 if (evlist) { 545 if (evlist) {
540 perf_evlist__delete(evlist); 546 perf_evlist__delete(evlist);
541 } else { 547 } else {
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index 513e5febbe5a..a218aeaf56a0 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -99,6 +99,17 @@ struct test_data_offset offsets[] = {
99 }, 99 },
100}; 100};
101 101
102/* move it from util/dso.c for compatibility */
103static int dso__data_fd(struct dso *dso, struct machine *machine)
104{
105 int fd = dso__data_get_fd(dso, machine);
106
107 if (fd >= 0)
108 dso__data_put_fd(dso);
109
110 return fd;
111}
112
102int test__dso_data(void) 113int test__dso_data(void)
103{ 114{
104 struct machine machine; 115 struct machine machine;
@@ -155,7 +166,7 @@ int test__dso_data(void)
155 free(buf); 166 free(buf);
156 } 167 }
157 168
158 dso__delete(dso); 169 dso__put(dso);
159 unlink(file); 170 unlink(file);
160 return 0; 171 return 0;
161} 172}
@@ -215,7 +226,7 @@ static void dsos__delete(int cnt)
215 struct dso *dso = dsos[i]; 226 struct dso *dso = dsos[i];
216 227
217 unlink(dso->name); 228 unlink(dso->name);
218 dso__delete(dso); 229 dso__put(dso);
219 } 230 }
220 231
221 free(dsos); 232 free(dsos);
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 0bf06bec68c7..40b36c462427 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -28,7 +28,7 @@ static int init_live_machine(struct machine *machine)
28 pid_t pid = getpid(); 28 pid_t pid = getpid();
29 29
30 return perf_event__synthesize_mmap_events(NULL, &event, pid, pid, 30 return perf_event__synthesize_mmap_events(NULL, &event, pid, pid,
31 mmap_handler, machine, true); 31 mmap_handler, machine, true, 500);
32} 32}
33 33
34#define MAX_STACK 8 34#define MAX_STACK 8
@@ -170,6 +170,7 @@ int test__dwarf_unwind(void)
170 } 170 }
171 171
172 err = krava_1(thread); 172 err = krava_1(thread);
173 thread__put(thread);
173 174
174 out: 175 out:
175 machine__delete_threads(machine); 176 machine__delete_threads(machine);
diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c
index b8d8341b383e..3fa715987a5e 100644
--- a/tools/perf/tests/evsel-roundtrip-name.c
+++ b/tools/perf/tests/evsel-roundtrip-name.c
@@ -23,7 +23,7 @@ static int perf_evsel__roundtrip_cache_name_test(void)
23 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 23 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
24 __perf_evsel__hw_cache_type_op_res_name(type, op, i, 24 __perf_evsel__hw_cache_type_op_res_name(type, op, i,
25 name, sizeof(name)); 25 name, sizeof(name));
26 err = parse_events(evlist, name); 26 err = parse_events(evlist, name, NULL);
27 if (err) 27 if (err)
28 ret = err; 28 ret = err;
29 } 29 }
@@ -71,7 +71,7 @@ static int __perf_evsel__name_array_test(const char *names[], int nr_names)
71 return -ENOMEM; 71 return -ENOMEM;
72 72
73 for (i = 0; i < nr_names; ++i) { 73 for (i = 0; i < nr_names; ++i) {
74 err = parse_events(evlist, names[i]); 74 err = parse_events(evlist, names[i], NULL);
75 if (err) { 75 if (err) {
76 pr_debug("failed to parse event '%s', err %d\n", 76 pr_debug("failed to parse event '%s', err %d\n",
77 names[i], err); 77 names[i], err);
diff --git a/tools/perf/tests/hists_common.c b/tools/perf/tests/hists_common.c
index a62c09134516..ce80b274b097 100644
--- a/tools/perf/tests/hists_common.c
+++ b/tools/perf/tests/hists_common.c
@@ -96,6 +96,7 @@ struct machine *setup_fake_machine(struct machines *machines)
96 goto out; 96 goto out;
97 97
98 thread__set_comm(thread, fake_threads[i].comm, 0); 98 thread__set_comm(thread, fake_threads[i].comm, 0);
99 thread__put(thread);
99 } 100 }
100 101
101 for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) { 102 for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) {
@@ -120,8 +121,7 @@ struct machine *setup_fake_machine(struct machines *machines)
120 size_t k; 121 size_t k;
121 struct dso *dso; 122 struct dso *dso;
122 123
123 dso = __dsos__findnew(&machine->user_dsos, 124 dso = machine__findnew_dso(machine, fake_symbols[i].dso_name);
124 fake_symbols[i].dso_name);
125 if (dso == NULL) 125 if (dso == NULL)
126 goto out; 126 goto out;
127 127
@@ -134,11 +134,15 @@ struct machine *setup_fake_machine(struct machines *machines)
134 134
135 sym = symbol__new(fsym->start, fsym->length, 135 sym = symbol__new(fsym->start, fsym->length,
136 STB_GLOBAL, fsym->name); 136 STB_GLOBAL, fsym->name);
137 if (sym == NULL) 137 if (sym == NULL) {
138 dso__put(dso);
138 goto out; 139 goto out;
140 }
139 141
140 symbols__insert(&dso->symbols[MAP__FUNCTION], sym); 142 symbols__insert(&dso->symbols[MAP__FUNCTION], sym);
141 } 143 }
144
145 dso__put(dso);
142 } 146 }
143 147
144 return machine; 148 return machine;
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index 18619966454c..7d82c8be5e36 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -87,6 +87,8 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
87 }, 87 },
88 }; 88 };
89 struct hist_entry_iter iter = { 89 struct hist_entry_iter iter = {
90 .evsel = evsel,
91 .sample = &sample,
90 .hide_unresolved = false, 92 .hide_unresolved = false,
91 }; 93 };
92 94
@@ -104,9 +106,11 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
104 &sample) < 0) 106 &sample) < 0)
105 goto out; 107 goto out;
106 108
107 if (hist_entry_iter__add(&iter, &al, evsel, &sample, 109 if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH,
108 PERF_MAX_STACK_DEPTH, NULL) < 0) 110 NULL) < 0) {
111 addr_location__put(&al);
109 goto out; 112 goto out;
113 }
110 114
111 fake_samples[i].thread = al.thread; 115 fake_samples[i].thread = al.thread;
112 fake_samples[i].map = al.map; 116 fake_samples[i].map = al.map;
@@ -695,7 +699,7 @@ int test__hists_cumulate(void)
695 699
696 TEST_ASSERT_VAL("No memory", evlist); 700 TEST_ASSERT_VAL("No memory", evlist);
697 701
698 err = parse_events(evlist, "cpu-clock"); 702 err = parse_events(evlist, "cpu-clock", NULL);
699 if (err) 703 if (err)
700 goto out; 704 goto out;
701 705
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index 59e53db7914c..ce48775e6ada 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -63,6 +63,8 @@ static int add_hist_entries(struct perf_evlist *evlist,
63 }, 63 },
64 }; 64 };
65 struct hist_entry_iter iter = { 65 struct hist_entry_iter iter = {
66 .evsel = evsel,
67 .sample = &sample,
66 .ops = &hist_iter_normal, 68 .ops = &hist_iter_normal,
67 .hide_unresolved = false, 69 .hide_unresolved = false,
68 }; 70 };
@@ -81,9 +83,11 @@ static int add_hist_entries(struct perf_evlist *evlist,
81 &sample) < 0) 83 &sample) < 0)
82 goto out; 84 goto out;
83 85
84 if (hist_entry_iter__add(&iter, &al, evsel, &sample, 86 if (hist_entry_iter__add(&iter, &al,
85 PERF_MAX_STACK_DEPTH, NULL) < 0) 87 PERF_MAX_STACK_DEPTH, NULL) < 0) {
88 addr_location__put(&al);
86 goto out; 89 goto out;
90 }
87 91
88 fake_samples[i].thread = al.thread; 92 fake_samples[i].thread = al.thread;
89 fake_samples[i].map = al.map; 93 fake_samples[i].map = al.map;
@@ -108,10 +112,10 @@ int test__hists_filter(void)
108 112
109 TEST_ASSERT_VAL("No memory", evlist); 113 TEST_ASSERT_VAL("No memory", evlist);
110 114
111 err = parse_events(evlist, "cpu-clock"); 115 err = parse_events(evlist, "cpu-clock", NULL);
112 if (err) 116 if (err)
113 goto out; 117 goto out;
114 err = parse_events(evlist, "task-clock"); 118 err = parse_events(evlist, "task-clock", NULL);
115 if (err) 119 if (err)
116 goto out; 120 goto out;
117 121
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index 278ba8344c23..8c102b011424 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -91,8 +91,10 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
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, 1, 1, 0, true);
94 if (he == NULL) 94 if (he == NULL) {
95 addr_location__put(&al);
95 goto out; 96 goto out;
97 }
96 98
97 fake_common_samples[k].thread = al.thread; 99 fake_common_samples[k].thread = al.thread;
98 fake_common_samples[k].map = al.map; 100 fake_common_samples[k].map = al.map;
@@ -115,8 +117,10 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
115 117
116 he = __hists__add_entry(hists, &al, NULL, 118 he = __hists__add_entry(hists, &al, NULL,
117 NULL, NULL, 1, 1, 0, true); 119 NULL, NULL, 1, 1, 0, true);
118 if (he == NULL) 120 if (he == NULL) {
121 addr_location__put(&al);
119 goto out; 122 goto out;
123 }
120 124
121 fake_samples[i][k].thread = al.thread; 125 fake_samples[i][k].thread = al.thread;
122 fake_samples[i][k].map = al.map; 126 fake_samples[i][k].map = al.map;
@@ -282,10 +286,10 @@ int test__hists_link(void)
282 if (evlist == NULL) 286 if (evlist == NULL)
283 return -ENOMEM; 287 return -ENOMEM;
284 288
285 err = parse_events(evlist, "cpu-clock"); 289 err = parse_events(evlist, "cpu-clock", NULL);
286 if (err) 290 if (err)
287 goto out; 291 goto out;
288 err = parse_events(evlist, "task-clock"); 292 err = parse_events(evlist, "task-clock", NULL);
289 if (err) 293 if (err)
290 goto out; 294 goto out;
291 295
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index b52c9faea224..adbebc852cc8 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -57,6 +57,8 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
57 }, 57 },
58 }; 58 };
59 struct hist_entry_iter iter = { 59 struct hist_entry_iter iter = {
60 .evsel = evsel,
61 .sample = &sample,
60 .ops = &hist_iter_normal, 62 .ops = &hist_iter_normal,
61 .hide_unresolved = false, 63 .hide_unresolved = false,
62 }; 64 };
@@ -70,9 +72,11 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
70 &sample) < 0) 72 &sample) < 0)
71 goto out; 73 goto out;
72 74
73 if (hist_entry_iter__add(&iter, &al, evsel, &sample, 75 if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH,
74 PERF_MAX_STACK_DEPTH, NULL) < 0) 76 NULL) < 0) {
77 addr_location__put(&al);
75 goto out; 78 goto out;
79 }
76 80
77 fake_samples[i].thread = al.thread; 81 fake_samples[i].thread = al.thread;
78 fake_samples[i].map = al.map; 82 fake_samples[i].map = al.map;
@@ -590,7 +594,7 @@ int test__hists_output(void)
590 594
591 TEST_ASSERT_VAL("No memory", evlist); 595 TEST_ASSERT_VAL("No memory", evlist);
592 596
593 err = parse_events(evlist, "cpu-clock"); 597 err = parse_events(evlist, "cpu-clock", NULL);
594 if (err) 598 if (err)
595 goto out; 599 goto out;
596 600
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index 7a5ab7b0b8f6..5b171d1e338b 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -78,8 +78,8 @@ int test__keep_tracking(void)
78 78
79 perf_evlist__set_maps(evlist, cpus, threads); 79 perf_evlist__set_maps(evlist, cpus, threads);
80 80
81 CHECK__(parse_events(evlist, "dummy:u")); 81 CHECK__(parse_events(evlist, "dummy:u", NULL));
82 CHECK__(parse_events(evlist, "cycles:u")); 82 CHECK__(parse_events(evlist, "cycles:u", NULL));
83 83
84 perf_evlist__config(evlist, &opts); 84 perf_evlist__config(evlist, &opts);
85 85
diff --git a/tools/perf/tests/kmod-path.c b/tools/perf/tests/kmod-path.c
index e8d7cbb9320c..08c433b4bf4f 100644
--- a/tools/perf/tests/kmod-path.c
+++ b/tools/perf/tests/kmod-path.c
@@ -34,9 +34,21 @@ static int test(const char *path, bool alloc_name, bool alloc_ext,
34 return 0; 34 return 0;
35} 35}
36 36
37static int test_is_kernel_module(const char *path, int cpumode, bool expect)
38{
39 TEST_ASSERT_VAL("is_kernel_module",
40 (!!is_kernel_module(path, cpumode)) == (!!expect));
41 pr_debug("%s (cpumode: %d) - is_kernel_module: %s\n",
42 path, cpumode, expect ? "true" : "false");
43 return 0;
44}
45
37#define T(path, an, ae, k, c, n, e) \ 46#define T(path, an, ae, k, c, n, e) \
38 TEST_ASSERT_VAL("failed", !test(path, an, ae, k, c, n, e)) 47 TEST_ASSERT_VAL("failed", !test(path, an, ae, k, c, n, e))
39 48
49#define M(path, c, e) \
50 TEST_ASSERT_VAL("failed", !test_is_kernel_module(path, c, e))
51
40int test__kmod_path__parse(void) 52int test__kmod_path__parse(void)
41{ 53{
42 /* path alloc_name alloc_ext kmod comp name ext */ 54 /* path alloc_name alloc_ext kmod comp name ext */
@@ -44,30 +56,90 @@ int test__kmod_path__parse(void)
44 T("/xxxx/xxxx/x-x.ko", false , true , true, false, NULL , NULL); 56 T("/xxxx/xxxx/x-x.ko", false , true , true, false, NULL , NULL);
45 T("/xxxx/xxxx/x-x.ko", true , false , true, false, "[x_x]", NULL); 57 T("/xxxx/xxxx/x-x.ko", true , false , true, false, "[x_x]", NULL);
46 T("/xxxx/xxxx/x-x.ko", false , false , true, false, NULL , NULL); 58 T("/xxxx/xxxx/x-x.ko", false , false , true, false, NULL , NULL);
59 M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
60 M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_KERNEL, true);
61 M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_USER, false);
47 62
48 /* path alloc_name alloc_ext kmod comp name ext */ 63 /* path alloc_name alloc_ext kmod comp name ext */
49 T("/xxxx/xxxx/x.ko.gz", true , true , true, true, "[x]", "gz"); 64 T("/xxxx/xxxx/x.ko.gz", true , true , true, true, "[x]", "gz");
50 T("/xxxx/xxxx/x.ko.gz", false , true , true, true, NULL , "gz"); 65 T("/xxxx/xxxx/x.ko.gz", false , true , true, true, NULL , "gz");
51 T("/xxxx/xxxx/x.ko.gz", true , false , true, true, "[x]", NULL); 66 T("/xxxx/xxxx/x.ko.gz", true , false , true, true, "[x]", NULL);
52 T("/xxxx/xxxx/x.ko.gz", false , false , true, true, NULL , NULL); 67 T("/xxxx/xxxx/x.ko.gz", false , false , true, true, NULL , NULL);
68 M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
69 M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_KERNEL, true);
70 M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_USER, false);
53 71
54 /* path alloc_name alloc_ext kmod comp name ext */ 72 /* path alloc_name alloc_ext kmod comp name ext */
55 T("/xxxx/xxxx/x.gz", true , true , false, true, "x.gz" ,"gz"); 73 T("/xxxx/xxxx/x.gz", true , true , false, true, "x.gz" ,"gz");
56 T("/xxxx/xxxx/x.gz", false , true , false, true, NULL ,"gz"); 74 T("/xxxx/xxxx/x.gz", false , true , false, true, NULL ,"gz");
57 T("/xxxx/xxxx/x.gz", true , false , false, true, "x.gz" , NULL); 75 T("/xxxx/xxxx/x.gz", true , false , false, true, "x.gz" , NULL);
58 T("/xxxx/xxxx/x.gz", false , false , false, true, NULL , NULL); 76 T("/xxxx/xxxx/x.gz", false , false , false, true, NULL , NULL);
77 M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
78 M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_KERNEL, false);
79 M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_USER, false);
59 80
60 /* path alloc_name alloc_ext kmod comp name ext */ 81 /* path alloc_name alloc_ext kmod comp name ext */
61 T("x.gz", true , true , false, true, "x.gz", "gz"); 82 T("x.gz", true , true , false, true, "x.gz", "gz");
62 T("x.gz", false , true , false, true, NULL , "gz"); 83 T("x.gz", false , true , false, true, NULL , "gz");
63 T("x.gz", true , false , false, true, "x.gz", NULL); 84 T("x.gz", true , false , false, true, "x.gz", NULL);
64 T("x.gz", false , false , false, true, NULL , NULL); 85 T("x.gz", false , false , false, true, NULL , NULL);
86 M("x.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
87 M("x.gz", PERF_RECORD_MISC_KERNEL, false);
88 M("x.gz", PERF_RECORD_MISC_USER, false);
65 89
66 /* path alloc_name alloc_ext kmod comp name ext */ 90 /* path alloc_name alloc_ext kmod comp name ext */
67 T("x.ko.gz", true , true , true, true, "[x]", "gz"); 91 T("x.ko.gz", true , true , true, true, "[x]", "gz");
68 T("x.ko.gz", false , true , true, true, NULL , "gz"); 92 T("x.ko.gz", false , true , true, true, NULL , "gz");
69 T("x.ko.gz", true , false , true, true, "[x]", NULL); 93 T("x.ko.gz", true , false , true, true, "[x]", NULL);
70 T("x.ko.gz", false , false , true, true, NULL , NULL); 94 T("x.ko.gz", false , false , true, true, NULL , NULL);
95 M("x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
96 M("x.ko.gz", PERF_RECORD_MISC_KERNEL, true);
97 M("x.ko.gz", PERF_RECORD_MISC_USER, false);
98
99 /* path alloc_name alloc_ext kmod comp name ext */
100 T("[test_module]", true , true , true, false, "[test_module]", NULL);
101 T("[test_module]", false , true , true, false, NULL , NULL);
102 T("[test_module]", true , false , true, false, "[test_module]", NULL);
103 T("[test_module]", false , false , true, false, NULL , NULL);
104 M("[test_module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
105 M("[test_module]", PERF_RECORD_MISC_KERNEL, true);
106 M("[test_module]", PERF_RECORD_MISC_USER, false);
107
108 /* path alloc_name alloc_ext kmod comp name ext */
109 T("[test.module]", true , true , true, false, "[test.module]", NULL);
110 T("[test.module]", false , true , true, false, NULL , NULL);
111 T("[test.module]", true , false , true, false, "[test.module]", NULL);
112 T("[test.module]", false , false , true, false, NULL , NULL);
113 M("[test.module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
114 M("[test.module]", PERF_RECORD_MISC_KERNEL, true);
115 M("[test.module]", PERF_RECORD_MISC_USER, false);
116
117 /* path alloc_name alloc_ext kmod comp name ext */
118 T("[vdso]", true , true , false, false, "[vdso]", NULL);
119 T("[vdso]", false , true , false, false, NULL , NULL);
120 T("[vdso]", true , false , false, false, "[vdso]", NULL);
121 T("[vdso]", false , false , false, false, NULL , NULL);
122 M("[vdso]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
123 M("[vdso]", PERF_RECORD_MISC_KERNEL, false);
124 M("[vdso]", PERF_RECORD_MISC_USER, false);
125
126 /* path alloc_name alloc_ext kmod comp name ext */
127 T("[vsyscall]", true , true , false, false, "[vsyscall]", NULL);
128 T("[vsyscall]", false , true , false, false, NULL , NULL);
129 T("[vsyscall]", true , false , false, false, "[vsyscall]", NULL);
130 T("[vsyscall]", false , false , false, false, NULL , NULL);
131 M("[vsyscall]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
132 M("[vsyscall]", PERF_RECORD_MISC_KERNEL, false);
133 M("[vsyscall]", PERF_RECORD_MISC_USER, false);
134
135 /* path alloc_name alloc_ext kmod comp name ext */
136 T("[kernel.kallsyms]", true , true , false, false, "[kernel.kallsyms]", NULL);
137 T("[kernel.kallsyms]", false , true , false, false, NULL , NULL);
138 T("[kernel.kallsyms]", true , false , false, false, "[kernel.kallsyms]", NULL);
139 T("[kernel.kallsyms]", false , false , false, false, NULL , NULL);
140 M("[kernel.kallsyms]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
141 M("[kernel.kallsyms]", PERF_RECORD_MISC_KERNEL, false);
142 M("[kernel.kallsyms]", PERF_RECORD_MISC_USER, false);
71 143
72 return 0; 144 return 0;
73} 145}
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index bff85324f799..65280d28662e 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -32,6 +32,7 @@ make_no_backtrace := NO_BACKTRACE=1
32make_no_libnuma := NO_LIBNUMA=1 32make_no_libnuma := NO_LIBNUMA=1
33make_no_libaudit := NO_LIBAUDIT=1 33make_no_libaudit := NO_LIBAUDIT=1
34make_no_libbionic := NO_LIBBIONIC=1 34make_no_libbionic := NO_LIBBIONIC=1
35make_no_auxtrace := NO_AUXTRACE=1
35make_tags := tags 36make_tags := tags
36make_cscope := cscope 37make_cscope := cscope
37make_help := help 38make_help := help
@@ -52,7 +53,7 @@ make_static := LDFLAGS=-static
52make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 53make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
53make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 54make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
54make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 55make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
55make_minimal += NO_LIBDW_DWARF_UNWIND=1 56make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1
56 57
57# $(run) contains all available tests 58# $(run) contains all available tests
58run := make_pure 59run := make_pure
@@ -74,6 +75,7 @@ run += make_no_backtrace
74run += make_no_libnuma 75run += make_no_libnuma
75run += make_no_libaudit 76run += make_no_libaudit
76run += make_no_libbionic 77run += make_no_libbionic
78run += make_no_auxtrace
77run += make_help 79run += make_help
78run += make_doc 80run += make_doc
79run += make_perf_o 81run += make_perf_o
@@ -223,7 +225,19 @@ tarpkg:
223 echo "- $@: $$cmd" && echo $$cmd > $@ && \ 225 echo "- $@: $$cmd" && echo $$cmd > $@ && \
224 ( eval $$cmd ) >> $@ 2>&1 226 ( eval $$cmd ) >> $@ 2>&1
225 227
226all: $(run) $(run_O) tarpkg 228make_kernelsrc:
229 @echo " - make -C <kernelsrc> tools/perf"
230 $(call clean); \
231 (make -C ../.. tools/perf) > $@ 2>&1 && \
232 test -x perf && rm -f $@ || (cat $@ ; false)
233
234make_kernelsrc_tools:
235 @echo " - make -C <kernelsrc>/tools perf"
236 $(call clean); \
237 (make -C ../../tools perf) > $@ 2>&1 && \
238 test -x perf && rm -f $@ || (cat $@ ; false)
239
240all: $(run) $(run_O) tarpkg make_kernelsrc make_kernelsrc_tools
227 @echo OK 241 @echo OK
228 242
229out: $(run_O) 243out: $(run_O)
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 9b9622a33932..5855cf471210 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -23,10 +23,8 @@ int test__basic_mmap(void)
23 struct cpu_map *cpus; 23 struct cpu_map *cpus;
24 struct perf_evlist *evlist; 24 struct perf_evlist *evlist;
25 cpu_set_t cpu_set; 25 cpu_set_t cpu_set;
26 const char *syscall_names[] = { "getsid", "getppid", "getpgrp", 26 const char *syscall_names[] = { "getsid", "getppid", "getpgid", };
27 "getpgid", }; 27 pid_t (*syscalls[])(void) = { (void *)getsid, getppid, (void*)getpgid };
28 pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp,
29 (void*)getpgid };
30#define nsyscalls ARRAY_SIZE(syscall_names) 28#define nsyscalls ARRAY_SIZE(syscall_names)
31 unsigned int nr_events[nsyscalls], 29 unsigned int nr_events[nsyscalls],
32 expected_nr_events[nsyscalls], i, j; 30 expected_nr_events[nsyscalls], i, j;
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c
index 2113f1c8611f..7f48efa7e295 100644
--- a/tools/perf/tests/mmap-thread-lookup.c
+++ b/tools/perf/tests/mmap-thread-lookup.c
@@ -129,7 +129,7 @@ static int synth_all(struct machine *machine)
129{ 129{
130 return perf_event__synthesize_threads(NULL, 130 return perf_event__synthesize_threads(NULL,
131 perf_event__process, 131 perf_event__process,
132 machine, 0); 132 machine, 0, 500);
133} 133}
134 134
135static int synth_process(struct machine *machine) 135static int synth_process(struct machine *machine)
@@ -141,7 +141,7 @@ static int synth_process(struct machine *machine)
141 141
142 err = perf_event__synthesize_thread_map(NULL, map, 142 err = perf_event__synthesize_thread_map(NULL, map,
143 perf_event__process, 143 perf_event__process,
144 machine, 0); 144 machine, 0, 500);
145 145
146 thread_map__delete(map); 146 thread_map__delete(map);
147 return err; 147 return err;
@@ -191,6 +191,8 @@ static int mmap_events(synth_cb synth)
191 PERF_RECORD_MISC_USER, MAP__FUNCTION, 191 PERF_RECORD_MISC_USER, MAP__FUNCTION,
192 (unsigned long) (td->map + 1), &al); 192 (unsigned long) (td->map + 1), &al);
193 193
194 thread__put(thread);
195
194 if (!al.map) { 196 if (!al.map) {
195 pr_debug("failed, couldn't find map\n"); 197 pr_debug("failed, couldn't find map\n");
196 err = -1; 198 err = -1;
diff --git a/tools/perf/tests/open-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index 3ec885c48f8f..9a7a116e09b8 100644
--- a/tools/perf/tests/open-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -3,13 +3,14 @@
3#include "thread_map.h" 3#include "thread_map.h"
4#include "cpumap.h" 4#include "cpumap.h"
5#include "debug.h" 5#include "debug.h"
6#include "stat.h"
6 7
7int test__open_syscall_event_on_all_cpus(void) 8int test__openat_syscall_event_on_all_cpus(void)
8{ 9{
9 int err = -1, fd, cpu; 10 int err = -1, fd, cpu;
10 struct cpu_map *cpus; 11 struct cpu_map *cpus;
11 struct perf_evsel *evsel; 12 struct perf_evsel *evsel;
12 unsigned int nr_open_calls = 111, i; 13 unsigned int nr_openat_calls = 111, i;
13 cpu_set_t cpu_set; 14 cpu_set_t cpu_set;
14 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); 15 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
15 char sbuf[STRERR_BUFSIZE]; 16 char sbuf[STRERR_BUFSIZE];
@@ -27,7 +28,7 @@ int test__open_syscall_event_on_all_cpus(void)
27 28
28 CPU_ZERO(&cpu_set); 29 CPU_ZERO(&cpu_set);
29 30
30 evsel = perf_evsel__newtp("syscalls", "sys_enter_open"); 31 evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
31 if (evsel == NULL) { 32 if (evsel == NULL) {
32 if (tracefs_configured()) 33 if (tracefs_configured())
33 pr_debug("is tracefs mounted on /sys/kernel/tracing?\n"); 34 pr_debug("is tracefs mounted on /sys/kernel/tracing?\n");
@@ -46,7 +47,7 @@ int test__open_syscall_event_on_all_cpus(void)
46 } 47 }
47 48
48 for (cpu = 0; cpu < cpus->nr; ++cpu) { 49 for (cpu = 0; cpu < cpus->nr; ++cpu) {
49 unsigned int ncalls = nr_open_calls + cpu; 50 unsigned int ncalls = nr_openat_calls + cpu;
50 /* 51 /*
51 * XXX eventually lift this restriction in a way that 52 * XXX eventually lift this restriction in a way that
52 * keeps perf building on older glibc installations 53 * keeps perf building on older glibc installations
@@ -66,7 +67,7 @@ int test__open_syscall_event_on_all_cpus(void)
66 goto out_close_fd; 67 goto out_close_fd;
67 } 68 }
68 for (i = 0; i < ncalls; ++i) { 69 for (i = 0; i < ncalls; ++i) {
69 fd = open("/etc/passwd", O_RDONLY); 70 fd = openat(0, "/etc/passwd", O_RDONLY);
70 close(fd); 71 close(fd);
71 } 72 }
72 CPU_CLR(cpus->map[cpu], &cpu_set); 73 CPU_CLR(cpus->map[cpu], &cpu_set);
@@ -96,7 +97,7 @@ int test__open_syscall_event_on_all_cpus(void)
96 break; 97 break;
97 } 98 }
98 99
99 expected = nr_open_calls + cpu; 100 expected = nr_openat_calls + cpu;
100 if (evsel->counts->cpu[cpu].val != expected) { 101 if (evsel->counts->cpu[cpu].val != expected) {
101 pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n", 102 pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n",
102 expected, cpus->map[cpu], evsel->counts->cpu[cpu].val); 103 expected, cpus->map[cpu], evsel->counts->cpu[cpu].val);
diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
index 127dcae0b760..6245221479d7 100644
--- a/tools/perf/tests/open-syscall-tp-fields.c
+++ b/tools/perf/tests/openat-syscall-tp-fields.c
@@ -5,7 +5,7 @@
5#include "tests.h" 5#include "tests.h"
6#include "debug.h" 6#include "debug.h"
7 7
8int test__syscall_open_tp_fields(void) 8int test__syscall_openat_tp_fields(void)
9{ 9{
10 struct record_opts opts = { 10 struct record_opts opts = {
11 .target = { 11 .target = {
@@ -29,7 +29,7 @@ int test__syscall_open_tp_fields(void)
29 goto out; 29 goto out;
30 } 30 }
31 31
32 evsel = perf_evsel__newtp("syscalls", "sys_enter_open"); 32 evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
33 if (evsel == NULL) { 33 if (evsel == NULL) {
34 pr_debug("%s: perf_evsel__newtp\n", __func__); 34 pr_debug("%s: perf_evsel__newtp\n", __func__);
35 goto out_delete_evlist; 35 goto out_delete_evlist;
@@ -66,7 +66,7 @@ int test__syscall_open_tp_fields(void)
66 /* 66 /*
67 * Generate the event: 67 * Generate the event:
68 */ 68 */
69 open(filename, flags); 69 openat(AT_FDCWD, filename, flags);
70 70
71 while (1) { 71 while (1) {
72 int before = nr_events; 72 int before = nr_events;
diff --git a/tools/perf/tests/open-syscall.c b/tools/perf/tests/openat-syscall.c
index 07aa319bf334..9f9491bb8e48 100644
--- a/tools/perf/tests/open-syscall.c
+++ b/tools/perf/tests/openat-syscall.c
@@ -3,11 +3,11 @@
3#include "debug.h" 3#include "debug.h"
4#include "tests.h" 4#include "tests.h"
5 5
6int test__open_syscall_event(void) 6int test__openat_syscall_event(void)
7{ 7{
8 int err = -1, fd; 8 int err = -1, fd;
9 struct perf_evsel *evsel; 9 struct perf_evsel *evsel;
10 unsigned int nr_open_calls = 111, i; 10 unsigned int nr_openat_calls = 111, i;
11 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); 11 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
12 char sbuf[STRERR_BUFSIZE]; 12 char sbuf[STRERR_BUFSIZE];
13 13
@@ -16,7 +16,7 @@ int test__open_syscall_event(void)
16 return -1; 16 return -1;
17 } 17 }
18 18
19 evsel = perf_evsel__newtp("syscalls", "sys_enter_open"); 19 evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
20 if (evsel == NULL) { 20 if (evsel == NULL) {
21 if (tracefs_configured()) 21 if (tracefs_configured())
22 pr_debug("is tracefs mounted on /sys/kernel/tracing?\n"); 22 pr_debug("is tracefs mounted on /sys/kernel/tracing?\n");
@@ -34,8 +34,8 @@ int test__open_syscall_event(void)
34 goto out_evsel_delete; 34 goto out_evsel_delete;
35 } 35 }
36 36
37 for (i = 0; i < nr_open_calls; ++i) { 37 for (i = 0; i < nr_openat_calls; ++i) {
38 fd = open("/etc/passwd", O_RDONLY); 38 fd = openat(0, "/etc/passwd", O_RDONLY);
39 close(fd); 39 close(fd);
40 } 40 }
41 41
@@ -44,9 +44,9 @@ int test__open_syscall_event(void)
44 goto out_close_fd; 44 goto out_close_fd;
45 } 45 }
46 46
47 if (evsel->counts->cpu[0].val != nr_open_calls) { 47 if (evsel->counts->cpu[0].val != nr_openat_calls) {
48 pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n", 48 pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n",
49 nr_open_calls, evsel->counts->cpu[0].val); 49 nr_openat_calls, evsel->counts->cpu[0].val);
50 goto out_close_fd; 50 goto out_close_fd;
51 } 51 }
52 52
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 3de744961739..d76963f7ad3d 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -427,7 +427,7 @@ static int test__checkevent_list(struct perf_evlist *evlist)
427 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); 427 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
428 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 428 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
429 429
430 /* syscalls:sys_enter_open:k */ 430 /* syscalls:sys_enter_openat:k */
431 evsel = perf_evsel__next(evsel); 431 evsel = perf_evsel__next(evsel);
432 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); 432 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
433 TEST_ASSERT_VAL("wrong sample_type", 433 TEST_ASSERT_VAL("wrong sample_type",
@@ -665,7 +665,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
665 TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries); 665 TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries);
666 TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->nr_groups); 666 TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->nr_groups);
667 667
668 /* group1 syscalls:sys_enter_open:H */ 668 /* group1 syscalls:sys_enter_openat:H */
669 evsel = leader = perf_evlist__first(evlist); 669 evsel = leader = perf_evlist__first(evlist);
670 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); 670 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
671 TEST_ASSERT_VAL("wrong sample_type", 671 TEST_ASSERT_VAL("wrong sample_type",
@@ -1293,7 +1293,7 @@ struct evlist_test {
1293 1293
1294static struct evlist_test test__events[] = { 1294static struct evlist_test test__events[] = {
1295 { 1295 {
1296 .name = "syscalls:sys_enter_open", 1296 .name = "syscalls:sys_enter_openat",
1297 .check = test__checkevent_tracepoint, 1297 .check = test__checkevent_tracepoint,
1298 .id = 0, 1298 .id = 0,
1299 }, 1299 },
@@ -1353,7 +1353,7 @@ static struct evlist_test test__events[] = {
1353 .id = 11, 1353 .id = 11,
1354 }, 1354 },
1355 { 1355 {
1356 .name = "syscalls:sys_enter_open:k", 1356 .name = "syscalls:sys_enter_openat:k",
1357 .check = test__checkevent_tracepoint_modifier, 1357 .check = test__checkevent_tracepoint_modifier,
1358 .id = 12, 1358 .id = 12,
1359 }, 1359 },
@@ -1408,7 +1408,7 @@ static struct evlist_test test__events[] = {
1408 .id = 22, 1408 .id = 22,
1409 }, 1409 },
1410 { 1410 {
1411 .name = "r1,syscalls:sys_enter_open:k,1:1:hp", 1411 .name = "r1,syscalls:sys_enter_openat:k,1:1:hp",
1412 .check = test__checkevent_list, 1412 .check = test__checkevent_list,
1413 .id = 23, 1413 .id = 23,
1414 }, 1414 },
@@ -1443,7 +1443,7 @@ static struct evlist_test test__events[] = {
1443 .id = 29, 1443 .id = 29,
1444 }, 1444 },
1445 { 1445 {
1446 .name = "group1{syscalls:sys_enter_open:H,cycles:kppp},group2{cycles,1:3}:G,instructions:u", 1446 .name = "group1{syscalls:sys_enter_openat:H,cycles:kppp},group2{cycles,1:3}:G,instructions:u",
1447 .check = test__group3, 1447 .check = test__group3,
1448 .id = 30, 1448 .id = 30,
1449 }, 1449 },
@@ -1571,7 +1571,7 @@ static int test_event(struct evlist_test *e)
1571 if (evlist == NULL) 1571 if (evlist == NULL)
1572 return -ENOMEM; 1572 return -ENOMEM;
1573 1573
1574 ret = parse_events(evlist, e->name); 1574 ret = parse_events(evlist, e->name, NULL);
1575 if (ret) { 1575 if (ret) {
1576 pr_debug("failed to parse event '%s', err %d\n", 1576 pr_debug("failed to parse event '%s', err %d\n",
1577 e->name, ret); 1577 e->name, ret);
diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c
index f238442b238a..5f49484f1abc 100644
--- a/tools/perf/tests/perf-time-to-tsc.c
+++ b/tools/perf/tests/perf-time-to-tsc.c
@@ -68,7 +68,7 @@ int test__perf_time_to_tsc(void)
68 68
69 perf_evlist__set_maps(evlist, cpus, threads); 69 perf_evlist__set_maps(evlist, cpus, threads);
70 70
71 CHECK__(parse_events(evlist, "cycles:u")); 71 CHECK__(parse_events(evlist, "cycles:u", NULL));
72 72
73 perf_evlist__config(evlist, &opts); 73 perf_evlist__config(evlist, &opts);
74 74
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index eeb68bb1972d..faa04e9d5d5f 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -152,7 +152,8 @@ int test__pmu(void)
152 if (ret) 152 if (ret)
153 break; 153 break;
154 154
155 ret = perf_pmu__config_terms(&formats, &attr, terms, false); 155 ret = perf_pmu__config_terms(&formats, &attr, terms,
156 false, NULL);
156 if (ret) 157 if (ret)
157 break; 158 break;
158 159
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
index cc68648c7c55..0d31403ea593 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -347,7 +347,7 @@ int test__switch_tracking(void)
347 perf_evlist__set_maps(evlist, cpus, threads); 347 perf_evlist__set_maps(evlist, cpus, threads);
348 348
349 /* First event */ 349 /* First event */
350 err = parse_events(evlist, "cpu-clock:u"); 350 err = parse_events(evlist, "cpu-clock:u", NULL);
351 if (err) { 351 if (err) {
352 pr_debug("Failed to parse event dummy:u\n"); 352 pr_debug("Failed to parse event dummy:u\n");
353 goto out_err; 353 goto out_err;
@@ -356,7 +356,7 @@ int test__switch_tracking(void)
356 cpu_clocks_evsel = perf_evlist__last(evlist); 356 cpu_clocks_evsel = perf_evlist__last(evlist);
357 357
358 /* Second event */ 358 /* Second event */
359 err = parse_events(evlist, "cycles:u"); 359 err = parse_events(evlist, "cycles:u", NULL);
360 if (err) { 360 if (err) {
361 pr_debug("Failed to parse event cycles:u\n"); 361 pr_debug("Failed to parse event cycles:u\n");
362 goto out_err; 362 goto out_err;
@@ -371,7 +371,7 @@ int test__switch_tracking(void)
371 goto out; 371 goto out;
372 } 372 }
373 373
374 err = parse_events(evlist, sched_switch); 374 err = parse_events(evlist, sched_switch, NULL);
375 if (err) { 375 if (err) {
376 pr_debug("Failed to parse event %s\n", sched_switch); 376 pr_debug("Failed to parse event %s\n", sched_switch);
377 goto out_err; 377 goto out_err;
@@ -401,7 +401,7 @@ int test__switch_tracking(void)
401 perf_evsel__set_sample_bit(cycles_evsel, TIME); 401 perf_evsel__set_sample_bit(cycles_evsel, TIME);
402 402
403 /* Fourth event */ 403 /* Fourth event */
404 err = parse_events(evlist, "dummy:u"); 404 err = parse_events(evlist, "dummy:u", NULL);
405 if (err) { 405 if (err) {
406 pr_debug("Failed to parse event dummy:u\n"); 406 pr_debug("Failed to parse event dummy:u\n");
407 goto out_err; 407 goto out_err;
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 52758a33f64c..8e5038b48ba8 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -9,6 +9,15 @@ do { \
9 } \ 9 } \
10} while (0) 10} while (0)
11 11
12#define TEST_ASSERT_EQUAL(text, val, expected) \
13do { \
14 if (val != expected) { \
15 pr_debug("FAILED %s:%d %s (%d != %d)\n", \
16 __FILE__, __LINE__, text, val, expected); \
17 return -1; \
18 } \
19} while (0)
20
12enum { 21enum {
13 TEST_OK = 0, 22 TEST_OK = 0,
14 TEST_FAIL = -1, 23 TEST_FAIL = -1,
@@ -17,14 +26,14 @@ enum {
17 26
18/* Tests */ 27/* Tests */
19int test__vmlinux_matches_kallsyms(void); 28int test__vmlinux_matches_kallsyms(void);
20int test__open_syscall_event(void); 29int test__openat_syscall_event(void);
21int test__open_syscall_event_on_all_cpus(void); 30int test__openat_syscall_event_on_all_cpus(void);
22int test__basic_mmap(void); 31int test__basic_mmap(void);
23int test__PERF_RECORD(void); 32int test__PERF_RECORD(void);
24int test__rdpmc(void); 33int test__rdpmc(void);
25int test__perf_evsel__roundtrip_name_test(void); 34int test__perf_evsel__roundtrip_name_test(void);
26int test__perf_evsel__tp_sched_test(void); 35int test__perf_evsel__tp_sched_test(void);
27int test__syscall_open_tp_fields(void); 36int test__syscall_openat_tp_fields(void);
28int test__pmu(void); 37int test__pmu(void);
29int test__attr(void); 38int test__attr(void);
30int test__dso_data(void); 39int test__dso_data(void);
@@ -53,7 +62,7 @@ int test__fdarray__filter(void);
53int test__fdarray__add(void); 62int test__fdarray__add(void);
54int test__kmod_path__parse(void); 63int test__kmod_path__parse(void);
55 64
56#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) 65#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)
57#ifdef HAVE_DWARF_UNWIND_SUPPORT 66#ifdef HAVE_DWARF_UNWIND_SUPPORT
58struct thread; 67struct thread;
59struct perf_sample; 68struct perf_sample;
diff --git a/tools/perf/tests/thread-mg-share.c b/tools/perf/tests/thread-mg-share.c
index b028499dd3cf..01fabb19d746 100644
--- a/tools/perf/tests/thread-mg-share.c
+++ b/tools/perf/tests/thread-mg-share.c
@@ -43,7 +43,7 @@ int test__thread_mg_share(void)
43 leader && t1 && t2 && t3 && other); 43 leader && t1 && t2 && t3 && other);
44 44
45 mg = leader->mg; 45 mg = leader->mg;
46 TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 4); 46 TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 4);
47 47
48 /* test the map groups pointer is shared */ 48 /* test the map groups pointer is shared */
49 TEST_ASSERT_VAL("map groups don't match", mg == t1->mg); 49 TEST_ASSERT_VAL("map groups don't match", mg == t1->mg);
@@ -58,33 +58,40 @@ int test__thread_mg_share(void)
58 other_leader = machine__find_thread(machine, 4, 4); 58 other_leader = machine__find_thread(machine, 4, 4);
59 TEST_ASSERT_VAL("failed to find other leader", other_leader); 59 TEST_ASSERT_VAL("failed to find other leader", other_leader);
60 60
61 /*
62 * Ok, now that all the rbtree related operations were done,
63 * lets remove all of them from there so that we can do the
64 * refcounting tests.
65 */
66 machine__remove_thread(machine, leader);
67 machine__remove_thread(machine, t1);
68 machine__remove_thread(machine, t2);
69 machine__remove_thread(machine, t3);
70 machine__remove_thread(machine, other);
71 machine__remove_thread(machine, other_leader);
72
61 other_mg = other->mg; 73 other_mg = other->mg;
62 TEST_ASSERT_VAL("wrong refcnt", other_mg->refcnt == 2); 74 TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&other_mg->refcnt), 2);
63 75
64 TEST_ASSERT_VAL("map groups don't match", other_mg == other_leader->mg); 76 TEST_ASSERT_VAL("map groups don't match", other_mg == other_leader->mg);
65 77
66 /* release thread group */ 78 /* release thread group */
67 thread__delete(leader); 79 thread__put(leader);
68 TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 3); 80 TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 3);
69 81
70 thread__delete(t1); 82 thread__put(t1);
71 TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 2); 83 TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 2);
72 84
73 thread__delete(t2); 85 thread__put(t2);
74 TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 1); 86 TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 1);
75 87
76 thread__delete(t3); 88 thread__put(t3);
77 89
78 /* release other group */ 90 /* release other group */
79 thread__delete(other_leader); 91 thread__put(other_leader);
80 TEST_ASSERT_VAL("wrong refcnt", other_mg->refcnt == 1); 92 TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&other_mg->refcnt), 1);
81 93
82 thread__delete(other); 94 thread__put(other);
83
84 /*
85 * Cannot call machine__delete_threads(machine) now,
86 * because we've already released all the threads.
87 */
88 95
89 machines__exit(&machines); 96 machines__exit(&machines);
90 return 0; 97 return 0;
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index 3d9088003a5b..b34c5fc829ae 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -23,9 +23,10 @@ int test__vmlinux_matches_kallsyms(void)
23 int err = -1; 23 int err = -1;
24 struct rb_node *nd; 24 struct rb_node *nd;
25 struct symbol *sym; 25 struct symbol *sym;
26 struct map *kallsyms_map, *vmlinux_map; 26 struct map *kallsyms_map, *vmlinux_map, *map;
27 struct machine kallsyms, vmlinux; 27 struct machine kallsyms, vmlinux;
28 enum map_type type = MAP__FUNCTION; 28 enum map_type type = MAP__FUNCTION;
29 struct maps *maps = &vmlinux.kmaps.maps[type];
29 u64 mem_start, mem_end; 30 u64 mem_start, mem_end;
30 31
31 /* 32 /*
@@ -184,8 +185,8 @@ detour:
184 185
185 pr_info("Maps only in vmlinux:\n"); 186 pr_info("Maps only in vmlinux:\n");
186 187
187 for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { 188 for (map = maps__first(maps); map; map = map__next(map)) {
188 struct map *pos = rb_entry(nd, struct map, rb_node), *pair; 189 struct map *
189 /* 190 /*
190 * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while 191 * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while
191 * the kernel will have the path for the vmlinux file being used, 192 * the kernel will have the path for the vmlinux file being used,
@@ -193,22 +194,22 @@ detour:
193 * both cases. 194 * both cases.
194 */ 195 */
195 pair = map_groups__find_by_name(&kallsyms.kmaps, type, 196 pair = map_groups__find_by_name(&kallsyms.kmaps, type,
196 (pos->dso->kernel ? 197 (map->dso->kernel ?
197 pos->dso->short_name : 198 map->dso->short_name :
198 pos->dso->name)); 199 map->dso->name));
199 if (pair) 200 if (pair)
200 pair->priv = 1; 201 pair->priv = 1;
201 else 202 else
202 map__fprintf(pos, stderr); 203 map__fprintf(map, stderr);
203 } 204 }
204 205
205 pr_info("Maps in vmlinux with a different name in kallsyms:\n"); 206 pr_info("Maps in vmlinux with a different name in kallsyms:\n");
206 207
207 for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { 208 for (map = maps__first(maps); map; map = map__next(map)) {
208 struct map *pos = rb_entry(nd, struct map, rb_node), *pair; 209 struct map *pair;
209 210
210 mem_start = vmlinux_map->unmap_ip(vmlinux_map, pos->start); 211 mem_start = vmlinux_map->unmap_ip(vmlinux_map, map->start);
211 mem_end = vmlinux_map->unmap_ip(vmlinux_map, pos->end); 212 mem_end = vmlinux_map->unmap_ip(vmlinux_map, map->end);
212 213
213 pair = map_groups__find(&kallsyms.kmaps, type, mem_start); 214 pair = map_groups__find(&kallsyms.kmaps, type, mem_start);
214 if (pair == NULL || pair->priv) 215 if (pair == NULL || pair->priv)
@@ -217,7 +218,7 @@ detour:
217 if (pair->start == mem_start) { 218 if (pair->start == mem_start) {
218 pair->priv = 1; 219 pair->priv = 1;
219 pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as", 220 pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as",
220 pos->start, pos->end, pos->pgoff, pos->dso->name); 221 map->start, map->end, map->pgoff, map->dso->name);
221 if (mem_end != pair->end) 222 if (mem_end != pair->end)
222 pr_info(":\n*%" PRIx64 "-%" PRIx64 " %" PRIx64, 223 pr_info(":\n*%" PRIx64 "-%" PRIx64 " %" PRIx64,
223 pair->start, pair->end, pair->pgoff); 224 pair->start, pair->end, pair->pgoff);
@@ -228,12 +229,11 @@ detour:
228 229
229 pr_info("Maps only in kallsyms:\n"); 230 pr_info("Maps only in kallsyms:\n");
230 231
231 for (nd = rb_first(&kallsyms.kmaps.maps[type]); 232 maps = &kallsyms.kmaps.maps[type];
232 nd; nd = rb_next(nd)) {
233 struct map *pos = rb_entry(nd, struct map, rb_node);
234 233
235 if (!pos->priv) 234 for (map = maps__first(maps); map; map = map__next(map)) {
236 map__fprintf(pos, stderr); 235 if (!map->priv)
236 map__fprintf(map, stderr);
237 } 237 }
238out: 238out:
239 machine__exit(&kallsyms); 239 machine__exit(&kallsyms);
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index e5250eb2dd57..5995a8bd7c69 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -11,16 +11,21 @@
11#include "../../util/evsel.h" 11#include "../../util/evsel.h"
12#include <pthread.h> 12#include <pthread.h>
13 13
14struct disasm_line_samples {
15 double percent;
16 u64 nr;
17};
18
14struct browser_disasm_line { 19struct browser_disasm_line {
15 struct rb_node rb_node; 20 struct rb_node rb_node;
16 u32 idx; 21 u32 idx;
17 int idx_asm; 22 int idx_asm;
18 int jump_sources; 23 int jump_sources;
19 /* 24 /*
20 * actual length of this array is saved on the nr_events field 25 * actual length of this array is saved on the nr_events field
21 * of the struct annotate_browser 26 * of the struct annotate_browser
22 */ 27 */
23 double percent[1]; 28 struct disasm_line_samples samples[1];
24}; 29};
25 30
26static struct annotate_browser_opt { 31static struct annotate_browser_opt {
@@ -28,7 +33,8 @@ static struct annotate_browser_opt {
28 use_offset, 33 use_offset,
29 jump_arrows, 34 jump_arrows,
30 show_linenr, 35 show_linenr,
31 show_nr_jumps; 36 show_nr_jumps,
37 show_total_period;
32} annotate_browser__opts = { 38} annotate_browser__opts = {
33 .use_offset = true, 39 .use_offset = true,
34 .jump_arrows = true, 40 .jump_arrows = true,
@@ -105,15 +111,20 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
105 char bf[256]; 111 char bf[256];
106 112
107 for (i = 0; i < ab->nr_events; i++) { 113 for (i = 0; i < ab->nr_events; i++) {
108 if (bdl->percent[i] > percent_max) 114 if (bdl->samples[i].percent > percent_max)
109 percent_max = bdl->percent[i]; 115 percent_max = bdl->samples[i].percent;
110 } 116 }
111 117
112 if (dl->offset != -1 && percent_max != 0.0) { 118 if (dl->offset != -1 && percent_max != 0.0) {
113 for (i = 0; i < ab->nr_events; i++) { 119 for (i = 0; i < ab->nr_events; i++) {
114 ui_browser__set_percent_color(browser, bdl->percent[i], 120 ui_browser__set_percent_color(browser,
121 bdl->samples[i].percent,
115 current_entry); 122 current_entry);
116 slsmg_printf("%6.2f ", bdl->percent[i]); 123 if (annotate_browser__opts.show_total_period)
124 slsmg_printf("%6" PRIu64 " ",
125 bdl->samples[i].nr);
126 else
127 slsmg_printf("%6.2f ", bdl->samples[i].percent);
117 } 128 }
118 } else { 129 } else {
119 ui_browser__set_percent_color(browser, 0, current_entry); 130 ui_browser__set_percent_color(browser, 0, current_entry);
@@ -273,9 +284,9 @@ static int disasm__cmp(struct browser_disasm_line *a,
273 int i; 284 int i;
274 285
275 for (i = 0; i < nr_pcnt; i++) { 286 for (i = 0; i < nr_pcnt; i++) {
276 if (a->percent[i] == b->percent[i]) 287 if (a->samples[i].percent == b->samples[i].percent)
277 continue; 288 continue;
278 return a->percent[i] < b->percent[i]; 289 return a->samples[i].percent < b->samples[i].percent;
279 } 290 }
280 return 0; 291 return 0;
281} 292}
@@ -366,14 +377,17 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
366 next = disasm__get_next_ip_line(&notes->src->source, pos); 377 next = disasm__get_next_ip_line(&notes->src->source, pos);
367 378
368 for (i = 0; i < browser->nr_events; i++) { 379 for (i = 0; i < browser->nr_events; i++) {
369 bpos->percent[i] = disasm__calc_percent(notes, 380 u64 nr_samples;
381
382 bpos->samples[i].percent = disasm__calc_percent(notes,
370 evsel->idx + i, 383 evsel->idx + i,
371 pos->offset, 384 pos->offset,
372 next ? next->offset : len, 385 next ? next->offset : len,
373 &path); 386 &path, &nr_samples);
387 bpos->samples[i].nr = nr_samples;
374 388
375 if (max_percent < bpos->percent[i]) 389 if (max_percent < bpos->samples[i].percent)
376 max_percent = bpos->percent[i]; 390 max_percent = bpos->samples[i].percent;
377 } 391 }
378 392
379 if (max_percent < 0.01) { 393 if (max_percent < 0.01) {
@@ -737,6 +751,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
737 "n Search next string\n" 751 "n Search next string\n"
738 "o Toggle disassembler output/simplified view\n" 752 "o Toggle disassembler output/simplified view\n"
739 "s Toggle source code view\n" 753 "s Toggle source code view\n"
754 "t Toggle total period view\n"
740 "/ Search string\n" 755 "/ Search string\n"
741 "k Toggle line numbers\n" 756 "k Toggle line numbers\n"
742 "r Run available scripts\n" 757 "r Run available scripts\n"
@@ -812,6 +827,11 @@ show_sup_ins:
812 ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions."); 827 ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions.");
813 } 828 }
814 continue; 829 continue;
830 case 't':
831 annotate_browser__opts.show_total_period =
832 !annotate_browser__opts.show_total_period;
833 annotate_browser__update_addr_width(browser);
834 continue;
815 case K_LEFT: 835 case K_LEFT:
816 case K_ESC: 836 case K_ESC:
817 case 'q': 837 case 'q':
@@ -832,12 +852,20 @@ out:
832int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 852int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
833 struct hist_browser_timer *hbt) 853 struct hist_browser_timer *hbt)
834{ 854{
855 /* Set default value for show_total_period. */
856 annotate_browser__opts.show_total_period =
857 symbol_conf.show_total_period;
858
835 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); 859 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt);
836} 860}
837 861
838int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 862int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
839 struct hist_browser_timer *hbt) 863 struct hist_browser_timer *hbt)
840{ 864{
865 /* reset abort key so that it can get Ctrl-C as a key */
866 SLang_reset_tty();
867 SLang_init_tty(0, 0, 0);
868
841 return map_symbol__tui_annotate(&he->ms, evsel, hbt); 869 return map_symbol__tui_annotate(&he->ms, evsel, hbt);
842} 870}
843 871
@@ -925,7 +953,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
925 953
926 if (perf_evsel__is_group_event(evsel)) { 954 if (perf_evsel__is_group_event(evsel)) {
927 nr_pcnt = evsel->nr_members; 955 nr_pcnt = evsel->nr_members;
928 sizeof_bdl += sizeof(double) * (nr_pcnt - 1); 956 sizeof_bdl += sizeof(struct disasm_line_samples) *
957 (nr_pcnt - 1);
929 } 958 }
930 959
931 if (symbol__annotate(sym, map, sizeof_bdl) < 0) { 960 if (symbol__annotate(sym, map, sizeof_bdl) < 0) {
@@ -1002,6 +1031,7 @@ static struct annotate_config {
1002 ANNOTATE_CFG(show_linenr), 1031 ANNOTATE_CFG(show_linenr),
1003 ANNOTATE_CFG(show_nr_jumps), 1032 ANNOTATE_CFG(show_nr_jumps),
1004 ANNOTATE_CFG(use_offset), 1033 ANNOTATE_CFG(use_offset),
1034 ANNOTATE_CFG(show_total_period),
1005}; 1035};
1006 1036
1007#undef ANNOTATE_CFG 1037#undef ANNOTATE_CFG
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 995b7a8596b1..c42adb600091 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -25,6 +25,9 @@ struct hist_browser {
25 struct hists *hists; 25 struct hists *hists;
26 struct hist_entry *he_selection; 26 struct hist_entry *he_selection;
27 struct map_symbol *selection; 27 struct map_symbol *selection;
28 struct hist_browser_timer *hbt;
29 struct pstack *pstack;
30 struct perf_session_env *env;
28 int print_seq; 31 int print_seq;
29 bool show_dso; 32 bool show_dso;
30 bool show_headers; 33 bool show_headers;
@@ -60,7 +63,7 @@ static int hist_browser__get_folding(struct hist_browser *browser)
60 struct hist_entry *he = 63 struct hist_entry *he =
61 rb_entry(nd, struct hist_entry, rb_node); 64 rb_entry(nd, struct hist_entry, rb_node);
62 65
63 if (he->ms.unfolded) 66 if (he->unfolded)
64 unfolded_rows += he->nr_rows; 67 unfolded_rows += he->nr_rows;
65 } 68 }
66 return unfolded_rows; 69 return unfolded_rows;
@@ -136,24 +139,19 @@ static char tree__folded_sign(bool unfolded)
136 return unfolded ? '-' : '+'; 139 return unfolded ? '-' : '+';
137} 140}
138 141
139static char map_symbol__folded(const struct map_symbol *ms)
140{
141 return ms->has_children ? tree__folded_sign(ms->unfolded) : ' ';
142}
143
144static char hist_entry__folded(const struct hist_entry *he) 142static char hist_entry__folded(const struct hist_entry *he)
145{ 143{
146 return map_symbol__folded(&he->ms); 144 return he->has_children ? tree__folded_sign(he->unfolded) : ' ';
147} 145}
148 146
149static char callchain_list__folded(const struct callchain_list *cl) 147static char callchain_list__folded(const struct callchain_list *cl)
150{ 148{
151 return map_symbol__folded(&cl->ms); 149 return cl->has_children ? tree__folded_sign(cl->unfolded) : ' ';
152} 150}
153 151
154static void map_symbol__set_folding(struct map_symbol *ms, bool unfold) 152static void callchain_list__set_folding(struct callchain_list *cl, bool unfold)
155{ 153{
156 ms->unfolded = unfold ? ms->has_children : false; 154 cl->unfolded = unfold ? cl->has_children : false;
157} 155}
158 156
159static int callchain_node__count_rows_rb_tree(struct callchain_node *node) 157static int callchain_node__count_rows_rb_tree(struct callchain_node *node)
@@ -189,7 +187,7 @@ static int callchain_node__count_rows(struct callchain_node *node)
189 187
190 list_for_each_entry(chain, &node->val, list) { 188 list_for_each_entry(chain, &node->val, list) {
191 ++n; 189 ++n;
192 unfolded = chain->ms.unfolded; 190 unfolded = chain->unfolded;
193 } 191 }
194 192
195 if (unfolded) 193 if (unfolded)
@@ -211,15 +209,27 @@ static int callchain__count_rows(struct rb_root *chain)
211 return n; 209 return n;
212} 210}
213 211
214static bool map_symbol__toggle_fold(struct map_symbol *ms) 212static bool hist_entry__toggle_fold(struct hist_entry *he)
215{ 213{
216 if (!ms) 214 if (!he)
217 return false; 215 return false;
218 216
219 if (!ms->has_children) 217 if (!he->has_children)
220 return false; 218 return false;
221 219
222 ms->unfolded = !ms->unfolded; 220 he->unfolded = !he->unfolded;
221 return true;
222}
223
224static bool callchain_list__toggle_fold(struct callchain_list *cl)
225{
226 if (!cl)
227 return false;
228
229 if (!cl->has_children)
230 return false;
231
232 cl->unfolded = !cl->unfolded;
223 return true; 233 return true;
224} 234}
225 235
@@ -235,10 +245,10 @@ static void callchain_node__init_have_children_rb_tree(struct callchain_node *no
235 list_for_each_entry(chain, &child->val, list) { 245 list_for_each_entry(chain, &child->val, list) {
236 if (first) { 246 if (first) {
237 first = false; 247 first = false;
238 chain->ms.has_children = chain->list.next != &child->val || 248 chain->has_children = chain->list.next != &child->val ||
239 !RB_EMPTY_ROOT(&child->rb_root); 249 !RB_EMPTY_ROOT(&child->rb_root);
240 } else 250 } else
241 chain->ms.has_children = chain->list.next == &child->val && 251 chain->has_children = chain->list.next == &child->val &&
242 !RB_EMPTY_ROOT(&child->rb_root); 252 !RB_EMPTY_ROOT(&child->rb_root);
243 } 253 }
244 254
@@ -252,11 +262,11 @@ static void callchain_node__init_have_children(struct callchain_node *node,
252 struct callchain_list *chain; 262 struct callchain_list *chain;
253 263
254 chain = list_entry(node->val.next, struct callchain_list, list); 264 chain = list_entry(node->val.next, struct callchain_list, list);
255 chain->ms.has_children = has_sibling; 265 chain->has_children = has_sibling;
256 266
257 if (!list_empty(&node->val)) { 267 if (!list_empty(&node->val)) {
258 chain = list_entry(node->val.prev, struct callchain_list, list); 268 chain = list_entry(node->val.prev, struct callchain_list, list);
259 chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root); 269 chain->has_children = !RB_EMPTY_ROOT(&node->rb_root);
260 } 270 }
261 271
262 callchain_node__init_have_children_rb_tree(node); 272 callchain_node__init_have_children_rb_tree(node);
@@ -276,7 +286,7 @@ static void callchain__init_have_children(struct rb_root *root)
276static void hist_entry__init_have_children(struct hist_entry *he) 286static void hist_entry__init_have_children(struct hist_entry *he)
277{ 287{
278 if (!he->init_have_children) { 288 if (!he->init_have_children) {
279 he->ms.has_children = !RB_EMPTY_ROOT(&he->sorted_chain); 289 he->has_children = !RB_EMPTY_ROOT(&he->sorted_chain);
280 callchain__init_have_children(&he->sorted_chain); 290 callchain__init_have_children(&he->sorted_chain);
281 he->init_have_children = true; 291 he->init_have_children = true;
282 } 292 }
@@ -284,14 +294,22 @@ static void hist_entry__init_have_children(struct hist_entry *he)
284 294
285static bool hist_browser__toggle_fold(struct hist_browser *browser) 295static bool hist_browser__toggle_fold(struct hist_browser *browser)
286{ 296{
287 if (map_symbol__toggle_fold(browser->selection)) { 297 struct hist_entry *he = browser->he_selection;
288 struct hist_entry *he = browser->he_selection; 298 struct map_symbol *ms = browser->selection;
299 struct callchain_list *cl = container_of(ms, struct callchain_list, ms);
300 bool has_children;
289 301
302 if (ms == &he->ms)
303 has_children = hist_entry__toggle_fold(he);
304 else
305 has_children = callchain_list__toggle_fold(cl);
306
307 if (has_children) {
290 hist_entry__init_have_children(he); 308 hist_entry__init_have_children(he);
291 browser->b.nr_entries -= he->nr_rows; 309 browser->b.nr_entries -= he->nr_rows;
292 browser->nr_callchain_rows -= he->nr_rows; 310 browser->nr_callchain_rows -= he->nr_rows;
293 311
294 if (he->ms.unfolded) 312 if (he->unfolded)
295 he->nr_rows = callchain__count_rows(&he->sorted_chain); 313 he->nr_rows = callchain__count_rows(&he->sorted_chain);
296 else 314 else
297 he->nr_rows = 0; 315 he->nr_rows = 0;
@@ -318,8 +336,8 @@ static int callchain_node__set_folding_rb_tree(struct callchain_node *node, bool
318 336
319 list_for_each_entry(chain, &child->val, list) { 337 list_for_each_entry(chain, &child->val, list) {
320 ++n; 338 ++n;
321 map_symbol__set_folding(&chain->ms, unfold); 339 callchain_list__set_folding(chain, unfold);
322 has_children = chain->ms.has_children; 340 has_children = chain->has_children;
323 } 341 }
324 342
325 if (has_children) 343 if (has_children)
@@ -337,8 +355,8 @@ static int callchain_node__set_folding(struct callchain_node *node, bool unfold)
337 355
338 list_for_each_entry(chain, &node->val, list) { 356 list_for_each_entry(chain, &node->val, list) {
339 ++n; 357 ++n;
340 map_symbol__set_folding(&chain->ms, unfold); 358 callchain_list__set_folding(chain, unfold);
341 has_children = chain->ms.has_children; 359 has_children = chain->has_children;
342 } 360 }
343 361
344 if (has_children) 362 if (has_children)
@@ -363,9 +381,9 @@ static int callchain__set_folding(struct rb_root *chain, bool unfold)
363static void hist_entry__set_folding(struct hist_entry *he, bool unfold) 381static void hist_entry__set_folding(struct hist_entry *he, bool unfold)
364{ 382{
365 hist_entry__init_have_children(he); 383 hist_entry__init_have_children(he);
366 map_symbol__set_folding(&he->ms, unfold); 384 he->unfolded = unfold ? he->has_children : false;
367 385
368 if (he->ms.has_children) { 386 if (he->has_children) {
369 int n = callchain__set_folding(&he->sorted_chain, unfold); 387 int n = callchain__set_folding(&he->sorted_chain, unfold);
370 he->nr_rows = unfold ? n : 0; 388 he->nr_rows = unfold ? n : 0;
371 } else 389 } else
@@ -406,11 +424,11 @@ static void ui_browser__warn_lost_events(struct ui_browser *browser)
406 "Or reduce the sampling frequency."); 424 "Or reduce the sampling frequency.");
407} 425}
408 426
409static int hist_browser__run(struct hist_browser *browser, 427static int hist_browser__run(struct hist_browser *browser, const char *help)
410 struct hist_browser_timer *hbt)
411{ 428{
412 int key; 429 int key;
413 char title[160]; 430 char title[160];
431 struct hist_browser_timer *hbt = browser->hbt;
414 int delay_secs = hbt ? hbt->refresh : 0; 432 int delay_secs = hbt ? hbt->refresh : 0;
415 433
416 browser->b.entries = &browser->hists->entries; 434 browser->b.entries = &browser->hists->entries;
@@ -418,8 +436,7 @@ static int hist_browser__run(struct hist_browser *browser,
418 436
419 hists__browser_title(browser->hists, hbt, title, sizeof(title)); 437 hists__browser_title(browser->hists, hbt, title, sizeof(title));
420 438
421 if (ui_browser__show(&browser->b, title, 439 if (ui_browser__show(&browser->b, title, help) < 0)
422 "Press '?' for help on key bindings") < 0)
423 return -1; 440 return -1;
424 441
425 while (1) { 442 while (1) {
@@ -1016,7 +1033,7 @@ do_offset:
1016 if (offset > 0) { 1033 if (offset > 0) {
1017 do { 1034 do {
1018 h = rb_entry(nd, struct hist_entry, rb_node); 1035 h = rb_entry(nd, struct hist_entry, rb_node);
1019 if (h->ms.unfolded) { 1036 if (h->unfolded) {
1020 u16 remaining = h->nr_rows - h->row_offset; 1037 u16 remaining = h->nr_rows - h->row_offset;
1021 if (offset > remaining) { 1038 if (offset > remaining) {
1022 offset -= remaining; 1039 offset -= remaining;
@@ -1037,7 +1054,7 @@ do_offset:
1037 } else if (offset < 0) { 1054 } else if (offset < 0) {
1038 while (1) { 1055 while (1) {
1039 h = rb_entry(nd, struct hist_entry, rb_node); 1056 h = rb_entry(nd, struct hist_entry, rb_node);
1040 if (h->ms.unfolded) { 1057 if (h->unfolded) {
1041 if (first) { 1058 if (first) {
1042 if (-offset > h->row_offset) { 1059 if (-offset > h->row_offset) {
1043 offset += h->row_offset; 1060 offset += h->row_offset;
@@ -1074,7 +1091,7 @@ do_offset:
1074 * row_offset at its last entry. 1091 * row_offset at its last entry.
1075 */ 1092 */
1076 h = rb_entry(nd, struct hist_entry, rb_node); 1093 h = rb_entry(nd, struct hist_entry, rb_node);
1077 if (h->ms.unfolded) 1094 if (h->unfolded)
1078 h->row_offset = h->nr_rows; 1095 h->row_offset = h->nr_rows;
1079 break; 1096 break;
1080 } 1097 }
@@ -1195,7 +1212,9 @@ static int hist_browser__dump(struct hist_browser *browser)
1195 return 0; 1212 return 0;
1196} 1213}
1197 1214
1198static struct hist_browser *hist_browser__new(struct hists *hists) 1215static struct hist_browser *hist_browser__new(struct hists *hists,
1216 struct hist_browser_timer *hbt,
1217 struct perf_session_env *env)
1199{ 1218{
1200 struct hist_browser *browser = zalloc(sizeof(*browser)); 1219 struct hist_browser *browser = zalloc(sizeof(*browser));
1201 1220
@@ -1206,6 +1225,8 @@ static struct hist_browser *hist_browser__new(struct hists *hists)
1206 browser->b.seek = ui_browser__hists_seek; 1225 browser->b.seek = ui_browser__hists_seek;
1207 browser->b.use_navkeypressed = true; 1226 browser->b.use_navkeypressed = true;
1208 browser->show_headers = symbol_conf.show_hist_headers; 1227 browser->show_headers = symbol_conf.show_hist_headers;
1228 browser->hbt = hbt;
1229 browser->env = env;
1209 } 1230 }
1210 1231
1211 return browser; 1232 return browser;
@@ -1395,6 +1416,257 @@ close_file_and_continue:
1395 return ret; 1416 return ret;
1396} 1417}
1397 1418
1419struct popup_action {
1420 struct thread *thread;
1421 struct dso *dso;
1422 struct map_symbol ms;
1423
1424 int (*fn)(struct hist_browser *browser, struct popup_action *act);
1425};
1426
1427static int
1428do_annotate(struct hist_browser *browser, struct popup_action *act)
1429{
1430 struct perf_evsel *evsel;
1431 struct annotation *notes;
1432 struct hist_entry *he;
1433 int err;
1434
1435 if (!objdump_path && perf_session_env__lookup_objdump(browser->env))
1436 return 0;
1437
1438 notes = symbol__annotation(act->ms.sym);
1439 if (!notes->src)
1440 return 0;
1441
1442 evsel = hists_to_evsel(browser->hists);
1443 err = map_symbol__tui_annotate(&act->ms, evsel, browser->hbt);
1444 he = hist_browser__selected_entry(browser);
1445 /*
1446 * offer option to annotate the other branch source or target
1447 * (if they exists) when returning from annotate
1448 */
1449 if ((err == 'q' || err == CTRL('c')) && he->branch_info)
1450 return 1;
1451
1452 ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);
1453 if (err)
1454 ui_browser__handle_resize(&browser->b);
1455 return 0;
1456}
1457
1458static int
1459add_annotate_opt(struct hist_browser *browser __maybe_unused,
1460 struct popup_action *act, char **optstr,
1461 struct map *map, struct symbol *sym)
1462{
1463 if (sym == NULL || map->dso->annotate_warned)
1464 return 0;
1465
1466 if (asprintf(optstr, "Annotate %s", sym->name) < 0)
1467 return 0;
1468
1469 act->ms.map = map;
1470 act->ms.sym = sym;
1471 act->fn = do_annotate;
1472 return 1;
1473}
1474
1475static int
1476do_zoom_thread(struct hist_browser *browser, struct popup_action *act)
1477{
1478 struct thread *thread = act->thread;
1479
1480 if (browser->hists->thread_filter) {
1481 pstack__remove(browser->pstack, &browser->hists->thread_filter);
1482 perf_hpp__set_elide(HISTC_THREAD, false);
1483 thread__zput(browser->hists->thread_filter);
1484 ui_helpline__pop();
1485 } else {
1486 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
1487 thread->comm_set ? thread__comm_str(thread) : "",
1488 thread->tid);
1489 browser->hists->thread_filter = thread__get(thread);
1490 perf_hpp__set_elide(HISTC_THREAD, false);
1491 pstack__push(browser->pstack, &browser->hists->thread_filter);
1492 }
1493
1494 hists__filter_by_thread(browser->hists);
1495 hist_browser__reset(browser);
1496 return 0;
1497}
1498
1499static int
1500add_thread_opt(struct hist_browser *browser, struct popup_action *act,
1501 char **optstr, struct thread *thread)
1502{
1503 if (thread == NULL)
1504 return 0;
1505
1506 if (asprintf(optstr, "Zoom %s %s(%d) thread",
1507 browser->hists->thread_filter ? "out of" : "into",
1508 thread->comm_set ? thread__comm_str(thread) : "",
1509 thread->tid) < 0)
1510 return 0;
1511
1512 act->thread = thread;
1513 act->fn = do_zoom_thread;
1514 return 1;
1515}
1516
1517static int
1518do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
1519{
1520 struct dso *dso = act->dso;
1521
1522 if (browser->hists->dso_filter) {
1523 pstack__remove(browser->pstack, &browser->hists->dso_filter);
1524 perf_hpp__set_elide(HISTC_DSO, false);
1525 browser->hists->dso_filter = NULL;
1526 ui_helpline__pop();
1527 } else {
1528 if (dso == NULL)
1529 return 0;
1530 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"",
1531 dso->kernel ? "the Kernel" : dso->short_name);
1532 browser->hists->dso_filter = dso;
1533 perf_hpp__set_elide(HISTC_DSO, true);
1534 pstack__push(browser->pstack, &browser->hists->dso_filter);
1535 }
1536
1537 hists__filter_by_dso(browser->hists);
1538 hist_browser__reset(browser);
1539 return 0;
1540}
1541
1542static int
1543add_dso_opt(struct hist_browser *browser, struct popup_action *act,
1544 char **optstr, struct dso *dso)
1545{
1546 if (dso == NULL)
1547 return 0;
1548
1549 if (asprintf(optstr, "Zoom %s %s DSO",
1550 browser->hists->dso_filter ? "out of" : "into",
1551 dso->kernel ? "the Kernel" : dso->short_name) < 0)
1552 return 0;
1553
1554 act->dso = dso;
1555 act->fn = do_zoom_dso;
1556 return 1;
1557}
1558
1559static int
1560do_browse_map(struct hist_browser *browser __maybe_unused,
1561 struct popup_action *act)
1562{
1563 map__browse(act->ms.map);
1564 return 0;
1565}
1566
1567static int
1568add_map_opt(struct hist_browser *browser __maybe_unused,
1569 struct popup_action *act, char **optstr, struct map *map)
1570{
1571 if (map == NULL)
1572 return 0;
1573
1574 if (asprintf(optstr, "Browse map details") < 0)
1575 return 0;
1576
1577 act->ms.map = map;
1578 act->fn = do_browse_map;
1579 return 1;
1580}
1581
1582static int
1583do_run_script(struct hist_browser *browser __maybe_unused,
1584 struct popup_action *act)
1585{
1586 char script_opt[64];
1587 memset(script_opt, 0, sizeof(script_opt));
1588
1589 if (act->thread) {
1590 scnprintf(script_opt, sizeof(script_opt), " -c %s ",
1591 thread__comm_str(act->thread));
1592 } else if (act->ms.sym) {
1593 scnprintf(script_opt, sizeof(script_opt), " -S %s ",
1594 act->ms.sym->name);
1595 }
1596
1597 script_browse(script_opt);
1598 return 0;
1599}
1600
1601static int
1602add_script_opt(struct hist_browser *browser __maybe_unused,
1603 struct popup_action *act, char **optstr,
1604 struct thread *thread, struct symbol *sym)
1605{
1606 if (thread) {
1607 if (asprintf(optstr, "Run scripts for samples of thread [%s]",
1608 thread__comm_str(thread)) < 0)
1609 return 0;
1610 } else if (sym) {
1611 if (asprintf(optstr, "Run scripts for samples of symbol [%s]",
1612 sym->name) < 0)
1613 return 0;
1614 } else {
1615 if (asprintf(optstr, "Run scripts for all samples") < 0)
1616 return 0;
1617 }
1618
1619 act->thread = thread;
1620 act->ms.sym = sym;
1621 act->fn = do_run_script;
1622 return 1;
1623}
1624
1625static int
1626do_switch_data(struct hist_browser *browser __maybe_unused,
1627 struct popup_action *act __maybe_unused)
1628{
1629 if (switch_data_file()) {
1630 ui__warning("Won't switch the data files due to\n"
1631 "no valid data file get selected!\n");
1632 return 0;
1633 }
1634
1635 return K_SWITCH_INPUT_DATA;
1636}
1637
1638static int
1639add_switch_opt(struct hist_browser *browser,
1640 struct popup_action *act, char **optstr)
1641{
1642 if (!is_report_browser(browser->hbt))
1643 return 0;
1644
1645 if (asprintf(optstr, "Switch to another data file in PWD") < 0)
1646 return 0;
1647
1648 act->fn = do_switch_data;
1649 return 1;
1650}
1651
1652static int
1653do_exit_browser(struct hist_browser *browser __maybe_unused,
1654 struct popup_action *act __maybe_unused)
1655{
1656 return 0;
1657}
1658
1659static int
1660add_exit_opt(struct hist_browser *browser __maybe_unused,
1661 struct popup_action *act, char **optstr)
1662{
1663 if (asprintf(optstr, "Exit") < 0)
1664 return 0;
1665
1666 act->fn = do_exit_browser;
1667 return 1;
1668}
1669
1398static void hist_browser__update_nr_entries(struct hist_browser *hb) 1670static void hist_browser__update_nr_entries(struct hist_browser *hb)
1399{ 1671{
1400 u64 nr_entries = 0; 1672 u64 nr_entries = 0;
@@ -1421,14 +1693,14 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1421 struct perf_session_env *env) 1693 struct perf_session_env *env)
1422{ 1694{
1423 struct hists *hists = evsel__hists(evsel); 1695 struct hists *hists = evsel__hists(evsel);
1424 struct hist_browser *browser = hist_browser__new(hists); 1696 struct hist_browser *browser = hist_browser__new(hists, hbt, env);
1425 struct branch_info *bi; 1697 struct branch_info *bi;
1426 struct pstack *fstack; 1698#define MAX_OPTIONS 16
1427 char *options[16]; 1699 char *options[MAX_OPTIONS];
1700 struct popup_action actions[MAX_OPTIONS];
1428 int nr_options = 0; 1701 int nr_options = 0;
1429 int key = -1; 1702 int key = -1;
1430 char buf[64]; 1703 char buf[64];
1431 char script_opt[64];
1432 int delay_secs = hbt ? hbt->refresh : 0; 1704 int delay_secs = hbt ? hbt->refresh : 0;
1433 struct perf_hpp_fmt *fmt; 1705 struct perf_hpp_fmt *fmt;
1434 1706
@@ -1463,23 +1735,29 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1463 "t Zoom into current Thread\n" 1735 "t Zoom into current Thread\n"
1464 "V Verbose (DSO names in callchains, etc)\n" 1736 "V Verbose (DSO names in callchains, etc)\n"
1465 "z Toggle zeroing of samples\n" 1737 "z Toggle zeroing of samples\n"
1738 "f Enable/Disable events\n"
1466 "/ Filter symbol by name"; 1739 "/ Filter symbol by name";
1467 1740
1468 if (browser == NULL) 1741 if (browser == NULL)
1469 return -1; 1742 return -1;
1470 1743
1744 /* reset abort key so that it can get Ctrl-C as a key */
1745 SLang_reset_tty();
1746 SLang_init_tty(0, 0, 0);
1747
1471 if (min_pcnt) { 1748 if (min_pcnt) {
1472 browser->min_pcnt = min_pcnt; 1749 browser->min_pcnt = min_pcnt;
1473 hist_browser__update_nr_entries(browser); 1750 hist_browser__update_nr_entries(browser);
1474 } 1751 }
1475 1752
1476 fstack = pstack__new(2); 1753 browser->pstack = pstack__new(2);
1477 if (fstack == NULL) 1754 if (browser->pstack == NULL)
1478 goto out; 1755 goto out;
1479 1756
1480 ui_helpline__push(helpline); 1757 ui_helpline__push(helpline);
1481 1758
1482 memset(options, 0, sizeof(options)); 1759 memset(options, 0, sizeof(options));
1760 memset(actions, 0, sizeof(actions));
1483 1761
1484 perf_hpp__for_each_format(fmt) 1762 perf_hpp__for_each_format(fmt)
1485 perf_hpp__reset_width(fmt, hists); 1763 perf_hpp__reset_width(fmt, hists);
@@ -1489,16 +1767,12 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1489 1767
1490 while (1) { 1768 while (1) {
1491 struct thread *thread = NULL; 1769 struct thread *thread = NULL;
1492 const struct dso *dso = NULL; 1770 struct dso *dso = NULL;
1493 int choice = 0, 1771 int choice = 0;
1494 annotate = -2, zoom_dso = -2, zoom_thread = -2,
1495 annotate_f = -2, annotate_t = -2, browse_map = -2;
1496 int scripts_comm = -2, scripts_symbol = -2,
1497 scripts_all = -2, switch_data = -2;
1498 1772
1499 nr_options = 0; 1773 nr_options = 0;
1500 1774
1501 key = hist_browser__run(browser, hbt); 1775 key = hist_browser__run(browser, helpline);
1502 1776
1503 if (browser->he_selection != NULL) { 1777 if (browser->he_selection != NULL) {
1504 thread = hist_browser__selected_thread(browser); 1778 thread = hist_browser__selected_thread(browser);
@@ -1526,17 +1800,25 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1526 browser->selection->sym == NULL || 1800 browser->selection->sym == NULL ||
1527 browser->selection->map->dso->annotate_warned) 1801 browser->selection->map->dso->annotate_warned)
1528 continue; 1802 continue;
1529 goto do_annotate; 1803
1804 actions->ms.map = browser->selection->map;
1805 actions->ms.sym = browser->selection->sym;
1806 do_annotate(browser, actions);
1807 continue;
1530 case 'P': 1808 case 'P':
1531 hist_browser__dump(browser); 1809 hist_browser__dump(browser);
1532 continue; 1810 continue;
1533 case 'd': 1811 case 'd':
1534 goto zoom_dso; 1812 actions->dso = dso;
1813 do_zoom_dso(browser, actions);
1814 continue;
1535 case 'V': 1815 case 'V':
1536 browser->show_dso = !browser->show_dso; 1816 browser->show_dso = !browser->show_dso;
1537 continue; 1817 continue;
1538 case 't': 1818 case 't':
1539 goto zoom_thread; 1819 actions->thread = thread;
1820 do_zoom_thread(browser, actions);
1821 continue;
1540 case '/': 1822 case '/':
1541 if (ui_browser__input_window("Symbol to show", 1823 if (ui_browser__input_window("Symbol to show",
1542 "Please enter the name of symbol you want to see", 1824 "Please enter the name of symbol you want to see",
@@ -1548,12 +1830,18 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1548 } 1830 }
1549 continue; 1831 continue;
1550 case 'r': 1832 case 'r':
1551 if (is_report_browser(hbt)) 1833 if (is_report_browser(hbt)) {
1552 goto do_scripts; 1834 actions->thread = NULL;
1835 actions->ms.sym = NULL;
1836 do_run_script(browser, actions);
1837 }
1553 continue; 1838 continue;
1554 case 's': 1839 case 's':
1555 if (is_report_browser(hbt)) 1840 if (is_report_browser(hbt)) {
1556 goto do_data_switch; 1841 key = do_switch_data(browser, actions);
1842 if (key == K_SWITCH_INPUT_DATA)
1843 goto out_free_stack;
1844 }
1557 continue; 1845 continue;
1558 case 'i': 1846 case 'i':
1559 /* env->arch is NULL for live-mode (i.e. perf top) */ 1847 /* env->arch is NULL for live-mode (i.e. perf top) */
@@ -1583,7 +1871,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1583 case K_LEFT: { 1871 case K_LEFT: {
1584 const void *top; 1872 const void *top;
1585 1873
1586 if (pstack__empty(fstack)) { 1874 if (pstack__empty(browser->pstack)) {
1587 /* 1875 /*
1588 * Go back to the perf_evsel_menu__run or other user 1876 * Go back to the perf_evsel_menu__run or other user
1589 */ 1877 */
@@ -1591,11 +1879,17 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1591 goto out_free_stack; 1879 goto out_free_stack;
1592 continue; 1880 continue;
1593 } 1881 }
1594 top = pstack__pop(fstack); 1882 top = pstack__peek(browser->pstack);
1595 if (top == &browser->hists->dso_filter) 1883 if (top == &browser->hists->dso_filter) {
1596 goto zoom_out_dso; 1884 /*
1885 * No need to set actions->dso here since
1886 * it's just to remove the current filter.
1887 * Ditto for thread below.
1888 */
1889 do_zoom_dso(browser, actions);
1890 }
1597 if (top == &browser->hists->thread_filter) 1891 if (top == &browser->hists->thread_filter)
1598 goto zoom_out_thread; 1892 do_zoom_thread(browser, actions);
1599 continue; 1893 continue;
1600 } 1894 }
1601 case K_ESC: 1895 case K_ESC:
@@ -1607,7 +1901,12 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1607 case 'q': 1901 case 'q':
1608 case CTRL('c'): 1902 case CTRL('c'):
1609 goto out_free_stack; 1903 goto out_free_stack;
1904 case 'f':
1905 if (!is_report_browser(hbt))
1906 goto out_free_stack;
1907 /* Fall thru */
1610 default: 1908 default:
1909 helpline = "Press '?' for help on key bindings";
1611 continue; 1910 continue;
1612 } 1911 }
1613 1912
@@ -1623,196 +1922,71 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1623 if (bi == NULL) 1922 if (bi == NULL)
1624 goto skip_annotation; 1923 goto skip_annotation;
1625 1924
1626 if (bi->from.sym != NULL && 1925 nr_options += add_annotate_opt(browser,
1627 !bi->from.map->dso->annotate_warned && 1926 &actions[nr_options],
1628 asprintf(&options[nr_options], "Annotate %s", bi->from.sym->name) > 0) { 1927 &options[nr_options],
1629 annotate_f = nr_options++; 1928 bi->from.map,
1630 } 1929 bi->from.sym);
1631 1930 if (bi->to.sym != bi->from.sym)
1632 if (bi->to.sym != NULL && 1931 nr_options += add_annotate_opt(browser,
1633 !bi->to.map->dso->annotate_warned && 1932 &actions[nr_options],
1634 (bi->to.sym != bi->from.sym || 1933 &options[nr_options],
1635 bi->to.map->dso != bi->from.map->dso) && 1934 bi->to.map,
1636 asprintf(&options[nr_options], "Annotate %s", bi->to.sym->name) > 0) { 1935 bi->to.sym);
1637 annotate_t = nr_options++;
1638 }
1639 } else { 1936 } else {
1640 if (browser->selection->sym != NULL && 1937 nr_options += add_annotate_opt(browser,
1641 !browser->selection->map->dso->annotate_warned) { 1938 &actions[nr_options],
1642 struct annotation *notes; 1939 &options[nr_options],
1643 1940 browser->selection->map,
1644 notes = symbol__annotation(browser->selection->sym); 1941 browser->selection->sym);
1645
1646 if (notes->src &&
1647 asprintf(&options[nr_options], "Annotate %s",
1648 browser->selection->sym->name) > 0) {
1649 annotate = nr_options++;
1650 }
1651 }
1652 } 1942 }
1653skip_annotation: 1943skip_annotation:
1654 if (thread != NULL && 1944 nr_options += add_thread_opt(browser, &actions[nr_options],
1655 asprintf(&options[nr_options], "Zoom %s %s(%d) thread", 1945 &options[nr_options], thread);
1656 (browser->hists->thread_filter ? "out of" : "into"), 1946 nr_options += add_dso_opt(browser, &actions[nr_options],
1657 (thread->comm_set ? thread__comm_str(thread) : ""), 1947 &options[nr_options], dso);
1658 thread->tid) > 0) 1948 nr_options += add_map_opt(browser, &actions[nr_options],
1659 zoom_thread = nr_options++; 1949 &options[nr_options],
1660 1950 browser->selection->map);
1661 if (dso != NULL &&
1662 asprintf(&options[nr_options], "Zoom %s %s DSO",
1663 (browser->hists->dso_filter ? "out of" : "into"),
1664 (dso->kernel ? "the Kernel" : dso->short_name)) > 0)
1665 zoom_dso = nr_options++;
1666
1667 if (browser->selection != NULL &&
1668 browser->selection->map != NULL &&
1669 asprintf(&options[nr_options], "Browse map details") > 0)
1670 browse_map = nr_options++;
1671 1951
1672 /* perf script support */ 1952 /* perf script support */
1673 if (browser->he_selection) { 1953 if (browser->he_selection) {
1674 struct symbol *sym; 1954 nr_options += add_script_opt(browser,
1675 1955 &actions[nr_options],
1676 if (asprintf(&options[nr_options], "Run scripts for samples of thread [%s]", 1956 &options[nr_options],
1677 thread__comm_str(browser->he_selection->thread)) > 0) 1957 thread, NULL);
1678 scripts_comm = nr_options++; 1958 nr_options += add_script_opt(browser,
1679 1959 &actions[nr_options],
1680 sym = browser->he_selection->ms.sym; 1960 &options[nr_options],
1681 if (sym && sym->namelen && 1961 NULL, browser->selection->sym);
1682 asprintf(&options[nr_options], "Run scripts for samples of symbol [%s]",
1683 sym->name) > 0)
1684 scripts_symbol = nr_options++;
1685 } 1962 }
1686 1963 nr_options += add_script_opt(browser, &actions[nr_options],
1687 if (asprintf(&options[nr_options], "Run scripts for all samples") > 0) 1964 &options[nr_options], NULL, NULL);
1688 scripts_all = nr_options++; 1965 nr_options += add_switch_opt(browser, &actions[nr_options],
1689 1966 &options[nr_options]);
1690 if (is_report_browser(hbt) && asprintf(&options[nr_options],
1691 "Switch to another data file in PWD") > 0)
1692 switch_data = nr_options++;
1693add_exit_option: 1967add_exit_option:
1694 options[nr_options++] = (char *)"Exit"; 1968 nr_options += add_exit_opt(browser, &actions[nr_options],
1695retry_popup_menu: 1969 &options[nr_options]);
1696 choice = ui__popup_menu(nr_options, options);
1697
1698 if (choice == nr_options - 1)
1699 break;
1700
1701 if (choice == -1) {
1702 free_popup_options(options, nr_options - 1);
1703 continue;
1704 }
1705
1706 if (choice == annotate || choice == annotate_t || choice == annotate_f) {
1707 struct hist_entry *he;
1708 struct annotation *notes;
1709 struct map_symbol ms;
1710 int err;
1711do_annotate:
1712 if (!objdump_path && perf_session_env__lookup_objdump(env))
1713 continue;
1714
1715 he = hist_browser__selected_entry(browser);
1716 if (he == NULL)
1717 continue;
1718
1719 if (choice == annotate_f) {
1720 ms.map = he->branch_info->from.map;
1721 ms.sym = he->branch_info->from.sym;
1722 } else if (choice == annotate_t) {
1723 ms.map = he->branch_info->to.map;
1724 ms.sym = he->branch_info->to.sym;
1725 } else {
1726 ms = *browser->selection;
1727 }
1728 1970
1729 notes = symbol__annotation(ms.sym); 1971 do {
1730 if (!notes->src) 1972 struct popup_action *act;
1731 continue;
1732
1733 err = map_symbol__tui_annotate(&ms, evsel, hbt);
1734 /*
1735 * offer option to annotate the other branch source or target
1736 * (if they exists) when returning from annotate
1737 */
1738 if ((err == 'q' || err == CTRL('c'))
1739 && annotate_t != -2 && annotate_f != -2)
1740 goto retry_popup_menu;
1741
1742 ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);
1743 if (err)
1744 ui_browser__handle_resize(&browser->b);
1745
1746 } else if (choice == browse_map)
1747 map__browse(browser->selection->map);
1748 else if (choice == zoom_dso) {
1749zoom_dso:
1750 if (browser->hists->dso_filter) {
1751 pstack__remove(fstack, &browser->hists->dso_filter);
1752zoom_out_dso:
1753 ui_helpline__pop();
1754 browser->hists->dso_filter = NULL;
1755 perf_hpp__set_elide(HISTC_DSO, false);
1756 } else {
1757 if (dso == NULL)
1758 continue;
1759 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"",
1760 dso->kernel ? "the Kernel" : dso->short_name);
1761 browser->hists->dso_filter = dso;
1762 perf_hpp__set_elide(HISTC_DSO, true);
1763 pstack__push(fstack, &browser->hists->dso_filter);
1764 }
1765 hists__filter_by_dso(hists);
1766 hist_browser__reset(browser);
1767 } else if (choice == zoom_thread) {
1768zoom_thread:
1769 if (browser->hists->thread_filter) {
1770 pstack__remove(fstack, &browser->hists->thread_filter);
1771zoom_out_thread:
1772 ui_helpline__pop();
1773 thread__zput(browser->hists->thread_filter);
1774 perf_hpp__set_elide(HISTC_THREAD, false);
1775 } else {
1776 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
1777 thread->comm_set ? thread__comm_str(thread) : "",
1778 thread->tid);
1779 browser->hists->thread_filter = thread__get(thread);
1780 perf_hpp__set_elide(HISTC_THREAD, false);
1781 pstack__push(fstack, &browser->hists->thread_filter);
1782 }
1783 hists__filter_by_thread(hists);
1784 hist_browser__reset(browser);
1785 }
1786 /* perf scripts support */
1787 else if (choice == scripts_all || choice == scripts_comm ||
1788 choice == scripts_symbol) {
1789do_scripts:
1790 memset(script_opt, 0, 64);
1791 1973
1792 if (choice == scripts_comm) 1974 choice = ui__popup_menu(nr_options, options);
1793 sprintf(script_opt, " -c %s ", thread__comm_str(browser->he_selection->thread)); 1975 if (choice == -1 || choice >= nr_options)
1976 break;
1794 1977
1795 if (choice == scripts_symbol) 1978 act = &actions[choice];
1796 sprintf(script_opt, " -S %s ", browser->he_selection->ms.sym->name); 1979 key = act->fn(browser, act);
1980 } while (key == 1);
1797 1981
1798 script_browse(script_opt); 1982 if (key == K_SWITCH_INPUT_DATA)
1799 } 1983 break;
1800 /* Switch to another data file */
1801 else if (choice == switch_data) {
1802do_data_switch:
1803 if (!switch_data_file()) {
1804 key = K_SWITCH_INPUT_DATA;
1805 break;
1806 } else
1807 ui__warning("Won't switch the data files due to\n"
1808 "no valid data file get selected!\n");
1809 }
1810 } 1984 }
1811out_free_stack: 1985out_free_stack:
1812 pstack__delete(fstack); 1986 pstack__delete(browser->pstack);
1813out: 1987out:
1814 hist_browser__delete(browser); 1988 hist_browser__delete(browser);
1815 free_popup_options(options, nr_options - 1); 1989 free_popup_options(options, MAX_OPTIONS);
1816 return key; 1990 return key;
1817} 1991}
1818 1992
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index b77e1d771363..60d1f29b4b50 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -129,7 +129,7 @@ int ui__init(void)
129 err = SLsmg_init_smg(); 129 err = SLsmg_init_smg();
130 if (err < 0) 130 if (err < 0)
131 goto out; 131 goto out;
132 err = SLang_init_tty(0, 0, 0); 132 err = SLang_init_tty(-1, 0, 0);
133 if (err < 0) 133 if (err < 0)
134 goto out; 134 goto out;
135 135
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 797490a40075..586a59d46022 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -68,12 +68,15 @@ libperf-y += rblist.o
68libperf-y += intlist.o 68libperf-y += intlist.o
69libperf-y += vdso.o 69libperf-y += vdso.o
70libperf-y += stat.o 70libperf-y += stat.o
71libperf-y += stat-shadow.o
71libperf-y += record.o 72libperf-y += record.o
72libperf-y += srcline.o 73libperf-y += srcline.o
73libperf-y += data.o 74libperf-y += data.o
74libperf-$(CONFIG_X86) += tsc.o 75libperf-$(CONFIG_X86) += tsc.o
75libperf-y += cloexec.o 76libperf-y += cloexec.o
76libperf-y += thread-stack.o 77libperf-y += thread-stack.o
78libperf-$(CONFIG_AUXTRACE) += auxtrace.o
79libperf-y += parse-branch-options.o
77 80
78libperf-$(CONFIG_LIBELF) += symbol-elf.o 81libperf-$(CONFIG_LIBELF) += symbol-elf.o
79libperf-$(CONFIG_LIBELF) += probe-event.o 82libperf-$(CONFIG_LIBELF) += probe-event.o
@@ -101,23 +104,23 @@ CFLAGS_exec_cmd.o += -DPERF_EXEC_PATH="BUILD_STR($(perfexecdir_SQ))" -DPREFIX="B
101 104
102$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c 105$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
103 $(call rule_mkdir) 106 $(call rule_mkdir)
104 @$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l 107 $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l
105 108
106$(OUTPUT)util/parse-events-bison.c: util/parse-events.y 109$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
107 $(call rule_mkdir) 110 $(call rule_mkdir)
108 @$(call echo-cmd,bison)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ 111 $(Q)$(call echo-cmd,bison)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_
109 112
110$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c 113$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
111 $(call rule_mkdir) 114 $(call rule_mkdir)
112 @$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l 115 $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l
113 116
114$(OUTPUT)util/pmu-bison.c: util/pmu.y 117$(OUTPUT)util/pmu-bison.c: util/pmu.y
115 $(call rule_mkdir) 118 $(call rule_mkdir)
116 @$(call echo-cmd,bison)$(BISON) -v util/pmu.y -d -o $@ -p perf_pmu_ 119 $(Q)$(call echo-cmd,bison)$(BISON) -v util/pmu.y -d -o $@ -p perf_pmu_
117 120
118CFLAGS_parse-events-flex.o += -w 121CFLAGS_parse-events-flex.o += -w
119CFLAGS_pmu-flex.o += -w 122CFLAGS_pmu-flex.o += -w
120CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w 123CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -w
121CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w 124CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w
122 125
123$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c 126$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 7f5bdfc9bc87..03b7bc70eb66 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -506,6 +506,17 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
506 return 0; 506 return 0;
507} 507}
508 508
509static struct annotation *symbol__get_annotation(struct symbol *sym)
510{
511 struct annotation *notes = symbol__annotation(sym);
512
513 if (notes->src == NULL) {
514 if (symbol__alloc_hist(sym) < 0)
515 return NULL;
516 }
517 return notes;
518}
519
509static int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 520static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
510 int evidx, u64 addr) 521 int evidx, u64 addr)
511{ 522{
@@ -513,13 +524,9 @@ static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
513 524
514 if (sym == NULL) 525 if (sym == NULL)
515 return 0; 526 return 0;
516 527 notes = symbol__get_annotation(sym);
517 notes = symbol__annotation(sym); 528 if (notes == NULL)
518 if (notes->src == NULL) { 529 return -ENOMEM;
519 if (symbol__alloc_hist(sym) < 0)
520 return -ENOMEM;
521 }
522
523 return __symbol__inc_addr_samples(sym, map, notes, evidx, addr); 530 return __symbol__inc_addr_samples(sym, map, notes, evidx, addr);
524} 531}
525 532
@@ -647,14 +654,15 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disa
647} 654}
648 655
649double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset, 656double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
650 s64 end, const char **path) 657 s64 end, const char **path, u64 *nr_samples)
651{ 658{
652 struct source_line *src_line = notes->src->lines; 659 struct source_line *src_line = notes->src->lines;
653 double percent = 0.0; 660 double percent = 0.0;
661 *nr_samples = 0;
654 662
655 if (src_line) { 663 if (src_line) {
656 size_t sizeof_src_line = sizeof(*src_line) + 664 size_t sizeof_src_line = sizeof(*src_line) +
657 sizeof(src_line->p) * (src_line->nr_pcnt - 1); 665 sizeof(src_line->samples) * (src_line->nr_pcnt - 1);
658 666
659 while (offset < end) { 667 while (offset < end) {
660 src_line = (void *)notes->src->lines + 668 src_line = (void *)notes->src->lines +
@@ -663,7 +671,8 @@ double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
663 if (*path == NULL) 671 if (*path == NULL)
664 *path = src_line->path; 672 *path = src_line->path;
665 673
666 percent += src_line->p[evidx].percent; 674 percent += src_line->samples[evidx].percent;
675 *nr_samples += src_line->samples[evidx].nr;
667 offset++; 676 offset++;
668 } 677 }
669 } else { 678 } else {
@@ -673,8 +682,10 @@ double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
673 while (offset < end) 682 while (offset < end)
674 hits += h->addr[offset++]; 683 hits += h->addr[offset++];
675 684
676 if (h->sum) 685 if (h->sum) {
686 *nr_samples = hits;
677 percent = 100.0 * hits / h->sum; 687 percent = 100.0 * hits / h->sum;
688 }
678 } 689 }
679 690
680 return percent; 691 return percent;
@@ -689,8 +700,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
689 700
690 if (dl->offset != -1) { 701 if (dl->offset != -1) {
691 const char *path = NULL; 702 const char *path = NULL;
703 u64 nr_samples;
692 double percent, max_percent = 0.0; 704 double percent, max_percent = 0.0;
693 double *ppercents = &percent; 705 double *ppercents = &percent;
706 u64 *psamples = &nr_samples;
694 int i, nr_percent = 1; 707 int i, nr_percent = 1;
695 const char *color; 708 const char *color;
696 struct annotation *notes = symbol__annotation(sym); 709 struct annotation *notes = symbol__annotation(sym);
@@ -703,8 +716,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
703 if (perf_evsel__is_group_event(evsel)) { 716 if (perf_evsel__is_group_event(evsel)) {
704 nr_percent = evsel->nr_members; 717 nr_percent = evsel->nr_members;
705 ppercents = calloc(nr_percent, sizeof(double)); 718 ppercents = calloc(nr_percent, sizeof(double));
706 if (ppercents == NULL) 719 psamples = calloc(nr_percent, sizeof(u64));
720 if (ppercents == NULL || psamples == NULL) {
707 return -1; 721 return -1;
722 }
708 } 723 }
709 724
710 for (i = 0; i < nr_percent; i++) { 725 for (i = 0; i < nr_percent; i++) {
@@ -712,9 +727,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
712 notes->src->lines ? i : evsel->idx + i, 727 notes->src->lines ? i : evsel->idx + i,
713 offset, 728 offset,
714 next ? next->offset : (s64) len, 729 next ? next->offset : (s64) len,
715 &path); 730 &path, &nr_samples);
716 731
717 ppercents[i] = percent; 732 ppercents[i] = percent;
733 psamples[i] = nr_samples;
718 if (percent > max_percent) 734 if (percent > max_percent)
719 max_percent = percent; 735 max_percent = percent;
720 } 736 }
@@ -752,8 +768,14 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
752 768
753 for (i = 0; i < nr_percent; i++) { 769 for (i = 0; i < nr_percent; i++) {
754 percent = ppercents[i]; 770 percent = ppercents[i];
771 nr_samples = psamples[i];
755 color = get_percent_color(percent); 772 color = get_percent_color(percent);
756 color_fprintf(stdout, color, " %7.2f", percent); 773
774 if (symbol_conf.show_total_period)
775 color_fprintf(stdout, color, " %7" PRIu64,
776 nr_samples);
777 else
778 color_fprintf(stdout, color, " %7.2f", percent);
757 } 779 }
758 780
759 printf(" : "); 781 printf(" : ");
@@ -763,6 +785,9 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
763 if (ppercents != &percent) 785 if (ppercents != &percent)
764 free(ppercents); 786 free(ppercents);
765 787
788 if (psamples != &nr_samples)
789 free(psamples);
790
766 } else if (max_lines && printed >= max_lines) 791 } else if (max_lines && printed >= max_lines)
767 return 1; 792 return 1;
768 else { 793 else {
@@ -1096,7 +1121,7 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin
1096 ret = strcmp(iter->path, src_line->path); 1121 ret = strcmp(iter->path, src_line->path);
1097 if (ret == 0) { 1122 if (ret == 0) {
1098 for (i = 0; i < src_line->nr_pcnt; i++) 1123 for (i = 0; i < src_line->nr_pcnt; i++)
1099 iter->p[i].percent_sum += src_line->p[i].percent; 1124 iter->samples[i].percent_sum += src_line->samples[i].percent;
1100 return; 1125 return;
1101 } 1126 }
1102 1127
@@ -1107,7 +1132,7 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin
1107 } 1132 }
1108 1133
1109 for (i = 0; i < src_line->nr_pcnt; i++) 1134 for (i = 0; i < src_line->nr_pcnt; i++)
1110 src_line->p[i].percent_sum = src_line->p[i].percent; 1135 src_line->samples[i].percent_sum = src_line->samples[i].percent;
1111 1136
1112 rb_link_node(&src_line->node, parent, p); 1137 rb_link_node(&src_line->node, parent, p);
1113 rb_insert_color(&src_line->node, root); 1138 rb_insert_color(&src_line->node, root);
@@ -1118,9 +1143,9 @@ static int cmp_source_line(struct source_line *a, struct source_line *b)
1118 int i; 1143 int i;
1119 1144
1120 for (i = 0; i < a->nr_pcnt; i++) { 1145 for (i = 0; i < a->nr_pcnt; i++) {
1121 if (a->p[i].percent_sum == b->p[i].percent_sum) 1146 if (a->samples[i].percent_sum == b->samples[i].percent_sum)
1122 continue; 1147 continue;
1123 return a->p[i].percent_sum > b->p[i].percent_sum; 1148 return a->samples[i].percent_sum > b->samples[i].percent_sum;
1124 } 1149 }
1125 1150
1126 return 0; 1151 return 0;
@@ -1172,7 +1197,7 @@ static void symbol__free_source_line(struct symbol *sym, int len)
1172 int i; 1197 int i;
1173 1198
1174 sizeof_src_line = sizeof(*src_line) + 1199 sizeof_src_line = sizeof(*src_line) +
1175 (sizeof(src_line->p) * (src_line->nr_pcnt - 1)); 1200 (sizeof(src_line->samples) * (src_line->nr_pcnt - 1));
1176 1201
1177 for (i = 0; i < len; i++) { 1202 for (i = 0; i < len; i++) {
1178 free_srcline(src_line->path); 1203 free_srcline(src_line->path);
@@ -1204,7 +1229,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1204 h_sum += h->sum; 1229 h_sum += h->sum;
1205 } 1230 }
1206 nr_pcnt = evsel->nr_members; 1231 nr_pcnt = evsel->nr_members;
1207 sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->p); 1232 sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->samples);
1208 } 1233 }
1209 1234
1210 if (!h_sum) 1235 if (!h_sum)
@@ -1224,10 +1249,10 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1224 1249
1225 for (k = 0; k < nr_pcnt; k++) { 1250 for (k = 0; k < nr_pcnt; k++) {
1226 h = annotation__histogram(notes, evidx + k); 1251 h = annotation__histogram(notes, evidx + k);
1227 src_line->p[k].percent = 100.0 * h->addr[i] / h->sum; 1252 src_line->samples[k].percent = 100.0 * h->addr[i] / h->sum;
1228 1253
1229 if (src_line->p[k].percent > percent_max) 1254 if (src_line->samples[k].percent > percent_max)
1230 percent_max = src_line->p[k].percent; 1255 percent_max = src_line->samples[k].percent;
1231 } 1256 }
1232 1257
1233 if (percent_max <= 0.5) 1258 if (percent_max <= 0.5)
@@ -1267,7 +1292,7 @@ static void print_summary(struct rb_root *root, const char *filename)
1267 1292
1268 src_line = rb_entry(node, struct source_line, node); 1293 src_line = rb_entry(node, struct source_line, node);
1269 for (i = 0; i < src_line->nr_pcnt; i++) { 1294 for (i = 0; i < src_line->nr_pcnt; i++) {
1270 percent = src_line->p[i].percent_sum; 1295 percent = src_line->samples[i].percent_sum;
1271 color = get_percent_color(percent); 1296 color = get_percent_color(percent);
1272 color_fprintf(stdout, color, " %7.2f", percent); 1297 color_fprintf(stdout, color, " %7.2f", percent);
1273 1298
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index cadbdc90a5cb..7e78e6c27078 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -72,23 +72,24 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disa
72int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); 72int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
73size_t disasm__fprintf(struct list_head *head, FILE *fp); 73size_t disasm__fprintf(struct list_head *head, FILE *fp);
74double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset, 74double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
75 s64 end, const char **path); 75 s64 end, const char **path, u64 *nr_samples);
76 76
77struct sym_hist { 77struct sym_hist {
78 u64 sum; 78 u64 sum;
79 u64 addr[0]; 79 u64 addr[0];
80}; 80};
81 81
82struct source_line_percent { 82struct source_line_samples {
83 double percent; 83 double percent;
84 double percent_sum; 84 double percent_sum;
85 double nr;
85}; 86};
86 87
87struct source_line { 88struct source_line {
88 struct rb_node node; 89 struct rb_node node;
89 char *path; 90 char *path;
90 int nr_pcnt; 91 int nr_pcnt;
91 struct source_line_percent p[1]; 92 struct source_line_samples samples[1];
92}; 93};
93 94
94/** struct annotated_source - symbols with hits have this attached as in sannotation 95/** struct annotated_source - symbols with hits have this attached as in sannotation
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
new file mode 100644
index 000000000000..df66966cfde7
--- /dev/null
+++ b/tools/perf/util/auxtrace.c
@@ -0,0 +1,1352 @@
1/*
2 * auxtrace.c: AUX area trace support
3 * Copyright (c) 2013-2015, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#include <sys/types.h>
17#include <sys/mman.h>
18#include <stdbool.h>
19
20#include <linux/kernel.h>
21#include <linux/perf_event.h>
22#include <linux/types.h>
23#include <linux/bitops.h>
24#include <linux/log2.h>
25#include <linux/string.h>
26
27#include <sys/param.h>
28#include <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31#include <limits.h>
32#include <errno.h>
33#include <linux/list.h>
34
35#include "../perf.h"
36#include "util.h"
37#include "evlist.h"
38#include "cpumap.h"
39#include "thread_map.h"
40#include "asm/bug.h"
41#include "auxtrace.h"
42
43#include <linux/hash.h>
44
45#include "event.h"
46#include "session.h"
47#include "debug.h"
48#include "parse-options.h"
49
50int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
51 struct auxtrace_mmap_params *mp,
52 void *userpg, int fd)
53{
54 struct perf_event_mmap_page *pc = userpg;
55
56#if BITS_PER_LONG != 64 && !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT)
57 pr_err("Cannot use AUX area tracing mmaps\n");
58 return -1;
59#endif
60
61 WARN_ONCE(mm->base, "Uninitialized auxtrace_mmap\n");
62
63 mm->userpg = userpg;
64 mm->mask = mp->mask;
65 mm->len = mp->len;
66 mm->prev = 0;
67 mm->idx = mp->idx;
68 mm->tid = mp->tid;
69 mm->cpu = mp->cpu;
70
71 if (!mp->len) {
72 mm->base = NULL;
73 return 0;
74 }
75
76 pc->aux_offset = mp->offset;
77 pc->aux_size = mp->len;
78
79 mm->base = mmap(NULL, mp->len, mp->prot, MAP_SHARED, fd, mp->offset);
80 if (mm->base == MAP_FAILED) {
81 pr_debug2("failed to mmap AUX area\n");
82 mm->base = NULL;
83 return -1;
84 }
85
86 return 0;
87}
88
89void auxtrace_mmap__munmap(struct auxtrace_mmap *mm)
90{
91 if (mm->base) {
92 munmap(mm->base, mm->len);
93 mm->base = NULL;
94 }
95}
96
97void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp,
98 off_t auxtrace_offset,
99 unsigned int auxtrace_pages,
100 bool auxtrace_overwrite)
101{
102 if (auxtrace_pages) {
103 mp->offset = auxtrace_offset;
104 mp->len = auxtrace_pages * (size_t)page_size;
105 mp->mask = is_power_of_2(mp->len) ? mp->len - 1 : 0;
106 mp->prot = PROT_READ | (auxtrace_overwrite ? 0 : PROT_WRITE);
107 pr_debug2("AUX area mmap length %zu\n", mp->len);
108 } else {
109 mp->len = 0;
110 }
111}
112
113void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
114 struct perf_evlist *evlist, int idx,
115 bool per_cpu)
116{
117 mp->idx = idx;
118
119 if (per_cpu) {
120 mp->cpu = evlist->cpus->map[idx];
121 if (evlist->threads)
122 mp->tid = evlist->threads->map[0];
123 else
124 mp->tid = -1;
125 } else {
126 mp->cpu = -1;
127 mp->tid = evlist->threads->map[idx];
128 }
129}
130
131#define AUXTRACE_INIT_NR_QUEUES 32
132
133static struct auxtrace_queue *auxtrace_alloc_queue_array(unsigned int nr_queues)
134{
135 struct auxtrace_queue *queue_array;
136 unsigned int max_nr_queues, i;
137
138 max_nr_queues = UINT_MAX / sizeof(struct auxtrace_queue);
139 if (nr_queues > max_nr_queues)
140 return NULL;
141
142 queue_array = calloc(nr_queues, sizeof(struct auxtrace_queue));
143 if (!queue_array)
144 return NULL;
145
146 for (i = 0; i < nr_queues; i++) {
147 INIT_LIST_HEAD(&queue_array[i].head);
148 queue_array[i].priv = NULL;
149 }
150
151 return queue_array;
152}
153
154int auxtrace_queues__init(struct auxtrace_queues *queues)
155{
156 queues->nr_queues = AUXTRACE_INIT_NR_QUEUES;
157 queues->queue_array = auxtrace_alloc_queue_array(queues->nr_queues);
158 if (!queues->queue_array)
159 return -ENOMEM;
160 return 0;
161}
162
163static int auxtrace_queues__grow(struct auxtrace_queues *queues,
164 unsigned int new_nr_queues)
165{
166 unsigned int nr_queues = queues->nr_queues;
167 struct auxtrace_queue *queue_array;
168 unsigned int i;
169
170 if (!nr_queues)
171 nr_queues = AUXTRACE_INIT_NR_QUEUES;
172
173 while (nr_queues && nr_queues < new_nr_queues)
174 nr_queues <<= 1;
175
176 if (nr_queues < queues->nr_queues || nr_queues < new_nr_queues)
177 return -EINVAL;
178
179 queue_array = auxtrace_alloc_queue_array(nr_queues);
180 if (!queue_array)
181 return -ENOMEM;
182
183 for (i = 0; i < queues->nr_queues; i++) {
184 list_splice_tail(&queues->queue_array[i].head,
185 &queue_array[i].head);
186 queue_array[i].priv = queues->queue_array[i].priv;
187 }
188
189 queues->nr_queues = nr_queues;
190 queues->queue_array = queue_array;
191
192 return 0;
193}
194
195static void *auxtrace_copy_data(u64 size, struct perf_session *session)
196{
197 int fd = perf_data_file__fd(session->file);
198 void *p;
199 ssize_t ret;
200
201 if (size > SSIZE_MAX)
202 return NULL;
203
204 p = malloc(size);
205 if (!p)
206 return NULL;
207
208 ret = readn(fd, p, size);
209 if (ret != (ssize_t)size) {
210 free(p);
211 return NULL;
212 }
213
214 return p;
215}
216
217static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues,
218 unsigned int idx,
219 struct auxtrace_buffer *buffer)
220{
221 struct auxtrace_queue *queue;
222 int err;
223
224 if (idx >= queues->nr_queues) {
225 err = auxtrace_queues__grow(queues, idx + 1);
226 if (err)
227 return err;
228 }
229
230 queue = &queues->queue_array[idx];
231
232 if (!queue->set) {
233 queue->set = true;
234 queue->tid = buffer->tid;
235 queue->cpu = buffer->cpu;
236 } else if (buffer->cpu != queue->cpu || buffer->tid != queue->tid) {
237 pr_err("auxtrace queue conflict: cpu %d, tid %d vs cpu %d, tid %d\n",
238 queue->cpu, queue->tid, buffer->cpu, buffer->tid);
239 return -EINVAL;
240 }
241
242 buffer->buffer_nr = queues->next_buffer_nr++;
243
244 list_add_tail(&buffer->list, &queue->head);
245
246 queues->new_data = true;
247 queues->populated = true;
248
249 return 0;
250}
251
252/* Limit buffers to 32MiB on 32-bit */
253#define BUFFER_LIMIT_FOR_32_BIT (32 * 1024 * 1024)
254
255static int auxtrace_queues__split_buffer(struct auxtrace_queues *queues,
256 unsigned int idx,
257 struct auxtrace_buffer *buffer)
258{
259 u64 sz = buffer->size;
260 bool consecutive = false;
261 struct auxtrace_buffer *b;
262 int err;
263
264 while (sz > BUFFER_LIMIT_FOR_32_BIT) {
265 b = memdup(buffer, sizeof(struct auxtrace_buffer));
266 if (!b)
267 return -ENOMEM;
268 b->size = BUFFER_LIMIT_FOR_32_BIT;
269 b->consecutive = consecutive;
270 err = auxtrace_queues__add_buffer(queues, idx, b);
271 if (err) {
272 auxtrace_buffer__free(b);
273 return err;
274 }
275 buffer->data_offset += BUFFER_LIMIT_FOR_32_BIT;
276 sz -= BUFFER_LIMIT_FOR_32_BIT;
277 consecutive = true;
278 }
279
280 buffer->size = sz;
281 buffer->consecutive = consecutive;
282
283 return 0;
284}
285
286static int auxtrace_queues__add_event_buffer(struct auxtrace_queues *queues,
287 struct perf_session *session,
288 unsigned int idx,
289 struct auxtrace_buffer *buffer)
290{
291 if (session->one_mmap) {
292 buffer->data = buffer->data_offset - session->one_mmap_offset +
293 session->one_mmap_addr;
294 } else if (perf_data_file__is_pipe(session->file)) {
295 buffer->data = auxtrace_copy_data(buffer->size, session);
296 if (!buffer->data)
297 return -ENOMEM;
298 buffer->data_needs_freeing = true;
299 } else if (BITS_PER_LONG == 32 &&
300 buffer->size > BUFFER_LIMIT_FOR_32_BIT) {
301 int err;
302
303 err = auxtrace_queues__split_buffer(queues, idx, buffer);
304 if (err)
305 return err;
306 }
307
308 return auxtrace_queues__add_buffer(queues, idx, buffer);
309}
310
311int auxtrace_queues__add_event(struct auxtrace_queues *queues,
312 struct perf_session *session,
313 union perf_event *event, off_t data_offset,
314 struct auxtrace_buffer **buffer_ptr)
315{
316 struct auxtrace_buffer *buffer;
317 unsigned int idx;
318 int err;
319
320 buffer = zalloc(sizeof(struct auxtrace_buffer));
321 if (!buffer)
322 return -ENOMEM;
323
324 buffer->pid = -1;
325 buffer->tid = event->auxtrace.tid;
326 buffer->cpu = event->auxtrace.cpu;
327 buffer->data_offset = data_offset;
328 buffer->offset = event->auxtrace.offset;
329 buffer->reference = event->auxtrace.reference;
330 buffer->size = event->auxtrace.size;
331 idx = event->auxtrace.idx;
332
333 err = auxtrace_queues__add_event_buffer(queues, session, idx, buffer);
334 if (err)
335 goto out_err;
336
337 if (buffer_ptr)
338 *buffer_ptr = buffer;
339
340 return 0;
341
342out_err:
343 auxtrace_buffer__free(buffer);
344 return err;
345}
346
347static int auxtrace_queues__add_indexed_event(struct auxtrace_queues *queues,
348 struct perf_session *session,
349 off_t file_offset, size_t sz)
350{
351 union perf_event *event;
352 int err;
353 char buf[PERF_SAMPLE_MAX_SIZE];
354
355 err = perf_session__peek_event(session, file_offset, buf,
356 PERF_SAMPLE_MAX_SIZE, &event, NULL);
357 if (err)
358 return err;
359
360 if (event->header.type == PERF_RECORD_AUXTRACE) {
361 if (event->header.size < sizeof(struct auxtrace_event) ||
362 event->header.size != sz) {
363 err = -EINVAL;
364 goto out;
365 }
366 file_offset += event->header.size;
367 err = auxtrace_queues__add_event(queues, session, event,
368 file_offset, NULL);
369 }
370out:
371 return err;
372}
373
374void auxtrace_queues__free(struct auxtrace_queues *queues)
375{
376 unsigned int i;
377
378 for (i = 0; i < queues->nr_queues; i++) {
379 while (!list_empty(&queues->queue_array[i].head)) {
380 struct auxtrace_buffer *buffer;
381
382 buffer = list_entry(queues->queue_array[i].head.next,
383 struct auxtrace_buffer, list);
384 list_del(&buffer->list);
385 auxtrace_buffer__free(buffer);
386 }
387 }
388
389 zfree(&queues->queue_array);
390 queues->nr_queues = 0;
391}
392
393static void auxtrace_heapify(struct auxtrace_heap_item *heap_array,
394 unsigned int pos, unsigned int queue_nr,
395 u64 ordinal)
396{
397 unsigned int parent;
398
399 while (pos) {
400 parent = (pos - 1) >> 1;
401 if (heap_array[parent].ordinal <= ordinal)
402 break;
403 heap_array[pos] = heap_array[parent];
404 pos = parent;
405 }
406 heap_array[pos].queue_nr = queue_nr;
407 heap_array[pos].ordinal = ordinal;
408}
409
410int auxtrace_heap__add(struct auxtrace_heap *heap, unsigned int queue_nr,
411 u64 ordinal)
412{
413 struct auxtrace_heap_item *heap_array;
414
415 if (queue_nr >= heap->heap_sz) {
416 unsigned int heap_sz = AUXTRACE_INIT_NR_QUEUES;
417
418 while (heap_sz <= queue_nr)
419 heap_sz <<= 1;
420 heap_array = realloc(heap->heap_array,
421 heap_sz * sizeof(struct auxtrace_heap_item));
422 if (!heap_array)
423 return -ENOMEM;
424 heap->heap_array = heap_array;
425 heap->heap_sz = heap_sz;
426 }
427
428 auxtrace_heapify(heap->heap_array, heap->heap_cnt++, queue_nr, ordinal);
429
430 return 0;
431}
432
433void auxtrace_heap__free(struct auxtrace_heap *heap)
434{
435 zfree(&heap->heap_array);
436 heap->heap_cnt = 0;
437 heap->heap_sz = 0;
438}
439
440void auxtrace_heap__pop(struct auxtrace_heap *heap)
441{
442 unsigned int pos, last, heap_cnt = heap->heap_cnt;
443 struct auxtrace_heap_item *heap_array;
444
445 if (!heap_cnt)
446 return;
447
448 heap->heap_cnt -= 1;
449
450 heap_array = heap->heap_array;
451
452 pos = 0;
453 while (1) {
454 unsigned int left, right;
455
456 left = (pos << 1) + 1;
457 if (left >= heap_cnt)
458 break;
459 right = left + 1;
460 if (right >= heap_cnt) {
461 heap_array[pos] = heap_array[left];
462 return;
463 }
464 if (heap_array[left].ordinal < heap_array[right].ordinal) {
465 heap_array[pos] = heap_array[left];
466 pos = left;
467 } else {
468 heap_array[pos] = heap_array[right];
469 pos = right;
470 }
471 }
472
473 last = heap_cnt - 1;
474 auxtrace_heapify(heap_array, pos, heap_array[last].queue_nr,
475 heap_array[last].ordinal);
476}
477
478size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr)
479{
480 if (itr)
481 return itr->info_priv_size(itr);
482 return 0;
483}
484
485static int auxtrace_not_supported(void)
486{
487 pr_err("AUX area tracing is not supported on this architecture\n");
488 return -EINVAL;
489}
490
491int auxtrace_record__info_fill(struct auxtrace_record *itr,
492 struct perf_session *session,
493 struct auxtrace_info_event *auxtrace_info,
494 size_t priv_size)
495{
496 if (itr)
497 return itr->info_fill(itr, session, auxtrace_info, priv_size);
498 return auxtrace_not_supported();
499}
500
501void auxtrace_record__free(struct auxtrace_record *itr)
502{
503 if (itr)
504 itr->free(itr);
505}
506
507int auxtrace_record__snapshot_start(struct auxtrace_record *itr)
508{
509 if (itr && itr->snapshot_start)
510 return itr->snapshot_start(itr);
511 return 0;
512}
513
514int auxtrace_record__snapshot_finish(struct auxtrace_record *itr)
515{
516 if (itr && itr->snapshot_finish)
517 return itr->snapshot_finish(itr);
518 return 0;
519}
520
521int auxtrace_record__find_snapshot(struct auxtrace_record *itr, int idx,
522 struct auxtrace_mmap *mm,
523 unsigned char *data, u64 *head, u64 *old)
524{
525 if (itr && itr->find_snapshot)
526 return itr->find_snapshot(itr, idx, mm, data, head, old);
527 return 0;
528}
529
530int auxtrace_record__options(struct auxtrace_record *itr,
531 struct perf_evlist *evlist,
532 struct record_opts *opts)
533{
534 if (itr)
535 return itr->recording_options(itr, evlist, opts);
536 return 0;
537}
538
539u64 auxtrace_record__reference(struct auxtrace_record *itr)
540{
541 if (itr)
542 return itr->reference(itr);
543 return 0;
544}
545
546int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
547 struct record_opts *opts, const char *str)
548{
549 if (!str)
550 return 0;
551
552 if (itr)
553 return itr->parse_snapshot_options(itr, opts, str);
554
555 pr_err("No AUX area tracing to snapshot\n");
556 return -EINVAL;
557}
558
559struct auxtrace_record *__weak
560auxtrace_record__init(struct perf_evlist *evlist __maybe_unused, int *err)
561{
562 *err = 0;
563 return NULL;
564}
565
566static int auxtrace_index__alloc(struct list_head *head)
567{
568 struct auxtrace_index *auxtrace_index;
569
570 auxtrace_index = malloc(sizeof(struct auxtrace_index));
571 if (!auxtrace_index)
572 return -ENOMEM;
573
574 auxtrace_index->nr = 0;
575 INIT_LIST_HEAD(&auxtrace_index->list);
576
577 list_add_tail(&auxtrace_index->list, head);
578
579 return 0;
580}
581
582void auxtrace_index__free(struct list_head *head)
583{
584 struct auxtrace_index *auxtrace_index, *n;
585
586 list_for_each_entry_safe(auxtrace_index, n, head, list) {
587 list_del(&auxtrace_index->list);
588 free(auxtrace_index);
589 }
590}
591
592static struct auxtrace_index *auxtrace_index__last(struct list_head *head)
593{
594 struct auxtrace_index *auxtrace_index;
595 int err;
596
597 if (list_empty(head)) {
598 err = auxtrace_index__alloc(head);
599 if (err)
600 return NULL;
601 }
602
603 auxtrace_index = list_entry(head->prev, struct auxtrace_index, list);
604
605 if (auxtrace_index->nr >= PERF_AUXTRACE_INDEX_ENTRY_COUNT) {
606 err = auxtrace_index__alloc(head);
607 if (err)
608 return NULL;
609 auxtrace_index = list_entry(head->prev, struct auxtrace_index,
610 list);
611 }
612
613 return auxtrace_index;
614}
615
616int auxtrace_index__auxtrace_event(struct list_head *head,
617 union perf_event *event, off_t file_offset)
618{
619 struct auxtrace_index *auxtrace_index;
620 size_t nr;
621
622 auxtrace_index = auxtrace_index__last(head);
623 if (!auxtrace_index)
624 return -ENOMEM;
625
626 nr = auxtrace_index->nr;
627 auxtrace_index->entries[nr].file_offset = file_offset;
628 auxtrace_index->entries[nr].sz = event->header.size;
629 auxtrace_index->nr += 1;
630
631 return 0;
632}
633
634static int auxtrace_index__do_write(int fd,
635 struct auxtrace_index *auxtrace_index)
636{
637 struct auxtrace_index_entry ent;
638 size_t i;
639
640 for (i = 0; i < auxtrace_index->nr; i++) {
641 ent.file_offset = auxtrace_index->entries[i].file_offset;
642 ent.sz = auxtrace_index->entries[i].sz;
643 if (writen(fd, &ent, sizeof(ent)) != sizeof(ent))
644 return -errno;
645 }
646 return 0;
647}
648
649int auxtrace_index__write(int fd, struct list_head *head)
650{
651 struct auxtrace_index *auxtrace_index;
652 u64 total = 0;
653 int err;
654
655 list_for_each_entry(auxtrace_index, head, list)
656 total += auxtrace_index->nr;
657
658 if (writen(fd, &total, sizeof(total)) != sizeof(total))
659 return -errno;
660
661 list_for_each_entry(auxtrace_index, head, list) {
662 err = auxtrace_index__do_write(fd, auxtrace_index);
663 if (err)
664 return err;
665 }
666
667 return 0;
668}
669
670static int auxtrace_index__process_entry(int fd, struct list_head *head,
671 bool needs_swap)
672{
673 struct auxtrace_index *auxtrace_index;
674 struct auxtrace_index_entry ent;
675 size_t nr;
676
677 if (readn(fd, &ent, sizeof(ent)) != sizeof(ent))
678 return -1;
679
680 auxtrace_index = auxtrace_index__last(head);
681 if (!auxtrace_index)
682 return -1;
683
684 nr = auxtrace_index->nr;
685 if (needs_swap) {
686 auxtrace_index->entries[nr].file_offset =
687 bswap_64(ent.file_offset);
688 auxtrace_index->entries[nr].sz = bswap_64(ent.sz);
689 } else {
690 auxtrace_index->entries[nr].file_offset = ent.file_offset;
691 auxtrace_index->entries[nr].sz = ent.sz;
692 }
693
694 auxtrace_index->nr = nr + 1;
695
696 return 0;
697}
698
699int auxtrace_index__process(int fd, u64 size, struct perf_session *session,
700 bool needs_swap)
701{
702 struct list_head *head = &session->auxtrace_index;
703 u64 nr;
704
705 if (readn(fd, &nr, sizeof(u64)) != sizeof(u64))
706 return -1;
707
708 if (needs_swap)
709 nr = bswap_64(nr);
710
711 if (sizeof(u64) + nr * sizeof(struct auxtrace_index_entry) > size)
712 return -1;
713
714 while (nr--) {
715 int err;
716
717 err = auxtrace_index__process_entry(fd, head, needs_swap);
718 if (err)
719 return -1;
720 }
721
722 return 0;
723}
724
725static int auxtrace_queues__process_index_entry(struct auxtrace_queues *queues,
726 struct perf_session *session,
727 struct auxtrace_index_entry *ent)
728{
729 return auxtrace_queues__add_indexed_event(queues, session,
730 ent->file_offset, ent->sz);
731}
732
733int auxtrace_queues__process_index(struct auxtrace_queues *queues,
734 struct perf_session *session)
735{
736 struct auxtrace_index *auxtrace_index;
737 struct auxtrace_index_entry *ent;
738 size_t i;
739 int err;
740
741 list_for_each_entry(auxtrace_index, &session->auxtrace_index, list) {
742 for (i = 0; i < auxtrace_index->nr; i++) {
743 ent = &auxtrace_index->entries[i];
744 err = auxtrace_queues__process_index_entry(queues,
745 session,
746 ent);
747 if (err)
748 return err;
749 }
750 }
751 return 0;
752}
753
754struct auxtrace_buffer *auxtrace_buffer__next(struct auxtrace_queue *queue,
755 struct auxtrace_buffer *buffer)
756{
757 if (buffer) {
758 if (list_is_last(&buffer->list, &queue->head))
759 return NULL;
760 return list_entry(buffer->list.next, struct auxtrace_buffer,
761 list);
762 } else {
763 if (list_empty(&queue->head))
764 return NULL;
765 return list_entry(queue->head.next, struct auxtrace_buffer,
766 list);
767 }
768}
769
770void *auxtrace_buffer__get_data(struct auxtrace_buffer *buffer, int fd)
771{
772 size_t adj = buffer->data_offset & (page_size - 1);
773 size_t size = buffer->size + adj;
774 off_t file_offset = buffer->data_offset - adj;
775 void *addr;
776
777 if (buffer->data)
778 return buffer->data;
779
780 addr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, file_offset);
781 if (addr == MAP_FAILED)
782 return NULL;
783
784 buffer->mmap_addr = addr;
785 buffer->mmap_size = size;
786
787 buffer->data = addr + adj;
788
789 return buffer->data;
790}
791
792void auxtrace_buffer__put_data(struct auxtrace_buffer *buffer)
793{
794 if (!buffer->data || !buffer->mmap_addr)
795 return;
796 munmap(buffer->mmap_addr, buffer->mmap_size);
797 buffer->mmap_addr = NULL;
798 buffer->mmap_size = 0;
799 buffer->data = NULL;
800 buffer->use_data = NULL;
801}
802
803void auxtrace_buffer__drop_data(struct auxtrace_buffer *buffer)
804{
805 auxtrace_buffer__put_data(buffer);
806 if (buffer->data_needs_freeing) {
807 buffer->data_needs_freeing = false;
808 zfree(&buffer->data);
809 buffer->use_data = NULL;
810 buffer->size = 0;
811 }
812}
813
814void auxtrace_buffer__free(struct auxtrace_buffer *buffer)
815{
816 auxtrace_buffer__drop_data(buffer);
817 free(buffer);
818}
819
820void auxtrace_synth_error(struct auxtrace_error_event *auxtrace_error, int type,
821 int code, int cpu, pid_t pid, pid_t tid, u64 ip,
822 const char *msg)
823{
824 size_t size;
825
826 memset(auxtrace_error, 0, sizeof(struct auxtrace_error_event));
827
828 auxtrace_error->header.type = PERF_RECORD_AUXTRACE_ERROR;
829 auxtrace_error->type = type;
830 auxtrace_error->code = code;
831 auxtrace_error->cpu = cpu;
832 auxtrace_error->pid = pid;
833 auxtrace_error->tid = tid;
834 auxtrace_error->ip = ip;
835 strlcpy(auxtrace_error->msg, msg, MAX_AUXTRACE_ERROR_MSG);
836
837 size = (void *)auxtrace_error->msg - (void *)auxtrace_error +
838 strlen(auxtrace_error->msg) + 1;
839 auxtrace_error->header.size = PERF_ALIGN(size, sizeof(u64));
840}
841
842int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
843 struct perf_tool *tool,
844 struct perf_session *session,
845 perf_event__handler_t process)
846{
847 union perf_event *ev;
848 size_t priv_size;
849 int err;
850
851 pr_debug2("Synthesizing auxtrace information\n");
852 priv_size = auxtrace_record__info_priv_size(itr);
853 ev = zalloc(sizeof(struct auxtrace_info_event) + priv_size);
854 if (!ev)
855 return -ENOMEM;
856
857 ev->auxtrace_info.header.type = PERF_RECORD_AUXTRACE_INFO;
858 ev->auxtrace_info.header.size = sizeof(struct auxtrace_info_event) +
859 priv_size;
860 err = auxtrace_record__info_fill(itr, session, &ev->auxtrace_info,
861 priv_size);
862 if (err)
863 goto out_free;
864
865 err = process(tool, ev, NULL, NULL);
866out_free:
867 free(ev);
868 return err;
869}
870
871static bool auxtrace__dont_decode(struct perf_session *session)
872{
873 return !session->itrace_synth_opts ||
874 session->itrace_synth_opts->dont_decode;
875}
876
877int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
878 union perf_event *event,
879 struct perf_session *session __maybe_unused)
880{
881 enum auxtrace_type type = event->auxtrace_info.type;
882
883 if (dump_trace)
884 fprintf(stdout, " type: %u\n", type);
885
886 switch (type) {
887 case PERF_AUXTRACE_UNKNOWN:
888 default:
889 return -EINVAL;
890 }
891}
892
893s64 perf_event__process_auxtrace(struct perf_tool *tool,
894 union perf_event *event,
895 struct perf_session *session)
896{
897 s64 err;
898
899 if (dump_trace)
900 fprintf(stdout, " size: %#"PRIx64" offset: %#"PRIx64" ref: %#"PRIx64" idx: %u tid: %d cpu: %d\n",
901 event->auxtrace.size, event->auxtrace.offset,
902 event->auxtrace.reference, event->auxtrace.idx,
903 event->auxtrace.tid, event->auxtrace.cpu);
904
905 if (auxtrace__dont_decode(session))
906 return event->auxtrace.size;
907
908 if (!session->auxtrace || event->header.type != PERF_RECORD_AUXTRACE)
909 return -EINVAL;
910
911 err = session->auxtrace->process_auxtrace_event(session, event, tool);
912 if (err < 0)
913 return err;
914
915 return event->auxtrace.size;
916}
917
918#define PERF_ITRACE_DEFAULT_PERIOD_TYPE PERF_ITRACE_PERIOD_NANOSECS
919#define PERF_ITRACE_DEFAULT_PERIOD 100000
920#define PERF_ITRACE_DEFAULT_CALLCHAIN_SZ 16
921#define PERF_ITRACE_MAX_CALLCHAIN_SZ 1024
922
923void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts)
924{
925 synth_opts->instructions = true;
926 synth_opts->branches = true;
927 synth_opts->transactions = true;
928 synth_opts->errors = true;
929 synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE;
930 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
931 synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ;
932}
933
934/*
935 * Please check tools/perf/Documentation/perf-script.txt for information
936 * about the options parsed here, which is introduced after this cset,
937 * when support in 'perf script' for these options is introduced.
938 */
939int itrace_parse_synth_opts(const struct option *opt, const char *str,
940 int unset)
941{
942 struct itrace_synth_opts *synth_opts = opt->value;
943 const char *p;
944 char *endptr;
945
946 synth_opts->set = true;
947
948 if (unset) {
949 synth_opts->dont_decode = true;
950 return 0;
951 }
952
953 if (!str) {
954 itrace_synth_opts__set_default(synth_opts);
955 return 0;
956 }
957
958 for (p = str; *p;) {
959 switch (*p++) {
960 case 'i':
961 synth_opts->instructions = true;
962 while (*p == ' ' || *p == ',')
963 p += 1;
964 if (isdigit(*p)) {
965 synth_opts->period = strtoull(p, &endptr, 10);
966 p = endptr;
967 while (*p == ' ' || *p == ',')
968 p += 1;
969 switch (*p++) {
970 case 'i':
971 synth_opts->period_type =
972 PERF_ITRACE_PERIOD_INSTRUCTIONS;
973 break;
974 case 't':
975 synth_opts->period_type =
976 PERF_ITRACE_PERIOD_TICKS;
977 break;
978 case 'm':
979 synth_opts->period *= 1000;
980 /* Fall through */
981 case 'u':
982 synth_opts->period *= 1000;
983 /* Fall through */
984 case 'n':
985 if (*p++ != 's')
986 goto out_err;
987 synth_opts->period_type =
988 PERF_ITRACE_PERIOD_NANOSECS;
989 break;
990 case '\0':
991 goto out;
992 default:
993 goto out_err;
994 }
995 }
996 break;
997 case 'b':
998 synth_opts->branches = true;
999 break;
1000 case 'x':
1001 synth_opts->transactions = true;
1002 break;
1003 case 'e':
1004 synth_opts->errors = true;
1005 break;
1006 case 'd':
1007 synth_opts->log = true;
1008 break;
1009 case 'c':
1010 synth_opts->branches = true;
1011 synth_opts->calls = true;
1012 break;
1013 case 'r':
1014 synth_opts->branches = true;
1015 synth_opts->returns = true;
1016 break;
1017 case 'g':
1018 synth_opts->callchain = true;
1019 synth_opts->callchain_sz =
1020 PERF_ITRACE_DEFAULT_CALLCHAIN_SZ;
1021 while (*p == ' ' || *p == ',')
1022 p += 1;
1023 if (isdigit(*p)) {
1024 unsigned int val;
1025
1026 val = strtoul(p, &endptr, 10);
1027 p = endptr;
1028 if (!val || val > PERF_ITRACE_MAX_CALLCHAIN_SZ)
1029 goto out_err;
1030 synth_opts->callchain_sz = val;
1031 }
1032 break;
1033 case ' ':
1034 case ',':
1035 break;
1036 default:
1037 goto out_err;
1038 }
1039 }
1040out:
1041 if (synth_opts->instructions) {
1042 if (!synth_opts->period_type)
1043 synth_opts->period_type =
1044 PERF_ITRACE_DEFAULT_PERIOD_TYPE;
1045 if (!synth_opts->period)
1046 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
1047 }
1048
1049 return 0;
1050
1051out_err:
1052 pr_err("Bad Instruction Tracing options '%s'\n", str);
1053 return -EINVAL;
1054}
1055
1056static const char * const auxtrace_error_type_name[] = {
1057 [PERF_AUXTRACE_ERROR_ITRACE] = "instruction trace",
1058};
1059
1060static const char *auxtrace_error_name(int type)
1061{
1062 const char *error_type_name = NULL;
1063
1064 if (type < PERF_AUXTRACE_ERROR_MAX)
1065 error_type_name = auxtrace_error_type_name[type];
1066 if (!error_type_name)
1067 error_type_name = "unknown AUX";
1068 return error_type_name;
1069}
1070
1071size_t perf_event__fprintf_auxtrace_error(union perf_event *event, FILE *fp)
1072{
1073 struct auxtrace_error_event *e = &event->auxtrace_error;
1074 int ret;
1075
1076 ret = fprintf(fp, " %s error type %u",
1077 auxtrace_error_name(e->type), e->type);
1078 ret += fprintf(fp, " cpu %d pid %d tid %d ip %#"PRIx64" code %u: %s\n",
1079 e->cpu, e->pid, e->tid, e->ip, e->code, e->msg);
1080 return ret;
1081}
1082
1083void perf_session__auxtrace_error_inc(struct perf_session *session,
1084 union perf_event *event)
1085{
1086 struct auxtrace_error_event *e = &event->auxtrace_error;
1087
1088 if (e->type < PERF_AUXTRACE_ERROR_MAX)
1089 session->evlist->stats.nr_auxtrace_errors[e->type] += 1;
1090}
1091
1092void events_stats__auxtrace_error_warn(const struct events_stats *stats)
1093{
1094 int i;
1095
1096 for (i = 0; i < PERF_AUXTRACE_ERROR_MAX; i++) {
1097 if (!stats->nr_auxtrace_errors[i])
1098 continue;
1099 ui__warning("%u %s errors\n",
1100 stats->nr_auxtrace_errors[i],
1101 auxtrace_error_name(i));
1102 }
1103}
1104
1105int perf_event__process_auxtrace_error(struct perf_tool *tool __maybe_unused,
1106 union perf_event *event,
1107 struct perf_session *session)
1108{
1109 if (auxtrace__dont_decode(session))
1110 return 0;
1111
1112 perf_event__fprintf_auxtrace_error(event, stdout);
1113 return 0;
1114}
1115
1116static int __auxtrace_mmap__read(struct auxtrace_mmap *mm,
1117 struct auxtrace_record *itr,
1118 struct perf_tool *tool, process_auxtrace_t fn,
1119 bool snapshot, size_t snapshot_size)
1120{
1121 u64 head, old = mm->prev, offset, ref;
1122 unsigned char *data = mm->base;
1123 size_t size, head_off, old_off, len1, len2, padding;
1124 union perf_event ev;
1125 void *data1, *data2;
1126
1127 if (snapshot) {
1128 head = auxtrace_mmap__read_snapshot_head(mm);
1129 if (auxtrace_record__find_snapshot(itr, mm->idx, mm, data,
1130 &head, &old))
1131 return -1;
1132 } else {
1133 head = auxtrace_mmap__read_head(mm);
1134 }
1135
1136 if (old == head)
1137 return 0;
1138
1139 pr_debug3("auxtrace idx %d old %#"PRIx64" head %#"PRIx64" diff %#"PRIx64"\n",
1140 mm->idx, old, head, head - old);
1141
1142 if (mm->mask) {
1143 head_off = head & mm->mask;
1144 old_off = old & mm->mask;
1145 } else {
1146 head_off = head % mm->len;
1147 old_off = old % mm->len;
1148 }
1149
1150 if (head_off > old_off)
1151 size = head_off - old_off;
1152 else
1153 size = mm->len - (old_off - head_off);
1154
1155 if (snapshot && size > snapshot_size)
1156 size = snapshot_size;
1157
1158 ref = auxtrace_record__reference(itr);
1159
1160 if (head > old || size <= head || mm->mask) {
1161 offset = head - size;
1162 } else {
1163 /*
1164 * When the buffer size is not a power of 2, 'head' wraps at the
1165 * highest multiple of the buffer size, so we have to subtract
1166 * the remainder here.
1167 */
1168 u64 rem = (0ULL - mm->len) % mm->len;
1169
1170 offset = head - size - rem;
1171 }
1172
1173 if (size > head_off) {
1174 len1 = size - head_off;
1175 data1 = &data[mm->len - len1];
1176 len2 = head_off;
1177 data2 = &data[0];
1178 } else {
1179 len1 = size;
1180 data1 = &data[head_off - len1];
1181 len2 = 0;
1182 data2 = NULL;
1183 }
1184
1185 /* padding must be written by fn() e.g. record__process_auxtrace() */
1186 padding = size & 7;
1187 if (padding)
1188 padding = 8 - padding;
1189
1190 memset(&ev, 0, sizeof(ev));
1191 ev.auxtrace.header.type = PERF_RECORD_AUXTRACE;
1192 ev.auxtrace.header.size = sizeof(ev.auxtrace);
1193 ev.auxtrace.size = size + padding;
1194 ev.auxtrace.offset = offset;
1195 ev.auxtrace.reference = ref;
1196 ev.auxtrace.idx = mm->idx;
1197 ev.auxtrace.tid = mm->tid;
1198 ev.auxtrace.cpu = mm->cpu;
1199
1200 if (fn(tool, &ev, data1, len1, data2, len2))
1201 return -1;
1202
1203 mm->prev = head;
1204
1205 if (!snapshot) {
1206 auxtrace_mmap__write_tail(mm, head);
1207 if (itr->read_finish) {
1208 int err;
1209
1210 err = itr->read_finish(itr, mm->idx);
1211 if (err < 0)
1212 return err;
1213 }
1214 }
1215
1216 return 1;
1217}
1218
1219int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
1220 struct perf_tool *tool, process_auxtrace_t fn)
1221{
1222 return __auxtrace_mmap__read(mm, itr, tool, fn, false, 0);
1223}
1224
1225int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm,
1226 struct auxtrace_record *itr,
1227 struct perf_tool *tool, process_auxtrace_t fn,
1228 size_t snapshot_size)
1229{
1230 return __auxtrace_mmap__read(mm, itr, tool, fn, true, snapshot_size);
1231}
1232
1233/**
1234 * struct auxtrace_cache - hash table to implement a cache
1235 * @hashtable: the hashtable
1236 * @sz: hashtable size (number of hlists)
1237 * @entry_size: size of an entry
1238 * @limit: limit the number of entries to this maximum, when reached the cache
1239 * is dropped and caching begins again with an empty cache
1240 * @cnt: current number of entries
1241 * @bits: hashtable size (@sz = 2^@bits)
1242 */
1243struct auxtrace_cache {
1244 struct hlist_head *hashtable;
1245 size_t sz;
1246 size_t entry_size;
1247 size_t limit;
1248 size_t cnt;
1249 unsigned int bits;
1250};
1251
1252struct auxtrace_cache *auxtrace_cache__new(unsigned int bits, size_t entry_size,
1253 unsigned int limit_percent)
1254{
1255 struct auxtrace_cache *c;
1256 struct hlist_head *ht;
1257 size_t sz, i;
1258
1259 c = zalloc(sizeof(struct auxtrace_cache));
1260 if (!c)
1261 return NULL;
1262
1263 sz = 1UL << bits;
1264
1265 ht = calloc(sz, sizeof(struct hlist_head));
1266 if (!ht)
1267 goto out_free;
1268
1269 for (i = 0; i < sz; i++)
1270 INIT_HLIST_HEAD(&ht[i]);
1271
1272 c->hashtable = ht;
1273 c->sz = sz;
1274 c->entry_size = entry_size;
1275 c->limit = (c->sz * limit_percent) / 100;
1276 c->bits = bits;
1277
1278 return c;
1279
1280out_free:
1281 free(c);
1282 return NULL;
1283}
1284
1285static void auxtrace_cache__drop(struct auxtrace_cache *c)
1286{
1287 struct auxtrace_cache_entry *entry;
1288 struct hlist_node *tmp;
1289 size_t i;
1290
1291 if (!c)
1292 return;
1293
1294 for (i = 0; i < c->sz; i++) {
1295 hlist_for_each_entry_safe(entry, tmp, &c->hashtable[i], hash) {
1296 hlist_del(&entry->hash);
1297 auxtrace_cache__free_entry(c, entry);
1298 }
1299 }
1300
1301 c->cnt = 0;
1302}
1303
1304void auxtrace_cache__free(struct auxtrace_cache *c)
1305{
1306 if (!c)
1307 return;
1308
1309 auxtrace_cache__drop(c);
1310 free(c->hashtable);
1311 free(c);
1312}
1313
1314void *auxtrace_cache__alloc_entry(struct auxtrace_cache *c)
1315{
1316 return malloc(c->entry_size);
1317}
1318
1319void auxtrace_cache__free_entry(struct auxtrace_cache *c __maybe_unused,
1320 void *entry)
1321{
1322 free(entry);
1323}
1324
1325int auxtrace_cache__add(struct auxtrace_cache *c, u32 key,
1326 struct auxtrace_cache_entry *entry)
1327{
1328 if (c->limit && ++c->cnt > c->limit)
1329 auxtrace_cache__drop(c);
1330
1331 entry->key = key;
1332 hlist_add_head(&entry->hash, &c->hashtable[hash_32(key, c->bits)]);
1333
1334 return 0;
1335}
1336
1337void *auxtrace_cache__lookup(struct auxtrace_cache *c, u32 key)
1338{
1339 struct auxtrace_cache_entry *entry;
1340 struct hlist_head *hlist;
1341
1342 if (!c)
1343 return NULL;
1344
1345 hlist = &c->hashtable[hash_32(key, c->bits)];
1346 hlist_for_each_entry(entry, hlist, hash) {
1347 if (entry->key == key)
1348 return entry;
1349 }
1350
1351 return NULL;
1352}
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
new file mode 100644
index 000000000000..a171abbe7301
--- /dev/null
+++ b/tools/perf/util/auxtrace.h
@@ -0,0 +1,643 @@
1/*
2 * auxtrace.h: AUX area trace support
3 * Copyright (c) 2013-2015, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#ifndef __PERF_AUXTRACE_H
17#define __PERF_AUXTRACE_H
18
19#include <sys/types.h>
20#include <stdbool.h>
21#include <stddef.h>
22#include <linux/list.h>
23#include <linux/perf_event.h>
24#include <linux/types.h>
25
26#include "../perf.h"
27#include "event.h"
28#include "session.h"
29#include "debug.h"
30
31union perf_event;
32struct perf_session;
33struct perf_evlist;
34struct perf_tool;
35struct option;
36struct record_opts;
37struct auxtrace_info_event;
38struct events_stats;
39
40enum auxtrace_type {
41 PERF_AUXTRACE_UNKNOWN,
42};
43
44enum itrace_period_type {
45 PERF_ITRACE_PERIOD_INSTRUCTIONS,
46 PERF_ITRACE_PERIOD_TICKS,
47 PERF_ITRACE_PERIOD_NANOSECS,
48};
49
50/**
51 * struct itrace_synth_opts - AUX area tracing synthesis options.
52 * @set: indicates whether or not options have been set
53 * @inject: indicates the event (not just the sample) must be fully synthesized
54 * because 'perf inject' will write it out
55 * @instructions: whether to synthesize 'instructions' events
56 * @branches: whether to synthesize 'branches' events
57 * @transactions: whether to synthesize events for transactions
58 * @errors: whether to synthesize decoder error events
59 * @dont_decode: whether to skip decoding entirely
60 * @log: write a decoding log
61 * @calls: limit branch samples to calls (can be combined with @returns)
62 * @returns: limit branch samples to returns (can be combined with @calls)
63 * @callchain: add callchain to 'instructions' events
64 * @callchain_sz: maximum callchain size
65 * @period: 'instructions' events period
66 * @period_type: 'instructions' events period type
67 */
68struct itrace_synth_opts {
69 bool set;
70 bool inject;
71 bool instructions;
72 bool branches;
73 bool transactions;
74 bool errors;
75 bool dont_decode;
76 bool log;
77 bool calls;
78 bool returns;
79 bool callchain;
80 unsigned int callchain_sz;
81 unsigned long long period;
82 enum itrace_period_type period_type;
83};
84
85/**
86 * struct auxtrace_index_entry - indexes a AUX area tracing event within a
87 * perf.data file.
88 * @file_offset: offset within the perf.data file
89 * @sz: size of the event
90 */
91struct auxtrace_index_entry {
92 u64 file_offset;
93 u64 sz;
94};
95
96#define PERF_AUXTRACE_INDEX_ENTRY_COUNT 256
97
98/**
99 * struct auxtrace_index - index of AUX area tracing events within a perf.data
100 * file.
101 * @list: linking a number of arrays of entries
102 * @nr: number of entries
103 * @entries: array of entries
104 */
105struct auxtrace_index {
106 struct list_head list;
107 size_t nr;
108 struct auxtrace_index_entry entries[PERF_AUXTRACE_INDEX_ENTRY_COUNT];
109};
110
111/**
112 * struct auxtrace - session callbacks to allow AUX area data decoding.
113 * @process_event: lets the decoder see all session events
114 * @flush_events: process any remaining data
115 * @free_events: free resources associated with event processing
116 * @free: free resources associated with the session
117 */
118struct auxtrace {
119 int (*process_event)(struct perf_session *session,
120 union perf_event *event,
121 struct perf_sample *sample,
122 struct perf_tool *tool);
123 int (*process_auxtrace_event)(struct perf_session *session,
124 union perf_event *event,
125 struct perf_tool *tool);
126 int (*flush_events)(struct perf_session *session,
127 struct perf_tool *tool);
128 void (*free_events)(struct perf_session *session);
129 void (*free)(struct perf_session *session);
130};
131
132/**
133 * struct auxtrace_buffer - a buffer containing AUX area tracing data.
134 * @list: buffers are queued in a list held by struct auxtrace_queue
135 * @size: size of the buffer in bytes
136 * @pid: in per-thread mode, the pid this buffer is associated with
137 * @tid: in per-thread mode, the tid this buffer is associated with
138 * @cpu: in per-cpu mode, the cpu this buffer is associated with
139 * @data: actual buffer data (can be null if the data has not been loaded)
140 * @data_offset: file offset at which the buffer can be read
141 * @mmap_addr: mmap address at which the buffer can be read
142 * @mmap_size: size of the mmap at @mmap_addr
143 * @data_needs_freeing: @data was malloc'd so free it when it is no longer
144 * needed
145 * @consecutive: the original data was split up and this buffer is consecutive
146 * to the previous buffer
147 * @offset: offset as determined by aux_head / aux_tail members of struct
148 * perf_event_mmap_page
149 * @reference: an implementation-specific reference determined when the data is
150 * recorded
151 * @buffer_nr: used to number each buffer
152 * @use_size: implementation actually only uses this number of bytes
153 * @use_data: implementation actually only uses data starting at this address
154 */
155struct auxtrace_buffer {
156 struct list_head list;
157 size_t size;
158 pid_t pid;
159 pid_t tid;
160 int cpu;
161 void *data;
162 off_t data_offset;
163 void *mmap_addr;
164 size_t mmap_size;
165 bool data_needs_freeing;
166 bool consecutive;
167 u64 offset;
168 u64 reference;
169 u64 buffer_nr;
170 size_t use_size;
171 void *use_data;
172};
173
174/**
175 * struct auxtrace_queue - a queue of AUX area tracing data buffers.
176 * @head: head of buffer list
177 * @tid: in per-thread mode, the tid this queue is associated with
178 * @cpu: in per-cpu mode, the cpu this queue is associated with
179 * @set: %true once this queue has been dedicated to a specific thread or cpu
180 * @priv: implementation-specific data
181 */
182struct auxtrace_queue {
183 struct list_head head;
184 pid_t tid;
185 int cpu;
186 bool set;
187 void *priv;
188};
189
190/**
191 * struct auxtrace_queues - an array of AUX area tracing queues.
192 * @queue_array: array of queues
193 * @nr_queues: number of queues
194 * @new_data: set whenever new data is queued
195 * @populated: queues have been fully populated using the auxtrace_index
196 * @next_buffer_nr: used to number each buffer
197 */
198struct auxtrace_queues {
199 struct auxtrace_queue *queue_array;
200 unsigned int nr_queues;
201 bool new_data;
202 bool populated;
203 u64 next_buffer_nr;
204};
205
206/**
207 * struct auxtrace_heap_item - element of struct auxtrace_heap.
208 * @queue_nr: queue number
209 * @ordinal: value used for sorting (lowest ordinal is top of the heap) expected
210 * to be a timestamp
211 */
212struct auxtrace_heap_item {
213 unsigned int queue_nr;
214 u64 ordinal;
215};
216
217/**
218 * struct auxtrace_heap - a heap suitable for sorting AUX area tracing queues.
219 * @heap_array: the heap
220 * @heap_cnt: the number of elements in the heap
221 * @heap_sz: maximum number of elements (grows as needed)
222 */
223struct auxtrace_heap {
224 struct auxtrace_heap_item *heap_array;
225 unsigned int heap_cnt;
226 unsigned int heap_sz;
227};
228
229/**
230 * struct auxtrace_mmap - records an mmap of the auxtrace buffer.
231 * @base: address of mapped area
232 * @userpg: pointer to buffer's perf_event_mmap_page
233 * @mask: %0 if @len is not a power of two, otherwise (@len - %1)
234 * @len: size of mapped area
235 * @prev: previous aux_head
236 * @idx: index of this mmap
237 * @tid: tid for a per-thread mmap (also set if there is only 1 tid on a per-cpu
238 * mmap) otherwise %0
239 * @cpu: cpu number for a per-cpu mmap otherwise %-1
240 */
241struct auxtrace_mmap {
242 void *base;
243 void *userpg;
244 size_t mask;
245 size_t len;
246 u64 prev;
247 int idx;
248 pid_t tid;
249 int cpu;
250};
251
252/**
253 * struct auxtrace_mmap_params - parameters to set up struct auxtrace_mmap.
254 * @mask: %0 if @len is not a power of two, otherwise (@len - %1)
255 * @offset: file offset of mapped area
256 * @len: size of mapped area
257 * @prot: mmap memory protection
258 * @idx: index of this mmap
259 * @tid: tid for a per-thread mmap (also set if there is only 1 tid on a per-cpu
260 * mmap) otherwise %0
261 * @cpu: cpu number for a per-cpu mmap otherwise %-1
262 */
263struct auxtrace_mmap_params {
264 size_t mask;
265 off_t offset;
266 size_t len;
267 int prot;
268 int idx;
269 pid_t tid;
270 int cpu;
271};
272
273/**
274 * struct auxtrace_record - callbacks for recording AUX area data.
275 * @recording_options: validate and process recording options
276 * @info_priv_size: return the size of the private data in auxtrace_info_event
277 * @info_fill: fill-in the private data in auxtrace_info_event
278 * @free: free this auxtrace record structure
279 * @snapshot_start: starting a snapshot
280 * @snapshot_finish: finishing a snapshot
281 * @find_snapshot: find data to snapshot within auxtrace mmap
282 * @parse_snapshot_options: parse snapshot options
283 * @reference: provide a 64-bit reference number for auxtrace_event
284 * @read_finish: called after reading from an auxtrace mmap
285 */
286struct auxtrace_record {
287 int (*recording_options)(struct auxtrace_record *itr,
288 struct perf_evlist *evlist,
289 struct record_opts *opts);
290 size_t (*info_priv_size)(struct auxtrace_record *itr);
291 int (*info_fill)(struct auxtrace_record *itr,
292 struct perf_session *session,
293 struct auxtrace_info_event *auxtrace_info,
294 size_t priv_size);
295 void (*free)(struct auxtrace_record *itr);
296 int (*snapshot_start)(struct auxtrace_record *itr);
297 int (*snapshot_finish)(struct auxtrace_record *itr);
298 int (*find_snapshot)(struct auxtrace_record *itr, int idx,
299 struct auxtrace_mmap *mm, unsigned char *data,
300 u64 *head, u64 *old);
301 int (*parse_snapshot_options)(struct auxtrace_record *itr,
302 struct record_opts *opts,
303 const char *str);
304 u64 (*reference)(struct auxtrace_record *itr);
305 int (*read_finish)(struct auxtrace_record *itr, int idx);
306};
307
308#ifdef HAVE_AUXTRACE_SUPPORT
309
310/*
311 * In snapshot mode the mmapped page is read-only which makes using
312 * __sync_val_compare_and_swap() problematic. However, snapshot mode expects
313 * the buffer is not updated while the snapshot is made (e.g. Intel PT disables
314 * the event) so there is not a race anyway.
315 */
316static inline u64 auxtrace_mmap__read_snapshot_head(struct auxtrace_mmap *mm)
317{
318 struct perf_event_mmap_page *pc = mm->userpg;
319 u64 head = ACCESS_ONCE(pc->aux_head);
320
321 /* Ensure all reads are done after we read the head */
322 rmb();
323 return head;
324}
325
326static inline u64 auxtrace_mmap__read_head(struct auxtrace_mmap *mm)
327{
328 struct perf_event_mmap_page *pc = mm->userpg;
329#if BITS_PER_LONG == 64 || !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT)
330 u64 head = ACCESS_ONCE(pc->aux_head);
331#else
332 u64 head = __sync_val_compare_and_swap(&pc->aux_head, 0, 0);
333#endif
334
335 /* Ensure all reads are done after we read the head */
336 rmb();
337 return head;
338}
339
340static inline void auxtrace_mmap__write_tail(struct auxtrace_mmap *mm, u64 tail)
341{
342 struct perf_event_mmap_page *pc = mm->userpg;
343#if BITS_PER_LONG != 64 && defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT)
344 u64 old_tail;
345#endif
346
347 /* Ensure all reads are done before we write the tail out */
348 mb();
349#if BITS_PER_LONG == 64 || !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT)
350 pc->aux_tail = tail;
351#else
352 do {
353 old_tail = __sync_val_compare_and_swap(&pc->aux_tail, 0, 0);
354 } while (!__sync_bool_compare_and_swap(&pc->aux_tail, old_tail, tail));
355#endif
356}
357
358int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
359 struct auxtrace_mmap_params *mp,
360 void *userpg, int fd);
361void auxtrace_mmap__munmap(struct auxtrace_mmap *mm);
362void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp,
363 off_t auxtrace_offset,
364 unsigned int auxtrace_pages,
365 bool auxtrace_overwrite);
366void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
367 struct perf_evlist *evlist, int idx,
368 bool per_cpu);
369
370typedef int (*process_auxtrace_t)(struct perf_tool *tool,
371 union perf_event *event, void *data1,
372 size_t len1, void *data2, size_t len2);
373
374int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
375 struct perf_tool *tool, process_auxtrace_t fn);
376
377int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm,
378 struct auxtrace_record *itr,
379 struct perf_tool *tool, process_auxtrace_t fn,
380 size_t snapshot_size);
381
382int auxtrace_queues__init(struct auxtrace_queues *queues);
383int auxtrace_queues__add_event(struct auxtrace_queues *queues,
384 struct perf_session *session,
385 union perf_event *event, off_t data_offset,
386 struct auxtrace_buffer **buffer_ptr);
387void auxtrace_queues__free(struct auxtrace_queues *queues);
388int auxtrace_queues__process_index(struct auxtrace_queues *queues,
389 struct perf_session *session);
390struct auxtrace_buffer *auxtrace_buffer__next(struct auxtrace_queue *queue,
391 struct auxtrace_buffer *buffer);
392void *auxtrace_buffer__get_data(struct auxtrace_buffer *buffer, int fd);
393void auxtrace_buffer__put_data(struct auxtrace_buffer *buffer);
394void auxtrace_buffer__drop_data(struct auxtrace_buffer *buffer);
395void auxtrace_buffer__free(struct auxtrace_buffer *buffer);
396
397int auxtrace_heap__add(struct auxtrace_heap *heap, unsigned int queue_nr,
398 u64 ordinal);
399void auxtrace_heap__pop(struct auxtrace_heap *heap);
400void auxtrace_heap__free(struct auxtrace_heap *heap);
401
402struct auxtrace_cache_entry {
403 struct hlist_node hash;
404 u32 key;
405};
406
407struct auxtrace_cache *auxtrace_cache__new(unsigned int bits, size_t entry_size,
408 unsigned int limit_percent);
409void auxtrace_cache__free(struct auxtrace_cache *auxtrace_cache);
410void *auxtrace_cache__alloc_entry(struct auxtrace_cache *c);
411void auxtrace_cache__free_entry(struct auxtrace_cache *c, void *entry);
412int auxtrace_cache__add(struct auxtrace_cache *c, u32 key,
413 struct auxtrace_cache_entry *entry);
414void *auxtrace_cache__lookup(struct auxtrace_cache *c, u32 key);
415
416struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist,
417 int *err);
418
419int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
420 struct record_opts *opts,
421 const char *str);
422int auxtrace_record__options(struct auxtrace_record *itr,
423 struct perf_evlist *evlist,
424 struct record_opts *opts);
425size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr);
426int auxtrace_record__info_fill(struct auxtrace_record *itr,
427 struct perf_session *session,
428 struct auxtrace_info_event *auxtrace_info,
429 size_t priv_size);
430void auxtrace_record__free(struct auxtrace_record *itr);
431int auxtrace_record__snapshot_start(struct auxtrace_record *itr);
432int auxtrace_record__snapshot_finish(struct auxtrace_record *itr);
433int auxtrace_record__find_snapshot(struct auxtrace_record *itr, int idx,
434 struct auxtrace_mmap *mm,
435 unsigned char *data, u64 *head, u64 *old);
436u64 auxtrace_record__reference(struct auxtrace_record *itr);
437
438int auxtrace_index__auxtrace_event(struct list_head *head, union perf_event *event,
439 off_t file_offset);
440int auxtrace_index__write(int fd, struct list_head *head);
441int auxtrace_index__process(int fd, u64 size, struct perf_session *session,
442 bool needs_swap);
443void auxtrace_index__free(struct list_head *head);
444
445void auxtrace_synth_error(struct auxtrace_error_event *auxtrace_error, int type,
446 int code, int cpu, pid_t pid, pid_t tid, u64 ip,
447 const char *msg);
448
449int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
450 struct perf_tool *tool,
451 struct perf_session *session,
452 perf_event__handler_t process);
453int perf_event__process_auxtrace_info(struct perf_tool *tool,
454 union perf_event *event,
455 struct perf_session *session);
456s64 perf_event__process_auxtrace(struct perf_tool *tool,
457 union perf_event *event,
458 struct perf_session *session);
459int perf_event__process_auxtrace_error(struct perf_tool *tool,
460 union perf_event *event,
461 struct perf_session *session);
462int itrace_parse_synth_opts(const struct option *opt, const char *str,
463 int unset);
464void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts);
465
466size_t perf_event__fprintf_auxtrace_error(union perf_event *event, FILE *fp);
467void perf_session__auxtrace_error_inc(struct perf_session *session,
468 union perf_event *event);
469void events_stats__auxtrace_error_warn(const struct events_stats *stats);
470
471static inline int auxtrace__process_event(struct perf_session *session,
472 union perf_event *event,
473 struct perf_sample *sample,
474 struct perf_tool *tool)
475{
476 if (!session->auxtrace)
477 return 0;
478
479 return session->auxtrace->process_event(session, event, sample, tool);
480}
481
482static inline int auxtrace__flush_events(struct perf_session *session,
483 struct perf_tool *tool)
484{
485 if (!session->auxtrace)
486 return 0;
487
488 return session->auxtrace->flush_events(session, tool);
489}
490
491static inline void auxtrace__free_events(struct perf_session *session)
492{
493 if (!session->auxtrace)
494 return;
495
496 return session->auxtrace->free_events(session);
497}
498
499static inline void auxtrace__free(struct perf_session *session)
500{
501 if (!session->auxtrace)
502 return;
503
504 return session->auxtrace->free(session);
505}
506
507#else
508
509static inline struct auxtrace_record *
510auxtrace_record__init(struct perf_evlist *evlist __maybe_unused,
511 int *err __maybe_unused)
512{
513 *err = 0;
514 return NULL;
515}
516
517static inline
518void auxtrace_record__free(struct auxtrace_record *itr __maybe_unused)
519{
520}
521
522static inline int
523perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr __maybe_unused,
524 struct perf_tool *tool __maybe_unused,
525 struct perf_session *session __maybe_unused,
526 perf_event__handler_t process __maybe_unused)
527{
528 return -EINVAL;
529}
530
531static inline
532int auxtrace_record__options(struct auxtrace_record *itr __maybe_unused,
533 struct perf_evlist *evlist __maybe_unused,
534 struct record_opts *opts __maybe_unused)
535{
536 return 0;
537}
538
539#define perf_event__process_auxtrace_info 0
540#define perf_event__process_auxtrace 0
541#define perf_event__process_auxtrace_error 0
542
543static inline
544void perf_session__auxtrace_error_inc(struct perf_session *session
545 __maybe_unused,
546 union perf_event *event
547 __maybe_unused)
548{
549}
550
551static inline
552void events_stats__auxtrace_error_warn(const struct events_stats *stats
553 __maybe_unused)
554{
555}
556
557static inline
558int itrace_parse_synth_opts(const struct option *opt __maybe_unused,
559 const char *str __maybe_unused,
560 int unset __maybe_unused)
561{
562 pr_err("AUX area tracing not supported\n");
563 return -EINVAL;
564}
565
566static inline
567int auxtrace_parse_snapshot_options(struct auxtrace_record *itr __maybe_unused,
568 struct record_opts *opts __maybe_unused,
569 const char *str)
570{
571 if (!str)
572 return 0;
573 pr_err("AUX area tracing not supported\n");
574 return -EINVAL;
575}
576
577static inline
578int auxtrace__process_event(struct perf_session *session __maybe_unused,
579 union perf_event *event __maybe_unused,
580 struct perf_sample *sample __maybe_unused,
581 struct perf_tool *tool __maybe_unused)
582{
583 return 0;
584}
585
586static inline
587int auxtrace__flush_events(struct perf_session *session __maybe_unused,
588 struct perf_tool *tool __maybe_unused)
589{
590 return 0;
591}
592
593static inline
594void auxtrace__free_events(struct perf_session *session __maybe_unused)
595{
596}
597
598static inline
599void auxtrace_cache__free(struct auxtrace_cache *auxtrace_cache __maybe_unused)
600{
601}
602
603static inline
604void auxtrace__free(struct perf_session *session __maybe_unused)
605{
606}
607
608static inline
609int auxtrace_index__write(int fd __maybe_unused,
610 struct list_head *head __maybe_unused)
611{
612 return -EINVAL;
613}
614
615static inline
616int auxtrace_index__process(int fd __maybe_unused,
617 u64 size __maybe_unused,
618 struct perf_session *session __maybe_unused,
619 bool needs_swap __maybe_unused)
620{
621 return -EINVAL;
622}
623
624static inline
625void auxtrace_index__free(struct list_head *head __maybe_unused)
626{
627}
628
629int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
630 struct auxtrace_mmap_params *mp,
631 void *userpg, int fd);
632void auxtrace_mmap__munmap(struct auxtrace_mmap *mm);
633void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp,
634 off_t auxtrace_offset,
635 unsigned int auxtrace_pages,
636 bool auxtrace_overwrite);
637void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
638 struct perf_evlist *evlist, int idx,
639 bool per_cpu);
640
641#endif
642
643#endif
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 61867dff5d5a..1f6fc2323ef9 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -43,6 +43,7 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
43 if (al.map != NULL) 43 if (al.map != NULL)
44 al.map->dso->hit = 1; 44 al.map->dso->hit = 1;
45 45
46 thread__put(thread);
46 return 0; 47 return 0;
47} 48}
48 49
@@ -59,8 +60,10 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
59 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, 60 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
60 event->fork.ppid, event->fork.ptid); 61 event->fork.ppid, event->fork.ptid);
61 62
62 if (thread) 63 if (thread) {
63 machine__remove_thread(machine, thread); 64 machine__remove_thread(machine, thread);
65 thread__put(thread);
66 }
64 67
65 return 0; 68 return 0;
66} 69}
@@ -159,15 +162,20 @@ static int write_buildid(const char *name, size_t name_len, u8 *build_id,
159 return write_padded(fd, name, name_len + 1, len); 162 return write_padded(fd, name, name_len + 1, len);
160} 163}
161 164
162static int __dsos__write_buildid_table(struct list_head *head, 165static int machine__write_buildid_table(struct machine *machine, int fd)
163 struct machine *machine,
164 pid_t pid, u16 misc, int fd)
165{ 166{
167 int err = 0;
166 char nm[PATH_MAX]; 168 char nm[PATH_MAX];
167 struct dso *pos; 169 struct dso *pos;
170 u16 kmisc = PERF_RECORD_MISC_KERNEL,
171 umisc = PERF_RECORD_MISC_USER;
168 172
169 dsos__for_each_with_build_id(pos, head) { 173 if (!machine__is_host(machine)) {
170 int err; 174 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
175 umisc = PERF_RECORD_MISC_GUEST_USER;
176 }
177
178 dsos__for_each_with_build_id(pos, &machine->dsos.head) {
171 const char *name; 179 const char *name;
172 size_t name_len; 180 size_t name_len;
173 181
@@ -186,32 +194,12 @@ static int __dsos__write_buildid_table(struct list_head *head,
186 name_len = pos->long_name_len + 1; 194 name_len = pos->long_name_len + 1;
187 } 195 }
188 196
189 err = write_buildid(name, name_len, pos->build_id, 197 err = write_buildid(name, name_len, pos->build_id, machine->pid,
190 pid, misc, fd); 198 pos->kernel ? kmisc : umisc, fd);
191 if (err) 199 if (err)
192 return err; 200 break;
193 }
194
195 return 0;
196}
197
198static int machine__write_buildid_table(struct machine *machine, int fd)
199{
200 int err;
201 u16 kmisc = PERF_RECORD_MISC_KERNEL,
202 umisc = PERF_RECORD_MISC_USER;
203
204 if (!machine__is_host(machine)) {
205 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
206 umisc = PERF_RECORD_MISC_GUEST_USER;
207 } 201 }
208 202
209 err = __dsos__write_buildid_table(&machine->kernel_dsos.head, machine,
210 machine->pid, kmisc, fd);
211 if (err == 0)
212 err = __dsos__write_buildid_table(&machine->user_dsos.head,
213 machine, machine->pid, umisc,
214 fd);
215 return err; 203 return err;
216} 204}
217 205
@@ -244,13 +232,7 @@ static int __dsos__hit_all(struct list_head *head)
244 232
245static int machine__hit_all_dsos(struct machine *machine) 233static int machine__hit_all_dsos(struct machine *machine)
246{ 234{
247 int err; 235 return __dsos__hit_all(&machine->dsos.head);
248
249 err = __dsos__hit_all(&machine->kernel_dsos.head);
250 if (err)
251 return err;
252
253 return __dsos__hit_all(&machine->user_dsos.head);
254} 236}
255 237
256int dsos__hit_all(struct perf_session *session) 238int dsos__hit_all(struct perf_session *session)
@@ -490,9 +472,7 @@ static int __dsos__cache_build_ids(struct list_head *head,
490 472
491static int machine__cache_build_ids(struct machine *machine) 473static int machine__cache_build_ids(struct machine *machine)
492{ 474{
493 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine); 475 return __dsos__cache_build_ids(&machine->dsos.head, machine);
494 ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine);
495 return ret;
496} 476}
497 477
498int perf_session__cache_build_ids(struct perf_session *session) 478int perf_session__cache_build_ids(struct perf_session *session)
@@ -517,11 +497,7 @@ int perf_session__cache_build_ids(struct perf_session *session)
517 497
518static bool machine__read_build_ids(struct machine *machine, bool with_hits) 498static bool machine__read_build_ids(struct machine *machine, bool with_hits)
519{ 499{
520 bool ret; 500 return __dsos__read_build_ids(&machine->dsos.head, with_hits);
521
522 ret = __dsos__read_build_ids(&machine->kernel_dsos.head, with_hits);
523 ret |= __dsos__read_build_ids(&machine->user_dsos.head, with_hits);
524 return ret;
525} 501}
526 502
527bool perf_session__read_build_ids(struct perf_session *session, bool with_hits) 503bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index fbcca21d66ab..c861373aaed3 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -30,7 +30,6 @@ extern const char *perf_config_dirname(const char *, const char *);
30 30
31/* pager.c */ 31/* pager.c */
32extern void setup_pager(void); 32extern void setup_pager(void);
33extern const char *pager_program;
34extern int pager_in_use(void); 33extern int pager_in_use(void);
35extern int pager_use_color; 34extern int pager_use_color;
36 35
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 6033a0a212ca..679c2c6d8ade 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -72,6 +72,10 @@ extern struct callchain_param callchain_param;
72struct callchain_list { 72struct callchain_list {
73 u64 ip; 73 u64 ip;
74 struct map_symbol ms; 74 struct map_symbol ms;
75 struct /* for TUI */ {
76 bool unfolded;
77 bool has_children;
78 };
75 char *srcline; 79 char *srcline;
76 struct list_head list; 80 struct list_head list;
77}; 81};
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 88f7be399432..32e12ecfe9c5 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -115,23 +115,19 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
115 goto found; 115 goto found;
116 n++; 116 n++;
117 } 117 }
118 if (cgrp->refcnt == 0) 118 if (atomic_read(&cgrp->refcnt) == 0)
119 free(cgrp); 119 free(cgrp);
120 120
121 return -1; 121 return -1;
122found: 122found:
123 cgrp->refcnt++; 123 atomic_inc(&cgrp->refcnt);
124 counter->cgrp = cgrp; 124 counter->cgrp = cgrp;
125 return 0; 125 return 0;
126} 126}
127 127
128void close_cgroup(struct cgroup_sel *cgrp) 128void close_cgroup(struct cgroup_sel *cgrp)
129{ 129{
130 if (!cgrp) 130 if (cgrp && atomic_dec_and_test(&cgrp->refcnt)) {
131 return;
132
133 /* XXX: not reentrant */
134 if (--cgrp->refcnt == 0) {
135 close(cgrp->fd); 131 close(cgrp->fd);
136 zfree(&cgrp->name); 132 zfree(&cgrp->name);
137 free(cgrp); 133 free(cgrp);
diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h
index 89acd6debdc5..b4b8cb42fe5e 100644
--- a/tools/perf/util/cgroup.h
+++ b/tools/perf/util/cgroup.h
@@ -1,12 +1,14 @@
1#ifndef __CGROUP_H__ 1#ifndef __CGROUP_H__
2#define __CGROUP_H__ 2#define __CGROUP_H__
3 3
4#include <linux/atomic.h>
5
4struct option; 6struct option;
5 7
6struct cgroup_sel { 8struct cgroup_sel {
7 char *name; 9 char *name;
8 int fd; 10 int fd;
9 int refcnt; 11 atomic_t refcnt;
10}; 12};
11 13
12 14
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
index b2bb59df65e1..21b7ff382c3f 100644
--- a/tools/perf/util/comm.c
+++ b/tools/perf/util/comm.c
@@ -2,24 +2,27 @@
2#include "util.h" 2#include "util.h"
3#include <stdlib.h> 3#include <stdlib.h>
4#include <stdio.h> 4#include <stdio.h>
5#include <linux/atomic.h>
5 6
6struct comm_str { 7struct comm_str {
7 char *str; 8 char *str;
8 struct rb_node rb_node; 9 struct rb_node rb_node;
9 int ref; 10 atomic_t refcnt;
10}; 11};
11 12
12/* Should perhaps be moved to struct machine */ 13/* Should perhaps be moved to struct machine */
13static struct rb_root comm_str_root; 14static struct rb_root comm_str_root;
14 15
15static void comm_str__get(struct comm_str *cs) 16static struct comm_str *comm_str__get(struct comm_str *cs)
16{ 17{
17 cs->ref++; 18 if (cs)
19 atomic_inc(&cs->refcnt);
20 return cs;
18} 21}
19 22
20static void comm_str__put(struct comm_str *cs) 23static void comm_str__put(struct comm_str *cs)
21{ 24{
22 if (!--cs->ref) { 25 if (cs && atomic_dec_and_test(&cs->refcnt)) {
23 rb_erase(&cs->rb_node, &comm_str_root); 26 rb_erase(&cs->rb_node, &comm_str_root);
24 zfree(&cs->str); 27 zfree(&cs->str);
25 free(cs); 28 free(cs);
@@ -40,6 +43,8 @@ static struct comm_str *comm_str__alloc(const char *str)
40 return NULL; 43 return NULL;
41 } 44 }
42 45
46 atomic_set(&cs->refcnt, 0);
47
43 return cs; 48 return cs;
44} 49}
45 50
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index dd17c9a32fbc..5bfc1198ab46 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -14,6 +14,7 @@
14#include <babeltrace/ctf-writer/event.h> 14#include <babeltrace/ctf-writer/event.h>
15#include <babeltrace/ctf-writer/event-types.h> 15#include <babeltrace/ctf-writer/event-types.h>
16#include <babeltrace/ctf-writer/event-fields.h> 16#include <babeltrace/ctf-writer/event-fields.h>
17#include <babeltrace/ctf-ir/utils.h>
17#include <babeltrace/ctf/events.h> 18#include <babeltrace/ctf/events.h>
18#include <traceevent/event-parse.h> 19#include <traceevent/event-parse.h>
19#include "asm/bug.h" 20#include "asm/bug.h"
@@ -38,12 +39,21 @@ struct evsel_priv {
38 struct bt_ctf_event_class *event_class; 39 struct bt_ctf_event_class *event_class;
39}; 40};
40 41
42#define MAX_CPUS 4096
43
44struct ctf_stream {
45 struct bt_ctf_stream *stream;
46 int cpu;
47 u32 count;
48};
49
41struct ctf_writer { 50struct ctf_writer {
42 /* writer primitives */ 51 /* writer primitives */
43 struct bt_ctf_writer *writer; 52 struct bt_ctf_writer *writer;
44 struct bt_ctf_stream *stream; 53 struct ctf_stream **stream;
45 struct bt_ctf_stream_class *stream_class; 54 int stream_cnt;
46 struct bt_ctf_clock *clock; 55 struct bt_ctf_stream_class *stream_class;
56 struct bt_ctf_clock *clock;
47 57
48 /* data types */ 58 /* data types */
49 union { 59 union {
@@ -65,6 +75,9 @@ struct convert {
65 75
66 u64 events_size; 76 u64 events_size;
67 u64 events_count; 77 u64 events_count;
78
79 /* Ordered events configured queue size. */
80 u64 queue_size;
68}; 81};
69 82
70static int value_set(struct bt_ctf_field_type *type, 83static int value_set(struct bt_ctf_field_type *type,
@@ -153,6 +166,43 @@ get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
153 return cw->data.u32; 166 return cw->data.u32;
154} 167}
155 168
169static unsigned long long adjust_signedness(unsigned long long value_int, int size)
170{
171 unsigned long long value_mask;
172
173 /*
174 * value_mask = (1 << (size * 8 - 1)) - 1.
175 * Directly set value_mask for code readers.
176 */
177 switch (size) {
178 case 1:
179 value_mask = 0x7fULL;
180 break;
181 case 2:
182 value_mask = 0x7fffULL;
183 break;
184 case 4:
185 value_mask = 0x7fffffffULL;
186 break;
187 case 8:
188 /*
189 * For 64 bit value, return it self. There is no need
190 * to fill high bit.
191 */
192 /* Fall through */
193 default:
194 /* BUG! */
195 return value_int;
196 }
197
198 /* If it is a positive value, don't adjust. */
199 if ((value_int & (~0ULL - value_mask)) == 0)
200 return value_int;
201
202 /* Fill upper part of value_int with 1 to make it a negative long long. */
203 return (value_int & value_mask) | ~value_mask;
204}
205
156static int add_tracepoint_field_value(struct ctf_writer *cw, 206static int add_tracepoint_field_value(struct ctf_writer *cw,
157 struct bt_ctf_event_class *event_class, 207 struct bt_ctf_event_class *event_class,
158 struct bt_ctf_event *event, 208 struct bt_ctf_event *event,
@@ -164,7 +214,6 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
164 struct bt_ctf_field *field; 214 struct bt_ctf_field *field;
165 const char *name = fmtf->name; 215 const char *name = fmtf->name;
166 void *data = sample->raw_data; 216 void *data = sample->raw_data;
167 unsigned long long value_int;
168 unsigned long flags = fmtf->flags; 217 unsigned long flags = fmtf->flags;
169 unsigned int n_items; 218 unsigned int n_items;
170 unsigned int i; 219 unsigned int i;
@@ -172,6 +221,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
172 unsigned int len; 221 unsigned int len;
173 int ret; 222 int ret;
174 223
224 name = fmtf->alias;
175 offset = fmtf->offset; 225 offset = fmtf->offset;
176 len = fmtf->size; 226 len = fmtf->size;
177 if (flags & FIELD_IS_STRING) 227 if (flags & FIELD_IS_STRING)
@@ -208,11 +258,6 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
208 type = get_tracepoint_field_type(cw, fmtf); 258 type = get_tracepoint_field_type(cw, fmtf);
209 259
210 for (i = 0; i < n_items; i++) { 260 for (i = 0; i < n_items; i++) {
211 if (!(flags & FIELD_IS_STRING))
212 value_int = pevent_read_number(
213 fmtf->event->pevent,
214 data + offset + i * len, len);
215
216 if (flags & FIELD_IS_ARRAY) 261 if (flags & FIELD_IS_ARRAY)
217 field = bt_ctf_field_array_get_field(array_field, i); 262 field = bt_ctf_field_array_get_field(array_field, i);
218 else 263 else
@@ -226,12 +271,21 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
226 if (flags & FIELD_IS_STRING) 271 if (flags & FIELD_IS_STRING)
227 ret = bt_ctf_field_string_set_value(field, 272 ret = bt_ctf_field_string_set_value(field,
228 data + offset + i * len); 273 data + offset + i * len);
229 else if (!(flags & FIELD_IS_SIGNED)) 274 else {
230 ret = bt_ctf_field_unsigned_integer_set_value( 275 unsigned long long value_int;
231 field, value_int); 276
232 else 277 value_int = pevent_read_number(
233 ret = bt_ctf_field_signed_integer_set_value( 278 fmtf->event->pevent,
234 field, value_int); 279 data + offset + i * len, len);
280
281 if (!(flags & FIELD_IS_SIGNED))
282 ret = bt_ctf_field_unsigned_integer_set_value(
283 field, value_int);
284 else
285 ret = bt_ctf_field_signed_integer_set_value(
286 field, adjust_signedness(value_int, len));
287 }
288
235 if (ret) { 289 if (ret) {
236 pr_err("failed to set file value %s\n", name); 290 pr_err("failed to set file value %s\n", name);
237 goto err_put_field; 291 goto err_put_field;
@@ -346,12 +400,6 @@ static int add_generic_values(struct ctf_writer *cw,
346 return -1; 400 return -1;
347 } 401 }
348 402
349 if (type & PERF_SAMPLE_CPU) {
350 ret = value_set_u32(cw, event, "perf_cpu", sample->cpu);
351 if (ret)
352 return -1;
353 }
354
355 if (type & PERF_SAMPLE_PERIOD) { 403 if (type & PERF_SAMPLE_PERIOD) {
356 ret = value_set_u64(cw, event, "perf_period", sample->period); 404 ret = value_set_u64(cw, event, "perf_period", sample->period);
357 if (ret) 405 if (ret)
@@ -381,6 +429,129 @@ static int add_generic_values(struct ctf_writer *cw,
381 return 0; 429 return 0;
382} 430}
383 431
432static int ctf_stream__flush(struct ctf_stream *cs)
433{
434 int err = 0;
435
436 if (cs) {
437 err = bt_ctf_stream_flush(cs->stream);
438 if (err)
439 pr_err("CTF stream %d flush failed\n", cs->cpu);
440
441 pr("Flush stream for cpu %d (%u samples)\n",
442 cs->cpu, cs->count);
443
444 cs->count = 0;
445 }
446
447 return err;
448}
449
450static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu)
451{
452 struct ctf_stream *cs;
453 struct bt_ctf_field *pkt_ctx = NULL;
454 struct bt_ctf_field *cpu_field = NULL;
455 struct bt_ctf_stream *stream = NULL;
456 int ret;
457
458 cs = zalloc(sizeof(*cs));
459 if (!cs) {
460 pr_err("Failed to allocate ctf stream\n");
461 return NULL;
462 }
463
464 stream = bt_ctf_writer_create_stream(cw->writer, cw->stream_class);
465 if (!stream) {
466 pr_err("Failed to create CTF stream\n");
467 goto out;
468 }
469
470 pkt_ctx = bt_ctf_stream_get_packet_context(stream);
471 if (!pkt_ctx) {
472 pr_err("Failed to obtain packet context\n");
473 goto out;
474 }
475
476 cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, "cpu_id");
477 bt_ctf_field_put(pkt_ctx);
478 if (!cpu_field) {
479 pr_err("Failed to obtain cpu field\n");
480 goto out;
481 }
482
483 ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu);
484 if (ret) {
485 pr_err("Failed to update CPU number\n");
486 goto out;
487 }
488
489 bt_ctf_field_put(cpu_field);
490
491 cs->cpu = cpu;
492 cs->stream = stream;
493 return cs;
494
495out:
496 if (cpu_field)
497 bt_ctf_field_put(cpu_field);
498 if (stream)
499 bt_ctf_stream_put(stream);
500
501 free(cs);
502 return NULL;
503}
504
505static void ctf_stream__delete(struct ctf_stream *cs)
506{
507 if (cs) {
508 bt_ctf_stream_put(cs->stream);
509 free(cs);
510 }
511}
512
513static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu)
514{
515 struct ctf_stream *cs = cw->stream[cpu];
516
517 if (!cs) {
518 cs = ctf_stream__create(cw, cpu);
519 cw->stream[cpu] = cs;
520 }
521
522 return cs;
523}
524
525static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample,
526 struct perf_evsel *evsel)
527{
528 int cpu = 0;
529
530 if (evsel->attr.sample_type & PERF_SAMPLE_CPU)
531 cpu = sample->cpu;
532
533 if (cpu > cw->stream_cnt) {
534 pr_err("Event was recorded for CPU %d, limit is at %d.\n",
535 cpu, cw->stream_cnt);
536 cpu = 0;
537 }
538
539 return cpu;
540}
541
542#define STREAM_FLUSH_COUNT 100000
543
544/*
545 * Currently we have no other way to determine the
546 * time for the stream flush other than keep track
547 * of the number of events and check it against
548 * threshold.
549 */
550static bool is_flush_needed(struct ctf_stream *cs)
551{
552 return cs->count >= STREAM_FLUSH_COUNT;
553}
554
384static int process_sample_event(struct perf_tool *tool, 555static int process_sample_event(struct perf_tool *tool,
385 union perf_event *_event __maybe_unused, 556 union perf_event *_event __maybe_unused,
386 struct perf_sample *sample, 557 struct perf_sample *sample,
@@ -390,6 +561,7 @@ static int process_sample_event(struct perf_tool *tool,
390 struct convert *c = container_of(tool, struct convert, tool); 561 struct convert *c = container_of(tool, struct convert, tool);
391 struct evsel_priv *priv = evsel->priv; 562 struct evsel_priv *priv = evsel->priv;
392 struct ctf_writer *cw = &c->writer; 563 struct ctf_writer *cw = &c->writer;
564 struct ctf_stream *cs;
393 struct bt_ctf_event_class *event_class; 565 struct bt_ctf_event_class *event_class;
394 struct bt_ctf_event *event; 566 struct bt_ctf_event *event;
395 int ret; 567 int ret;
@@ -424,9 +596,93 @@ static int process_sample_event(struct perf_tool *tool,
424 return -1; 596 return -1;
425 } 597 }
426 598
427 bt_ctf_stream_append_event(cw->stream, event); 599 cs = ctf_stream(cw, get_sample_cpu(cw, sample, evsel));
600 if (cs) {
601 if (is_flush_needed(cs))
602 ctf_stream__flush(cs);
603
604 cs->count++;
605 bt_ctf_stream_append_event(cs->stream, event);
606 }
607
428 bt_ctf_event_put(event); 608 bt_ctf_event_put(event);
429 return 0; 609 return cs ? 0 : -1;
610}
611
612/* If dup < 0, add a prefix. Else, add _dupl_X suffix. */
613static char *change_name(char *name, char *orig_name, int dup)
614{
615 char *new_name = NULL;
616 size_t len;
617
618 if (!name)
619 name = orig_name;
620
621 if (dup >= 10)
622 goto out;
623 /*
624 * Add '_' prefix to potential keywork. According to
625 * Mathieu Desnoyers (https://lkml.org/lkml/2015/1/23/652),
626 * futher CTF spec updating may require us to use '$'.
627 */
628 if (dup < 0)
629 len = strlen(name) + sizeof("_");
630 else
631 len = strlen(orig_name) + sizeof("_dupl_X");
632
633 new_name = malloc(len);
634 if (!new_name)
635 goto out;
636
637 if (dup < 0)
638 snprintf(new_name, len, "_%s", name);
639 else
640 snprintf(new_name, len, "%s_dupl_%d", orig_name, dup);
641
642out:
643 if (name != orig_name)
644 free(name);
645 return new_name;
646}
647
648static int event_class_add_field(struct bt_ctf_event_class *event_class,
649 struct bt_ctf_field_type *type,
650 struct format_field *field)
651{
652 struct bt_ctf_field_type *t = NULL;
653 char *name;
654 int dup = 1;
655 int ret;
656
657 /* alias was already assigned */
658 if (field->alias != field->name)
659 return bt_ctf_event_class_add_field(event_class, type,
660 (char *)field->alias);
661
662 name = field->name;
663
664 /* If 'name' is a keywork, add prefix. */
665 if (bt_ctf_validate_identifier(name))
666 name = change_name(name, field->name, -1);
667
668 if (!name) {
669 pr_err("Failed to fix invalid identifier.");
670 return -1;
671 }
672 while ((t = bt_ctf_event_class_get_field_by_name(event_class, name))) {
673 bt_ctf_field_type_put(t);
674 name = change_name(name, field->name, dup++);
675 if (!name) {
676 pr_err("Failed to create dup name for '%s'\n", field->name);
677 return -1;
678 }
679 }
680
681 ret = bt_ctf_event_class_add_field(event_class, type, name);
682 if (!ret)
683 field->alias = name;
684
685 return ret;
430} 686}
431 687
432static int add_tracepoint_fields_types(struct ctf_writer *cw, 688static int add_tracepoint_fields_types(struct ctf_writer *cw,
@@ -457,14 +713,14 @@ static int add_tracepoint_fields_types(struct ctf_writer *cw,
457 if (flags & FIELD_IS_ARRAY) 713 if (flags & FIELD_IS_ARRAY)
458 type = bt_ctf_field_type_array_create(type, field->arraylen); 714 type = bt_ctf_field_type_array_create(type, field->arraylen);
459 715
460 ret = bt_ctf_event_class_add_field(event_class, type, 716 ret = event_class_add_field(event_class, type, field);
461 field->name);
462 717
463 if (flags & FIELD_IS_ARRAY) 718 if (flags & FIELD_IS_ARRAY)
464 bt_ctf_field_type_put(type); 719 bt_ctf_field_type_put(type);
465 720
466 if (ret) { 721 if (ret) {
467 pr_err("Failed to add field '%s\n", field->name); 722 pr_err("Failed to add field '%s': %d\n",
723 field->name, ret);
468 return -1; 724 return -1;
469 } 725 }
470 } 726 }
@@ -508,7 +764,7 @@ static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
508 do { \ 764 do { \
509 pr2(" field '%s'\n", n); \ 765 pr2(" field '%s'\n", n); \
510 if (bt_ctf_event_class_add_field(cl, t, n)) { \ 766 if (bt_ctf_event_class_add_field(cl, t, n)) { \
511 pr_err("Failed to add field '%s;\n", n); \ 767 pr_err("Failed to add field '%s';\n", n); \
512 return -1; \ 768 return -1; \
513 } \ 769 } \
514 } while (0) 770 } while (0)
@@ -528,9 +784,6 @@ static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
528 if (type & PERF_SAMPLE_STREAM_ID) 784 if (type & PERF_SAMPLE_STREAM_ID)
529 ADD_FIELD(event_class, cw->data.u64, "perf_stream_id"); 785 ADD_FIELD(event_class, cw->data.u64, "perf_stream_id");
530 786
531 if (type & PERF_SAMPLE_CPU)
532 ADD_FIELD(event_class, cw->data.u32, "perf_cpu");
533
534 if (type & PERF_SAMPLE_PERIOD) 787 if (type & PERF_SAMPLE_PERIOD)
535 ADD_FIELD(event_class, cw->data.u64, "perf_period"); 788 ADD_FIELD(event_class, cw->data.u64, "perf_period");
536 789
@@ -604,6 +857,39 @@ static int setup_events(struct ctf_writer *cw, struct perf_session *session)
604 return 0; 857 return 0;
605} 858}
606 859
860static int setup_streams(struct ctf_writer *cw, struct perf_session *session)
861{
862 struct ctf_stream **stream;
863 struct perf_header *ph = &session->header;
864 int ncpus;
865
866 /*
867 * Try to get the number of cpus used in the data file,
868 * if not present fallback to the MAX_CPUS.
869 */
870 ncpus = ph->env.nr_cpus_avail ?: MAX_CPUS;
871
872 stream = zalloc(sizeof(*stream) * ncpus);
873 if (!stream) {
874 pr_err("Failed to allocate streams.\n");
875 return -ENOMEM;
876 }
877
878 cw->stream = stream;
879 cw->stream_cnt = ncpus;
880 return 0;
881}
882
883static void free_streams(struct ctf_writer *cw)
884{
885 int cpu;
886
887 for (cpu = 0; cpu < cw->stream_cnt; cpu++)
888 ctf_stream__delete(cw->stream[cpu]);
889
890 free(cw->stream);
891}
892
607static int ctf_writer__setup_env(struct ctf_writer *cw, 893static int ctf_writer__setup_env(struct ctf_writer *cw,
608 struct perf_session *session) 894 struct perf_session *session)
609{ 895{
@@ -713,7 +999,7 @@ static void ctf_writer__cleanup(struct ctf_writer *cw)
713 ctf_writer__cleanup_data(cw); 999 ctf_writer__cleanup_data(cw);
714 1000
715 bt_ctf_clock_put(cw->clock); 1001 bt_ctf_clock_put(cw->clock);
716 bt_ctf_stream_put(cw->stream); 1002 free_streams(cw);
717 bt_ctf_stream_class_put(cw->stream_class); 1003 bt_ctf_stream_class_put(cw->stream_class);
718 bt_ctf_writer_put(cw->writer); 1004 bt_ctf_writer_put(cw->writer);
719 1005
@@ -725,8 +1011,9 @@ static int ctf_writer__init(struct ctf_writer *cw, const char *path)
725{ 1011{
726 struct bt_ctf_writer *writer; 1012 struct bt_ctf_writer *writer;
727 struct bt_ctf_stream_class *stream_class; 1013 struct bt_ctf_stream_class *stream_class;
728 struct bt_ctf_stream *stream;
729 struct bt_ctf_clock *clock; 1014 struct bt_ctf_clock *clock;
1015 struct bt_ctf_field_type *pkt_ctx_type;
1016 int ret;
730 1017
731 /* CTF writer */ 1018 /* CTF writer */
732 writer = bt_ctf_writer_create(path); 1019 writer = bt_ctf_writer_create(path);
@@ -767,14 +1054,15 @@ static int ctf_writer__init(struct ctf_writer *cw, const char *path)
767 if (ctf_writer__init_data(cw)) 1054 if (ctf_writer__init_data(cw))
768 goto err_cleanup; 1055 goto err_cleanup;
769 1056
770 /* CTF stream instance */ 1057 /* Add cpu_id for packet context */
771 stream = bt_ctf_writer_create_stream(writer, stream_class); 1058 pkt_ctx_type = bt_ctf_stream_class_get_packet_context_type(stream_class);
772 if (!stream) { 1059 if (!pkt_ctx_type)
773 pr("Failed to create CTF stream.\n");
774 goto err_cleanup; 1060 goto err_cleanup;
775 }
776 1061
777 cw->stream = stream; 1062 ret = bt_ctf_field_type_structure_add_field(pkt_ctx_type, cw->data.u32, "cpu_id");
1063 bt_ctf_field_type_put(pkt_ctx_type);
1064 if (ret)
1065 goto err_cleanup;
778 1066
779 /* CTF clock writer setup */ 1067 /* CTF clock writer setup */
780 if (bt_ctf_writer_add_clock(writer, clock)) { 1068 if (bt_ctf_writer_add_clock(writer, clock)) {
@@ -791,6 +1079,28 @@ err:
791 return -1; 1079 return -1;
792} 1080}
793 1081
1082static int ctf_writer__flush_streams(struct ctf_writer *cw)
1083{
1084 int cpu, ret = 0;
1085
1086 for (cpu = 0; cpu < cw->stream_cnt && !ret; cpu++)
1087 ret = ctf_stream__flush(cw->stream[cpu]);
1088
1089 return ret;
1090}
1091
1092static int convert__config(const char *var, const char *value, void *cb)
1093{
1094 struct convert *c = cb;
1095
1096 if (!strcmp(var, "convert.queue-size")) {
1097 c->queue_size = perf_config_u64(var, value);
1098 return 0;
1099 }
1100
1101 return perf_default_config(var, value, cb);
1102}
1103
794int bt_convert__perf2ctf(const char *input, const char *path, bool force) 1104int bt_convert__perf2ctf(const char *input, const char *path, bool force)
795{ 1105{
796 struct perf_session *session; 1106 struct perf_session *session;
@@ -817,6 +1127,8 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force)
817 struct ctf_writer *cw = &c.writer; 1127 struct ctf_writer *cw = &c.writer;
818 int err = -1; 1128 int err = -1;
819 1129
1130 perf_config(convert__config, &c);
1131
820 /* CTF writer */ 1132 /* CTF writer */
821 if (ctf_writer__init(cw, path)) 1133 if (ctf_writer__init(cw, path))
822 return -1; 1134 return -1;
@@ -826,6 +1138,11 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force)
826 if (!session) 1138 if (!session)
827 goto free_writer; 1139 goto free_writer;
828 1140
1141 if (c.queue_size) {
1142 ordered_events__set_alloc_size(&session->ordered_events,
1143 c.queue_size);
1144 }
1145
829 /* CTF writer env/clock setup */ 1146 /* CTF writer env/clock setup */
830 if (ctf_writer__setup_env(cw, session)) 1147 if (ctf_writer__setup_env(cw, session))
831 goto free_session; 1148 goto free_session;
@@ -834,9 +1151,14 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force)
834 if (setup_events(cw, session)) 1151 if (setup_events(cw, session))
835 goto free_session; 1152 goto free_session;
836 1153
1154 if (setup_streams(cw, session))
1155 goto free_session;
1156
837 err = perf_session__process_events(session); 1157 err = perf_session__process_events(session);
838 if (!err) 1158 if (!err)
839 err = bt_ctf_stream_flush(cw->stream); 1159 err = ctf_writer__flush_streams(cw);
1160 else
1161 pr_err("Error during conversion.\n");
840 1162
841 fprintf(stderr, 1163 fprintf(stderr,
842 "[ perf data convert: Converted '%s' into CTF data '%s' ]\n", 1164 "[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
@@ -847,11 +1169,15 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force)
847 (double) c.events_size / 1024.0 / 1024.0, 1169 (double) c.events_size / 1024.0 / 1024.0,
848 c.events_count); 1170 c.events_count);
849 1171
850 /* its all good */
851free_session:
852 perf_session__delete(session); 1172 perf_session__delete(session);
1173 ctf_writer__cleanup(cw);
1174
1175 return err;
853 1176
1177free_session:
1178 perf_session__delete(session);
854free_writer: 1179free_writer:
855 ctf_writer__cleanup(cw); 1180 ctf_writer__cleanup(cw);
1181 pr_err("Error during conversion setup.\n");
856 return err; 1182 return err;
857} 1183}
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index bb39a3ffc70b..1c9689e4cc17 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -122,6 +122,7 @@ int db_export__machine(struct db_export *dbe, struct machine *machine)
122int db_export__thread(struct db_export *dbe, struct thread *thread, 122int db_export__thread(struct db_export *dbe, struct thread *thread,
123 struct machine *machine, struct comm *comm) 123 struct machine *machine, struct comm *comm)
124{ 124{
125 struct thread *main_thread;
125 u64 main_thread_db_id = 0; 126 u64 main_thread_db_id = 0;
126 int err; 127 int err;
127 128
@@ -131,8 +132,6 @@ int db_export__thread(struct db_export *dbe, struct thread *thread,
131 thread->db_id = ++dbe->thread_last_db_id; 132 thread->db_id = ++dbe->thread_last_db_id;
132 133
133 if (thread->pid_ != -1) { 134 if (thread->pid_ != -1) {
134 struct thread *main_thread;
135
136 if (thread->pid_ == thread->tid) { 135 if (thread->pid_ == thread->tid) {
137 main_thread = thread; 136 main_thread = thread;
138 } else { 137 } else {
@@ -144,14 +143,16 @@ int db_export__thread(struct db_export *dbe, struct thread *thread,
144 err = db_export__thread(dbe, main_thread, machine, 143 err = db_export__thread(dbe, main_thread, machine,
145 comm); 144 comm);
146 if (err) 145 if (err)
147 return err; 146 goto out_put;
148 if (comm) { 147 if (comm) {
149 err = db_export__comm_thread(dbe, comm, thread); 148 err = db_export__comm_thread(dbe, comm, thread);
150 if (err) 149 if (err)
151 return err; 150 goto out_put;
152 } 151 }
153 } 152 }
154 main_thread_db_id = main_thread->db_id; 153 main_thread_db_id = main_thread->db_id;
154 if (main_thread != thread)
155 thread__put(main_thread);
155 } 156 }
156 157
157 if (dbe->export_thread) 158 if (dbe->export_thread)
@@ -159,6 +160,10 @@ int db_export__thread(struct db_export *dbe, struct thread *thread,
159 machine); 160 machine);
160 161
161 return 0; 162 return 0;
163
164out_put:
165 thread__put(main_thread);
166 return err;
162} 167}
163 168
164int db_export__comm(struct db_export *dbe, struct comm *comm, 169int db_export__comm(struct db_export *dbe, struct comm *comm,
@@ -229,7 +234,7 @@ int db_export__symbol(struct db_export *dbe, struct symbol *sym,
229static struct thread *get_main_thread(struct machine *machine, struct thread *thread) 234static struct thread *get_main_thread(struct machine *machine, struct thread *thread)
230{ 235{
231 if (thread->pid_ == thread->tid) 236 if (thread->pid_ == thread->tid)
232 return thread; 237 return thread__get(thread);
233 238
234 if (thread->pid_ == -1) 239 if (thread->pid_ == -1)
235 return NULL; 240 return NULL;
@@ -309,12 +314,12 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
309 314
310 err = db_export__thread(dbe, thread, al->machine, comm); 315 err = db_export__thread(dbe, thread, al->machine, comm);
311 if (err) 316 if (err)
312 return err; 317 goto out_put;
313 318
314 if (comm) { 319 if (comm) {
315 err = db_export__comm(dbe, comm, main_thread); 320 err = db_export__comm(dbe, comm, main_thread);
316 if (err) 321 if (err)
317 return err; 322 goto out_put;
318 es.comm_db_id = comm->db_id; 323 es.comm_db_id = comm->db_id;
319 } 324 }
320 325
@@ -322,7 +327,7 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
322 327
323 err = db_ids_from_al(dbe, al, &es.dso_db_id, &es.sym_db_id, &es.offset); 328 err = db_ids_from_al(dbe, al, &es.dso_db_id, &es.sym_db_id, &es.offset);
324 if (err) 329 if (err)
325 return err; 330 goto out_put;
326 331
327 if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && 332 if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
328 sample_addr_correlates_sym(&evsel->attr)) { 333 sample_addr_correlates_sym(&evsel->attr)) {
@@ -332,20 +337,22 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
332 err = db_ids_from_al(dbe, &addr_al, &es.addr_dso_db_id, 337 err = db_ids_from_al(dbe, &addr_al, &es.addr_dso_db_id,
333 &es.addr_sym_db_id, &es.addr_offset); 338 &es.addr_sym_db_id, &es.addr_offset);
334 if (err) 339 if (err)
335 return err; 340 goto out_put;
336 if (dbe->crp) { 341 if (dbe->crp) {
337 err = thread_stack__process(thread, comm, sample, al, 342 err = thread_stack__process(thread, comm, sample, al,
338 &addr_al, es.db_id, 343 &addr_al, es.db_id,
339 dbe->crp); 344 dbe->crp);
340 if (err) 345 if (err)
341 return err; 346 goto out_put;
342 } 347 }
343 } 348 }
344 349
345 if (dbe->export_sample) 350 if (dbe->export_sample)
346 return dbe->export_sample(dbe, &es); 351 err = dbe->export_sample(dbe, &es);
347 352
348 return 0; 353out_put:
354 thread__put(main_thread);
355 return err;
349} 356}
350 357
351static struct { 358static struct {
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index fc0ddd5792a9..7c0c08386a1d 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -4,6 +4,7 @@
4#include "symbol.h" 4#include "symbol.h"
5#include "dso.h" 5#include "dso.h"
6#include "machine.h" 6#include "machine.h"
7#include "auxtrace.h"
7#include "util.h" 8#include "util.h"
8#include "debug.h" 9#include "debug.h"
9 10
@@ -165,12 +166,28 @@ bool is_supported_compression(const char *ext)
165 return false; 166 return false;
166} 167}
167 168
168bool is_kernel_module(const char *pathname) 169bool is_kernel_module(const char *pathname, int cpumode)
169{ 170{
170 struct kmod_path m; 171 struct kmod_path m;
171 172 int mode = cpumode & PERF_RECORD_MISC_CPUMODE_MASK;
172 if (kmod_path__parse(&m, pathname)) 173
173 return NULL; 174 WARN_ONCE(mode != cpumode,
175 "Internal error: passing unmasked cpumode (%x) to is_kernel_module",
176 cpumode);
177
178 switch (mode) {
179 case PERF_RECORD_MISC_USER:
180 case PERF_RECORD_MISC_HYPERVISOR:
181 case PERF_RECORD_MISC_GUEST_USER:
182 return false;
183 /* Treat PERF_RECORD_MISC_CPUMODE_UNKNOWN as kernel */
184 default:
185 if (kmod_path__parse(&m, pathname)) {
186 pr_err("Failed to check whether %s is a kernel module or not. Assume it is.",
187 pathname);
188 return true;
189 }
190 }
174 191
175 return m.kmod; 192 return m.kmod;
176} 193}
@@ -214,12 +231,33 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
214{ 231{
215 const char *name = strrchr(path, '/'); 232 const char *name = strrchr(path, '/');
216 const char *ext = strrchr(path, '.'); 233 const char *ext = strrchr(path, '.');
234 bool is_simple_name = false;
217 235
218 memset(m, 0x0, sizeof(*m)); 236 memset(m, 0x0, sizeof(*m));
219 name = name ? name + 1 : path; 237 name = name ? name + 1 : path;
220 238
239 /*
240 * '.' is also a valid character for module name. For example:
241 * [aaa.bbb] is a valid module name. '[' should have higher
242 * priority than '.ko' suffix.
243 *
244 * The kernel names are from machine__mmap_name. Such
245 * name should belong to kernel itself, not kernel module.
246 */
247 if (name[0] == '[') {
248 is_simple_name = true;
249 if ((strncmp(name, "[kernel.kallsyms]", 17) == 0) ||
250 (strncmp(name, "[guest.kernel.kallsyms", 22) == 0) ||
251 (strncmp(name, "[vdso]", 6) == 0) ||
252 (strncmp(name, "[vsyscall]", 10) == 0)) {
253 m->kmod = false;
254
255 } else
256 m->kmod = true;
257 }
258
221 /* No extension, just return name. */ 259 /* No extension, just return name. */
222 if (ext == NULL) { 260 if ((ext == NULL) || is_simple_name) {
223 if (alloc_name) { 261 if (alloc_name) {
224 m->name = strdup(name); 262 m->name = strdup(name);
225 return m->name ? 0 : -ENOMEM; 263 return m->name ? 0 : -ENOMEM;
@@ -264,6 +302,7 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
264 */ 302 */
265static LIST_HEAD(dso__data_open); 303static LIST_HEAD(dso__data_open);
266static long dso__data_open_cnt; 304static long dso__data_open_cnt;
305static pthread_mutex_t dso__data_open_lock = PTHREAD_MUTEX_INITIALIZER;
267 306
268static void dso__list_add(struct dso *dso) 307static void dso__list_add(struct dso *dso)
269{ 308{
@@ -433,18 +472,12 @@ static void check_data_close(void)
433 */ 472 */
434void dso__data_close(struct dso *dso) 473void dso__data_close(struct dso *dso)
435{ 474{
475 pthread_mutex_lock(&dso__data_open_lock);
436 close_dso(dso); 476 close_dso(dso);
477 pthread_mutex_unlock(&dso__data_open_lock);
437} 478}
438 479
439/** 480static void try_to_open_dso(struct dso *dso, struct machine *machine)
440 * dso__data_fd - Get dso's data file descriptor
441 * @dso: dso object
442 * @machine: machine object
443 *
444 * External interface to find dso's file, open it and
445 * returns file descriptor.
446 */
447int dso__data_fd(struct dso *dso, struct machine *machine)
448{ 481{
449 enum dso_binary_type binary_type_data[] = { 482 enum dso_binary_type binary_type_data[] = {
450 DSO_BINARY_TYPE__BUILD_ID_CACHE, 483 DSO_BINARY_TYPE__BUILD_ID_CACHE,
@@ -453,11 +486,8 @@ int dso__data_fd(struct dso *dso, struct machine *machine)
453 }; 486 };
454 int i = 0; 487 int i = 0;
455 488
456 if (dso->data.status == DSO_DATA_STATUS_ERROR)
457 return -1;
458
459 if (dso->data.fd >= 0) 489 if (dso->data.fd >= 0)
460 goto out; 490 return;
461 491
462 if (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND) { 492 if (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND) {
463 dso->data.fd = open_dso(dso, machine); 493 dso->data.fd = open_dso(dso, machine);
@@ -477,10 +507,38 @@ out:
477 dso->data.status = DSO_DATA_STATUS_OK; 507 dso->data.status = DSO_DATA_STATUS_OK;
478 else 508 else
479 dso->data.status = DSO_DATA_STATUS_ERROR; 509 dso->data.status = DSO_DATA_STATUS_ERROR;
510}
511
512/**
513 * dso__data_get_fd - Get dso's data file descriptor
514 * @dso: dso object
515 * @machine: machine object
516 *
517 * External interface to find dso's file, open it and
518 * returns file descriptor. It should be paired with
519 * dso__data_put_fd() if it returns non-negative value.
520 */
521int dso__data_get_fd(struct dso *dso, struct machine *machine)
522{
523 if (dso->data.status == DSO_DATA_STATUS_ERROR)
524 return -1;
525
526 if (pthread_mutex_lock(&dso__data_open_lock) < 0)
527 return -1;
528
529 try_to_open_dso(dso, machine);
530
531 if (dso->data.fd < 0)
532 pthread_mutex_unlock(&dso__data_open_lock);
480 533
481 return dso->data.fd; 534 return dso->data.fd;
482} 535}
483 536
537void dso__data_put_fd(struct dso *dso __maybe_unused)
538{
539 pthread_mutex_unlock(&dso__data_open_lock);
540}
541
484bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by) 542bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by)
485{ 543{
486 u32 flag = 1 << by; 544 u32 flag = 1 << by;
@@ -494,10 +552,12 @@ bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by)
494} 552}
495 553
496static void 554static void
497dso_cache__free(struct rb_root *root) 555dso_cache__free(struct dso *dso)
498{ 556{
557 struct rb_root *root = &dso->data.cache;
499 struct rb_node *next = rb_first(root); 558 struct rb_node *next = rb_first(root);
500 559
560 pthread_mutex_lock(&dso->lock);
501 while (next) { 561 while (next) {
502 struct dso_cache *cache; 562 struct dso_cache *cache;
503 563
@@ -506,10 +566,12 @@ dso_cache__free(struct rb_root *root)
506 rb_erase(&cache->rb_node, root); 566 rb_erase(&cache->rb_node, root);
507 free(cache); 567 free(cache);
508 } 568 }
569 pthread_mutex_unlock(&dso->lock);
509} 570}
510 571
511static struct dso_cache *dso_cache__find(const struct rb_root *root, u64 offset) 572static struct dso_cache *dso_cache__find(struct dso *dso, u64 offset)
512{ 573{
574 const struct rb_root *root = &dso->data.cache;
513 struct rb_node * const *p = &root->rb_node; 575 struct rb_node * const *p = &root->rb_node;
514 const struct rb_node *parent = NULL; 576 const struct rb_node *parent = NULL;
515 struct dso_cache *cache; 577 struct dso_cache *cache;
@@ -528,17 +590,20 @@ static struct dso_cache *dso_cache__find(const struct rb_root *root, u64 offset)
528 else 590 else
529 return cache; 591 return cache;
530 } 592 }
593
531 return NULL; 594 return NULL;
532} 595}
533 596
534static void 597static struct dso_cache *
535dso_cache__insert(struct rb_root *root, struct dso_cache *new) 598dso_cache__insert(struct dso *dso, struct dso_cache *new)
536{ 599{
600 struct rb_root *root = &dso->data.cache;
537 struct rb_node **p = &root->rb_node; 601 struct rb_node **p = &root->rb_node;
538 struct rb_node *parent = NULL; 602 struct rb_node *parent = NULL;
539 struct dso_cache *cache; 603 struct dso_cache *cache;
540 u64 offset = new->offset; 604 u64 offset = new->offset;
541 605
606 pthread_mutex_lock(&dso->lock);
542 while (*p != NULL) { 607 while (*p != NULL) {
543 u64 end; 608 u64 end;
544 609
@@ -550,10 +615,17 @@ dso_cache__insert(struct rb_root *root, struct dso_cache *new)
550 p = &(*p)->rb_left; 615 p = &(*p)->rb_left;
551 else if (offset >= end) 616 else if (offset >= end)
552 p = &(*p)->rb_right; 617 p = &(*p)->rb_right;
618 else
619 goto out;
553 } 620 }
554 621
555 rb_link_node(&new->rb_node, parent, p); 622 rb_link_node(&new->rb_node, parent, p);
556 rb_insert_color(&new->rb_node, root); 623 rb_insert_color(&new->rb_node, root);
624
625 cache = NULL;
626out:
627 pthread_mutex_unlock(&dso->lock);
628 return cache;
557} 629}
558 630
559static ssize_t 631static ssize_t
@@ -568,19 +640,33 @@ dso_cache__memcpy(struct dso_cache *cache, u64 offset,
568} 640}
569 641
570static ssize_t 642static ssize_t
571dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size) 643dso_cache__read(struct dso *dso, struct machine *machine,
644 u64 offset, u8 *data, ssize_t size)
572{ 645{
573 struct dso_cache *cache; 646 struct dso_cache *cache;
647 struct dso_cache *old;
574 ssize_t ret; 648 ssize_t ret;
575 649
576 do { 650 do {
577 u64 cache_offset; 651 u64 cache_offset;
578 652
579 ret = -ENOMEM;
580
581 cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE); 653 cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
582 if (!cache) 654 if (!cache)
655 return -ENOMEM;
656
657 pthread_mutex_lock(&dso__data_open_lock);
658
659 /*
660 * dso->data.fd might be closed if other thread opened another
661 * file (dso) due to open file limit (RLIMIT_NOFILE).
662 */
663 try_to_open_dso(dso, machine);
664
665 if (dso->data.fd < 0) {
666 ret = -errno;
667 dso->data.status = DSO_DATA_STATUS_ERROR;
583 break; 668 break;
669 }
584 670
585 cache_offset = offset & DSO__DATA_CACHE_MASK; 671 cache_offset = offset & DSO__DATA_CACHE_MASK;
586 672
@@ -590,11 +676,20 @@ dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size)
590 676
591 cache->offset = cache_offset; 677 cache->offset = cache_offset;
592 cache->size = ret; 678 cache->size = ret;
593 dso_cache__insert(&dso->data.cache, cache); 679 } while (0);
594 680
595 ret = dso_cache__memcpy(cache, offset, data, size); 681 pthread_mutex_unlock(&dso__data_open_lock);
596 682
597 } while (0); 683 if (ret > 0) {
684 old = dso_cache__insert(dso, cache);
685 if (old) {
686 /* we lose the race */
687 free(cache);
688 cache = old;
689 }
690
691 ret = dso_cache__memcpy(cache, offset, data, size);
692 }
598 693
599 if (ret <= 0) 694 if (ret <= 0)
600 free(cache); 695 free(cache);
@@ -602,16 +697,16 @@ dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size)
602 return ret; 697 return ret;
603} 698}
604 699
605static ssize_t dso_cache_read(struct dso *dso, u64 offset, 700static ssize_t dso_cache_read(struct dso *dso, struct machine *machine,
606 u8 *data, ssize_t size) 701 u64 offset, u8 *data, ssize_t size)
607{ 702{
608 struct dso_cache *cache; 703 struct dso_cache *cache;
609 704
610 cache = dso_cache__find(&dso->data.cache, offset); 705 cache = dso_cache__find(dso, offset);
611 if (cache) 706 if (cache)
612 return dso_cache__memcpy(cache, offset, data, size); 707 return dso_cache__memcpy(cache, offset, data, size);
613 else 708 else
614 return dso_cache__read(dso, offset, data, size); 709 return dso_cache__read(dso, machine, offset, data, size);
615} 710}
616 711
617/* 712/*
@@ -619,7 +714,8 @@ static ssize_t dso_cache_read(struct dso *dso, u64 offset,
619 * in the rb_tree. Any read to already cached data is served 714 * in the rb_tree. Any read to already cached data is served
620 * by cached data. 715 * by cached data.
621 */ 716 */
622static ssize_t cached_read(struct dso *dso, u64 offset, u8 *data, ssize_t size) 717static ssize_t cached_read(struct dso *dso, struct machine *machine,
718 u64 offset, u8 *data, ssize_t size)
623{ 719{
624 ssize_t r = 0; 720 ssize_t r = 0;
625 u8 *p = data; 721 u8 *p = data;
@@ -627,7 +723,7 @@ static ssize_t cached_read(struct dso *dso, u64 offset, u8 *data, ssize_t size)
627 do { 723 do {
628 ssize_t ret; 724 ssize_t ret;
629 725
630 ret = dso_cache_read(dso, offset, p, size); 726 ret = dso_cache_read(dso, machine, offset, p, size);
631 if (ret < 0) 727 if (ret < 0)
632 return ret; 728 return ret;
633 729
@@ -647,21 +743,44 @@ static ssize_t cached_read(struct dso *dso, u64 offset, u8 *data, ssize_t size)
647 return r; 743 return r;
648} 744}
649 745
650static int data_file_size(struct dso *dso) 746static int data_file_size(struct dso *dso, struct machine *machine)
651{ 747{
748 int ret = 0;
652 struct stat st; 749 struct stat st;
653 char sbuf[STRERR_BUFSIZE]; 750 char sbuf[STRERR_BUFSIZE];
654 751
655 if (!dso->data.file_size) { 752 if (dso->data.file_size)
656 if (fstat(dso->data.fd, &st)) { 753 return 0;
657 pr_err("dso mmap failed, fstat: %s\n", 754
658 strerror_r(errno, sbuf, sizeof(sbuf))); 755 if (dso->data.status == DSO_DATA_STATUS_ERROR)
659 return -1; 756 return -1;
660 } 757
661 dso->data.file_size = st.st_size; 758 pthread_mutex_lock(&dso__data_open_lock);
759
760 /*
761 * dso->data.fd might be closed if other thread opened another
762 * file (dso) due to open file limit (RLIMIT_NOFILE).
763 */
764 try_to_open_dso(dso, machine);
765
766 if (dso->data.fd < 0) {
767 ret = -errno;
768 dso->data.status = DSO_DATA_STATUS_ERROR;
769 goto out;
662 } 770 }
663 771
664 return 0; 772 if (fstat(dso->data.fd, &st) < 0) {
773 ret = -errno;
774 pr_err("dso cache fstat failed: %s\n",
775 strerror_r(errno, sbuf, sizeof(sbuf)));
776 dso->data.status = DSO_DATA_STATUS_ERROR;
777 goto out;
778 }
779 dso->data.file_size = st.st_size;
780
781out:
782 pthread_mutex_unlock(&dso__data_open_lock);
783 return ret;
665} 784}
666 785
667/** 786/**
@@ -673,23 +792,17 @@ static int data_file_size(struct dso *dso)
673 */ 792 */
674off_t dso__data_size(struct dso *dso, struct machine *machine) 793off_t dso__data_size(struct dso *dso, struct machine *machine)
675{ 794{
676 int fd; 795 if (data_file_size(dso, machine))
677
678 fd = dso__data_fd(dso, machine);
679 if (fd < 0)
680 return fd;
681
682 if (data_file_size(dso))
683 return -1; 796 return -1;
684 797
685 /* For now just estimate dso data size is close to file size */ 798 /* For now just estimate dso data size is close to file size */
686 return dso->data.file_size; 799 return dso->data.file_size;
687} 800}
688 801
689static ssize_t data_read_offset(struct dso *dso, u64 offset, 802static ssize_t data_read_offset(struct dso *dso, struct machine *machine,
690 u8 *data, ssize_t size) 803 u64 offset, u8 *data, ssize_t size)
691{ 804{
692 if (data_file_size(dso)) 805 if (data_file_size(dso, machine))
693 return -1; 806 return -1;
694 807
695 /* Check the offset sanity. */ 808 /* Check the offset sanity. */
@@ -699,7 +812,7 @@ static ssize_t data_read_offset(struct dso *dso, u64 offset,
699 if (offset + size < offset) 812 if (offset + size < offset)
700 return -1; 813 return -1;
701 814
702 return cached_read(dso, offset, data, size); 815 return cached_read(dso, machine, offset, data, size);
703} 816}
704 817
705/** 818/**
@@ -716,10 +829,10 @@ static ssize_t data_read_offset(struct dso *dso, u64 offset,
716ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, 829ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
717 u64 offset, u8 *data, ssize_t size) 830 u64 offset, u8 *data, ssize_t size)
718{ 831{
719 if (dso__data_fd(dso, machine) < 0) 832 if (dso->data.status == DSO_DATA_STATUS_ERROR)
720 return -1; 833 return -1;
721 834
722 return data_read_offset(dso, offset, data, size); 835 return data_read_offset(dso, machine, offset, data, size);
723} 836}
724 837
725/** 838/**
@@ -751,13 +864,13 @@ struct map *dso__new_map(const char *name)
751 return map; 864 return map;
752} 865}
753 866
754struct dso *dso__kernel_findnew(struct machine *machine, const char *name, 867struct dso *machine__findnew_kernel(struct machine *machine, const char *name,
755 const char *short_name, int dso_type) 868 const char *short_name, int dso_type)
756{ 869{
757 /* 870 /*
758 * The kernel dso could be created by build_id processing. 871 * The kernel dso could be created by build_id processing.
759 */ 872 */
760 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, name); 873 struct dso *dso = machine__findnew_dso(machine, name);
761 874
762 /* 875 /*
763 * We need to run this in all cases, since during the build_id 876 * We need to run this in all cases, since during the build_id
@@ -776,8 +889,8 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
776 * Either one of the dso or name parameter must be non-NULL or the 889 * Either one of the dso or name parameter must be non-NULL or the
777 * function will not work. 890 * function will not work.
778 */ 891 */
779static struct dso *dso__findlink_by_longname(struct rb_root *root, 892static struct dso *__dso__findlink_by_longname(struct rb_root *root,
780 struct dso *dso, const char *name) 893 struct dso *dso, const char *name)
781{ 894{
782 struct rb_node **p = &root->rb_node; 895 struct rb_node **p = &root->rb_node;
783 struct rb_node *parent = NULL; 896 struct rb_node *parent = NULL;
@@ -824,10 +937,10 @@ static struct dso *dso__findlink_by_longname(struct rb_root *root,
824 return NULL; 937 return NULL;
825} 938}
826 939
827static inline struct dso * 940static inline struct dso *__dso__find_by_longname(struct rb_root *root,
828dso__find_by_longname(const struct rb_root *root, const char *name) 941 const char *name)
829{ 942{
830 return dso__findlink_by_longname((struct rb_root *)root, NULL, name); 943 return __dso__findlink_by_longname(root, NULL, name);
831} 944}
832 945
833void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated) 946void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
@@ -935,6 +1048,8 @@ struct dso *dso__new(const char *name)
935 RB_CLEAR_NODE(&dso->rb_node); 1048 RB_CLEAR_NODE(&dso->rb_node);
936 INIT_LIST_HEAD(&dso->node); 1049 INIT_LIST_HEAD(&dso->node);
937 INIT_LIST_HEAD(&dso->data.open_entry); 1050 INIT_LIST_HEAD(&dso->data.open_entry);
1051 pthread_mutex_init(&dso->lock, NULL);
1052 atomic_set(&dso->refcnt, 1);
938 } 1053 }
939 1054
940 return dso; 1055 return dso;
@@ -961,12 +1076,27 @@ void dso__delete(struct dso *dso)
961 } 1076 }
962 1077
963 dso__data_close(dso); 1078 dso__data_close(dso);
964 dso_cache__free(&dso->data.cache); 1079 auxtrace_cache__free(dso->auxtrace_cache);
1080 dso_cache__free(dso);
965 dso__free_a2l(dso); 1081 dso__free_a2l(dso);
966 zfree(&dso->symsrc_filename); 1082 zfree(&dso->symsrc_filename);
1083 pthread_mutex_destroy(&dso->lock);
967 free(dso); 1084 free(dso);
968} 1085}
969 1086
1087struct dso *dso__get(struct dso *dso)
1088{
1089 if (dso)
1090 atomic_inc(&dso->refcnt);
1091 return dso;
1092}
1093
1094void dso__put(struct dso *dso)
1095{
1096 if (dso && atomic_dec_and_test(&dso->refcnt))
1097 dso__delete(dso);
1098}
1099
970void dso__set_build_id(struct dso *dso, void *build_id) 1100void dso__set_build_id(struct dso *dso, void *build_id)
971{ 1101{
972 memcpy(dso->build_id, build_id, sizeof(dso->build_id)); 1102 memcpy(dso->build_id, build_id, sizeof(dso->build_id));
@@ -1033,14 +1163,41 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1033 return have_build_id; 1163 return have_build_id;
1034} 1164}
1035 1165
1036void dsos__add(struct dsos *dsos, struct dso *dso) 1166void __dsos__add(struct dsos *dsos, struct dso *dso)
1037{ 1167{
1038 list_add_tail(&dso->node, &dsos->head); 1168 list_add_tail(&dso->node, &dsos->head);
1039 dso__findlink_by_longname(&dsos->root, dso, NULL); 1169 __dso__findlink_by_longname(&dsos->root, dso, NULL);
1170 /*
1171 * It is now in the linked list, grab a reference, then garbage collect
1172 * this when needing memory, by looking at LRU dso instances in the
1173 * list with atomic_read(&dso->refcnt) == 1, i.e. no references
1174 * anywhere besides the one for the list, do, under a lock for the
1175 * list: remove it from the list, then a dso__put(), that probably will
1176 * be the last and will then call dso__delete(), end of life.
1177 *
1178 * That, or at the end of the 'struct machine' lifetime, when all
1179 * 'struct dso' instances will be removed from the list, in
1180 * dsos__exit(), if they have no other reference from some other data
1181 * structure.
1182 *
1183 * E.g.: after processing a 'perf.data' file and storing references
1184 * to objects instantiated while processing events, we will have
1185 * references to the 'thread', 'map', 'dso' structs all from 'struct
1186 * hist_entry' instances, but we may not need anything not referenced,
1187 * so we might as well call machines__exit()/machines__delete() and
1188 * garbage collect it.
1189 */
1190 dso__get(dso);
1191}
1192
1193void dsos__add(struct dsos *dsos, struct dso *dso)
1194{
1195 pthread_rwlock_wrlock(&dsos->lock);
1196 __dsos__add(dsos, dso);
1197 pthread_rwlock_unlock(&dsos->lock);
1040} 1198}
1041 1199
1042struct dso *dsos__find(const struct dsos *dsos, const char *name, 1200struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
1043 bool cmp_short)
1044{ 1201{
1045 struct dso *pos; 1202 struct dso *pos;
1046 1203
@@ -1050,15 +1207,24 @@ struct dso *dsos__find(const struct dsos *dsos, const char *name,
1050 return pos; 1207 return pos;
1051 return NULL; 1208 return NULL;
1052 } 1209 }
1053 return dso__find_by_longname(&dsos->root, name); 1210 return __dso__find_by_longname(&dsos->root, name);
1211}
1212
1213struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
1214{
1215 struct dso *dso;
1216 pthread_rwlock_rdlock(&dsos->lock);
1217 dso = __dsos__find(dsos, name, cmp_short);
1218 pthread_rwlock_unlock(&dsos->lock);
1219 return dso;
1054} 1220}
1055 1221
1056struct dso *dsos__addnew(struct dsos *dsos, const char *name) 1222struct dso *__dsos__addnew(struct dsos *dsos, const char *name)
1057{ 1223{
1058 struct dso *dso = dso__new(name); 1224 struct dso *dso = dso__new(name);
1059 1225
1060 if (dso != NULL) { 1226 if (dso != NULL) {
1061 dsos__add(dsos, dso); 1227 __dsos__add(dsos, dso);
1062 dso__set_basename(dso); 1228 dso__set_basename(dso);
1063 } 1229 }
1064 return dso; 1230 return dso;
@@ -1066,9 +1232,18 @@ struct dso *dsos__addnew(struct dsos *dsos, const char *name)
1066 1232
1067struct dso *__dsos__findnew(struct dsos *dsos, const char *name) 1233struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
1068{ 1234{
1069 struct dso *dso = dsos__find(dsos, name, false); 1235 struct dso *dso = __dsos__find(dsos, name, false);
1070 1236
1071 return dso ? dso : dsos__addnew(dsos, name); 1237 return dso ? dso : __dsos__addnew(dsos, name);
1238}
1239
1240struct dso *dsos__findnew(struct dsos *dsos, const char *name)
1241{
1242 struct dso *dso;
1243 pthread_rwlock_wrlock(&dsos->lock);
1244 dso = dso__get(__dsos__findnew(dsos, name));
1245 pthread_rwlock_unlock(&dsos->lock);
1246 return dso;
1072} 1247}
1073 1248
1074size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 1249size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
@@ -1130,12 +1305,15 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
1130enum dso_type dso__type(struct dso *dso, struct machine *machine) 1305enum dso_type dso__type(struct dso *dso, struct machine *machine)
1131{ 1306{
1132 int fd; 1307 int fd;
1308 enum dso_type type = DSO__TYPE_UNKNOWN;
1133 1309
1134 fd = dso__data_fd(dso, machine); 1310 fd = dso__data_get_fd(dso, machine);
1135 if (fd < 0) 1311 if (fd >= 0) {
1136 return DSO__TYPE_UNKNOWN; 1312 type = dso__type_fd(fd);
1313 dso__data_put_fd(dso);
1314 }
1137 1315
1138 return dso__type_fd(fd); 1316 return type;
1139} 1317}
1140 1318
1141int dso__strerror_load(struct dso *dso, char *buf, size_t buflen) 1319int dso__strerror_load(struct dso *dso, char *buf, size_t buflen)
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index e0901b4ed8de..2fe98bb0e95b 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -1,9 +1,11 @@
1#ifndef __PERF_DSO 1#ifndef __PERF_DSO
2#define __PERF_DSO 2#define __PERF_DSO
3 3
4#include <linux/atomic.h>
4#include <linux/types.h> 5#include <linux/types.h>
5#include <linux/rbtree.h> 6#include <linux/rbtree.h>
6#include <stdbool.h> 7#include <stdbool.h>
8#include <pthread.h>
7#include <linux/types.h> 9#include <linux/types.h>
8#include <linux/bitops.h> 10#include <linux/bitops.h>
9#include "map.h" 11#include "map.h"
@@ -124,9 +126,13 @@ struct dso_cache {
124struct dsos { 126struct dsos {
125 struct list_head head; 127 struct list_head head;
126 struct rb_root root; /* rbtree root sorted by long name */ 128 struct rb_root root; /* rbtree root sorted by long name */
129 pthread_rwlock_t lock;
127}; 130};
128 131
132struct auxtrace_cache;
133
129struct dso { 134struct dso {
135 pthread_mutex_t lock;
130 struct list_head node; 136 struct list_head node;
131 struct rb_node rb_node; /* rbtree node sorted by long name */ 137 struct rb_node rb_node; /* rbtree node sorted by long name */
132 struct rb_root symbols[MAP__NR_TYPES]; 138 struct rb_root symbols[MAP__NR_TYPES];
@@ -156,6 +162,7 @@ struct dso {
156 u16 long_name_len; 162 u16 long_name_len;
157 u16 short_name_len; 163 u16 short_name_len;
158 void *dwfl; /* DWARF debug info */ 164 void *dwfl; /* DWARF debug info */
165 struct auxtrace_cache *auxtrace_cache;
159 166
160 /* dso data file */ 167 /* dso data file */
161 struct { 168 struct {
@@ -173,7 +180,7 @@ struct dso {
173 void *priv; 180 void *priv;
174 u64 db_id; 181 u64 db_id;
175 }; 182 };
176 183 atomic_t refcnt;
177 char name[0]; 184 char name[0];
178}; 185};
179 186
@@ -200,6 +207,17 @@ void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated);
200 207
201int dso__name_len(const struct dso *dso); 208int dso__name_len(const struct dso *dso);
202 209
210struct dso *dso__get(struct dso *dso);
211void dso__put(struct dso *dso);
212
213static inline void __dso__zput(struct dso **dso)
214{
215 dso__put(*dso);
216 *dso = NULL;
217}
218
219#define dso__zput(dso) __dso__zput(&dso)
220
203bool dso__loaded(const struct dso *dso, enum map_type type); 221bool dso__loaded(const struct dso *dso, enum map_type type);
204 222
205bool dso__sorted_by_name(const struct dso *dso, enum map_type type); 223bool dso__sorted_by_name(const struct dso *dso, enum map_type type);
@@ -216,7 +234,7 @@ char dso__symtab_origin(const struct dso *dso);
216int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, 234int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type,
217 char *root_dir, char *filename, size_t size); 235 char *root_dir, char *filename, size_t size);
218bool is_supported_compression(const char *ext); 236bool is_supported_compression(const char *ext);
219bool is_kernel_module(const char *pathname); 237bool is_kernel_module(const char *pathname, int cpumode);
220bool decompress_to_file(const char *ext, const char *filename, int output_fd); 238bool decompress_to_file(const char *ext, const char *filename, int output_fd);
221bool dso__needs_decompress(struct dso *dso); 239bool dso__needs_decompress(struct dso *dso);
222 240
@@ -236,7 +254,8 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
236 254
237/* 255/*
238 * The dso__data_* external interface provides following functions: 256 * The dso__data_* external interface provides following functions:
239 * dso__data_fd 257 * dso__data_get_fd
258 * dso__data_put_fd
240 * dso__data_close 259 * dso__data_close
241 * dso__data_size 260 * dso__data_size
242 * dso__data_read_offset 261 * dso__data_read_offset
@@ -253,8 +272,11 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
253 * The current usage of the dso__data_* interface is as follows: 272 * The current usage of the dso__data_* interface is as follows:
254 * 273 *
255 * Get DSO's fd: 274 * Get DSO's fd:
256 * int fd = dso__data_fd(dso, machine); 275 * int fd = dso__data_get_fd(dso, machine);
257 * USE 'fd' SOMEHOW 276 * if (fd >= 0) {
277 * USE 'fd' SOMEHOW
278 * dso__data_put_fd(dso);
279 * }
258 * 280 *
259 * Read DSO's data: 281 * Read DSO's data:
260 * n = dso__data_read_offset(dso_0, &machine, 0, buf, BUFSIZE); 282 * n = dso__data_read_offset(dso_0, &machine, 0, buf, BUFSIZE);
@@ -273,7 +295,8 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
273 * 295 *
274 * TODO 296 * TODO
275*/ 297*/
276int dso__data_fd(struct dso *dso, struct machine *machine); 298int dso__data_get_fd(struct dso *dso, struct machine *machine);
299void dso__data_put_fd(struct dso *dso __maybe_unused);
277void dso__data_close(struct dso *dso); 300void dso__data_close(struct dso *dso);
278 301
279off_t dso__data_size(struct dso *dso, struct machine *machine); 302off_t dso__data_size(struct dso *dso, struct machine *machine);
@@ -285,14 +308,16 @@ ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
285bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by); 308bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by);
286 309
287struct map *dso__new_map(const char *name); 310struct map *dso__new_map(const char *name);
288struct dso *dso__kernel_findnew(struct machine *machine, const char *name, 311struct dso *machine__findnew_kernel(struct machine *machine, const char *name,
289 const char *short_name, int dso_type); 312 const char *short_name, int dso_type);
290 313
314void __dsos__add(struct dsos *dsos, struct dso *dso);
291void dsos__add(struct dsos *dsos, struct dso *dso); 315void dsos__add(struct dsos *dsos, struct dso *dso);
292struct dso *dsos__addnew(struct dsos *dsos, const char *name); 316struct dso *__dsos__addnew(struct dsos *dsos, const char *name);
293struct dso *dsos__find(const struct dsos *dsos, const char *name, 317struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short);
294 bool cmp_short); 318struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short);
295struct dso *__dsos__findnew(struct dsos *dsos, const char *name); 319struct dso *__dsos__findnew(struct dsos *dsos, const char *name);
320struct dso *dsos__findnew(struct dsos *dsos, const char *name);
296bool __dsos__read_build_ids(struct list_head *head, bool with_hits); 321bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
297 322
298size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 323size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index c34e024020c7..57f3ef41c2bc 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -139,11 +139,27 @@ int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
139bool die_compare_name(Dwarf_Die *dw_die, const char *tname) 139bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
140{ 140{
141 const char *name; 141 const char *name;
142
142 name = dwarf_diename(dw_die); 143 name = dwarf_diename(dw_die);
143 return name ? (strcmp(tname, name) == 0) : false; 144 return name ? (strcmp(tname, name) == 0) : false;
144} 145}
145 146
146/** 147/**
148 * die_match_name - Match diename and glob
149 * @dw_die: a DIE
150 * @glob: a string of target glob pattern
151 *
152 * Glob matching the name of @dw_die and @glob. Return false if matching fail.
153 */
154bool die_match_name(Dwarf_Die *dw_die, const char *glob)
155{
156 const char *name;
157
158 name = dwarf_diename(dw_die);
159 return name ? strglobmatch(name, glob) : false;
160}
161
162/**
147 * die_get_call_lineno - Get callsite line number of inline-function instance 163 * die_get_call_lineno - Get callsite line number of inline-function instance
148 * @in_die: a DIE of an inlined function instance 164 * @in_die: a DIE of an inlined function instance
149 * 165 *
@@ -417,6 +433,43 @@ struct __addr_die_search_param {
417 Dwarf_Die *die_mem; 433 Dwarf_Die *die_mem;
418}; 434};
419 435
436static int __die_search_func_tail_cb(Dwarf_Die *fn_die, void *data)
437{
438 struct __addr_die_search_param *ad = data;
439 Dwarf_Addr addr = 0;
440
441 if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
442 !dwarf_highpc(fn_die, &addr) &&
443 addr == ad->addr) {
444 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
445 return DWARF_CB_ABORT;
446 }
447 return DWARF_CB_OK;
448}
449
450/**
451 * die_find_tailfunc - Search for a non-inlined function with tail call at
452 * given address
453 * @cu_die: a CU DIE which including @addr
454 * @addr: target address
455 * @die_mem: a buffer for result DIE
456 *
457 * Search for a non-inlined function DIE with tail call at @addr. Stores the
458 * DIE to @die_mem and returns it if found. Returns NULL if failed.
459 */
460Dwarf_Die *die_find_tailfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
461 Dwarf_Die *die_mem)
462{
463 struct __addr_die_search_param ad;
464 ad.addr = addr;
465 ad.die_mem = die_mem;
466 /* dwarf_getscopes can't find subprogram. */
467 if (!dwarf_getfuncs(cu_die, __die_search_func_tail_cb, &ad, 0))
468 return NULL;
469 else
470 return die_mem;
471}
472
420/* die_find callback for non-inlined function search */ 473/* die_find callback for non-inlined function search */
421static int __die_search_func_cb(Dwarf_Die *fn_die, void *data) 474static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
422{ 475{
@@ -832,19 +885,17 @@ Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
832/** 885/**
833 * die_get_typename - Get the name of given variable DIE 886 * die_get_typename - Get the name of given variable DIE
834 * @vr_die: a variable DIE 887 * @vr_die: a variable DIE
835 * @buf: a buffer for result type name 888 * @buf: a strbuf for result type name
836 * @len: a max-length of @buf
837 * 889 *
838 * Get the name of @vr_die and stores it to @buf. Return the actual length 890 * Get the name of @vr_die and stores it to @buf. Return 0 if succeeded.
839 * of type name if succeeded. Return -E2BIG if @len is not enough long, and 891 * and Return -ENOENT if failed to find type name.
840 * Return -ENOENT if failed to find type name.
841 * Note that the result will stores typedef name if possible, and stores 892 * Note that the result will stores typedef name if possible, and stores
842 * "*(function_type)" if the type is a function pointer. 893 * "*(function_type)" if the type is a function pointer.
843 */ 894 */
844int die_get_typename(Dwarf_Die *vr_die, char *buf, int len) 895int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf)
845{ 896{
846 Dwarf_Die type; 897 Dwarf_Die type;
847 int tag, ret, ret2; 898 int tag, ret;
848 const char *tmp = ""; 899 const char *tmp = "";
849 900
850 if (__die_get_real_type(vr_die, &type) == NULL) 901 if (__die_get_real_type(vr_die, &type) == NULL)
@@ -855,8 +906,8 @@ int die_get_typename(Dwarf_Die *vr_die, char *buf, int len)
855 tmp = "*"; 906 tmp = "*";
856 else if (tag == DW_TAG_subroutine_type) { 907 else if (tag == DW_TAG_subroutine_type) {
857 /* Function pointer */ 908 /* Function pointer */
858 ret = snprintf(buf, len, "(function_type)"); 909 strbuf_addf(buf, "(function_type)");
859 return (ret >= len) ? -E2BIG : ret; 910 return 0;
860 } else { 911 } else {
861 if (!dwarf_diename(&type)) 912 if (!dwarf_diename(&type))
862 return -ENOENT; 913 return -ENOENT;
@@ -867,39 +918,156 @@ int die_get_typename(Dwarf_Die *vr_die, char *buf, int len)
867 else if (tag == DW_TAG_enumeration_type) 918 else if (tag == DW_TAG_enumeration_type)
868 tmp = "enum "; 919 tmp = "enum ";
869 /* Write a base name */ 920 /* Write a base name */
870 ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type)); 921 strbuf_addf(buf, "%s%s", tmp, dwarf_diename(&type));
871 return (ret >= len) ? -E2BIG : ret; 922 return 0;
872 }
873 ret = die_get_typename(&type, buf, len);
874 if (ret > 0) {
875 ret2 = snprintf(buf + ret, len - ret, "%s", tmp);
876 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
877 } 923 }
924 ret = die_get_typename(&type, buf);
925 if (ret == 0)
926 strbuf_addf(buf, "%s", tmp);
927
878 return ret; 928 return ret;
879} 929}
880 930
881/** 931/**
882 * die_get_varname - Get the name and type of given variable DIE 932 * die_get_varname - Get the name and type of given variable DIE
883 * @vr_die: a variable DIE 933 * @vr_die: a variable DIE
884 * @buf: a buffer for type and variable name 934 * @buf: a strbuf for type and variable name
885 * @len: the max-length of @buf
886 * 935 *
887 * Get the name and type of @vr_die and stores it in @buf as "type\tname". 936 * Get the name and type of @vr_die and stores it in @buf as "type\tname".
888 */ 937 */
889int die_get_varname(Dwarf_Die *vr_die, char *buf, int len) 938int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf)
890{ 939{
891 int ret, ret2; 940 int ret;
892 941
893 ret = die_get_typename(vr_die, buf, len); 942 ret = die_get_typename(vr_die, buf);
894 if (ret < 0) { 943 if (ret < 0) {
895 pr_debug("Failed to get type, make it unknown.\n"); 944 pr_debug("Failed to get type, make it unknown.\n");
896 ret = snprintf(buf, len, "(unknown_type)"); 945 strbuf_addf(buf, "(unknown_type)");
897 } 946 }
898 if (ret > 0) { 947
899 ret2 = snprintf(buf + ret, len - ret, "\t%s", 948 strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
900 dwarf_diename(vr_die)); 949
901 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret; 950 return 0;
951}
952
953/**
954 * die_get_var_innermost_scope - Get innermost scope range of given variable DIE
955 * @sp_die: a subprogram DIE
956 * @vr_die: a variable DIE
957 * @buf: a strbuf for variable byte offset range
958 *
959 * Get the innermost scope range of @vr_die and stores it in @buf as
960 * "@<function_name+[NN-NN,NN-NN]>".
961 */
962static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die,
963 struct strbuf *buf)
964{
965 Dwarf_Die *scopes;
966 int count;
967 size_t offset = 0;
968 Dwarf_Addr base;
969 Dwarf_Addr start, end;
970 Dwarf_Addr entry;
971 int ret;
972 bool first = true;
973 const char *name;
974
975 ret = dwarf_entrypc(sp_die, &entry);
976 if (ret)
977 return ret;
978
979 name = dwarf_diename(sp_die);
980 if (!name)
981 return -ENOENT;
982
983 count = dwarf_getscopes_die(vr_die, &scopes);
984
985 /* (*SCOPES)[1] is the DIE for the scope containing that scope */
986 if (count <= 1) {
987 ret = -EINVAL;
988 goto out;
902 } 989 }
990
991 while ((offset = dwarf_ranges(&scopes[1], offset, &base,
992 &start, &end)) > 0) {
993 start -= entry;
994 end -= entry;
995
996 if (first) {
997 strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
998 name, start, end);
999 first = false;
1000 } else {
1001 strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1002 start, end);
1003 }
1004 }
1005
1006 if (!first)
1007 strbuf_addf(buf, "]>");
1008
1009out:
1010 free(scopes);
903 return ret; 1011 return ret;
904} 1012}
905 1013
1014/**
1015 * die_get_var_range - Get byte offset range of given variable DIE
1016 * @sp_die: a subprogram DIE
1017 * @vr_die: a variable DIE
1018 * @buf: a strbuf for type and variable name and byte offset range
1019 *
1020 * Get the byte offset range of @vr_die and stores it in @buf as
1021 * "@<function_name+[NN-NN,NN-NN]>".
1022 */
1023int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf)
1024{
1025 int ret = 0;
1026 Dwarf_Addr base;
1027 Dwarf_Addr start, end;
1028 Dwarf_Addr entry;
1029 Dwarf_Op *op;
1030 size_t nops;
1031 size_t offset = 0;
1032 Dwarf_Attribute attr;
1033 bool first = true;
1034 const char *name;
1035
1036 ret = dwarf_entrypc(sp_die, &entry);
1037 if (ret)
1038 return ret;
1039
1040 name = dwarf_diename(sp_die);
1041 if (!name)
1042 return -ENOENT;
1043
1044 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
1045 return -EINVAL;
1046
1047 while ((offset = dwarf_getlocations(
1048 &attr, offset, &base,
1049 &start, &end, &op, &nops)) > 0) {
1050 if (start == 0) {
1051 /* Single Location Descriptions */
1052 ret = die_get_var_innermost_scope(sp_die, vr_die, buf);
1053 return ret;
1054 }
1055
1056 /* Location Lists */
1057 start -= entry;
1058 end -= entry;
1059 if (first) {
1060 strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1061 name, start, end);
1062 first = false;
1063 } else {
1064 strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1065 start, end);
1066 }
1067 }
1068
1069 if (!first)
1070 strbuf_addf(buf, "]>");
1071
1072 return ret;
1073}
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index af7dbcd5f929..c42ec366f2a7 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -47,6 +47,9 @@ extern bool die_is_func_instance(Dwarf_Die *dw_die);
47/* Compare diename and tname */ 47/* Compare diename and tname */
48extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname); 48extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);
49 49
50/* Matching diename with glob pattern */
51extern bool die_match_name(Dwarf_Die *dw_die, const char *glob);
52
50/* Get callsite line number of inline-function instance */ 53/* Get callsite line number of inline-function instance */
51extern int die_get_call_lineno(Dwarf_Die *in_die); 54extern int die_get_call_lineno(Dwarf_Die *in_die);
52 55
@@ -82,6 +85,10 @@ extern Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
82extern Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr, 85extern Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
83 Dwarf_Die *die_mem); 86 Dwarf_Die *die_mem);
84 87
88/* Search a non-inlined function with tail call at given address */
89Dwarf_Die *die_find_tailfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
90 Dwarf_Die *die_mem);
91
85/* Search the top inlined function including given address */ 92/* Search the top inlined function including given address */
86extern Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, 93extern Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
87 Dwarf_Die *die_mem); 94 Dwarf_Die *die_mem);
@@ -114,8 +121,10 @@ extern Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
114 Dwarf_Die *die_mem); 121 Dwarf_Die *die_mem);
115 122
116/* Get the name of given variable DIE */ 123/* Get the name of given variable DIE */
117extern int die_get_typename(Dwarf_Die *vr_die, char *buf, int len); 124extern int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf);
118 125
119/* Get the name and type of given variable DIE, stored as "type\tname" */ 126/* Get the name and type of given variable DIE, stored as "type\tname" */
120extern int die_get_varname(Dwarf_Die *vr_die, char *buf, int len); 127extern int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf);
128extern int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die,
129 struct strbuf *buf);
121#endif 130#endif
diff --git a/tools/perf/util/environment.c b/tools/perf/util/environment.c
index 275b0ee345f5..7405123692f1 100644
--- a/tools/perf/util/environment.c
+++ b/tools/perf/util/environment.c
@@ -5,5 +5,4 @@
5 */ 5 */
6#include "cache.h" 6#include "cache.h"
7 7
8const char *pager_program;
9int pager_use_color = 1; 8int pager_use_color = 1;
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index ff866c4d2e2f..d7d986d8f23e 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -23,12 +23,18 @@ static const char *perf_event__names[] = {
23 [PERF_RECORD_FORK] = "FORK", 23 [PERF_RECORD_FORK] = "FORK",
24 [PERF_RECORD_READ] = "READ", 24 [PERF_RECORD_READ] = "READ",
25 [PERF_RECORD_SAMPLE] = "SAMPLE", 25 [PERF_RECORD_SAMPLE] = "SAMPLE",
26 [PERF_RECORD_AUX] = "AUX",
27 [PERF_RECORD_ITRACE_START] = "ITRACE_START",
28 [PERF_RECORD_LOST_SAMPLES] = "LOST_SAMPLES",
26 [PERF_RECORD_HEADER_ATTR] = "ATTR", 29 [PERF_RECORD_HEADER_ATTR] = "ATTR",
27 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", 30 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE",
28 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", 31 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
29 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", 32 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID",
30 [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", 33 [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND",
31 [PERF_RECORD_ID_INDEX] = "ID_INDEX", 34 [PERF_RECORD_ID_INDEX] = "ID_INDEX",
35 [PERF_RECORD_AUXTRACE_INFO] = "AUXTRACE_INFO",
36 [PERF_RECORD_AUXTRACE] = "AUXTRACE",
37 [PERF_RECORD_AUXTRACE_ERROR] = "AUXTRACE_ERROR",
32}; 38};
33 39
34const char *perf_event__name(unsigned int id) 40const char *perf_event__name(unsigned int id)
@@ -212,10 +218,14 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
212 pid_t pid, pid_t tgid, 218 pid_t pid, pid_t tgid,
213 perf_event__handler_t process, 219 perf_event__handler_t process,
214 struct machine *machine, 220 struct machine *machine,
215 bool mmap_data) 221 bool mmap_data,
222 unsigned int proc_map_timeout)
216{ 223{
217 char filename[PATH_MAX]; 224 char filename[PATH_MAX];
218 FILE *fp; 225 FILE *fp;
226 unsigned long long t;
227 bool truncation = false;
228 unsigned long long timeout = proc_map_timeout * 1000000ULL;
219 int rc = 0; 229 int rc = 0;
220 230
221 if (machine__is_default_guest(machine)) 231 if (machine__is_default_guest(machine))
@@ -234,6 +244,7 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
234 } 244 }
235 245
236 event->header.type = PERF_RECORD_MMAP2; 246 event->header.type = PERF_RECORD_MMAP2;
247 t = rdclock();
237 248
238 while (1) { 249 while (1) {
239 char bf[BUFSIZ]; 250 char bf[BUFSIZ];
@@ -247,6 +258,15 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
247 if (fgets(bf, sizeof(bf), fp) == NULL) 258 if (fgets(bf, sizeof(bf), fp) == NULL)
248 break; 259 break;
249 260
261 if ((rdclock() - t) > timeout) {
262 pr_warning("Reading %s time out. "
263 "You may want to increase "
264 "the time limit by --proc-map-timeout\n",
265 filename);
266 truncation = true;
267 goto out;
268 }
269
250 /* ensure null termination since stack will be reused. */ 270 /* ensure null termination since stack will be reused. */
251 strcpy(execname, ""); 271 strcpy(execname, "");
252 272
@@ -295,6 +315,10 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
295 event->header.misc |= PERF_RECORD_MISC_MMAP_DATA; 315 event->header.misc |= PERF_RECORD_MISC_MMAP_DATA;
296 } 316 }
297 317
318out:
319 if (truncation)
320 event->header.misc |= PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT;
321
298 if (!strcmp(execname, "")) 322 if (!strcmp(execname, ""))
299 strcpy(execname, anonstr); 323 strcpy(execname, anonstr);
300 324
@@ -313,6 +337,9 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
313 rc = -1; 337 rc = -1;
314 break; 338 break;
315 } 339 }
340
341 if (truncation)
342 break;
316 } 343 }
317 344
318 fclose(fp); 345 fclose(fp);
@@ -324,8 +351,9 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
324 struct machine *machine) 351 struct machine *machine)
325{ 352{
326 int rc = 0; 353 int rc = 0;
327 struct rb_node *nd; 354 struct map *pos;
328 struct map_groups *kmaps = &machine->kmaps; 355 struct map_groups *kmaps = &machine->kmaps;
356 struct maps *maps = &kmaps->maps[MAP__FUNCTION];
329 union perf_event *event = zalloc((sizeof(event->mmap) + 357 union perf_event *event = zalloc((sizeof(event->mmap) +
330 machine->id_hdr_size)); 358 machine->id_hdr_size));
331 if (event == NULL) { 359 if (event == NULL) {
@@ -345,10 +373,8 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
345 else 373 else
346 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 374 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
347 375
348 for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]); 376 for (pos = maps__first(maps); pos; pos = map__next(pos)) {
349 nd; nd = rb_next(nd)) {
350 size_t size; 377 size_t size;
351 struct map *pos = rb_entry(nd, struct map, rb_node);
352 378
353 if (pos->dso->kernel) 379 if (pos->dso->kernel)
354 continue; 380 continue;
@@ -381,7 +407,9 @@ static int __event__synthesize_thread(union perf_event *comm_event,
381 pid_t pid, int full, 407 pid_t pid, int full,
382 perf_event__handler_t process, 408 perf_event__handler_t process,
383 struct perf_tool *tool, 409 struct perf_tool *tool,
384 struct machine *machine, bool mmap_data) 410 struct machine *machine,
411 bool mmap_data,
412 unsigned int proc_map_timeout)
385{ 413{
386 char filename[PATH_MAX]; 414 char filename[PATH_MAX];
387 DIR *tasks; 415 DIR *tasks;
@@ -398,7 +426,8 @@ static int __event__synthesize_thread(union perf_event *comm_event,
398 return -1; 426 return -1;
399 427
400 return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 428 return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
401 process, machine, mmap_data); 429 process, machine, mmap_data,
430 proc_map_timeout);
402 } 431 }
403 432
404 if (machine__is_default_guest(machine)) 433 if (machine__is_default_guest(machine))
@@ -439,7 +468,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,
439 if (_pid == pid) { 468 if (_pid == pid) {
440 /* process the parent's maps too */ 469 /* process the parent's maps too */
441 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 470 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
442 process, machine, mmap_data); 471 process, machine, mmap_data, proc_map_timeout);
443 if (rc) 472 if (rc)
444 break; 473 break;
445 } 474 }
@@ -453,7 +482,8 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
453 struct thread_map *threads, 482 struct thread_map *threads,
454 perf_event__handler_t process, 483 perf_event__handler_t process,
455 struct machine *machine, 484 struct machine *machine,
456 bool mmap_data) 485 bool mmap_data,
486 unsigned int proc_map_timeout)
457{ 487{
458 union perf_event *comm_event, *mmap_event, *fork_event; 488 union perf_event *comm_event, *mmap_event, *fork_event;
459 int err = -1, thread, j; 489 int err = -1, thread, j;
@@ -476,7 +506,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
476 fork_event, 506 fork_event,
477 threads->map[thread], 0, 507 threads->map[thread], 0,
478 process, tool, machine, 508 process, tool, machine,
479 mmap_data)) { 509 mmap_data, proc_map_timeout)) {
480 err = -1; 510 err = -1;
481 break; 511 break;
482 } 512 }
@@ -502,7 +532,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
502 fork_event, 532 fork_event,
503 comm_event->comm.pid, 0, 533 comm_event->comm.pid, 0,
504 process, tool, machine, 534 process, tool, machine,
505 mmap_data)) { 535 mmap_data, proc_map_timeout)) {
506 err = -1; 536 err = -1;
507 break; 537 break;
508 } 538 }
@@ -519,7 +549,9 @@ out:
519 549
520int perf_event__synthesize_threads(struct perf_tool *tool, 550int perf_event__synthesize_threads(struct perf_tool *tool,
521 perf_event__handler_t process, 551 perf_event__handler_t process,
522 struct machine *machine, bool mmap_data) 552 struct machine *machine,
553 bool mmap_data,
554 unsigned int proc_map_timeout)
523{ 555{
524 DIR *proc; 556 DIR *proc;
525 char proc_path[PATH_MAX]; 557 char proc_path[PATH_MAX];
@@ -559,7 +591,8 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
559 * one thread couldn't be synthesized. 591 * one thread couldn't be synthesized.
560 */ 592 */
561 __event__synthesize_thread(comm_event, mmap_event, fork_event, pid, 593 __event__synthesize_thread(comm_event, mmap_event, fork_event, pid,
562 1, process, tool, machine, mmap_data); 594 1, process, tool, machine, mmap_data,
595 proc_map_timeout);
563 } 596 }
564 597
565 err = 0; 598 err = 0;
@@ -692,6 +725,30 @@ int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
692 return machine__process_lost_event(machine, event, sample); 725 return machine__process_lost_event(machine, event, sample);
693} 726}
694 727
728int perf_event__process_aux(struct perf_tool *tool __maybe_unused,
729 union perf_event *event,
730 struct perf_sample *sample __maybe_unused,
731 struct machine *machine)
732{
733 return machine__process_aux_event(machine, event);
734}
735
736int perf_event__process_itrace_start(struct perf_tool *tool __maybe_unused,
737 union perf_event *event,
738 struct perf_sample *sample __maybe_unused,
739 struct machine *machine)
740{
741 return machine__process_itrace_start_event(machine, event);
742}
743
744int perf_event__process_lost_samples(struct perf_tool *tool __maybe_unused,
745 union perf_event *event,
746 struct perf_sample *sample,
747 struct machine *machine)
748{
749 return machine__process_lost_samples_event(machine, event, sample);
750}
751
695size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) 752size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
696{ 753{
697 return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n", 754 return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n",
@@ -755,6 +812,21 @@ int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
755 return machine__process_exit_event(machine, event, sample); 812 return machine__process_exit_event(machine, event, sample);
756} 813}
757 814
815size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp)
816{
817 return fprintf(fp, " offset: %#"PRIx64" size: %#"PRIx64" flags: %#"PRIx64" [%s%s]\n",
818 event->aux.aux_offset, event->aux.aux_size,
819 event->aux.flags,
820 event->aux.flags & PERF_AUX_FLAG_TRUNCATED ? "T" : "",
821 event->aux.flags & PERF_AUX_FLAG_OVERWRITE ? "O" : "");
822}
823
824size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp)
825{
826 return fprintf(fp, " pid: %u tid: %u\n",
827 event->itrace_start.pid, event->itrace_start.tid);
828}
829
758size_t perf_event__fprintf(union perf_event *event, FILE *fp) 830size_t perf_event__fprintf(union perf_event *event, FILE *fp)
759{ 831{
760 size_t ret = fprintf(fp, "PERF_RECORD_%s", 832 size_t ret = fprintf(fp, "PERF_RECORD_%s",
@@ -774,6 +846,12 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
774 case PERF_RECORD_MMAP2: 846 case PERF_RECORD_MMAP2:
775 ret += perf_event__fprintf_mmap2(event, fp); 847 ret += perf_event__fprintf_mmap2(event, fp);
776 break; 848 break;
849 case PERF_RECORD_AUX:
850 ret += perf_event__fprintf_aux(event, fp);
851 break;
852 case PERF_RECORD_ITRACE_START:
853 ret += perf_event__fprintf_itrace_start(event, fp);
854 break;
777 default: 855 default:
778 ret += fprintf(fp, "\n"); 856 ret += fprintf(fp, "\n");
779 } 857 }
@@ -877,6 +955,10 @@ void thread__find_addr_location(struct thread *thread,
877 al->sym = NULL; 955 al->sym = NULL;
878} 956}
879 957
958/*
959 * Callers need to drop the reference to al->thread, obtained in
960 * machine__findnew_thread()
961 */
880int perf_event__preprocess_sample(const union perf_event *event, 962int perf_event__preprocess_sample(const union perf_event *event,
881 struct machine *machine, 963 struct machine *machine,
882 struct addr_location *al, 964 struct addr_location *al,
@@ -937,6 +1019,17 @@ int perf_event__preprocess_sample(const union perf_event *event,
937 return 0; 1019 return 0;
938} 1020}
939 1021
1022/*
1023 * The preprocess_sample method will return with reference counts for the
1024 * in it, when done using (and perhaps getting ref counts if needing to
1025 * keep a pointer to one of those entries) it must be paired with
1026 * addr_location__put(), so that the refcounts can be decremented.
1027 */
1028void addr_location__put(struct addr_location *al)
1029{
1030 thread__zput(al->thread);
1031}
1032
940bool is_bts_event(struct perf_event_attr *attr) 1033bool is_bts_event(struct perf_event_attr *attr)
941{ 1034{
942 return attr->type == PERF_TYPE_HARDWARE && 1035 return attr->type == PERF_TYPE_HARDWARE &&
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 09b9e8d3fcf7..c53f36384b64 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -52,6 +52,11 @@ struct lost_event {
52 u64 lost; 52 u64 lost;
53}; 53};
54 54
55struct lost_samples_event {
56 struct perf_event_header header;
57 u64 lost;
58};
59
55/* 60/*
56 * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID 61 * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID
57 */ 62 */
@@ -157,6 +162,8 @@ enum {
157 PERF_IP_FLAG_IN_TX = 1ULL << 10, 162 PERF_IP_FLAG_IN_TX = 1ULL << 10,
158}; 163};
159 164
165#define PERF_IP_FLAG_CHARS "bcrosyiABEx"
166
160#define PERF_BRANCH_MASK (\ 167#define PERF_BRANCH_MASK (\
161 PERF_IP_FLAG_BRANCH |\ 168 PERF_IP_FLAG_BRANCH |\
162 PERF_IP_FLAG_CALL |\ 169 PERF_IP_FLAG_CALL |\
@@ -215,9 +222,17 @@ enum perf_user_event_type { /* above any possible kernel type */
215 PERF_RECORD_HEADER_BUILD_ID = 67, 222 PERF_RECORD_HEADER_BUILD_ID = 67,
216 PERF_RECORD_FINISHED_ROUND = 68, 223 PERF_RECORD_FINISHED_ROUND = 68,
217 PERF_RECORD_ID_INDEX = 69, 224 PERF_RECORD_ID_INDEX = 69,
225 PERF_RECORD_AUXTRACE_INFO = 70,
226 PERF_RECORD_AUXTRACE = 71,
227 PERF_RECORD_AUXTRACE_ERROR = 72,
218 PERF_RECORD_HEADER_MAX 228 PERF_RECORD_HEADER_MAX
219}; 229};
220 230
231enum auxtrace_error_type {
232 PERF_AUXTRACE_ERROR_ITRACE = 1,
233 PERF_AUXTRACE_ERROR_MAX
234};
235
221/* 236/*
222 * The kernel collects the number of events it couldn't send in a stretch and 237 * The kernel collects the number of events it couldn't send in a stretch and
223 * when possible sends this number in a PERF_RECORD_LOST event. The number of 238 * when possible sends this number in a PERF_RECORD_LOST event. The number of
@@ -225,6 +240,12 @@ enum perf_user_event_type { /* above any possible kernel type */
225 * total_lost tells exactly how many events the kernel in fact lost, i.e. it is 240 * total_lost tells exactly how many events the kernel in fact lost, i.e. it is
226 * the sum of all struct lost_event.lost fields reported. 241 * the sum of all struct lost_event.lost fields reported.
227 * 242 *
243 * The kernel discards mixed up samples and sends the number in a
244 * PERF_RECORD_LOST_SAMPLES event. The number of lost-samples events is stored
245 * in .nr_events[PERF_RECORD_LOST_SAMPLES] while total_lost_samples tells
246 * exactly how many samples the kernel in fact dropped, i.e. it is the sum of
247 * all struct lost_samples_event.lost fields reported.
248 *
228 * The total_period is needed because by default auto-freq is used, so 249 * The total_period is needed because by default auto-freq is used, so
229 * multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get 250 * multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get
230 * the total number of low level events, it is necessary to to sum all struct 251 * the total number of low level events, it is necessary to to sum all struct
@@ -234,6 +255,7 @@ struct events_stats {
234 u64 total_period; 255 u64 total_period;
235 u64 total_non_filtered_period; 256 u64 total_non_filtered_period;
236 u64 total_lost; 257 u64 total_lost;
258 u64 total_lost_samples;
237 u64 total_invalid_chains; 259 u64 total_invalid_chains;
238 u32 nr_events[PERF_RECORD_HEADER_MAX]; 260 u32 nr_events[PERF_RECORD_HEADER_MAX];
239 u32 nr_non_filtered_samples; 261 u32 nr_non_filtered_samples;
@@ -242,6 +264,8 @@ struct events_stats {
242 u32 nr_invalid_chains; 264 u32 nr_invalid_chains;
243 u32 nr_unknown_id; 265 u32 nr_unknown_id;
244 u32 nr_unprocessable_samples; 266 u32 nr_unprocessable_samples;
267 u32 nr_auxtrace_errors[PERF_AUXTRACE_ERROR_MAX];
268 u32 nr_proc_map_timeout;
245}; 269};
246 270
247struct attr_event { 271struct attr_event {
@@ -280,6 +304,50 @@ struct id_index_event {
280 struct id_index_entry entries[0]; 304 struct id_index_entry entries[0];
281}; 305};
282 306
307struct auxtrace_info_event {
308 struct perf_event_header header;
309 u32 type;
310 u32 reserved__; /* For alignment */
311 u64 priv[];
312};
313
314struct auxtrace_event {
315 struct perf_event_header header;
316 u64 size;
317 u64 offset;
318 u64 reference;
319 u32 idx;
320 u32 tid;
321 u32 cpu;
322 u32 reserved__; /* For alignment */
323};
324
325#define MAX_AUXTRACE_ERROR_MSG 64
326
327struct auxtrace_error_event {
328 struct perf_event_header header;
329 u32 type;
330 u32 code;
331 u32 cpu;
332 u32 pid;
333 u32 tid;
334 u32 reserved__; /* For alignment */
335 u64 ip;
336 char msg[MAX_AUXTRACE_ERROR_MSG];
337};
338
339struct aux_event {
340 struct perf_event_header header;
341 u64 aux_offset;
342 u64 aux_size;
343 u64 flags;
344};
345
346struct itrace_start_event {
347 struct perf_event_header header;
348 u32 pid, tid;
349};
350
283union perf_event { 351union perf_event {
284 struct perf_event_header header; 352 struct perf_event_header header;
285 struct mmap_event mmap; 353 struct mmap_event mmap;
@@ -287,6 +355,7 @@ union perf_event {
287 struct comm_event comm; 355 struct comm_event comm;
288 struct fork_event fork; 356 struct fork_event fork;
289 struct lost_event lost; 357 struct lost_event lost;
358 struct lost_samples_event lost_samples;
290 struct read_event read; 359 struct read_event read;
291 struct throttle_event throttle; 360 struct throttle_event throttle;
292 struct sample_event sample; 361 struct sample_event sample;
@@ -295,6 +364,11 @@ union perf_event {
295 struct tracing_data_event tracing_data; 364 struct tracing_data_event tracing_data;
296 struct build_id_event build_id; 365 struct build_id_event build_id;
297 struct id_index_event id_index; 366 struct id_index_event id_index;
367 struct auxtrace_info_event auxtrace_info;
368 struct auxtrace_event auxtrace;
369 struct auxtrace_error_event auxtrace_error;
370 struct aux_event aux;
371 struct itrace_start_event itrace_start;
298}; 372};
299 373
300void perf_event__print_totals(void); 374void perf_event__print_totals(void);
@@ -310,10 +384,12 @@ typedef int (*perf_event__handler_t)(struct perf_tool *tool,
310int perf_event__synthesize_thread_map(struct perf_tool *tool, 384int perf_event__synthesize_thread_map(struct perf_tool *tool,
311 struct thread_map *threads, 385 struct thread_map *threads,
312 perf_event__handler_t process, 386 perf_event__handler_t process,
313 struct machine *machine, bool mmap_data); 387 struct machine *machine, bool mmap_data,
388 unsigned int proc_map_timeout);
314int perf_event__synthesize_threads(struct perf_tool *tool, 389int perf_event__synthesize_threads(struct perf_tool *tool,
315 perf_event__handler_t process, 390 perf_event__handler_t process,
316 struct machine *machine, bool mmap_data); 391 struct machine *machine, bool mmap_data,
392 unsigned int proc_map_timeout);
317int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, 393int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
318 perf_event__handler_t process, 394 perf_event__handler_t process,
319 struct machine *machine); 395 struct machine *machine);
@@ -330,6 +406,18 @@ int perf_event__process_lost(struct perf_tool *tool,
330 union perf_event *event, 406 union perf_event *event,
331 struct perf_sample *sample, 407 struct perf_sample *sample,
332 struct machine *machine); 408 struct machine *machine);
409int perf_event__process_lost_samples(struct perf_tool *tool,
410 union perf_event *event,
411 struct perf_sample *sample,
412 struct machine *machine);
413int perf_event__process_aux(struct perf_tool *tool,
414 union perf_event *event,
415 struct perf_sample *sample,
416 struct machine *machine);
417int perf_event__process_itrace_start(struct perf_tool *tool,
418 union perf_event *event,
419 struct perf_sample *sample,
420 struct machine *machine);
333int perf_event__process_mmap(struct perf_tool *tool, 421int perf_event__process_mmap(struct perf_tool *tool,
334 union perf_event *event, 422 union perf_event *event,
335 struct perf_sample *sample, 423 struct perf_sample *sample,
@@ -358,6 +446,8 @@ int perf_event__preprocess_sample(const union perf_event *event,
358 struct addr_location *al, 446 struct addr_location *al,
359 struct perf_sample *sample); 447 struct perf_sample *sample);
360 448
449void addr_location__put(struct addr_location *al);
450
361struct thread; 451struct thread;
362 452
363bool is_bts_event(struct perf_event_attr *attr); 453bool is_bts_event(struct perf_event_attr *attr);
@@ -381,12 +471,15 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
381 pid_t pid, pid_t tgid, 471 pid_t pid, pid_t tgid,
382 perf_event__handler_t process, 472 perf_event__handler_t process,
383 struct machine *machine, 473 struct machine *machine,
384 bool mmap_data); 474 bool mmap_data,
475 unsigned int proc_map_timeout);
385 476
386size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp); 477size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
387size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp); 478size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
388size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp); 479size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
389size_t perf_event__fprintf_task(union perf_event *event, FILE *fp); 480size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
481size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp);
482size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp);
390size_t perf_event__fprintf(union perf_event *event, FILE *fp); 483size_t perf_event__fprintf(union perf_event *event, FILE *fp);
391 484
392u64 kallsyms__get_function_start(const char *kallsyms_filename, 485u64 kallsyms__get_function_start(const char *kallsyms_filename,
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 080be93eea96..8366511b45f8 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -297,6 +297,8 @@ void perf_evlist__disable(struct perf_evlist *evlist)
297 PERF_EVENT_IOC_DISABLE, 0); 297 PERF_EVENT_IOC_DISABLE, 0);
298 } 298 }
299 } 299 }
300
301 evlist->enabled = false;
300} 302}
301 303
302void perf_evlist__enable(struct perf_evlist *evlist) 304void perf_evlist__enable(struct perf_evlist *evlist)
@@ -316,6 +318,13 @@ void perf_evlist__enable(struct perf_evlist *evlist)
316 PERF_EVENT_IOC_ENABLE, 0); 318 PERF_EVENT_IOC_ENABLE, 0);
317 } 319 }
318 } 320 }
321
322 evlist->enabled = true;
323}
324
325void perf_evlist__toggle_enable(struct perf_evlist *evlist)
326{
327 (evlist->enabled ? perf_evlist__disable : perf_evlist__enable)(evlist);
319} 328}
320 329
321int perf_evlist__disable_event(struct perf_evlist *evlist, 330int perf_evlist__disable_event(struct perf_evlist *evlist,
@@ -634,11 +643,18 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
634union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) 643union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
635{ 644{
636 struct perf_mmap *md = &evlist->mmap[idx]; 645 struct perf_mmap *md = &evlist->mmap[idx];
637 u64 head = perf_mmap__read_head(md); 646 u64 head;
638 u64 old = md->prev; 647 u64 old = md->prev;
639 unsigned char *data = md->base + page_size; 648 unsigned char *data = md->base + page_size;
640 union perf_event *event = NULL; 649 union perf_event *event = NULL;
641 650
651 /*
652 * Check if event was unmapped due to a POLLHUP/POLLERR.
653 */
654 if (!atomic_read(&md->refcnt))
655 return NULL;
656
657 head = perf_mmap__read_head(md);
642 if (evlist->overwrite) { 658 if (evlist->overwrite) {
643 /* 659 /*
644 * If we're further behind than half the buffer, there's a chance 660 * If we're further behind than half the buffer, there's a chance
@@ -695,19 +711,19 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
695 711
696static bool perf_mmap__empty(struct perf_mmap *md) 712static bool perf_mmap__empty(struct perf_mmap *md)
697{ 713{
698 return perf_mmap__read_head(md) == md->prev; 714 return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
699} 715}
700 716
701static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx) 717static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx)
702{ 718{
703 ++evlist->mmap[idx].refcnt; 719 atomic_inc(&evlist->mmap[idx].refcnt);
704} 720}
705 721
706static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx) 722static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx)
707{ 723{
708 BUG_ON(evlist->mmap[idx].refcnt == 0); 724 BUG_ON(atomic_read(&evlist->mmap[idx].refcnt) == 0);
709 725
710 if (--evlist->mmap[idx].refcnt == 0) 726 if (atomic_dec_and_test(&evlist->mmap[idx].refcnt))
711 __perf_evlist__munmap(evlist, idx); 727 __perf_evlist__munmap(evlist, idx);
712} 728}
713 729
@@ -721,17 +737,46 @@ void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
721 perf_mmap__write_tail(md, old); 737 perf_mmap__write_tail(md, old);
722 } 738 }
723 739
724 if (md->refcnt == 1 && perf_mmap__empty(md)) 740 if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md))
725 perf_evlist__mmap_put(evlist, idx); 741 perf_evlist__mmap_put(evlist, idx);
726} 742}
727 743
744int __weak auxtrace_mmap__mmap(struct auxtrace_mmap *mm __maybe_unused,
745 struct auxtrace_mmap_params *mp __maybe_unused,
746 void *userpg __maybe_unused,
747 int fd __maybe_unused)
748{
749 return 0;
750}
751
752void __weak auxtrace_mmap__munmap(struct auxtrace_mmap *mm __maybe_unused)
753{
754}
755
756void __weak auxtrace_mmap_params__init(
757 struct auxtrace_mmap_params *mp __maybe_unused,
758 off_t auxtrace_offset __maybe_unused,
759 unsigned int auxtrace_pages __maybe_unused,
760 bool auxtrace_overwrite __maybe_unused)
761{
762}
763
764void __weak auxtrace_mmap_params__set_idx(
765 struct auxtrace_mmap_params *mp __maybe_unused,
766 struct perf_evlist *evlist __maybe_unused,
767 int idx __maybe_unused,
768 bool per_cpu __maybe_unused)
769{
770}
771
728static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) 772static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
729{ 773{
730 if (evlist->mmap[idx].base != NULL) { 774 if (evlist->mmap[idx].base != NULL) {
731 munmap(evlist->mmap[idx].base, evlist->mmap_len); 775 munmap(evlist->mmap[idx].base, evlist->mmap_len);
732 evlist->mmap[idx].base = NULL; 776 evlist->mmap[idx].base = NULL;
733 evlist->mmap[idx].refcnt = 0; 777 atomic_set(&evlist->mmap[idx].refcnt, 0);
734 } 778 }
779 auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap);
735} 780}
736 781
737void perf_evlist__munmap(struct perf_evlist *evlist) 782void perf_evlist__munmap(struct perf_evlist *evlist)
@@ -759,6 +804,7 @@ static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
759struct mmap_params { 804struct mmap_params {
760 int prot; 805 int prot;
761 int mask; 806 int mask;
807 struct auxtrace_mmap_params auxtrace_mp;
762}; 808};
763 809
764static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, 810static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
@@ -777,7 +823,7 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
777 * evlist layer can't just drop it when filtering events in 823 * evlist layer can't just drop it when filtering events in
778 * perf_evlist__filter_pollfd(). 824 * perf_evlist__filter_pollfd().
779 */ 825 */
780 evlist->mmap[idx].refcnt = 2; 826 atomic_set(&evlist->mmap[idx].refcnt, 2);
781 evlist->mmap[idx].prev = 0; 827 evlist->mmap[idx].prev = 0;
782 evlist->mmap[idx].mask = mp->mask; 828 evlist->mmap[idx].mask = mp->mask;
783 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot, 829 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot,
@@ -789,6 +835,10 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
789 return -1; 835 return -1;
790 } 836 }
791 837
838 if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap,
839 &mp->auxtrace_mp, evlist->mmap[idx].base, fd))
840 return -1;
841
792 return 0; 842 return 0;
793} 843}
794 844
@@ -853,6 +903,9 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist,
853 for (cpu = 0; cpu < nr_cpus; cpu++) { 903 for (cpu = 0; cpu < nr_cpus; cpu++) {
854 int output = -1; 904 int output = -1;
855 905
906 auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, cpu,
907 true);
908
856 for (thread = 0; thread < nr_threads; thread++) { 909 for (thread = 0; thread < nr_threads; thread++) {
857 if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu, 910 if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu,
858 thread, &output)) 911 thread, &output))
@@ -878,6 +931,9 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist,
878 for (thread = 0; thread < nr_threads; thread++) { 931 for (thread = 0; thread < nr_threads; thread++) {
879 int output = -1; 932 int output = -1;
880 933
934 auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, thread,
935 false);
936
881 if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread, 937 if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread,
882 &output)) 938 &output))
883 goto out_unmap; 939 goto out_unmap;
@@ -960,10 +1016,8 @@ static long parse_pages_arg(const char *str, unsigned long min,
960 return pages; 1016 return pages;
961} 1017}
962 1018
963int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, 1019int __perf_evlist__parse_mmap_pages(unsigned int *mmap_pages, const char *str)
964 int unset __maybe_unused)
965{ 1020{
966 unsigned int *mmap_pages = opt->value;
967 unsigned long max = UINT_MAX; 1021 unsigned long max = UINT_MAX;
968 long pages; 1022 long pages;
969 1023
@@ -980,20 +1034,32 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
980 return 0; 1034 return 0;
981} 1035}
982 1036
1037int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
1038 int unset __maybe_unused)
1039{
1040 return __perf_evlist__parse_mmap_pages(opt->value, str);
1041}
1042
983/** 1043/**
984 * perf_evlist__mmap - Create mmaps to receive events. 1044 * perf_evlist__mmap_ex - Create mmaps to receive events.
985 * @evlist: list of events 1045 * @evlist: list of events
986 * @pages: map length in pages 1046 * @pages: map length in pages
987 * @overwrite: overwrite older events? 1047 * @overwrite: overwrite older events?
1048 * @auxtrace_pages - auxtrace map length in pages
1049 * @auxtrace_overwrite - overwrite older auxtrace data?
988 * 1050 *
989 * If @overwrite is %false the user needs to signal event consumption using 1051 * If @overwrite is %false the user needs to signal event consumption using
990 * perf_mmap__write_tail(). Using perf_evlist__mmap_read() does this 1052 * perf_mmap__write_tail(). Using perf_evlist__mmap_read() does this
991 * automatically. 1053 * automatically.
992 * 1054 *
1055 * Similarly, if @auxtrace_overwrite is %false the user needs to signal data
1056 * consumption using auxtrace_mmap__write_tail().
1057 *
993 * Return: %0 on success, negative error code otherwise. 1058 * Return: %0 on success, negative error code otherwise.
994 */ 1059 */
995int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, 1060int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
996 bool overwrite) 1061 bool overwrite, unsigned int auxtrace_pages,
1062 bool auxtrace_overwrite)
997{ 1063{
998 struct perf_evsel *evsel; 1064 struct perf_evsel *evsel;
999 const struct cpu_map *cpus = evlist->cpus; 1065 const struct cpu_map *cpus = evlist->cpus;
@@ -1013,6 +1079,9 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
1013 pr_debug("mmap size %zuB\n", evlist->mmap_len); 1079 pr_debug("mmap size %zuB\n", evlist->mmap_len);
1014 mp.mask = evlist->mmap_len - page_size - 1; 1080 mp.mask = evlist->mmap_len - page_size - 1;
1015 1081
1082 auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->mmap_len,
1083 auxtrace_pages, auxtrace_overwrite);
1084
1016 evlist__for_each(evlist, evsel) { 1085 evlist__for_each(evlist, evsel) {
1017 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 1086 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
1018 evsel->sample_id == NULL && 1087 evsel->sample_id == NULL &&
@@ -1026,6 +1095,12 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
1026 return perf_evlist__mmap_per_cpu(evlist, &mp); 1095 return perf_evlist__mmap_per_cpu(evlist, &mp);
1027} 1096}
1028 1097
1098int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
1099 bool overwrite)
1100{
1101 return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false);
1102}
1103
1029int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) 1104int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
1030{ 1105{
1031 evlist->threads = thread_map__new_str(target->pid, target->tid, 1106 evlist->threads = thread_map__new_str(target->pid, target->tid,
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index b5cce95d644e..a8489b9d2812 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -1,6 +1,7 @@
1#ifndef __PERF_EVLIST_H 1#ifndef __PERF_EVLIST_H
2#define __PERF_EVLIST_H 1 2#define __PERF_EVLIST_H 1
3 3
4#include <linux/atomic.h>
4#include <linux/list.h> 5#include <linux/list.h>
5#include <api/fd/array.h> 6#include <api/fd/array.h>
6#include <stdio.h> 7#include <stdio.h>
@@ -8,6 +9,7 @@
8#include "event.h" 9#include "event.h"
9#include "evsel.h" 10#include "evsel.h"
10#include "util.h" 11#include "util.h"
12#include "auxtrace.h"
11#include <unistd.h> 13#include <unistd.h>
12 14
13struct pollfd; 15struct pollfd;
@@ -26,8 +28,9 @@ struct record_opts;
26struct perf_mmap { 28struct perf_mmap {
27 void *base; 29 void *base;
28 int mask; 30 int mask;
29 int refcnt; 31 atomic_t refcnt;
30 u64 prev; 32 u64 prev;
33 struct auxtrace_mmap auxtrace_mmap;
31 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8))); 34 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
32}; 35};
33 36
@@ -37,6 +40,8 @@ struct perf_evlist {
37 int nr_entries; 40 int nr_entries;
38 int nr_groups; 41 int nr_groups;
39 int nr_mmaps; 42 int nr_mmaps;
43 bool overwrite;
44 bool enabled;
40 size_t mmap_len; 45 size_t mmap_len;
41 int id_pos; 46 int id_pos;
42 int is_pos; 47 int is_pos;
@@ -45,7 +50,6 @@ struct perf_evlist {
45 int cork_fd; 50 int cork_fd;
46 pid_t pid; 51 pid_t pid;
47 } workload; 52 } workload;
48 bool overwrite;
49 struct fdarray pollfd; 53 struct fdarray pollfd;
50 struct perf_mmap *mmap; 54 struct perf_mmap *mmap;
51 struct thread_map *threads; 55 struct thread_map *threads;
@@ -122,16 +126,21 @@ int perf_evlist__start_workload(struct perf_evlist *evlist);
122 126
123struct option; 127struct option;
124 128
129int __perf_evlist__parse_mmap_pages(unsigned int *mmap_pages, const char *str);
125int perf_evlist__parse_mmap_pages(const struct option *opt, 130int perf_evlist__parse_mmap_pages(const struct option *opt,
126 const char *str, 131 const char *str,
127 int unset); 132 int unset);
128 133
134int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
135 bool overwrite, unsigned int auxtrace_pages,
136 bool auxtrace_overwrite);
129int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, 137int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
130 bool overwrite); 138 bool overwrite);
131void perf_evlist__munmap(struct perf_evlist *evlist); 139void perf_evlist__munmap(struct perf_evlist *evlist);
132 140
133void perf_evlist__disable(struct perf_evlist *evlist); 141void perf_evlist__disable(struct perf_evlist *evlist);
134void perf_evlist__enable(struct perf_evlist *evlist); 142void perf_evlist__enable(struct perf_evlist *evlist);
143void perf_evlist__toggle_enable(struct perf_evlist *evlist);
135 144
136int perf_evlist__disable_event(struct perf_evlist *evlist, 145int perf_evlist__disable_event(struct perf_evlist *evlist,
137 struct perf_evsel *evsel); 146 struct perf_evsel *evsel);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 33e3fd8c2e68..33449decf7bd 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -26,6 +26,7 @@
26#include "perf_regs.h" 26#include "perf_regs.h"
27#include "debug.h" 27#include "debug.h"
28#include "trace-event.h" 28#include "trace-event.h"
29#include "stat.h"
29 30
30static struct { 31static struct {
31 bool sample_id_all; 32 bool sample_id_all;
@@ -851,19 +852,6 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
851 return 0; 852 return 0;
852} 853}
853 854
854void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus)
855{
856 memset(evsel->counts, 0, (sizeof(*evsel->counts) +
857 (ncpus * sizeof(struct perf_counts_values))));
858}
859
860int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
861{
862 evsel->counts = zalloc((sizeof(*evsel->counts) +
863 (ncpus * sizeof(struct perf_counts_values))));
864 return evsel->counts != NULL ? 0 : -ENOMEM;
865}
866
867static void perf_evsel__free_fd(struct perf_evsel *evsel) 855static void perf_evsel__free_fd(struct perf_evsel *evsel)
868{ 856{
869 xyarray__delete(evsel->fd); 857 xyarray__delete(evsel->fd);
@@ -891,11 +879,6 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
891 } 879 }
892} 880}
893 881
894void perf_evsel__free_counts(struct perf_evsel *evsel)
895{
896 zfree(&evsel->counts);
897}
898
899void perf_evsel__exit(struct perf_evsel *evsel) 882void perf_evsel__exit(struct perf_evsel *evsel)
900{ 883{
901 assert(list_empty(&evsel->node)); 884 assert(list_empty(&evsel->node));
@@ -1058,7 +1041,7 @@ static void __p_read_format(char *buf, size_t size, u64 value)
1058 1041
1059#define BUF_SIZE 1024 1042#define BUF_SIZE 1024
1060 1043
1061#define p_hex(val) snprintf(buf, BUF_SIZE, "%"PRIx64, (uint64_t)(val)) 1044#define p_hex(val) snprintf(buf, BUF_SIZE, "%#"PRIx64, (uint64_t)(val))
1062#define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val)) 1045#define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val))
1063#define p_signed(val) snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val)) 1046#define p_signed(val) snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val))
1064#define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val) 1047#define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val)
@@ -1121,6 +1104,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
1121 PRINT_ATTRf(sample_stack_user, p_unsigned); 1104 PRINT_ATTRf(sample_stack_user, p_unsigned);
1122 PRINT_ATTRf(clockid, p_signed); 1105 PRINT_ATTRf(clockid, p_signed);
1123 PRINT_ATTRf(sample_regs_intr, p_hex); 1106 PRINT_ATTRf(sample_regs_intr, p_hex);
1107 PRINT_ATTRf(aux_watermark, p_unsigned);
1124 1108
1125 return ret; 1109 return ret;
1126} 1110}
@@ -2148,7 +2132,9 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2148 case EMFILE: 2132 case EMFILE:
2149 return scnprintf(msg, size, "%s", 2133 return scnprintf(msg, size, "%s",
2150 "Too many events are opened.\n" 2134 "Too many events are opened.\n"
2151 "Try again after reducing the number of events."); 2135 "Probably the maximum number of open file descriptors has been reached.\n"
2136 "Hint: Try again after reducing the number of events.\n"
2137 "Hint: Try increasing the limit with 'ulimit -n <limit>'");
2152 case ENODEV: 2138 case ENODEV:
2153 if (target->cpu_list) 2139 if (target->cpu_list)
2154 return scnprintf(msg, size, "%s", 2140 return scnprintf(msg, size, "%s",
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index e486151b0308..bb0579e8a10a 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -73,7 +73,6 @@ struct perf_evsel {
73 char *name; 73 char *name;
74 double scale; 74 double scale;
75 const char *unit; 75 const char *unit;
76 bool snapshot;
77 struct event_format *tp_format; 76 struct event_format *tp_format;
78 union { 77 union {
79 void *priv; 78 void *priv;
@@ -86,6 +85,7 @@ struct perf_evsel {
86 unsigned int sample_size; 85 unsigned int sample_size;
87 int id_pos; 86 int id_pos;
88 int is_pos; 87 int is_pos;
88 bool snapshot;
89 bool supported; 89 bool supported;
90 bool needs_swap; 90 bool needs_swap;
91 bool no_aux_samples; 91 bool no_aux_samples;
@@ -93,11 +93,11 @@ struct perf_evsel {
93 bool system_wide; 93 bool system_wide;
94 bool tracking; 94 bool tracking;
95 bool per_pkg; 95 bool per_pkg;
96 unsigned long *per_pkg_mask;
97 /* parse modifier helper */ 96 /* parse modifier helper */
98 int exclude_GH; 97 int exclude_GH;
99 int nr_members; 98 int nr_members;
100 int sample_read; 99 int sample_read;
100 unsigned long *per_pkg_mask;
101 struct perf_evsel *leader; 101 struct perf_evsel *leader;
102 char *group_name; 102 char *group_name;
103}; 103};
@@ -170,9 +170,6 @@ const char *perf_evsel__group_name(struct perf_evsel *evsel);
170int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size); 170int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);
171 171
172int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); 172int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
173int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
174void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
175void perf_evsel__free_counts(struct perf_evsel *evsel);
176void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 173void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
177 174
178void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, 175void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 918fd8ae2d80..21a77e7a171e 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -869,6 +869,20 @@ static int write_branch_stack(int fd __maybe_unused,
869 return 0; 869 return 0;
870} 870}
871 871
872static int write_auxtrace(int fd, struct perf_header *h,
873 struct perf_evlist *evlist __maybe_unused)
874{
875 struct perf_session *session;
876 int err;
877
878 session = container_of(h, struct perf_session, header);
879
880 err = auxtrace_index__write(fd, &session->auxtrace_index);
881 if (err < 0)
882 pr_err("Failed to write auxtrace index\n");
883 return err;
884}
885
872static void print_hostname(struct perf_header *ph, int fd __maybe_unused, 886static void print_hostname(struct perf_header *ph, int fd __maybe_unused,
873 FILE *fp) 887 FILE *fp)
874{ 888{
@@ -1151,6 +1165,12 @@ static void print_branch_stack(struct perf_header *ph __maybe_unused,
1151 fprintf(fp, "# contains samples with branch stack\n"); 1165 fprintf(fp, "# contains samples with branch stack\n");
1152} 1166}
1153 1167
1168static void print_auxtrace(struct perf_header *ph __maybe_unused,
1169 int fd __maybe_unused, FILE *fp)
1170{
1171 fprintf(fp, "# contains AUX area data (e.g. instruction trace)\n");
1172}
1173
1154static void print_pmu_mappings(struct perf_header *ph, int fd __maybe_unused, 1174static void print_pmu_mappings(struct perf_header *ph, int fd __maybe_unused,
1155 FILE *fp) 1175 FILE *fp)
1156{ 1176{
@@ -1218,9 +1238,8 @@ static int __event_process_build_id(struct build_id_event *bev,
1218 struct perf_session *session) 1238 struct perf_session *session)
1219{ 1239{
1220 int err = -1; 1240 int err = -1;
1221 struct dsos *dsos;
1222 struct machine *machine; 1241 struct machine *machine;
1223 u16 misc; 1242 u16 cpumode;
1224 struct dso *dso; 1243 struct dso *dso;
1225 enum dso_kernel_type dso_type; 1244 enum dso_kernel_type dso_type;
1226 1245
@@ -1228,39 +1247,37 @@ static int __event_process_build_id(struct build_id_event *bev,
1228 if (!machine) 1247 if (!machine)
1229 goto out; 1248 goto out;
1230 1249
1231 misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 1250 cpumode = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1232 1251
1233 switch (misc) { 1252 switch (cpumode) {
1234 case PERF_RECORD_MISC_KERNEL: 1253 case PERF_RECORD_MISC_KERNEL:
1235 dso_type = DSO_TYPE_KERNEL; 1254 dso_type = DSO_TYPE_KERNEL;
1236 dsos = &machine->kernel_dsos;
1237 break; 1255 break;
1238 case PERF_RECORD_MISC_GUEST_KERNEL: 1256 case PERF_RECORD_MISC_GUEST_KERNEL:
1239 dso_type = DSO_TYPE_GUEST_KERNEL; 1257 dso_type = DSO_TYPE_GUEST_KERNEL;
1240 dsos = &machine->kernel_dsos;
1241 break; 1258 break;
1242 case PERF_RECORD_MISC_USER: 1259 case PERF_RECORD_MISC_USER:
1243 case PERF_RECORD_MISC_GUEST_USER: 1260 case PERF_RECORD_MISC_GUEST_USER:
1244 dso_type = DSO_TYPE_USER; 1261 dso_type = DSO_TYPE_USER;
1245 dsos = &machine->user_dsos;
1246 break; 1262 break;
1247 default: 1263 default:
1248 goto out; 1264 goto out;
1249 } 1265 }
1250 1266
1251 dso = __dsos__findnew(dsos, filename); 1267 dso = machine__findnew_dso(machine, filename);
1252 if (dso != NULL) { 1268 if (dso != NULL) {
1253 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 1269 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1254 1270
1255 dso__set_build_id(dso, &bev->build_id); 1271 dso__set_build_id(dso, &bev->build_id);
1256 1272
1257 if (!is_kernel_module(filename)) 1273 if (!is_kernel_module(filename, cpumode))
1258 dso->kernel = dso_type; 1274 dso->kernel = dso_type;
1259 1275
1260 build_id__sprintf(dso->build_id, sizeof(dso->build_id), 1276 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1261 sbuild_id); 1277 sbuild_id);
1262 pr_debug("build id event received for %s: %s\n", 1278 pr_debug("build id event received for %s: %s\n",
1263 dso->long_name, sbuild_id); 1279 dso->long_name, sbuild_id);
1280 dso__put(dso);
1264 } 1281 }
1265 1282
1266 err = 0; 1283 err = 0;
@@ -1821,6 +1838,22 @@ out_free:
1821 return ret; 1838 return ret;
1822} 1839}
1823 1840
1841static int process_auxtrace(struct perf_file_section *section,
1842 struct perf_header *ph, int fd,
1843 void *data __maybe_unused)
1844{
1845 struct perf_session *session;
1846 int err;
1847
1848 session = container_of(ph, struct perf_session, header);
1849
1850 err = auxtrace_index__process(fd, section->size, session,
1851 ph->needs_swap);
1852 if (err < 0)
1853 pr_err("Failed to process auxtrace index\n");
1854 return err;
1855}
1856
1824struct feature_ops { 1857struct feature_ops {
1825 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); 1858 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
1826 void (*print)(struct perf_header *h, int fd, FILE *fp); 1859 void (*print)(struct perf_header *h, int fd, FILE *fp);
@@ -1861,6 +1894,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
1861 FEAT_OPA(HEADER_BRANCH_STACK, branch_stack), 1894 FEAT_OPA(HEADER_BRANCH_STACK, branch_stack),
1862 FEAT_OPP(HEADER_PMU_MAPPINGS, pmu_mappings), 1895 FEAT_OPP(HEADER_PMU_MAPPINGS, pmu_mappings),
1863 FEAT_OPP(HEADER_GROUP_DESC, group_desc), 1896 FEAT_OPP(HEADER_GROUP_DESC, group_desc),
1897 FEAT_OPP(HEADER_AUXTRACE, auxtrace),
1864}; 1898};
1865 1899
1866struct header_print_data { 1900struct header_print_data {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 3bb90ac172a1..d4d57962c591 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -30,6 +30,7 @@ enum {
30 HEADER_BRANCH_STACK, 30 HEADER_BRANCH_STACK,
31 HEADER_PMU_MAPPINGS, 31 HEADER_PMU_MAPPINGS,
32 HEADER_GROUP_DESC, 32 HEADER_GROUP_DESC,
33 HEADER_AUXTRACE,
33 HEADER_LAST_FEATURE, 34 HEADER_LAST_FEATURE,
34 HEADER_FEAT_BITS = 256, 35 HEADER_FEAT_BITS = 256,
35}; 36};
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index cc22b9158b93..6f28d53d4e46 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -313,8 +313,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
313 memset(&he->stat, 0, sizeof(he->stat)); 313 memset(&he->stat, 0, sizeof(he->stat));
314 } 314 }
315 315
316 if (he->ms.map) 316 map__get(he->ms.map);
317 he->ms.map->referenced = true;
318 317
319 if (he->branch_info) { 318 if (he->branch_info) {
320 /* 319 /*
@@ -324,6 +323,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
324 */ 323 */
325 he->branch_info = malloc(sizeof(*he->branch_info)); 324 he->branch_info = malloc(sizeof(*he->branch_info));
326 if (he->branch_info == NULL) { 325 if (he->branch_info == NULL) {
326 map__zput(he->ms.map);
327 free(he->stat_acc); 327 free(he->stat_acc);
328 free(he); 328 free(he);
329 return NULL; 329 return NULL;
@@ -332,17 +332,13 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
332 memcpy(he->branch_info, template->branch_info, 332 memcpy(he->branch_info, template->branch_info,
333 sizeof(*he->branch_info)); 333 sizeof(*he->branch_info));
334 334
335 if (he->branch_info->from.map) 335 map__get(he->branch_info->from.map);
336 he->branch_info->from.map->referenced = true; 336 map__get(he->branch_info->to.map);
337 if (he->branch_info->to.map)
338 he->branch_info->to.map->referenced = true;
339 } 337 }
340 338
341 if (he->mem_info) { 339 if (he->mem_info) {
342 if (he->mem_info->iaddr.map) 340 map__get(he->mem_info->iaddr.map);
343 he->mem_info->iaddr.map->referenced = true; 341 map__get(he->mem_info->daddr.map);
344 if (he->mem_info->daddr.map)
345 he->mem_info->daddr.map->referenced = true;
346 } 342 }
347 343
348 if (symbol_conf.use_callchain) 344 if (symbol_conf.use_callchain)
@@ -362,10 +358,10 @@ static u8 symbol__parent_filter(const struct symbol *parent)
362 return 0; 358 return 0;
363} 359}
364 360
365static struct hist_entry *add_hist_entry(struct hists *hists, 361static struct hist_entry *hists__findnew_entry(struct hists *hists,
366 struct hist_entry *entry, 362 struct hist_entry *entry,
367 struct addr_location *al, 363 struct addr_location *al,
368 bool sample_self) 364 bool sample_self)
369{ 365{
370 struct rb_node **p; 366 struct rb_node **p;
371 struct rb_node *parent = NULL; 367 struct rb_node *parent = NULL;
@@ -407,9 +403,8 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
407 * the history counter to increment. 403 * the history counter to increment.
408 */ 404 */
409 if (he->ms.map != entry->ms.map) { 405 if (he->ms.map != entry->ms.map) {
410 he->ms.map = entry->ms.map; 406 map__put(he->ms.map);
411 if (he->ms.map) 407 he->ms.map = map__get(entry->ms.map);
412 he->ms.map->referenced = true;
413 } 408 }
414 goto out; 409 goto out;
415 } 410 }
@@ -468,7 +463,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
468 .transaction = transaction, 463 .transaction = transaction,
469 }; 464 };
470 465
471 return add_hist_entry(hists, &entry, al, sample_self); 466 return hists__findnew_entry(hists, &entry, al, sample_self);
472} 467}
473 468
474static int 469static int
@@ -548,9 +543,9 @@ iter_finish_mem_entry(struct hist_entry_iter *iter,
548 543
549out: 544out:
550 /* 545 /*
551 * We don't need to free iter->priv (mem_info) here since 546 * We don't need to free iter->priv (mem_info) here since the mem info
552 * the mem info was either already freed in add_hist_entry() or 547 * was either already freed in hists__findnew_entry() or passed to a
553 * passed to a new hist entry by hist_entry__new(). 548 * new hist entry by hist_entry__new().
554 */ 549 */
555 iter->priv = NULL; 550 iter->priv = NULL;
556 551
@@ -851,19 +846,15 @@ const struct hist_iter_ops hist_iter_cumulative = {
851}; 846};
852 847
853int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, 848int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
854 struct perf_evsel *evsel, struct perf_sample *sample,
855 int max_stack_depth, void *arg) 849 int max_stack_depth, void *arg)
856{ 850{
857 int err, err2; 851 int err, err2;
858 852
859 err = sample__resolve_callchain(sample, &iter->parent, evsel, al, 853 err = sample__resolve_callchain(iter->sample, &iter->parent,
860 max_stack_depth); 854 iter->evsel, al, max_stack_depth);
861 if (err) 855 if (err)
862 return err; 856 return err;
863 857
864 iter->evsel = evsel;
865 iter->sample = sample;
866
867 err = iter->ops->prepare_entry(iter, al); 858 err = iter->ops->prepare_entry(iter, al);
868 if (err) 859 if (err)
869 goto out; 860 goto out;
@@ -937,8 +928,20 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
937void hist_entry__delete(struct hist_entry *he) 928void hist_entry__delete(struct hist_entry *he)
938{ 929{
939 thread__zput(he->thread); 930 thread__zput(he->thread);
940 zfree(&he->branch_info); 931 map__zput(he->ms.map);
941 zfree(&he->mem_info); 932
933 if (he->branch_info) {
934 map__zput(he->branch_info->from.map);
935 map__zput(he->branch_info->to.map);
936 zfree(&he->branch_info);
937 }
938
939 if (he->mem_info) {
940 map__zput(he->mem_info->iaddr.map);
941 map__zput(he->mem_info->daddr.map);
942 zfree(&he->mem_info);
943 }
944
942 zfree(&he->stat_acc); 945 zfree(&he->stat_acc);
943 free_srcline(he->srcline); 946 free_srcline(he->srcline);
944 free_callchain(he->callchain); 947 free_callchain(he->callchain);
@@ -1163,7 +1166,7 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
1163 return; 1166 return;
1164 1167
1165 /* force fold unfiltered entry for simplicity */ 1168 /* force fold unfiltered entry for simplicity */
1166 h->ms.unfolded = false; 1169 h->unfolded = false;
1167 h->row_offset = 0; 1170 h->row_offset = 0;
1168 h->nr_rows = 0; 1171 h->nr_rows = 0;
1169 1172
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 9f31b89a527a..5ed8d9c22981 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -111,7 +111,6 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
111 u64 weight, u64 transaction, 111 u64 weight, u64 transaction,
112 bool sample_self); 112 bool sample_self);
113int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, 113int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
114 struct perf_evsel *evsel, struct perf_sample *sample,
115 int max_stack_depth, void *arg); 114 int max_stack_depth, void *arg);
116 115
117int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); 116int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
diff --git a/tools/perf/util/include/linux/poison.h b/tools/perf/util/include/linux/poison.h
deleted file mode 100644
index fef6dbc9ce13..000000000000
--- a/tools/perf/util/include/linux/poison.h
+++ /dev/null
@@ -1 +0,0 @@
1#include "../../../../include/linux/poison.h"
diff --git a/tools/perf/util/include/linux/rbtree.h b/tools/perf/util/include/linux/rbtree.h
index 2a030c5af3aa..f06d89f0b867 100644
--- a/tools/perf/util/include/linux/rbtree.h
+++ b/tools/perf/util/include/linux/rbtree.h
@@ -1,2 +1,16 @@
1#ifndef __TOOLS_LINUX_PERF_RBTREE_H
2#define __TOOLS_LINUX_PERF_RBTREE_H
1#include <stdbool.h> 3#include <stdbool.h>
2#include "../../../../include/linux/rbtree.h" 4#include "../../../../include/linux/rbtree.h"
5
6/*
7 * Handy for checking that we are not deleting an entry that is
8 * already in a list, found in block/{blk-throttle,cfq-iosched}.c,
9 * probably should be moved to lib/rbtree.c...
10 */
11static inline void rb_erase_init(struct rb_node *n, struct rb_root *root)
12{
13 rb_erase(n, root);
14 RB_CLEAR_NODE(n);
15}
16#endif /* __TOOLS_LINUX_PERF_RBTREE_H */
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 527e032e24f6..4744673aff1b 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -14,20 +14,23 @@
14#include "unwind.h" 14#include "unwind.h"
15#include "linux/hash.h" 15#include "linux/hash.h"
16 16
17static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock);
18
17static void dsos__init(struct dsos *dsos) 19static void dsos__init(struct dsos *dsos)
18{ 20{
19 INIT_LIST_HEAD(&dsos->head); 21 INIT_LIST_HEAD(&dsos->head);
20 dsos->root = RB_ROOT; 22 dsos->root = RB_ROOT;
23 pthread_rwlock_init(&dsos->lock, NULL);
21} 24}
22 25
23int 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)
24{ 27{
25 map_groups__init(&machine->kmaps, machine); 28 map_groups__init(&machine->kmaps, machine);
26 RB_CLEAR_NODE(&machine->rb_node); 29 RB_CLEAR_NODE(&machine->rb_node);
27 dsos__init(&machine->user_dsos); 30 dsos__init(&machine->dsos);
28 dsos__init(&machine->kernel_dsos);
29 31
30 machine->threads = RB_ROOT; 32 machine->threads = RB_ROOT;
33 pthread_rwlock_init(&machine->threads_lock, NULL);
31 INIT_LIST_HEAD(&machine->dead_threads); 34 INIT_LIST_HEAD(&machine->dead_threads);
32 machine->last_match = NULL; 35 machine->last_match = NULL;
33 36
@@ -54,6 +57,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
54 57
55 snprintf(comm, sizeof(comm), "[guest/%d]", pid); 58 snprintf(comm, sizeof(comm), "[guest/%d]", pid);
56 thread__set_comm(thread, comm, 0); 59 thread__set_comm(thread, comm, 0);
60 thread__put(thread);
57 } 61 }
58 62
59 machine->current_tid = NULL; 63 machine->current_tid = NULL;
@@ -78,37 +82,50 @@ out_delete:
78 return NULL; 82 return NULL;
79} 83}
80 84
81static void dsos__delete(struct dsos *dsos) 85static void dsos__purge(struct dsos *dsos)
82{ 86{
83 struct dso *pos, *n; 87 struct dso *pos, *n;
84 88
89 pthread_rwlock_wrlock(&dsos->lock);
90
85 list_for_each_entry_safe(pos, n, &dsos->head, node) { 91 list_for_each_entry_safe(pos, n, &dsos->head, node) {
86 RB_CLEAR_NODE(&pos->rb_node); 92 RB_CLEAR_NODE(&pos->rb_node);
87 list_del(&pos->node); 93 list_del_init(&pos->node);
88 dso__delete(pos); 94 dso__put(pos);
89 } 95 }
96
97 pthread_rwlock_unlock(&dsos->lock);
98}
99
100static void dsos__exit(struct dsos *dsos)
101{
102 dsos__purge(dsos);
103 pthread_rwlock_destroy(&dsos->lock);
90} 104}
91 105
92void machine__delete_threads(struct machine *machine) 106void machine__delete_threads(struct machine *machine)
93{ 107{
94 struct rb_node *nd = rb_first(&machine->threads); 108 struct rb_node *nd;
95 109
110 pthread_rwlock_wrlock(&machine->threads_lock);
111 nd = rb_first(&machine->threads);
96 while (nd) { 112 while (nd) {
97 struct thread *t = rb_entry(nd, struct thread, rb_node); 113 struct thread *t = rb_entry(nd, struct thread, rb_node);
98 114
99 nd = rb_next(nd); 115 nd = rb_next(nd);
100 machine__remove_thread(machine, t); 116 __machine__remove_thread(machine, t, false);
101 } 117 }
118 pthread_rwlock_unlock(&machine->threads_lock);
102} 119}
103 120
104void machine__exit(struct machine *machine) 121void machine__exit(struct machine *machine)
105{ 122{
106 map_groups__exit(&machine->kmaps); 123 map_groups__exit(&machine->kmaps);
107 dsos__delete(&machine->user_dsos); 124 dsos__exit(&machine->dsos);
108 dsos__delete(&machine->kernel_dsos); 125 machine__exit_vdso(machine);
109 vdso__exit(machine);
110 zfree(&machine->root_dir); 126 zfree(&machine->root_dir);
111 zfree(&machine->current_tid); 127 zfree(&machine->current_tid);
128 pthread_rwlock_destroy(&machine->threads_lock);
112} 129}
113 130
114void machine__delete(struct machine *machine) 131void machine__delete(struct machine *machine)
@@ -303,7 +320,7 @@ static void machine__update_thread_pid(struct machine *machine,
303 if (th->pid_ == th->tid) 320 if (th->pid_ == th->tid)
304 return; 321 return;
305 322
306 leader = machine__findnew_thread(machine, th->pid_, th->pid_); 323 leader = __machine__findnew_thread(machine, th->pid_, th->pid_);
307 if (!leader) 324 if (!leader)
308 goto out_err; 325 goto out_err;
309 326
@@ -325,7 +342,7 @@ static void machine__update_thread_pid(struct machine *machine,
325 if (!map_groups__empty(th->mg)) 342 if (!map_groups__empty(th->mg))
326 pr_err("Discarding thread maps for %d:%d\n", 343 pr_err("Discarding thread maps for %d:%d\n",
327 th->pid_, th->tid); 344 th->pid_, th->tid);
328 map_groups__delete(th->mg); 345 map_groups__put(th->mg);
329 } 346 }
330 347
331 th->mg = map_groups__get(leader->mg); 348 th->mg = map_groups__get(leader->mg);
@@ -336,9 +353,9 @@ out_err:
336 pr_err("Failed to join map groups for %d:%d\n", th->pid_, th->tid); 353 pr_err("Failed to join map groups for %d:%d\n", th->pid_, th->tid);
337} 354}
338 355
339static struct thread *__machine__findnew_thread(struct machine *machine, 356static struct thread *____machine__findnew_thread(struct machine *machine,
340 pid_t pid, pid_t tid, 357 pid_t pid, pid_t tid,
341 bool create) 358 bool create)
342{ 359{
343 struct rb_node **p = &machine->threads.rb_node; 360 struct rb_node **p = &machine->threads.rb_node;
344 struct rb_node *parent = NULL; 361 struct rb_node *parent = NULL;
@@ -356,7 +373,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
356 return th; 373 return th;
357 } 374 }
358 375
359 thread__zput(machine->last_match); 376 machine->last_match = NULL;
360 } 377 }
361 378
362 while (*p != NULL) { 379 while (*p != NULL) {
@@ -364,7 +381,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
364 th = rb_entry(parent, struct thread, rb_node); 381 th = rb_entry(parent, struct thread, rb_node);
365 382
366 if (th->tid == tid) { 383 if (th->tid == tid) {
367 machine->last_match = thread__get(th); 384 machine->last_match = th;
368 machine__update_thread_pid(machine, th, pid); 385 machine__update_thread_pid(machine, th, pid);
369 return th; 386 return th;
370 } 387 }
@@ -392,7 +409,8 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
392 * leader and that would screwed the rb tree. 409 * leader and that would screwed the rb tree.
393 */ 410 */
394 if (thread__init_map_groups(th, machine)) { 411 if (thread__init_map_groups(th, machine)) {
395 rb_erase(&th->rb_node, &machine->threads); 412 rb_erase_init(&th->rb_node, &machine->threads);
413 RB_CLEAR_NODE(&th->rb_node);
396 thread__delete(th); 414 thread__delete(th);
397 return NULL; 415 return NULL;
398 } 416 }
@@ -400,22 +418,36 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
400 * It is now in the rbtree, get a ref 418 * It is now in the rbtree, get a ref
401 */ 419 */
402 thread__get(th); 420 thread__get(th);
403 machine->last_match = thread__get(th); 421 machine->last_match = th;
404 } 422 }
405 423
406 return th; 424 return th;
407} 425}
408 426
427struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid)
428{
429 return ____machine__findnew_thread(machine, pid, tid, true);
430}
431
409struct thread *machine__findnew_thread(struct machine *machine, pid_t pid, 432struct thread *machine__findnew_thread(struct machine *machine, pid_t pid,
410 pid_t tid) 433 pid_t tid)
411{ 434{
412 return __machine__findnew_thread(machine, pid, tid, true); 435 struct thread *th;
436
437 pthread_rwlock_wrlock(&machine->threads_lock);
438 th = thread__get(__machine__findnew_thread(machine, pid, tid));
439 pthread_rwlock_unlock(&machine->threads_lock);
440 return th;
413} 441}
414 442
415struct thread *machine__find_thread(struct machine *machine, pid_t pid, 443struct thread *machine__find_thread(struct machine *machine, pid_t pid,
416 pid_t tid) 444 pid_t tid)
417{ 445{
418 return __machine__findnew_thread(machine, pid, tid, false); 446 struct thread *th;
447 pthread_rwlock_rdlock(&machine->threads_lock);
448 th = thread__get(____machine__findnew_thread(machine, pid, tid, false));
449 pthread_rwlock_unlock(&machine->threads_lock);
450 return th;
419} 451}
420 452
421struct comm *machine__thread_exec_comm(struct machine *machine, 453struct comm *machine__thread_exec_comm(struct machine *machine,
@@ -434,6 +466,7 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event
434 event->comm.pid, 466 event->comm.pid,
435 event->comm.tid); 467 event->comm.tid);
436 bool exec = event->header.misc & PERF_RECORD_MISC_COMM_EXEC; 468 bool exec = event->header.misc & PERF_RECORD_MISC_COMM_EXEC;
469 int err = 0;
437 470
438 if (exec) 471 if (exec)
439 machine->comm_exec = true; 472 machine->comm_exec = true;
@@ -444,10 +477,12 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event
444 if (thread == NULL || 477 if (thread == NULL ||
445 __thread__set_comm(thread, event->comm.comm, sample->time, exec)) { 478 __thread__set_comm(thread, event->comm.comm, sample->time, exec)) {
446 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 479 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
447 return -1; 480 err = -1;
448 } 481 }
449 482
450 return 0; 483 thread__put(thread);
484
485 return err;
451} 486}
452 487
453int machine__process_lost_event(struct machine *machine __maybe_unused, 488int machine__process_lost_event(struct machine *machine __maybe_unused,
@@ -458,17 +493,27 @@ int machine__process_lost_event(struct machine *machine __maybe_unused,
458 return 0; 493 return 0;
459} 494}
460 495
461static struct dso* 496int machine__process_lost_samples_event(struct machine *machine __maybe_unused,
462machine__module_dso(struct machine *machine, struct kmod_path *m, 497 union perf_event *event, struct perf_sample *sample)
463 const char *filename) 498{
499 dump_printf(": id:%" PRIu64 ": lost samples :%" PRIu64 "\n",
500 sample->id, event->lost_samples.lost);
501 return 0;
502}
503
504static struct dso *machine__findnew_module_dso(struct machine *machine,
505 struct kmod_path *m,
506 const char *filename)
464{ 507{
465 struct dso *dso; 508 struct dso *dso;
466 509
467 dso = dsos__find(&machine->kernel_dsos, m->name, true); 510 pthread_rwlock_wrlock(&machine->dsos.lock);
511
512 dso = __dsos__find(&machine->dsos, m->name, true);
468 if (!dso) { 513 if (!dso) {
469 dso = dsos__addnew(&machine->kernel_dsos, m->name); 514 dso = __dsos__addnew(&machine->dsos, m->name);
470 if (dso == NULL) 515 if (dso == NULL)
471 return NULL; 516 goto out_unlock;
472 517
473 if (machine__is_host(machine)) 518 if (machine__is_host(machine))
474 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; 519 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
@@ -483,11 +528,30 @@ machine__module_dso(struct machine *machine, struct kmod_path *m,
483 dso__set_long_name(dso, strdup(filename), true); 528 dso__set_long_name(dso, strdup(filename), true);
484 } 529 }
485 530
531 dso__get(dso);
532out_unlock:
533 pthread_rwlock_unlock(&machine->dsos.lock);
486 return dso; 534 return dso;
487} 535}
488 536
489struct map *machine__new_module(struct machine *machine, u64 start, 537int machine__process_aux_event(struct machine *machine __maybe_unused,
490 const char *filename) 538 union perf_event *event)
539{
540 if (dump_trace)
541 perf_event__fprintf_aux(event, stdout);
542 return 0;
543}
544
545int machine__process_itrace_start_event(struct machine *machine __maybe_unused,
546 union perf_event *event)
547{
548 if (dump_trace)
549 perf_event__fprintf_itrace_start(event, stdout);
550 return 0;
551}
552
553struct map *machine__findnew_module_map(struct machine *machine, u64 start,
554 const char *filename)
491{ 555{
492 struct map *map = NULL; 556 struct map *map = NULL;
493 struct dso *dso; 557 struct dso *dso;
@@ -501,7 +565,7 @@ struct map *machine__new_module(struct machine *machine, u64 start,
501 if (map) 565 if (map)
502 goto out; 566 goto out;
503 567
504 dso = machine__module_dso(machine, &m, filename); 568 dso = machine__findnew_module_dso(machine, &m, filename);
505 if (dso == NULL) 569 if (dso == NULL)
506 goto out; 570 goto out;
507 571
@@ -519,13 +583,11 @@ out:
519size_t machines__fprintf_dsos(struct machines *machines, FILE *fp) 583size_t machines__fprintf_dsos(struct machines *machines, FILE *fp)
520{ 584{
521 struct rb_node *nd; 585 struct rb_node *nd;
522 size_t ret = __dsos__fprintf(&machines->host.kernel_dsos.head, fp) + 586 size_t ret = __dsos__fprintf(&machines->host.dsos.head, fp);
523 __dsos__fprintf(&machines->host.user_dsos.head, fp);
524 587
525 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) { 588 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
526 struct machine *pos = rb_entry(nd, struct machine, rb_node); 589 struct machine *pos = rb_entry(nd, struct machine, rb_node);
527 ret += __dsos__fprintf(&pos->kernel_dsos.head, fp); 590 ret += __dsos__fprintf(&pos->dsos.head, fp);
528 ret += __dsos__fprintf(&pos->user_dsos.head, fp);
529 } 591 }
530 592
531 return ret; 593 return ret;
@@ -534,8 +596,7 @@ size_t machines__fprintf_dsos(struct machines *machines, FILE *fp)
534size_t machine__fprintf_dsos_buildid(struct machine *m, FILE *fp, 596size_t machine__fprintf_dsos_buildid(struct machine *m, FILE *fp,
535 bool (skip)(struct dso *dso, int parm), int parm) 597 bool (skip)(struct dso *dso, int parm), int parm)
536{ 598{
537 return __dsos__fprintf_buildid(&m->kernel_dsos.head, fp, skip, parm) + 599 return __dsos__fprintf_buildid(&m->dsos.head, fp, skip, parm);
538 __dsos__fprintf_buildid(&m->user_dsos.head, fp, skip, parm);
539} 600}
540 601
541size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp, 602size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp,
@@ -575,12 +636,16 @@ size_t machine__fprintf(struct machine *machine, FILE *fp)
575 size_t ret = 0; 636 size_t ret = 0;
576 struct rb_node *nd; 637 struct rb_node *nd;
577 638
639 pthread_rwlock_rdlock(&machine->threads_lock);
640
578 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) { 641 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
579 struct thread *pos = rb_entry(nd, struct thread, rb_node); 642 struct thread *pos = rb_entry(nd, struct thread, rb_node);
580 643
581 ret += thread__fprintf(pos, fp); 644 ret += thread__fprintf(pos, fp);
582 } 645 }
583 646
647 pthread_rwlock_unlock(&machine->threads_lock);
648
584 return ret; 649 return ret;
585} 650}
586 651
@@ -594,9 +659,8 @@ static struct dso *machine__get_kernel(struct machine *machine)
594 if (!vmlinux_name) 659 if (!vmlinux_name)
595 vmlinux_name = "[kernel.kallsyms]"; 660 vmlinux_name = "[kernel.kallsyms]";
596 661
597 kernel = dso__kernel_findnew(machine, vmlinux_name, 662 kernel = machine__findnew_kernel(machine, vmlinux_name,
598 "[kernel]", 663 "[kernel]", DSO_TYPE_KERNEL);
599 DSO_TYPE_KERNEL);
600 } else { 664 } else {
601 char bf[PATH_MAX]; 665 char bf[PATH_MAX];
602 666
@@ -606,9 +670,9 @@ static struct dso *machine__get_kernel(struct machine *machine)
606 vmlinux_name = machine__mmap_name(machine, bf, 670 vmlinux_name = machine__mmap_name(machine, bf,
607 sizeof(bf)); 671 sizeof(bf));
608 672
609 kernel = dso__kernel_findnew(machine, vmlinux_name, 673 kernel = machine__findnew_kernel(machine, vmlinux_name,
610 "[guest.kernel]", 674 "[guest.kernel]",
611 DSO_TYPE_GUEST_KERNEL); 675 DSO_TYPE_GUEST_KERNEL);
612 } 676 }
613 677
614 if (kernel != NULL && (!kernel->has_build_id)) 678 if (kernel != NULL && (!kernel->has_build_id))
@@ -713,7 +777,6 @@ void machine__destroy_kernel_maps(struct machine *machine)
713 kmap->ref_reloc_sym = NULL; 777 kmap->ref_reloc_sym = NULL;
714 } 778 }
715 779
716 map__delete(machine->vmlinux_maps[type]);
717 machine->vmlinux_maps[type] = NULL; 780 machine->vmlinux_maps[type] = NULL;
718 } 781 }
719} 782}
@@ -970,7 +1033,7 @@ static int machine__create_module(void *arg, const char *name, u64 start)
970 struct machine *machine = arg; 1033 struct machine *machine = arg;
971 struct map *map; 1034 struct map *map;
972 1035
973 map = machine__new_module(machine, start, name); 1036 map = machine__findnew_module_map(machine, start, name);
974 if (map == NULL) 1037 if (map == NULL)
975 return -1; 1038 return -1;
976 1039
@@ -1062,7 +1125,7 @@ static bool machine__uses_kcore(struct machine *machine)
1062{ 1125{
1063 struct dso *dso; 1126 struct dso *dso;
1064 1127
1065 list_for_each_entry(dso, &machine->kernel_dsos.head, node) { 1128 list_for_each_entry(dso, &machine->dsos.head, node) {
1066 if (dso__is_kcore(dso)) 1129 if (dso__is_kcore(dso))
1067 return true; 1130 return true;
1068 } 1131 }
@@ -1093,8 +1156,8 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1093 strlen(kmmap_prefix) - 1) == 0; 1156 strlen(kmmap_prefix) - 1) == 0;
1094 if (event->mmap.filename[0] == '/' || 1157 if (event->mmap.filename[0] == '/' ||
1095 (!is_kernel_mmap && event->mmap.filename[0] == '[')) { 1158 (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
1096 map = machine__new_module(machine, event->mmap.start, 1159 map = machine__findnew_module_map(machine, event->mmap.start,
1097 event->mmap.filename); 1160 event->mmap.filename);
1098 if (map == NULL) 1161 if (map == NULL)
1099 goto out_problem; 1162 goto out_problem;
1100 1163
@@ -1109,23 +1172,48 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1109 struct dso *kernel = NULL; 1172 struct dso *kernel = NULL;
1110 struct dso *dso; 1173 struct dso *dso;
1111 1174
1112 list_for_each_entry(dso, &machine->kernel_dsos.head, node) { 1175 pthread_rwlock_rdlock(&machine->dsos.lock);
1113 if (is_kernel_module(dso->long_name)) 1176
1177 list_for_each_entry(dso, &machine->dsos.head, node) {
1178
1179 /*
1180 * The cpumode passed to is_kernel_module is not the
1181 * cpumode of *this* event. If we insist on passing
1182 * correct cpumode to is_kernel_module, we should
1183 * record the cpumode when we adding this dso to the
1184 * linked list.
1185 *
1186 * However we don't really need passing correct
1187 * cpumode. We know the correct cpumode must be kernel
1188 * mode (if not, we should not link it onto kernel_dsos
1189 * list).
1190 *
1191 * Therefore, we pass PERF_RECORD_MISC_CPUMODE_UNKNOWN.
1192 * is_kernel_module() treats it as a kernel cpumode.
1193 */
1194
1195 if (!dso->kernel ||
1196 is_kernel_module(dso->long_name,
1197 PERF_RECORD_MISC_CPUMODE_UNKNOWN))
1114 continue; 1198 continue;
1115 1199
1200
1116 kernel = dso; 1201 kernel = dso;
1117 break; 1202 break;
1118 } 1203 }
1119 1204
1205 pthread_rwlock_unlock(&machine->dsos.lock);
1206
1120 if (kernel == NULL) 1207 if (kernel == NULL)
1121 kernel = __dsos__findnew(&machine->kernel_dsos, 1208 kernel = machine__findnew_dso(machine, kmmap_prefix);
1122 kmmap_prefix);
1123 if (kernel == NULL) 1209 if (kernel == NULL)
1124 goto out_problem; 1210 goto out_problem;
1125 1211
1126 kernel->kernel = kernel_type; 1212 kernel->kernel = kernel_type;
1127 if (__machine__create_kernel_maps(machine, kernel) < 0) 1213 if (__machine__create_kernel_maps(machine, kernel) < 0) {
1214 dso__put(kernel);
1128 goto out_problem; 1215 goto out_problem;
1216 }
1129 1217
1130 if (strstr(kernel->long_name, "vmlinux")) 1218 if (strstr(kernel->long_name, "vmlinux"))
1131 dso__set_short_name(kernel, "[kernel.vmlinux]", false); 1219 dso__set_short_name(kernel, "[kernel.vmlinux]", false);
@@ -1197,11 +1285,15 @@ int machine__process_mmap2_event(struct machine *machine,
1197 event->mmap2.filename, type, thread); 1285 event->mmap2.filename, type, thread);
1198 1286
1199 if (map == NULL) 1287 if (map == NULL)
1200 goto out_problem; 1288 goto out_problem_map;
1201 1289
1202 thread__insert_map(thread, map); 1290 thread__insert_map(thread, map);
1291 thread__put(thread);
1292 map__put(map);
1203 return 0; 1293 return 0;
1204 1294
1295out_problem_map:
1296 thread__put(thread);
1205out_problem: 1297out_problem:
1206 dump_printf("problem processing PERF_RECORD_MMAP2, skipping event.\n"); 1298 dump_printf("problem processing PERF_RECORD_MMAP2, skipping event.\n");
1207 return 0; 1299 return 0;
@@ -1244,31 +1336,46 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
1244 type, thread); 1336 type, thread);
1245 1337
1246 if (map == NULL) 1338 if (map == NULL)
1247 goto out_problem; 1339 goto out_problem_map;
1248 1340
1249 thread__insert_map(thread, map); 1341 thread__insert_map(thread, map);
1342 thread__put(thread);
1343 map__put(map);
1250 return 0; 1344 return 0;
1251 1345
1346out_problem_map:
1347 thread__put(thread);
1252out_problem: 1348out_problem:
1253 dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n"); 1349 dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
1254 return 0; 1350 return 0;
1255} 1351}
1256 1352
1257void machine__remove_thread(struct machine *machine, struct thread *th) 1353static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock)
1258{ 1354{
1259 if (machine->last_match == th) 1355 if (machine->last_match == th)
1260 thread__zput(machine->last_match); 1356 machine->last_match = NULL;
1261 1357
1262 rb_erase(&th->rb_node, &machine->threads); 1358 BUG_ON(atomic_read(&th->refcnt) == 0);
1359 if (lock)
1360 pthread_rwlock_wrlock(&machine->threads_lock);
1361 rb_erase_init(&th->rb_node, &machine->threads);
1362 RB_CLEAR_NODE(&th->rb_node);
1263 /* 1363 /*
1264 * Move it first to the dead_threads list, then drop the reference, 1364 * Move it first to the dead_threads list, then drop the reference,
1265 * if this is the last reference, then the thread__delete destructor 1365 * if this is the last reference, then the thread__delete destructor
1266 * will be called and we will remove it from the dead_threads list. 1366 * will be called and we will remove it from the dead_threads list.
1267 */ 1367 */
1268 list_add_tail(&th->node, &machine->dead_threads); 1368 list_add_tail(&th->node, &machine->dead_threads);
1369 if (lock)
1370 pthread_rwlock_unlock(&machine->threads_lock);
1269 thread__put(th); 1371 thread__put(th);
1270} 1372}
1271 1373
1374void machine__remove_thread(struct machine *machine, struct thread *th)
1375{
1376 return __machine__remove_thread(machine, th, true);
1377}
1378
1272int machine__process_fork_event(struct machine *machine, union perf_event *event, 1379int machine__process_fork_event(struct machine *machine, union perf_event *event,
1273 struct perf_sample *sample) 1380 struct perf_sample *sample)
1274{ 1381{
@@ -1278,10 +1385,13 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
1278 struct thread *parent = machine__findnew_thread(machine, 1385 struct thread *parent = machine__findnew_thread(machine,
1279 event->fork.ppid, 1386 event->fork.ppid,
1280 event->fork.ptid); 1387 event->fork.ptid);
1388 int err = 0;
1281 1389
1282 /* if a thread currently exists for the thread id remove it */ 1390 /* if a thread currently exists for the thread id remove it */
1283 if (thread != NULL) 1391 if (thread != NULL) {
1284 machine__remove_thread(machine, thread); 1392 machine__remove_thread(machine, thread);
1393 thread__put(thread);
1394 }
1285 1395
1286 thread = machine__findnew_thread(machine, event->fork.pid, 1396 thread = machine__findnew_thread(machine, event->fork.pid,
1287 event->fork.tid); 1397 event->fork.tid);
@@ -1291,10 +1401,12 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
1291 if (thread == NULL || parent == NULL || 1401 if (thread == NULL || parent == NULL ||
1292 thread__fork(thread, parent, sample->time) < 0) { 1402 thread__fork(thread, parent, sample->time) < 0) {
1293 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n"); 1403 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
1294 return -1; 1404 err = -1;
1295 } 1405 }
1406 thread__put(thread);
1407 thread__put(parent);
1296 1408
1297 return 0; 1409 return err;
1298} 1410}
1299 1411
1300int machine__process_exit_event(struct machine *machine, union perf_event *event, 1412int machine__process_exit_event(struct machine *machine, union perf_event *event,
@@ -1307,8 +1419,10 @@ int machine__process_exit_event(struct machine *machine, union perf_event *event
1307 if (dump_trace) 1419 if (dump_trace)
1308 perf_event__fprintf_task(event, stdout); 1420 perf_event__fprintf_task(event, stdout);
1309 1421
1310 if (thread != NULL) 1422 if (thread != NULL) {
1311 thread__exited(thread); 1423 thread__exited(thread);
1424 thread__put(thread);
1425 }
1312 1426
1313 return 0; 1427 return 0;
1314} 1428}
@@ -1331,6 +1445,13 @@ int machine__process_event(struct machine *machine, union perf_event *event,
1331 ret = machine__process_exit_event(machine, event, sample); break; 1445 ret = machine__process_exit_event(machine, event, sample); break;
1332 case PERF_RECORD_LOST: 1446 case PERF_RECORD_LOST:
1333 ret = machine__process_lost_event(machine, event, sample); break; 1447 ret = machine__process_lost_event(machine, event, sample); break;
1448 case PERF_RECORD_AUX:
1449 ret = machine__process_aux_event(machine, event); break;
1450 case PERF_RECORD_ITRACE_START:
1451 ret = machine__process_itrace_start_event(machine, event);
1452 case PERF_RECORD_LOST_SAMPLES:
1453 ret = machine__process_lost_samples_event(machine, event, sample); break;
1454 break;
1334 default: 1455 default:
1335 ret = -1; 1456 ret = -1;
1336 break; 1457 break;
@@ -1769,14 +1890,36 @@ int machine__for_each_thread(struct machine *machine,
1769 return rc; 1890 return rc;
1770} 1891}
1771 1892
1893int machines__for_each_thread(struct machines *machines,
1894 int (*fn)(struct thread *thread, void *p),
1895 void *priv)
1896{
1897 struct rb_node *nd;
1898 int rc = 0;
1899
1900 rc = machine__for_each_thread(&machines->host, fn, priv);
1901 if (rc != 0)
1902 return rc;
1903
1904 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
1905 struct machine *machine = rb_entry(nd, struct machine, rb_node);
1906
1907 rc = machine__for_each_thread(machine, fn, priv);
1908 if (rc != 0)
1909 return rc;
1910 }
1911 return rc;
1912}
1913
1772int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, 1914int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
1773 struct target *target, struct thread_map *threads, 1915 struct target *target, struct thread_map *threads,
1774 perf_event__handler_t process, bool data_mmap) 1916 perf_event__handler_t process, bool data_mmap,
1917 unsigned int proc_map_timeout)
1775{ 1918{
1776 if (target__has_task(target)) 1919 if (target__has_task(target))
1777 return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap); 1920 return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap, proc_map_timeout);
1778 else if (target__has_cpu(target)) 1921 else if (target__has_cpu(target))
1779 return perf_event__synthesize_threads(tool, process, machine, data_mmap); 1922 return perf_event__synthesize_threads(tool, process, machine, data_mmap, proc_map_timeout);
1780 /* command specified */ 1923 /* command specified */
1781 return 0; 1924 return 0;
1782} 1925}
@@ -1820,6 +1963,7 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
1820 return -ENOMEM; 1963 return -ENOMEM;
1821 1964
1822 thread->cpu = cpu; 1965 thread->cpu = cpu;
1966 thread__put(thread);
1823 1967
1824 return 0; 1968 return 0;
1825} 1969}
@@ -1845,3 +1989,8 @@ int machine__get_kernel_start(struct machine *machine)
1845 } 1989 }
1846 return err; 1990 return err;
1847} 1991}
1992
1993struct dso *machine__findnew_dso(struct machine *machine, const char *filename)
1994{
1995 return dsos__findnew(&machine->dsos, filename);
1996}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 6d64cedb9d1e..887798e511e9 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -30,11 +30,11 @@ struct machine {
30 bool comm_exec; 30 bool comm_exec;
31 char *root_dir; 31 char *root_dir;
32 struct rb_root threads; 32 struct rb_root threads;
33 pthread_rwlock_t threads_lock;
33 struct list_head dead_threads; 34 struct list_head dead_threads;
34 struct thread *last_match; 35 struct thread *last_match;
35 struct vdso_info *vdso_info; 36 struct vdso_info *vdso_info;
36 struct dsos user_dsos; 37 struct dsos dsos;
37 struct dsos kernel_dsos;
38 struct map_groups kmaps; 38 struct map_groups kmaps;
39 struct map *vmlinux_maps[MAP__NR_TYPES]; 39 struct map *vmlinux_maps[MAP__NR_TYPES];
40 u64 kernel_start; 40 u64 kernel_start;
@@ -81,6 +81,12 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
81 struct perf_sample *sample); 81 struct perf_sample *sample);
82int machine__process_lost_event(struct machine *machine, union perf_event *event, 82int machine__process_lost_event(struct machine *machine, union perf_event *event,
83 struct perf_sample *sample); 83 struct perf_sample *sample);
84int machine__process_lost_samples_event(struct machine *machine, union perf_event *event,
85 struct perf_sample *sample);
86int machine__process_aux_event(struct machine *machine,
87 union perf_event *event);
88int machine__process_itrace_start_event(struct machine *machine,
89 union perf_event *event);
84int machine__process_mmap_event(struct machine *machine, union perf_event *event, 90int machine__process_mmap_event(struct machine *machine, union perf_event *event,
85 struct perf_sample *sample); 91 struct perf_sample *sample);
86int machine__process_mmap2_event(struct machine *machine, union perf_event *event, 92int machine__process_mmap2_event(struct machine *machine, union perf_event *event,
@@ -147,8 +153,10 @@ static inline bool machine__is_host(struct machine *machine)
147 return machine ? machine->pid == HOST_KERNEL_ID : false; 153 return machine ? machine->pid == HOST_KERNEL_ID : false;
148} 154}
149 155
150struct thread *machine__findnew_thread(struct machine *machine, pid_t pid, 156struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid);
151 pid_t tid); 157struct thread *machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid);
158
159struct dso *machine__findnew_dso(struct machine *machine, const char *filename);
152 160
153size_t machine__fprintf(struct machine *machine, FILE *fp); 161size_t machine__fprintf(struct machine *machine, FILE *fp);
154 162
@@ -181,8 +189,8 @@ struct symbol *machine__find_kernel_function_by_name(struct machine *machine,
181 filter); 189 filter);
182} 190}
183 191
184struct map *machine__new_module(struct machine *machine, u64 start, 192struct map *machine__findnew_module_map(struct machine *machine, u64 start,
185 const char *filename); 193 const char *filename);
186 194
187int machine__load_kallsyms(struct machine *machine, const char *filename, 195int machine__load_kallsyms(struct machine *machine, const char *filename,
188 enum map_type type, symbol_filter_t filter); 196 enum map_type type, symbol_filter_t filter);
@@ -208,16 +216,22 @@ size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
208int machine__for_each_thread(struct machine *machine, 216int machine__for_each_thread(struct machine *machine,
209 int (*fn)(struct thread *thread, void *p), 217 int (*fn)(struct thread *thread, void *p),
210 void *priv); 218 void *priv);
219int machines__for_each_thread(struct machines *machines,
220 int (*fn)(struct thread *thread, void *p),
221 void *priv);
211 222
212int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, 223int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
213 struct target *target, struct thread_map *threads, 224 struct target *target, struct thread_map *threads,
214 perf_event__handler_t process, bool data_mmap); 225 perf_event__handler_t process, bool data_mmap,
226 unsigned int proc_map_timeout);
215static inline 227static inline
216int machine__synthesize_threads(struct machine *machine, struct target *target, 228int machine__synthesize_threads(struct machine *machine, struct target *target,
217 struct thread_map *threads, bool data_mmap) 229 struct thread_map *threads, bool data_mmap,
230 unsigned int proc_map_timeout)
218{ 231{
219 return __machine__synthesize_threads(machine, NULL, target, threads, 232 return __machine__synthesize_threads(machine, NULL, target, threads,
220 perf_event__process, data_mmap); 233 perf_event__process, data_mmap,
234 proc_map_timeout);
221} 235}
222 236
223pid_t machine__get_current_tid(struct machine *machine, int cpu); 237pid_t machine__get_current_tid(struct machine *machine, int cpu);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index a14f08f41686..b5a5e9c02437 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -16,6 +16,8 @@
16#include "machine.h" 16#include "machine.h"
17#include <linux/string.h> 17#include <linux/string.h>
18 18
19static void __maps__insert(struct maps *maps, struct map *map);
20
19const char *map_type__name[MAP__NR_TYPES] = { 21const char *map_type__name[MAP__NR_TYPES] = {
20 [MAP__FUNCTION] = "Functions", 22 [MAP__FUNCTION] = "Functions",
21 [MAP__VARIABLE] = "Variables", 23 [MAP__VARIABLE] = "Variables",
@@ -130,13 +132,13 @@ void map__init(struct map *map, enum map_type type,
130 map->end = end; 132 map->end = end;
131 map->pgoff = pgoff; 133 map->pgoff = pgoff;
132 map->reloc = 0; 134 map->reloc = 0;
133 map->dso = dso; 135 map->dso = dso__get(dso);
134 map->map_ip = map__map_ip; 136 map->map_ip = map__map_ip;
135 map->unmap_ip = map__unmap_ip; 137 map->unmap_ip = map__unmap_ip;
136 RB_CLEAR_NODE(&map->rb_node); 138 RB_CLEAR_NODE(&map->rb_node);
137 map->groups = NULL; 139 map->groups = NULL;
138 map->referenced = false;
139 map->erange_warned = false; 140 map->erange_warned = false;
141 atomic_set(&map->refcnt, 1);
140} 142}
141 143
142struct map *map__new(struct machine *machine, u64 start, u64 len, 144struct map *map__new(struct machine *machine, u64 start, u64 len,
@@ -175,9 +177,9 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
175 177
176 if (vdso) { 178 if (vdso) {
177 pgoff = 0; 179 pgoff = 0;
178 dso = vdso__dso_findnew(machine, thread); 180 dso = machine__findnew_vdso(machine, thread);
179 } else 181 } else
180 dso = __dsos__findnew(&machine->user_dsos, filename); 182 dso = machine__findnew_dso(machine, filename);
181 183
182 if (dso == NULL) 184 if (dso == NULL)
183 goto out_delete; 185 goto out_delete;
@@ -195,6 +197,7 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
195 if (type != MAP__FUNCTION) 197 if (type != MAP__FUNCTION)
196 dso__set_loaded(dso, map->type); 198 dso__set_loaded(dso, map->type);
197 } 199 }
200 dso__put(dso);
198 } 201 }
199 return map; 202 return map;
200out_delete: 203out_delete:
@@ -221,11 +224,24 @@ struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
221 return map; 224 return map;
222} 225}
223 226
227static void map__exit(struct map *map)
228{
229 BUG_ON(!RB_EMPTY_NODE(&map->rb_node));
230 dso__zput(map->dso);
231}
232
224void map__delete(struct map *map) 233void map__delete(struct map *map)
225{ 234{
235 map__exit(map);
226 free(map); 236 free(map);
227} 237}
228 238
239void map__put(struct map *map)
240{
241 if (map && atomic_dec_and_test(&map->refcnt))
242 map__delete(map);
243}
244
229void map__fixup_start(struct map *map) 245void map__fixup_start(struct map *map)
230{ 246{
231 struct rb_root *symbols = &map->dso->symbols[map->type]; 247 struct rb_root *symbols = &map->dso->symbols[map->type];
@@ -292,6 +308,11 @@ int map__load(struct map *map, symbol_filter_t filter)
292 return 0; 308 return 0;
293} 309}
294 310
311int __weak arch__compare_symbol_names(const char *namea, const char *nameb)
312{
313 return strcmp(namea, nameb);
314}
315
295struct symbol *map__find_symbol(struct map *map, u64 addr, 316struct symbol *map__find_symbol(struct map *map, u64 addr,
296 symbol_filter_t filter) 317 symbol_filter_t filter)
297{ 318{
@@ -413,48 +434,49 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
413 return ip + map->reloc; 434 return ip + map->reloc;
414} 435}
415 436
437static void maps__init(struct maps *maps)
438{
439 maps->entries = RB_ROOT;
440 pthread_rwlock_init(&maps->lock, NULL);
441}
442
416void map_groups__init(struct map_groups *mg, struct machine *machine) 443void map_groups__init(struct map_groups *mg, struct machine *machine)
417{ 444{
418 int i; 445 int i;
419 for (i = 0; i < MAP__NR_TYPES; ++i) { 446 for (i = 0; i < MAP__NR_TYPES; ++i) {
420 mg->maps[i] = RB_ROOT; 447 maps__init(&mg->maps[i]);
421 INIT_LIST_HEAD(&mg->removed_maps[i]);
422 } 448 }
423 mg->machine = machine; 449 mg->machine = machine;
424 mg->refcnt = 1; 450 atomic_set(&mg->refcnt, 1);
425} 451}
426 452
427static void maps__delete(struct rb_root *maps) 453static void __maps__purge(struct maps *maps)
428{ 454{
429 struct rb_node *next = rb_first(maps); 455 struct rb_root *root = &maps->entries;
456 struct rb_node *next = rb_first(root);
430 457
431 while (next) { 458 while (next) {
432 struct map *pos = rb_entry(next, struct map, rb_node); 459 struct map *pos = rb_entry(next, struct map, rb_node);
433 460
434 next = rb_next(&pos->rb_node); 461 next = rb_next(&pos->rb_node);
435 rb_erase(&pos->rb_node, maps); 462 rb_erase_init(&pos->rb_node, root);
436 map__delete(pos); 463 map__put(pos);
437 } 464 }
438} 465}
439 466
440static void maps__delete_removed(struct list_head *maps) 467static void maps__exit(struct maps *maps)
441{ 468{
442 struct map *pos, *n; 469 pthread_rwlock_wrlock(&maps->lock);
443 470 __maps__purge(maps);
444 list_for_each_entry_safe(pos, n, maps, node) { 471 pthread_rwlock_unlock(&maps->lock);
445 list_del(&pos->node);
446 map__delete(pos);
447 }
448} 472}
449 473
450void map_groups__exit(struct map_groups *mg) 474void map_groups__exit(struct map_groups *mg)
451{ 475{
452 int i; 476 int i;
453 477
454 for (i = 0; i < MAP__NR_TYPES; ++i) { 478 for (i = 0; i < MAP__NR_TYPES; ++i)
455 maps__delete(&mg->maps[i]); 479 maps__exit(&mg->maps[i]);
456 maps__delete_removed(&mg->removed_maps[i]);
457 }
458} 480}
459 481
460bool map_groups__empty(struct map_groups *mg) 482bool map_groups__empty(struct map_groups *mg)
@@ -464,8 +486,6 @@ bool map_groups__empty(struct map_groups *mg)
464 for (i = 0; i < MAP__NR_TYPES; ++i) { 486 for (i = 0; i < MAP__NR_TYPES; ++i) {
465 if (maps__first(&mg->maps[i])) 487 if (maps__first(&mg->maps[i]))
466 return false; 488 return false;
467 if (!list_empty(&mg->removed_maps[i]))
468 return false;
469 } 489 }
470 490
471 return true; 491 return true;
@@ -489,32 +509,10 @@ void map_groups__delete(struct map_groups *mg)
489 509
490void map_groups__put(struct map_groups *mg) 510void map_groups__put(struct map_groups *mg)
491{ 511{
492 if (--mg->refcnt == 0) 512 if (mg && atomic_dec_and_test(&mg->refcnt))
493 map_groups__delete(mg); 513 map_groups__delete(mg);
494} 514}
495 515
496void map_groups__flush(struct map_groups *mg)
497{
498 int type;
499
500 for (type = 0; type < MAP__NR_TYPES; type++) {
501 struct rb_root *root = &mg->maps[type];
502 struct rb_node *next = rb_first(root);
503
504 while (next) {
505 struct map *pos = rb_entry(next, struct map, rb_node);
506 next = rb_next(&pos->rb_node);
507 rb_erase(&pos->rb_node, root);
508 /*
509 * We may have references to this map, for
510 * instance in some hist_entry instances, so
511 * just move them to a separate list.
512 */
513 list_add_tail(&pos->node, &mg->removed_maps[pos->type]);
514 }
515 }
516}
517
518struct symbol *map_groups__find_symbol(struct map_groups *mg, 516struct symbol *map_groups__find_symbol(struct map_groups *mg,
519 enum map_type type, u64 addr, 517 enum map_type type, u64 addr,
520 struct map **mapp, 518 struct map **mapp,
@@ -538,20 +536,28 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
538 struct map **mapp, 536 struct map **mapp,
539 symbol_filter_t filter) 537 symbol_filter_t filter)
540{ 538{
539 struct maps *maps = &mg->maps[type];
540 struct symbol *sym;
541 struct rb_node *nd; 541 struct rb_node *nd;
542 542
543 for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) { 543 pthread_rwlock_rdlock(&maps->lock);
544
545 for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) {
544 struct map *pos = rb_entry(nd, struct map, rb_node); 546 struct map *pos = rb_entry(nd, struct map, rb_node);
545 struct symbol *sym = map__find_symbol_by_name(pos, name, filter); 547
548 sym = map__find_symbol_by_name(pos, name, filter);
546 549
547 if (sym == NULL) 550 if (sym == NULL)
548 continue; 551 continue;
549 if (mapp != NULL) 552 if (mapp != NULL)
550 *mapp = pos; 553 *mapp = pos;
551 return sym; 554 goto out;
552 } 555 }
553 556
554 return NULL; 557 sym = NULL;
558out:
559 pthread_rwlock_unlock(&maps->lock);
560 return sym;
555} 561}
556 562
557int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter) 563int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter)
@@ -571,73 +577,54 @@ int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter)
571 return ams->sym ? 0 : -1; 577 return ams->sym ? 0 : -1;
572} 578}
573 579
574size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type, 580static size_t maps__fprintf(struct maps *maps, FILE *fp)
575 FILE *fp)
576{ 581{
577 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); 582 size_t printed = 0;
578 struct rb_node *nd; 583 struct rb_node *nd;
579 584
580 for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) { 585 pthread_rwlock_rdlock(&maps->lock);
586
587 for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) {
581 struct map *pos = rb_entry(nd, struct map, rb_node); 588 struct map *pos = rb_entry(nd, struct map, rb_node);
582 printed += fprintf(fp, "Map:"); 589 printed += fprintf(fp, "Map:");
583 printed += map__fprintf(pos, fp); 590 printed += map__fprintf(pos, fp);
584 if (verbose > 2) { 591 if (verbose > 2) {
585 printed += dso__fprintf(pos->dso, type, fp); 592 printed += dso__fprintf(pos->dso, pos->type, fp);
586 printed += fprintf(fp, "--\n"); 593 printed += fprintf(fp, "--\n");
587 } 594 }
588 } 595 }
589 596
590 return printed; 597 pthread_rwlock_unlock(&maps->lock);
591}
592 598
593static size_t map_groups__fprintf_maps(struct map_groups *mg, FILE *fp)
594{
595 size_t printed = 0, i;
596 for (i = 0; i < MAP__NR_TYPES; ++i)
597 printed += __map_groups__fprintf_maps(mg, i, fp);
598 return printed; 599 return printed;
599} 600}
600 601
601static size_t __map_groups__fprintf_removed_maps(struct map_groups *mg, 602size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type,
602 enum map_type type, FILE *fp) 603 FILE *fp)
603{ 604{
604 struct map *pos; 605 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
605 size_t printed = 0; 606 return printed += maps__fprintf(&mg->maps[type], fp);
606
607 list_for_each_entry(pos, &mg->removed_maps[type], node) {
608 printed += fprintf(fp, "Map:");
609 printed += map__fprintf(pos, fp);
610 if (verbose > 1) {
611 printed += dso__fprintf(pos->dso, type, fp);
612 printed += fprintf(fp, "--\n");
613 }
614 }
615 return printed;
616} 607}
617 608
618static size_t map_groups__fprintf_removed_maps(struct map_groups *mg, 609size_t map_groups__fprintf(struct map_groups *mg, FILE *fp)
619 FILE *fp)
620{ 610{
621 size_t printed = 0, i; 611 size_t printed = 0, i;
622 for (i = 0; i < MAP__NR_TYPES; ++i) 612 for (i = 0; i < MAP__NR_TYPES; ++i)
623 printed += __map_groups__fprintf_removed_maps(mg, i, fp); 613 printed += __map_groups__fprintf_maps(mg, i, fp);
624 return printed; 614 return printed;
625} 615}
626 616
627size_t map_groups__fprintf(struct map_groups *mg, FILE *fp) 617static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
628{ 618{
629 size_t printed = map_groups__fprintf_maps(mg, fp); 619 struct rb_root *root;
630 printed += fprintf(fp, "Removed maps:\n"); 620 struct rb_node *next;
631 return printed + map_groups__fprintf_removed_maps(mg, fp);
632}
633
634int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
635 FILE *fp)
636{
637 struct rb_root *root = &mg->maps[map->type];
638 struct rb_node *next = rb_first(root);
639 int err = 0; 621 int err = 0;
640 622
623 pthread_rwlock_wrlock(&maps->lock);
624
625 root = &maps->entries;
626 next = rb_first(root);
627
641 while (next) { 628 while (next) {
642 struct map *pos = rb_entry(next, struct map, rb_node); 629 struct map *pos = rb_entry(next, struct map, rb_node);
643 next = rb_next(&pos->rb_node); 630 next = rb_next(&pos->rb_node);
@@ -651,7 +638,7 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
651 map__fprintf(pos, fp); 638 map__fprintf(pos, fp);
652 } 639 }
653 640
654 rb_erase(&pos->rb_node, root); 641 rb_erase_init(&pos->rb_node, root);
655 /* 642 /*
656 * Now check if we need to create new maps for areas not 643 * Now check if we need to create new maps for areas not
657 * overlapped by the new map: 644 * overlapped by the new map:
@@ -661,11 +648,11 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
661 648
662 if (before == NULL) { 649 if (before == NULL) {
663 err = -ENOMEM; 650 err = -ENOMEM;
664 goto move_map; 651 goto put_map;
665 } 652 }
666 653
667 before->end = map->start; 654 before->end = map->start;
668 map_groups__insert(mg, before); 655 __maps__insert(maps, before);
669 if (verbose >= 2) 656 if (verbose >= 2)
670 map__fprintf(before, fp); 657 map__fprintf(before, fp);
671 } 658 }
@@ -675,28 +662,31 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
675 662
676 if (after == NULL) { 663 if (after == NULL) {
677 err = -ENOMEM; 664 err = -ENOMEM;
678 goto move_map; 665 goto put_map;
679 } 666 }
680 667
681 after->start = map->end; 668 after->start = map->end;
682 map_groups__insert(mg, after); 669 __maps__insert(maps, after);
683 if (verbose >= 2) 670 if (verbose >= 2)
684 map__fprintf(after, fp); 671 map__fprintf(after, fp);
685 } 672 }
686move_map: 673put_map:
687 /* 674 map__put(pos);
688 * If we have references, just move them to a separate list.
689 */
690 if (pos->referenced)
691 list_add_tail(&pos->node, &mg->removed_maps[map->type]);
692 else
693 map__delete(pos);
694 675
695 if (err) 676 if (err)
696 return err; 677 goto out;
697 } 678 }
698 679
699 return 0; 680 err = 0;
681out:
682 pthread_rwlock_unlock(&maps->lock);
683 return err;
684}
685
686int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
687 FILE *fp)
688{
689 return maps__fixup_overlappings(&mg->maps[map->type], map, fp);
700} 690}
701 691
702/* 692/*
@@ -705,20 +695,28 @@ move_map:
705int map_groups__clone(struct map_groups *mg, 695int map_groups__clone(struct map_groups *mg,
706 struct map_groups *parent, enum map_type type) 696 struct map_groups *parent, enum map_type type)
707{ 697{
708 struct rb_node *nd; 698 int err = -ENOMEM;
709 for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) { 699 struct map *map;
710 struct map *map = rb_entry(nd, struct map, rb_node); 700 struct maps *maps = &parent->maps[type];
701
702 pthread_rwlock_rdlock(&maps->lock);
703
704 for (map = maps__first(maps); map; map = map__next(map)) {
711 struct map *new = map__clone(map); 705 struct map *new = map__clone(map);
712 if (new == NULL) 706 if (new == NULL)
713 return -ENOMEM; 707 goto out_unlock;
714 map_groups__insert(mg, new); 708 map_groups__insert(mg, new);
715 } 709 }
716 return 0; 710
711 err = 0;
712out_unlock:
713 pthread_rwlock_unlock(&maps->lock);
714 return err;
717} 715}
718 716
719void maps__insert(struct rb_root *maps, struct map *map) 717static void __maps__insert(struct maps *maps, struct map *map)
720{ 718{
721 struct rb_node **p = &maps->rb_node; 719 struct rb_node **p = &maps->entries.rb_node;
722 struct rb_node *parent = NULL; 720 struct rb_node *parent = NULL;
723 const u64 ip = map->start; 721 const u64 ip = map->start;
724 struct map *m; 722 struct map *m;
@@ -733,20 +731,38 @@ void maps__insert(struct rb_root *maps, struct map *map)
733 } 731 }
734 732
735 rb_link_node(&map->rb_node, parent, p); 733 rb_link_node(&map->rb_node, parent, p);
736 rb_insert_color(&map->rb_node, maps); 734 rb_insert_color(&map->rb_node, &maps->entries);
735 map__get(map);
737} 736}
738 737
739void maps__remove(struct rb_root *maps, struct map *map) 738void maps__insert(struct maps *maps, struct map *map)
740{ 739{
741 rb_erase(&map->rb_node, maps); 740 pthread_rwlock_wrlock(&maps->lock);
741 __maps__insert(maps, map);
742 pthread_rwlock_unlock(&maps->lock);
742} 743}
743 744
744struct map *maps__find(struct rb_root *maps, u64 ip) 745static void __maps__remove(struct maps *maps, struct map *map)
745{ 746{
746 struct rb_node **p = &maps->rb_node; 747 rb_erase_init(&map->rb_node, &maps->entries);
747 struct rb_node *parent = NULL; 748 map__put(map);
749}
750
751void maps__remove(struct maps *maps, struct map *map)
752{
753 pthread_rwlock_wrlock(&maps->lock);
754 __maps__remove(maps, map);
755 pthread_rwlock_unlock(&maps->lock);
756}
757
758struct map *maps__find(struct maps *maps, u64 ip)
759{
760 struct rb_node **p, *parent = NULL;
748 struct map *m; 761 struct map *m;
749 762
763 pthread_rwlock_rdlock(&maps->lock);
764
765 p = &maps->entries.rb_node;
750 while (*p != NULL) { 766 while (*p != NULL) {
751 parent = *p; 767 parent = *p;
752 m = rb_entry(parent, struct map, rb_node); 768 m = rb_entry(parent, struct map, rb_node);
@@ -755,22 +771,25 @@ struct map *maps__find(struct rb_root *maps, u64 ip)
755 else if (ip >= m->end) 771 else if (ip >= m->end)
756 p = &(*p)->rb_right; 772 p = &(*p)->rb_right;
757 else 773 else
758 return m; 774 goto out;
759 } 775 }
760 776
761 return NULL; 777 m = NULL;
778out:
779 pthread_rwlock_unlock(&maps->lock);
780 return m;
762} 781}
763 782
764struct map *maps__first(struct rb_root *maps) 783struct map *maps__first(struct maps *maps)
765{ 784{
766 struct rb_node *first = rb_first(maps); 785 struct rb_node *first = rb_first(&maps->entries);
767 786
768 if (first) 787 if (first)
769 return rb_entry(first, struct map, rb_node); 788 return rb_entry(first, struct map, rb_node);
770 return NULL; 789 return NULL;
771} 790}
772 791
773struct map *maps__next(struct map *map) 792struct map *map__next(struct map *map)
774{ 793{
775 struct rb_node *next = rb_next(&map->rb_node); 794 struct rb_node *next = rb_next(&map->rb_node);
776 795
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index ec19c59ca38e..d73e687b224e 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -1,9 +1,11 @@
1#ifndef __PERF_MAP_H 1#ifndef __PERF_MAP_H
2#define __PERF_MAP_H 2#define __PERF_MAP_H
3 3
4#include <linux/atomic.h>
4#include <linux/compiler.h> 5#include <linux/compiler.h>
5#include <linux/list.h> 6#include <linux/list.h>
6#include <linux/rbtree.h> 7#include <linux/rbtree.h>
8#include <pthread.h>
7#include <stdio.h> 9#include <stdio.h>
8#include <stdbool.h> 10#include <stdbool.h>
9#include <linux/types.h> 11#include <linux/types.h>
@@ -32,7 +34,6 @@ struct map {
32 u64 start; 34 u64 start;
33 u64 end; 35 u64 end;
34 u8 /* enum map_type */ type; 36 u8 /* enum map_type */ type;
35 bool referenced;
36 bool erange_warned; 37 bool erange_warned;
37 u32 priv; 38 u32 priv;
38 u32 prot; 39 u32 prot;
@@ -50,6 +51,7 @@ struct map {
50 51
51 struct dso *dso; 52 struct dso *dso;
52 struct map_groups *groups; 53 struct map_groups *groups;
54 atomic_t refcnt;
53}; 55};
54 56
55struct kmap { 57struct kmap {
@@ -57,11 +59,15 @@ struct kmap {
57 struct map_groups *kmaps; 59 struct map_groups *kmaps;
58}; 60};
59 61
62struct maps {
63 struct rb_root entries;
64 pthread_rwlock_t lock;
65};
66
60struct map_groups { 67struct map_groups {
61 struct rb_root maps[MAP__NR_TYPES]; 68 struct maps maps[MAP__NR_TYPES];
62 struct list_head removed_maps[MAP__NR_TYPES];
63 struct machine *machine; 69 struct machine *machine;
64 int refcnt; 70 atomic_t refcnt;
65}; 71};
66 72
67struct map_groups *map_groups__new(struct machine *machine); 73struct map_groups *map_groups__new(struct machine *machine);
@@ -70,7 +76,8 @@ bool map_groups__empty(struct map_groups *mg);
70 76
71static inline struct map_groups *map_groups__get(struct map_groups *mg) 77static inline struct map_groups *map_groups__get(struct map_groups *mg)
72{ 78{
73 ++mg->refcnt; 79 if (mg)
80 atomic_inc(&mg->refcnt);
74 return mg; 81 return mg;
75} 82}
76 83
@@ -124,7 +131,7 @@ struct thread;
124 */ 131 */
125#define __map__for_each_symbol_by_name(map, sym_name, pos, filter) \ 132#define __map__for_each_symbol_by_name(map, sym_name, pos, filter) \
126 for (pos = map__find_symbol_by_name(map, sym_name, filter); \ 133 for (pos = map__find_symbol_by_name(map, sym_name, filter); \
127 pos && strcmp(pos->name, sym_name) == 0; \ 134 pos && arch__compare_symbol_names(pos->name, sym_name) == 0; \
128 pos = symbol__next_by_name(pos)) 135 pos = symbol__next_by_name(pos))
129 136
130#define map__for_each_symbol_by_name(map, sym_name, pos) \ 137#define map__for_each_symbol_by_name(map, sym_name, pos) \
@@ -132,6 +139,7 @@ struct thread;
132 139
133typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); 140typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
134 141
142int arch__compare_symbol_names(const char *namea, const char *nameb);
135void map__init(struct map *map, enum map_type type, 143void map__init(struct map *map, enum map_type type,
136 u64 start, u64 end, u64 pgoff, struct dso *dso); 144 u64 start, u64 end, u64 pgoff, struct dso *dso);
137struct map *map__new(struct machine *machine, u64 start, u64 len, 145struct map *map__new(struct machine *machine, u64 start, u64 len,
@@ -141,6 +149,24 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
141struct map *map__new2(u64 start, struct dso *dso, enum map_type type); 149struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
142void map__delete(struct map *map); 150void map__delete(struct map *map);
143struct map *map__clone(struct map *map); 151struct map *map__clone(struct map *map);
152
153static inline struct map *map__get(struct map *map)
154{
155 if (map)
156 atomic_inc(&map->refcnt);
157 return map;
158}
159
160void map__put(struct map *map);
161
162static inline void __map__zput(struct map **map)
163{
164 map__put(*map);
165 *map = NULL;
166}
167
168#define map__zput(map) __map__zput(&map)
169
144int map__overlap(struct map *l, struct map *r); 170int map__overlap(struct map *l, struct map *r);
145size_t map__fprintf(struct map *map, FILE *fp); 171size_t map__fprintf(struct map *map, FILE *fp);
146size_t map__fprintf_dsoname(struct map *map, FILE *fp); 172size_t map__fprintf_dsoname(struct map *map, FILE *fp);
@@ -159,11 +185,11 @@ void map__reloc_vmlinux(struct map *map);
159 185
160size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type, 186size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type,
161 FILE *fp); 187 FILE *fp);
162void maps__insert(struct rb_root *maps, struct map *map); 188void maps__insert(struct maps *maps, struct map *map);
163void maps__remove(struct rb_root *maps, struct map *map); 189void maps__remove(struct maps *maps, struct map *map);
164struct map *maps__find(struct rb_root *maps, u64 addr); 190struct map *maps__find(struct maps *maps, u64 addr);
165struct map *maps__first(struct rb_root *maps); 191struct map *maps__first(struct maps *maps);
166struct map *maps__next(struct map *map); 192struct map *map__next(struct map *map);
167void map_groups__init(struct map_groups *mg, struct machine *machine); 193void map_groups__init(struct map_groups *mg, struct machine *machine);
168void map_groups__exit(struct map_groups *mg); 194void map_groups__exit(struct map_groups *mg);
169int map_groups__clone(struct map_groups *mg, 195int map_groups__clone(struct map_groups *mg,
@@ -198,7 +224,7 @@ static inline struct map *map_groups__first(struct map_groups *mg,
198 224
199static inline struct map *map_groups__next(struct map *map) 225static inline struct map *map_groups__next(struct map *map)
200{ 226{
201 return maps__next(map); 227 return map__next(map);
202} 228}
203 229
204struct symbol *map_groups__find_symbol(struct map_groups *mg, 230struct symbol *map_groups__find_symbol(struct map_groups *mg,
@@ -230,6 +256,4 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
230struct map *map_groups__find_by_name(struct map_groups *mg, 256struct map *map_groups__find_by_name(struct map_groups *mg,
231 enum map_type type, const char *name); 257 enum map_type type, const char *name);
232 258
233void map_groups__flush(struct map_groups *mg);
234
235#endif /* __PERF_MAP_H */ 259#endif /* __PERF_MAP_H */
diff --git a/tools/perf/util/pager.c b/tools/perf/util/pager.c
index 31ee02d4e988..53ef006a951c 100644
--- a/tools/perf/util/pager.c
+++ b/tools/perf/util/pager.c
@@ -50,11 +50,6 @@ void setup_pager(void)
50 50
51 if (!isatty(1)) 51 if (!isatty(1))
52 return; 52 return;
53 if (!pager) {
54 if (!pager_program)
55 perf_config(perf_default_config, NULL);
56 pager = pager_program;
57 }
58 if (!pager) 53 if (!pager)
59 pager = getenv("PAGER"); 54 pager = getenv("PAGER");
60 if (!(pager || access("/usr/bin/pager", X_OK))) 55 if (!(pager || access("/usr/bin/pager", X_OK)))
diff --git a/tools/perf/util/parse-branch-options.c b/tools/perf/util/parse-branch-options.c
new file mode 100644
index 000000000000..a3b1e13a05c0
--- /dev/null
+++ b/tools/perf/util/parse-branch-options.c
@@ -0,0 +1,94 @@
1#include "perf.h"
2#include "util/util.h"
3#include "util/debug.h"
4#include "util/parse-options.h"
5#include "util/parse-branch-options.h"
6
7#define BRANCH_OPT(n, m) \
8 { .name = n, .mode = (m) }
9
10#define BRANCH_END { .name = NULL }
11
12struct branch_mode {
13 const char *name;
14 int mode;
15};
16
17static const struct branch_mode branch_modes[] = {
18 BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
19 BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
20 BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
21 BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
22 BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
23 BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
24 BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
25 BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX),
26 BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX),
27 BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX),
28 BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND),
29 BRANCH_OPT("ind_jmp", PERF_SAMPLE_BRANCH_IND_JUMP),
30 BRANCH_END
31};
32
33int
34parse_branch_stack(const struct option *opt, const char *str, int unset)
35{
36#define ONLY_PLM \
37 (PERF_SAMPLE_BRANCH_USER |\
38 PERF_SAMPLE_BRANCH_KERNEL |\
39 PERF_SAMPLE_BRANCH_HV)
40
41 uint64_t *mode = (uint64_t *)opt->value;
42 const struct branch_mode *br;
43 char *s, *os = NULL, *p;
44 int ret = -1;
45
46 if (unset)
47 return 0;
48
49 /*
50 * cannot set it twice, -b + --branch-filter for instance
51 */
52 if (*mode)
53 return -1;
54
55 /* str may be NULL in case no arg is passed to -b */
56 if (str) {
57 /* because str is read-only */
58 s = os = strdup(str);
59 if (!s)
60 return -1;
61
62 for (;;) {
63 p = strchr(s, ',');
64 if (p)
65 *p = '\0';
66
67 for (br = branch_modes; br->name; br++) {
68 if (!strcasecmp(s, br->name))
69 break;
70 }
71 if (!br->name) {
72 ui__warning("unknown branch filter %s,"
73 " check man page\n", s);
74 goto error;
75 }
76
77 *mode |= br->mode;
78
79 if (!p)
80 break;
81
82 s = p + 1;
83 }
84 }
85 ret = 0;
86
87 /* default to any branch */
88 if ((*mode & ~ONLY_PLM) == 0) {
89 *mode = PERF_SAMPLE_BRANCH_ANY;
90 }
91error:
92 free(os);
93 return ret;
94}
diff --git a/tools/perf/util/parse-branch-options.h b/tools/perf/util/parse-branch-options.h
new file mode 100644
index 000000000000..b9d9470c2e82
--- /dev/null
+++ b/tools/perf/util/parse-branch-options.h
@@ -0,0 +1,5 @@
1#ifndef _PERF_PARSE_BRANCH_OPTIONS_H
2#define _PERF_PARSE_BRANCH_OPTIONS_H 1
3struct option;
4int parse_branch_stack(const struct option *opt, const char *str, int unset);
5#endif /* _PERF_PARSE_BRANCH_OPTIONS_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index be0655388b38..2a4d1ec02846 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -17,6 +17,7 @@
17#include "parse-events-flex.h" 17#include "parse-events-flex.h"
18#include "pmu.h" 18#include "pmu.h"
19#include "thread_map.h" 19#include "thread_map.h"
20#include "asm/bug.h"
20 21
21#define MAX_NAME_LEN 100 22#define MAX_NAME_LEN 100
22 23
@@ -538,16 +539,40 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
538 return add_event(list, idx, &attr, NULL); 539 return add_event(list, idx, &attr, NULL);
539} 540}
540 541
542static int check_type_val(struct parse_events_term *term,
543 struct parse_events_error *err,
544 int type)
545{
546 if (type == term->type_val)
547 return 0;
548
549 if (err) {
550 err->idx = term->err_val;
551 if (type == PARSE_EVENTS__TERM_TYPE_NUM)
552 err->str = strdup("expected numeric value");
553 else
554 err->str = strdup("expected string value");
555 }
556 return -EINVAL;
557}
558
541static int config_term(struct perf_event_attr *attr, 559static int config_term(struct perf_event_attr *attr,
542 struct parse_events_term *term) 560 struct parse_events_term *term,
561 struct parse_events_error *err)
543{ 562{
544#define CHECK_TYPE_VAL(type) \ 563#define CHECK_TYPE_VAL(type) \
545do { \ 564do { \
546 if (PARSE_EVENTS__TERM_TYPE_ ## type != term->type_val) \ 565 if (check_type_val(term, err, PARSE_EVENTS__TERM_TYPE_ ## type)) \
547 return -EINVAL; \ 566 return -EINVAL; \
548} while (0) 567} while (0)
549 568
550 switch (term->type_term) { 569 switch (term->type_term) {
570 case PARSE_EVENTS__TERM_TYPE_USER:
571 /*
572 * Always succeed for sysfs terms, as we dont know
573 * at this point what type they need to have.
574 */
575 return 0;
551 case PARSE_EVENTS__TERM_TYPE_CONFIG: 576 case PARSE_EVENTS__TERM_TYPE_CONFIG:
552 CHECK_TYPE_VAL(NUM); 577 CHECK_TYPE_VAL(NUM);
553 attr->config = term->val.num; 578 attr->config = term->val.num;
@@ -582,18 +607,20 @@ do { \
582} 607}
583 608
584static int config_attr(struct perf_event_attr *attr, 609static int config_attr(struct perf_event_attr *attr,
585 struct list_head *head, int fail) 610 struct list_head *head,
611 struct parse_events_error *err)
586{ 612{
587 struct parse_events_term *term; 613 struct parse_events_term *term;
588 614
589 list_for_each_entry(term, head, list) 615 list_for_each_entry(term, head, list)
590 if (config_term(attr, term) && fail) 616 if (config_term(attr, term, err))
591 return -EINVAL; 617 return -EINVAL;
592 618
593 return 0; 619 return 0;
594} 620}
595 621
596int parse_events_add_numeric(struct list_head *list, int *idx, 622int parse_events_add_numeric(struct parse_events_evlist *data,
623 struct list_head *list,
597 u32 type, u64 config, 624 u32 type, u64 config,
598 struct list_head *head_config) 625 struct list_head *head_config)
599{ 626{
@@ -604,10 +631,10 @@ int parse_events_add_numeric(struct list_head *list, int *idx,
604 attr.config = config; 631 attr.config = config;
605 632
606 if (head_config && 633 if (head_config &&
607 config_attr(&attr, head_config, 1)) 634 config_attr(&attr, head_config, data->error))
608 return -EINVAL; 635 return -EINVAL;
609 636
610 return add_event(list, idx, &attr, NULL); 637 return add_event(list, &data->idx, &attr, NULL);
611} 638}
612 639
613static int parse_events__is_name_term(struct parse_events_term *term) 640static int parse_events__is_name_term(struct parse_events_term *term)
@@ -626,8 +653,9 @@ static char *pmu_event_name(struct list_head *head_terms)
626 return NULL; 653 return NULL;
627} 654}
628 655
629int parse_events_add_pmu(struct list_head *list, int *idx, 656int parse_events_add_pmu(struct parse_events_evlist *data,
630 char *name, struct list_head *head_config) 657 struct list_head *list, char *name,
658 struct list_head *head_config)
631{ 659{
632 struct perf_event_attr attr; 660 struct perf_event_attr attr;
633 struct perf_pmu_info info; 661 struct perf_pmu_info info;
@@ -647,7 +675,7 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
647 675
648 if (!head_config) { 676 if (!head_config) {
649 attr.type = pmu->type; 677 attr.type = pmu->type;
650 evsel = __add_event(list, idx, &attr, NULL, pmu->cpus); 678 evsel = __add_event(list, &data->idx, &attr, NULL, pmu->cpus);
651 return evsel ? 0 : -ENOMEM; 679 return evsel ? 0 : -ENOMEM;
652 } 680 }
653 681
@@ -658,13 +686,14 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
658 * Configure hardcoded terms first, no need to check 686 * Configure hardcoded terms first, no need to check
659 * return value when called with fail == 0 ;) 687 * return value when called with fail == 0 ;)
660 */ 688 */
661 config_attr(&attr, head_config, 0); 689 if (config_attr(&attr, head_config, data->error))
690 return -EINVAL;
662 691
663 if (perf_pmu__config(pmu, &attr, head_config)) 692 if (perf_pmu__config(pmu, &attr, head_config, data->error))
664 return -EINVAL; 693 return -EINVAL;
665 694
666 evsel = __add_event(list, idx, &attr, pmu_event_name(head_config), 695 evsel = __add_event(list, &data->idx, &attr,
667 pmu->cpus); 696 pmu_event_name(head_config), pmu->cpus);
668 if (evsel) { 697 if (evsel) {
669 evsel->unit = info.unit; 698 evsel->unit = info.unit;
670 evsel->scale = info.scale; 699 evsel->scale = info.scale;
@@ -1019,11 +1048,13 @@ int parse_events_terms(struct list_head *terms, const char *str)
1019 return ret; 1048 return ret;
1020} 1049}
1021 1050
1022int parse_events(struct perf_evlist *evlist, const char *str) 1051int parse_events(struct perf_evlist *evlist, const char *str,
1052 struct parse_events_error *err)
1023{ 1053{
1024 struct parse_events_evlist data = { 1054 struct parse_events_evlist data = {
1025 .list = LIST_HEAD_INIT(data.list), 1055 .list = LIST_HEAD_INIT(data.list),
1026 .idx = evlist->nr_entries, 1056 .idx = evlist->nr_entries,
1057 .error = err,
1027 }; 1058 };
1028 int ret; 1059 int ret;
1029 1060
@@ -1044,16 +1075,87 @@ int parse_events(struct perf_evlist *evlist, const char *str)
1044 return ret; 1075 return ret;
1045} 1076}
1046 1077
1078#define MAX_WIDTH 1000
1079static int get_term_width(void)
1080{
1081 struct winsize ws;
1082
1083 get_term_dimensions(&ws);
1084 return ws.ws_col > MAX_WIDTH ? MAX_WIDTH : ws.ws_col;
1085}
1086
1087static void parse_events_print_error(struct parse_events_error *err,
1088 const char *event)
1089{
1090 const char *str = "invalid or unsupported event: ";
1091 char _buf[MAX_WIDTH];
1092 char *buf = (char *) event;
1093 int idx = 0;
1094
1095 if (err->str) {
1096 /* -2 for extra '' in the final fprintf */
1097 int width = get_term_width() - 2;
1098 int len_event = strlen(event);
1099 int len_str, max_len, cut = 0;
1100
1101 /*
1102 * Maximum error index indent, we will cut
1103 * the event string if it's bigger.
1104 */
1105 int max_err_idx = 10;
1106
1107 /*
1108 * Let's be specific with the message when
1109 * we have the precise error.
1110 */
1111 str = "event syntax error: ";
1112 len_str = strlen(str);
1113 max_len = width - len_str;
1114
1115 buf = _buf;
1116
1117 /* We're cutting from the beggining. */
1118 if (err->idx > max_err_idx)
1119 cut = err->idx - max_err_idx;
1120
1121 strncpy(buf, event + cut, max_len);
1122
1123 /* Mark cut parts with '..' on both sides. */
1124 if (cut)
1125 buf[0] = buf[1] = '.';
1126
1127 if ((len_event - cut) > max_len) {
1128 buf[max_len - 1] = buf[max_len - 2] = '.';
1129 buf[max_len] = 0;
1130 }
1131
1132 idx = len_str + err->idx - cut;
1133 }
1134
1135 fprintf(stderr, "%s'%s'\n", str, buf);
1136 if (idx) {
1137 fprintf(stderr, "%*s\\___ %s\n", idx + 1, "", err->str);
1138 if (err->help)
1139 fprintf(stderr, "\n%s\n", err->help);
1140 free(err->str);
1141 free(err->help);
1142 }
1143
1144 fprintf(stderr, "Run 'perf list' for a list of valid events\n");
1145}
1146
1147#undef MAX_WIDTH
1148
1047int parse_events_option(const struct option *opt, const char *str, 1149int parse_events_option(const struct option *opt, const char *str,
1048 int unset __maybe_unused) 1150 int unset __maybe_unused)
1049{ 1151{
1050 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 1152 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
1051 int ret = parse_events(evlist, str); 1153 struct parse_events_error err = { .idx = 0, };
1154 int ret = parse_events(evlist, str, &err);
1155
1156 if (ret)
1157 parse_events_print_error(&err, str);
1052 1158
1053 if (ret) {
1054 fprintf(stderr, "invalid or unsupported event: '%s'\n", str);
1055 fprintf(stderr, "Run 'perf list' for a list of valid events\n");
1056 }
1057 return ret; 1159 return ret;
1058} 1160}
1059 1161
@@ -1460,7 +1562,7 @@ int parse_events__is_hardcoded_term(struct parse_events_term *term)
1460 1562
1461static int new_term(struct parse_events_term **_term, int type_val, 1563static int new_term(struct parse_events_term **_term, int type_val,
1462 int type_term, char *config, 1564 int type_term, char *config,
1463 char *str, u64 num) 1565 char *str, u64 num, int err_term, int err_val)
1464{ 1566{
1465 struct parse_events_term *term; 1567 struct parse_events_term *term;
1466 1568
@@ -1472,6 +1574,8 @@ static int new_term(struct parse_events_term **_term, int type_val,
1472 term->type_val = type_val; 1574 term->type_val = type_val;
1473 term->type_term = type_term; 1575 term->type_term = type_term;
1474 term->config = config; 1576 term->config = config;
1577 term->err_term = err_term;
1578 term->err_val = err_val;
1475 1579
1476 switch (type_val) { 1580 switch (type_val) {
1477 case PARSE_EVENTS__TERM_TYPE_NUM: 1581 case PARSE_EVENTS__TERM_TYPE_NUM:
@@ -1490,17 +1594,29 @@ static int new_term(struct parse_events_term **_term, int type_val,
1490} 1594}
1491 1595
1492int parse_events_term__num(struct parse_events_term **term, 1596int parse_events_term__num(struct parse_events_term **term,
1493 int type_term, char *config, u64 num) 1597 int type_term, char *config, u64 num,
1598 void *loc_term_, void *loc_val_)
1494{ 1599{
1600 YYLTYPE *loc_term = loc_term_;
1601 YYLTYPE *loc_val = loc_val_;
1602
1495 return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term, 1603 return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term,
1496 config, NULL, num); 1604 config, NULL, num,
1605 loc_term ? loc_term->first_column : 0,
1606 loc_val ? loc_val->first_column : 0);
1497} 1607}
1498 1608
1499int parse_events_term__str(struct parse_events_term **term, 1609int parse_events_term__str(struct parse_events_term **term,
1500 int type_term, char *config, char *str) 1610 int type_term, char *config, char *str,
1611 void *loc_term_, void *loc_val_)
1501{ 1612{
1613 YYLTYPE *loc_term = loc_term_;
1614 YYLTYPE *loc_val = loc_val_;
1615
1502 return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term, 1616 return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term,
1503 config, str, 0); 1617 config, str, 0,
1618 loc_term ? loc_term->first_column : 0,
1619 loc_val ? loc_val->first_column : 0);
1504} 1620}
1505 1621
1506int parse_events_term__sym_hw(struct parse_events_term **term, 1622int parse_events_term__sym_hw(struct parse_events_term **term,
@@ -1514,18 +1630,20 @@ int parse_events_term__sym_hw(struct parse_events_term **term,
1514 if (config) 1630 if (config)
1515 return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, 1631 return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
1516 PARSE_EVENTS__TERM_TYPE_USER, config, 1632 PARSE_EVENTS__TERM_TYPE_USER, config,
1517 (char *) sym->symbol, 0); 1633 (char *) sym->symbol, 0, 0, 0);
1518 else 1634 else
1519 return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, 1635 return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
1520 PARSE_EVENTS__TERM_TYPE_USER, 1636 PARSE_EVENTS__TERM_TYPE_USER,
1521 (char *) "event", (char *) sym->symbol, 0); 1637 (char *) "event", (char *) sym->symbol,
1638 0, 0, 0);
1522} 1639}
1523 1640
1524int parse_events_term__clone(struct parse_events_term **new, 1641int parse_events_term__clone(struct parse_events_term **new,
1525 struct parse_events_term *term) 1642 struct parse_events_term *term)
1526{ 1643{
1527 return new_term(new, term->type_val, term->type_term, term->config, 1644 return new_term(new, term->type_val, term->type_term, term->config,
1528 term->val.str, term->val.num); 1645 term->val.str, term->val.num,
1646 term->err_term, term->err_val);
1529} 1647}
1530 1648
1531void parse_events__free_terms(struct list_head *terms) 1649void parse_events__free_terms(struct list_head *terms)
@@ -1535,3 +1653,15 @@ void parse_events__free_terms(struct list_head *terms)
1535 list_for_each_entry_safe(term, h, terms, list) 1653 list_for_each_entry_safe(term, h, terms, list)
1536 free(term); 1654 free(term);
1537} 1655}
1656
1657void parse_events_evlist_error(struct parse_events_evlist *data,
1658 int idx, const char *str)
1659{
1660 struct parse_events_error *err = data->error;
1661
1662 if (!err)
1663 return;
1664 err->idx = idx;
1665 err->str = strdup(str);
1666 WARN_ONCE(!err->str, "WARNING: failed to allocate error string");
1667}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 52a2dda4f954..131f29b2f132 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -12,6 +12,7 @@
12struct list_head; 12struct list_head;
13struct perf_evsel; 13struct perf_evsel;
14struct perf_evlist; 14struct perf_evlist;
15struct parse_events_error;
15 16
16struct option; 17struct option;
17 18
@@ -29,7 +30,8 @@ const char *event_type(int type);
29 30
30extern int parse_events_option(const struct option *opt, const char *str, 31extern int parse_events_option(const struct option *opt, const char *str,
31 int unset); 32 int unset);
32extern int parse_events(struct perf_evlist *evlist, const char *str); 33extern int parse_events(struct perf_evlist *evlist, const char *str,
34 struct parse_events_error *error);
33extern int parse_events_terms(struct list_head *terms, const char *str); 35extern int parse_events_terms(struct list_head *terms, const char *str);
34extern int parse_filter(const struct option *opt, const char *str, int unset); 36extern int parse_filter(const struct option *opt, const char *str, int unset);
35 37
@@ -72,12 +74,23 @@ struct parse_events_term {
72 int type_term; 74 int type_term;
73 struct list_head list; 75 struct list_head list;
74 bool used; 76 bool used;
77
78 /* error string indexes for within parsed string */
79 int err_term;
80 int err_val;
81};
82
83struct parse_events_error {
84 int idx; /* index in the parsed string */
85 char *str; /* string to display at the index */
86 char *help; /* optional help string */
75}; 87};
76 88
77struct parse_events_evlist { 89struct parse_events_evlist {
78 struct list_head list; 90 struct list_head list;
79 int idx; 91 int idx;
80 int nr_groups; 92 int nr_groups;
93 struct parse_events_error *error;
81}; 94};
82 95
83struct parse_events_terms { 96struct parse_events_terms {
@@ -85,10 +98,12 @@ struct parse_events_terms {
85}; 98};
86 99
87int parse_events__is_hardcoded_term(struct parse_events_term *term); 100int parse_events__is_hardcoded_term(struct parse_events_term *term);
88int parse_events_term__num(struct parse_events_term **_term, 101int parse_events_term__num(struct parse_events_term **term,
89 int type_term, char *config, u64 num); 102 int type_term, char *config, u64 num,
90int parse_events_term__str(struct parse_events_term **_term, 103 void *loc_term, void *loc_val);
91 int type_term, char *config, char *str); 104int parse_events_term__str(struct parse_events_term **term,
105 int type_term, char *config, char *str,
106 void *loc_term, void *loc_val);
92int parse_events_term__sym_hw(struct parse_events_term **term, 107int parse_events_term__sym_hw(struct parse_events_term **term,
93 char *config, unsigned idx); 108 char *config, unsigned idx);
94int parse_events_term__clone(struct parse_events_term **new, 109int parse_events_term__clone(struct parse_events_term **new,
@@ -99,21 +114,24 @@ int parse_events__modifier_group(struct list_head *list, char *event_mod);
99int parse_events_name(struct list_head *list, char *name); 114int parse_events_name(struct list_head *list, char *name);
100int parse_events_add_tracepoint(struct list_head *list, int *idx, 115int parse_events_add_tracepoint(struct list_head *list, int *idx,
101 char *sys, char *event); 116 char *sys, char *event);
102int parse_events_add_numeric(struct list_head *list, int *idx, 117int parse_events_add_numeric(struct parse_events_evlist *data,
118 struct list_head *list,
103 u32 type, u64 config, 119 u32 type, u64 config,
104 struct list_head *head_config); 120 struct list_head *head_config);
105int parse_events_add_cache(struct list_head *list, int *idx, 121int parse_events_add_cache(struct list_head *list, int *idx,
106 char *type, char *op_result1, char *op_result2); 122 char *type, char *op_result1, char *op_result2);
107int parse_events_add_breakpoint(struct list_head *list, int *idx, 123int parse_events_add_breakpoint(struct list_head *list, int *idx,
108 void *ptr, char *type, u64 len); 124 void *ptr, char *type, u64 len);
109int parse_events_add_pmu(struct list_head *list, int *idx, 125int parse_events_add_pmu(struct parse_events_evlist *data,
110 char *pmu , struct list_head *head_config); 126 struct list_head *list, char *name,
127 struct list_head *head_config);
111enum perf_pmu_event_symbol_type 128enum perf_pmu_event_symbol_type
112perf_pmu__parse_check(const char *name); 129perf_pmu__parse_check(const char *name);
113void parse_events__set_leader(char *name, struct list_head *list); 130void parse_events__set_leader(char *name, struct list_head *list);
114void parse_events_update_lists(struct list_head *list_event, 131void parse_events_update_lists(struct list_head *list_event,
115 struct list_head *list_all); 132 struct list_head *list_all);
116void parse_events_error(void *data, void *scanner, char const *msg); 133void parse_events_evlist_error(struct parse_events_evlist *data,
134 int idx, const char *str);
117 135
118void print_events(const char *event_glob, bool name_only); 136void print_events(const char *event_glob, bool name_only);
119 137
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 8895cf3132ab..09e738fe9ea2 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -3,6 +3,8 @@
3%option bison-bridge 3%option bison-bridge
4%option prefix="parse_events_" 4%option prefix="parse_events_"
5%option stack 5%option stack
6%option bison-locations
7%option yylineno
6 8
7%{ 9%{
8#include <errno.h> 10#include <errno.h>
@@ -51,6 +53,18 @@ static int str(yyscan_t scanner, int token)
51 return token; 53 return token;
52} 54}
53 55
56#define REWIND(__alloc) \
57do { \
58 YYSTYPE *__yylval = parse_events_get_lval(yyscanner); \
59 char *text = parse_events_get_text(yyscanner); \
60 \
61 if (__alloc) \
62 __yylval->str = strdup(text); \
63 \
64 yycolumn -= strlen(text); \
65 yyless(0); \
66} while (0)
67
54static int pmu_str_check(yyscan_t scanner) 68static int pmu_str_check(yyscan_t scanner)
55{ 69{
56 YYSTYPE *yylval = parse_events_get_lval(scanner); 70 YYSTYPE *yylval = parse_events_get_lval(scanner);
@@ -85,6 +99,13 @@ static int term(yyscan_t scanner, int type)
85 return PE_TERM; 99 return PE_TERM;
86} 100}
87 101
102#define YY_USER_ACTION \
103do { \
104 yylloc->last_column = yylloc->first_column; \
105 yylloc->first_column = yycolumn; \
106 yycolumn += yyleng; \
107} while (0);
108
88%} 109%}
89 110
90%x mem 111%x mem
@@ -119,6 +140,12 @@ modifier_bp [rwx]{1,3}
119 140
120 if (start_token) { 141 if (start_token) {
121 parse_events_set_extra(NULL, yyscanner); 142 parse_events_set_extra(NULL, yyscanner);
143 /*
144 * The flex parser does not init locations variable
145 * via the scan_string interface, so we need do the
146 * init in here.
147 */
148 yycolumn = 0;
122 return start_token; 149 return start_token;
123 } 150 }
124 } 151 }
@@ -127,24 +154,30 @@ modifier_bp [rwx]{1,3}
127<event>{ 154<event>{
128 155
129{group} { 156{group} {
130 BEGIN(INITIAL); yyless(0); 157 BEGIN(INITIAL);
158 REWIND(0);
131 } 159 }
132 160
133{event_pmu} | 161{event_pmu} |
134{event} { 162{event} {
135 str(yyscanner, PE_EVENT_NAME); 163 BEGIN(INITIAL);
136 BEGIN(INITIAL); yyless(0); 164 REWIND(1);
137 return PE_EVENT_NAME; 165 return PE_EVENT_NAME;
138 } 166 }
139 167
140. | 168. |
141<<EOF>> { 169<<EOF>> {
142 BEGIN(INITIAL); yyless(0); 170 BEGIN(INITIAL);
171 REWIND(0);
143 } 172 }
144 173
145} 174}
146 175
147<config>{ 176<config>{
177 /*
178 * Please update formats_error_string any time
179 * new static term is added.
180 */
148config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); } 181config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
149config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); } 182config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
150config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); } 183config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 72def077dbbf..591905a02b92 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -2,6 +2,7 @@
2%parse-param {void *_data} 2%parse-param {void *_data}
3%parse-param {void *scanner} 3%parse-param {void *scanner}
4%lex-param {void* scanner} 4%lex-param {void* scanner}
5%locations
5 6
6%{ 7%{
7 8
@@ -14,8 +15,6 @@
14#include "parse-events.h" 15#include "parse-events.h"
15#include "parse-events-bison.h" 16#include "parse-events-bison.h"
16 17
17extern int parse_events_lex (YYSTYPE* lvalp, void* scanner);
18
19#define ABORT_ON(val) \ 18#define ABORT_ON(val) \
20do { \ 19do { \
21 if (val) \ 20 if (val) \
@@ -208,7 +207,7 @@ PE_NAME '/' event_config '/'
208 struct list_head *list; 207 struct list_head *list;
209 208
210 ALLOC_LIST(list); 209 ALLOC_LIST(list);
211 ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, $3)); 210 ABORT_ON(parse_events_add_pmu(data, list, $1, $3));
212 parse_events__free_terms($3); 211 parse_events__free_terms($3);
213 $$ = list; 212 $$ = list;
214} 213}
@@ -219,7 +218,7 @@ PE_NAME '/' '/'
219 struct list_head *list; 218 struct list_head *list;
220 219
221 ALLOC_LIST(list); 220 ALLOC_LIST(list);
222 ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, NULL)); 221 ABORT_ON(parse_events_add_pmu(data, list, $1, NULL));
223 $$ = list; 222 $$ = list;
224} 223}
225| 224|
@@ -232,11 +231,11 @@ PE_KERNEL_PMU_EVENT sep_dc
232 231
233 ALLOC_LIST(head); 232 ALLOC_LIST(head);
234 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 233 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
235 $1, 1)); 234 $1, 1, &@1, NULL));
236 list_add_tail(&term->list, head); 235 list_add_tail(&term->list, head);
237 236
238 ALLOC_LIST(list); 237 ALLOC_LIST(list);
239 ABORT_ON(parse_events_add_pmu(list, &data->idx, "cpu", head)); 238 ABORT_ON(parse_events_add_pmu(data, list, "cpu", head));
240 parse_events__free_terms(head); 239 parse_events__free_terms(head);
241 $$ = list; 240 $$ = list;
242} 241}
@@ -252,7 +251,7 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
252 251
253 ALLOC_LIST(head); 252 ALLOC_LIST(head);
254 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 253 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
255 &pmu_name, 1)); 254 &pmu_name, 1, &@1, NULL));
256 list_add_tail(&term->list, head); 255 list_add_tail(&term->list, head);
257 256
258 ALLOC_LIST(list); 257 ALLOC_LIST(list);
@@ -275,8 +274,7 @@ value_sym '/' event_config '/'
275 int config = $1 & 255; 274 int config = $1 & 255;
276 275
277 ALLOC_LIST(list); 276 ALLOC_LIST(list);
278 ABORT_ON(parse_events_add_numeric(list, &data->idx, 277 ABORT_ON(parse_events_add_numeric(data, list, type, config, $3));
279 type, config, $3));
280 parse_events__free_terms($3); 278 parse_events__free_terms($3);
281 $$ = list; 279 $$ = list;
282} 280}
@@ -289,8 +287,7 @@ value_sym sep_slash_dc
289 int config = $1 & 255; 287 int config = $1 & 255;
290 288
291 ALLOC_LIST(list); 289 ALLOC_LIST(list);
292 ABORT_ON(parse_events_add_numeric(list, &data->idx, 290 ABORT_ON(parse_events_add_numeric(data, list, type, config, NULL));
293 type, config, NULL));
294 $$ = list; 291 $$ = list;
295} 292}
296 293
@@ -389,7 +386,15 @@ PE_NAME ':' PE_NAME
389 struct list_head *list; 386 struct list_head *list;
390 387
391 ALLOC_LIST(list); 388 ALLOC_LIST(list);
392 ABORT_ON(parse_events_add_tracepoint(list, &data->idx, $1, $3)); 389 if (parse_events_add_tracepoint(list, &data->idx, $1, $3)) {
390 struct parse_events_error *error = data->error;
391
392 if (error) {
393 error->idx = @1.first_column;
394 error->str = strdup("unknown tracepoint");
395 }
396 return -1;
397 }
393 $$ = list; 398 $$ = list;
394} 399}
395 400
@@ -400,7 +405,7 @@ PE_VALUE ':' PE_VALUE
400 struct list_head *list; 405 struct list_head *list;
401 406
402 ALLOC_LIST(list); 407 ALLOC_LIST(list);
403 ABORT_ON(parse_events_add_numeric(list, &data->idx, (u32)$1, $3, NULL)); 408 ABORT_ON(parse_events_add_numeric(data, list, (u32)$1, $3, NULL));
404 $$ = list; 409 $$ = list;
405} 410}
406 411
@@ -411,8 +416,7 @@ PE_RAW
411 struct list_head *list; 416 struct list_head *list;
412 417
413 ALLOC_LIST(list); 418 ALLOC_LIST(list);
414 ABORT_ON(parse_events_add_numeric(list, &data->idx, 419 ABORT_ON(parse_events_add_numeric(data, list, PERF_TYPE_RAW, $1, NULL));
415 PERF_TYPE_RAW, $1, NULL));
416 $$ = list; 420 $$ = list;
417} 421}
418 422
@@ -450,7 +454,7 @@ PE_NAME '=' PE_NAME
450 struct parse_events_term *term; 454 struct parse_events_term *term;
451 455
452 ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 456 ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
453 $1, $3)); 457 $1, $3, &@1, &@3));
454 $$ = term; 458 $$ = term;
455} 459}
456| 460|
@@ -459,7 +463,7 @@ PE_NAME '=' PE_VALUE
459 struct parse_events_term *term; 463 struct parse_events_term *term;
460 464
461 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 465 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
462 $1, $3)); 466 $1, $3, &@1, &@3));
463 $$ = term; 467 $$ = term;
464} 468}
465| 469|
@@ -477,7 +481,7 @@ PE_NAME
477 struct parse_events_term *term; 481 struct parse_events_term *term;
478 482
479 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 483 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
480 $1, 1)); 484 $1, 1, &@1, NULL));
481 $$ = term; 485 $$ = term;
482} 486}
483| 487|
@@ -494,7 +498,7 @@ PE_TERM '=' PE_NAME
494{ 498{
495 struct parse_events_term *term; 499 struct parse_events_term *term;
496 500
497 ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3)); 501 ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3));
498 $$ = term; 502 $$ = term;
499} 503}
500| 504|
@@ -502,7 +506,7 @@ PE_TERM '=' PE_VALUE
502{ 506{
503 struct parse_events_term *term; 507 struct parse_events_term *term;
504 508
505 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3)); 509 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, &@1, &@3));
506 $$ = term; 510 $$ = term;
507} 511}
508| 512|
@@ -510,7 +514,7 @@ PE_TERM
510{ 514{
511 struct parse_events_term *term; 515 struct parse_events_term *term;
512 516
513 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1)); 517 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, &@1, NULL));
514 $$ = term; 518 $$ = term;
515} 519}
516 520
@@ -520,7 +524,9 @@ sep_slash_dc: '/' | ':' |
520 524
521%% 525%%
522 526
523void parse_events_error(void *data __maybe_unused, void *scanner __maybe_unused, 527void parse_events_error(YYLTYPE *loc, void *data,
528 void *scanner __maybe_unused,
524 char const *msg __maybe_unused) 529 char const *msg __maybe_unused)
525{ 530{
531 parse_events_evlist_error(data, loc->last_column, "parser error");
526} 532}
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index 59561fd86278..367d8b816cc7 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -123,6 +123,10 @@ struct option {
123#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) } 123#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
124#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) } 124#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
125#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) } 125#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) }
126#define OPT_STRING_OPTARG(s, l, v, a, h, d) \
127 { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \
128 .value = check_vtype(v, const char **), (a), .help = (h), \
129 .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) }
126#define OPT_STRING_NOEMPTY(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY} 130#define OPT_STRING_NOEMPTY(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY}
127#define OPT_DATE(s, l, v, h) \ 131#define OPT_DATE(s, l, v, h) \
128 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } 132 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 48411674da0f..0fcc624eb767 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -112,7 +112,11 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *
112 if (sret < 0) 112 if (sret < 0)
113 goto error; 113 goto error;
114 114
115 scale[sret] = '\0'; 115 if (scale[sret - 1] == '\n')
116 scale[sret - 1] = '\0';
117 else
118 scale[sret] = '\0';
119
116 /* 120 /*
117 * save current locale 121 * save current locale
118 */ 122 */
@@ -154,7 +158,10 @@ static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *n
154 158
155 close(fd); 159 close(fd);
156 160
157 alias->unit[sret] = '\0'; 161 if (alias->unit[sret - 1] == '\n')
162 alias->unit[sret - 1] = '\0';
163 else
164 alias->unit[sret] = '\0';
158 165
159 return 0; 166 return 0;
160error: 167error:
@@ -442,6 +449,10 @@ static struct perf_pmu *pmu_lookup(const char *name)
442 LIST_HEAD(aliases); 449 LIST_HEAD(aliases);
443 __u32 type; 450 __u32 type;
444 451
452 /* No support for intel_bts or intel_pt so disallow them */
453 if (!strcmp(name, "intel_bts") || !strcmp(name, "intel_pt"))
454 return NULL;
455
445 /* 456 /*
446 * The pmu data we store & need consists of the pmu 457 * The pmu data we store & need consists of the pmu
447 * type value and format definitions. Load both right 458 * type value and format definitions. Load both right
@@ -579,6 +590,38 @@ static int pmu_resolve_param_term(struct parse_events_term *term,
579 return -1; 590 return -1;
580} 591}
581 592
593static char *formats_error_string(struct list_head *formats)
594{
595 struct perf_pmu_format *format;
596 char *err, *str;
597 static const char *static_terms = "config,config1,config2,name,period,branch_type\n";
598 unsigned i = 0;
599
600 if (!asprintf(&str, "valid terms:"))
601 return NULL;
602
603 /* sysfs exported terms */
604 list_for_each_entry(format, formats, list) {
605 char c = i++ ? ',' : ' ';
606
607 err = str;
608 if (!asprintf(&str, "%s%c%s", err, c, format->name))
609 goto fail;
610 free(err);
611 }
612
613 /* static terms */
614 err = str;
615 if (!asprintf(&str, "%s,%s", err, static_terms))
616 goto fail;
617
618 free(err);
619 return str;
620fail:
621 free(err);
622 return NULL;
623}
624
582/* 625/*
583 * Setup one of config[12] attr members based on the 626 * Setup one of config[12] attr members based on the
584 * user input data - term parameter. 627 * user input data - term parameter.
@@ -587,7 +630,7 @@ static int pmu_config_term(struct list_head *formats,
587 struct perf_event_attr *attr, 630 struct perf_event_attr *attr,
588 struct parse_events_term *term, 631 struct parse_events_term *term,
589 struct list_head *head_terms, 632 struct list_head *head_terms,
590 bool zero) 633 bool zero, struct parse_events_error *err)
591{ 634{
592 struct perf_pmu_format *format; 635 struct perf_pmu_format *format;
593 __u64 *vp; 636 __u64 *vp;
@@ -611,6 +654,11 @@ static int pmu_config_term(struct list_head *formats,
611 if (!format) { 654 if (!format) {
612 if (verbose) 655 if (verbose)
613 printf("Invalid event/parameter '%s'\n", term->config); 656 printf("Invalid event/parameter '%s'\n", term->config);
657 if (err) {
658 err->idx = term->err_term;
659 err->str = strdup("unknown term");
660 err->help = formats_error_string(formats);
661 }
614 return -EINVAL; 662 return -EINVAL;
615 } 663 }
616 664
@@ -636,9 +684,14 @@ static int pmu_config_term(struct list_head *formats,
636 val = term->val.num; 684 val = term->val.num;
637 else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 685 else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
638 if (strcmp(term->val.str, "?")) { 686 if (strcmp(term->val.str, "?")) {
639 if (verbose) 687 if (verbose) {
640 pr_info("Invalid sysfs entry %s=%s\n", 688 pr_info("Invalid sysfs entry %s=%s\n",
641 term->config, term->val.str); 689 term->config, term->val.str);
690 }
691 if (err) {
692 err->idx = term->err_val;
693 err->str = strdup("expected numeric value");
694 }
642 return -EINVAL; 695 return -EINVAL;
643 } 696 }
644 697
@@ -654,12 +707,13 @@ static int pmu_config_term(struct list_head *formats,
654int perf_pmu__config_terms(struct list_head *formats, 707int perf_pmu__config_terms(struct list_head *formats,
655 struct perf_event_attr *attr, 708 struct perf_event_attr *attr,
656 struct list_head *head_terms, 709 struct list_head *head_terms,
657 bool zero) 710 bool zero, struct parse_events_error *err)
658{ 711{
659 struct parse_events_term *term; 712 struct parse_events_term *term;
660 713
661 list_for_each_entry(term, head_terms, list) { 714 list_for_each_entry(term, head_terms, list) {
662 if (pmu_config_term(formats, attr, term, head_terms, zero)) 715 if (pmu_config_term(formats, attr, term, head_terms,
716 zero, err))
663 return -EINVAL; 717 return -EINVAL;
664 } 718 }
665 719
@@ -672,12 +726,14 @@ int perf_pmu__config_terms(struct list_head *formats,
672 * 2) pmu format definitions - specified by pmu parameter 726 * 2) pmu format definitions - specified by pmu parameter
673 */ 727 */
674int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 728int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
675 struct list_head *head_terms) 729 struct list_head *head_terms,
730 struct parse_events_error *err)
676{ 731{
677 bool zero = !!pmu->default_config; 732 bool zero = !!pmu->default_config;
678 733
679 attr->type = pmu->type; 734 attr->type = pmu->type;
680 return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero); 735 return perf_pmu__config_terms(&pmu->format, attr, head_terms,
736 zero, err);
681} 737}
682 738
683static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 739static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 6b1249fbdb5f..7b9c8cf8ae3e 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -4,6 +4,7 @@
4#include <linux/bitmap.h> 4#include <linux/bitmap.h>
5#include <linux/perf_event.h> 5#include <linux/perf_event.h>
6#include <stdbool.h> 6#include <stdbool.h>
7#include "parse-events.h"
7 8
8enum { 9enum {
9 PERF_PMU_FORMAT_VALUE_CONFIG, 10 PERF_PMU_FORMAT_VALUE_CONFIG,
@@ -47,11 +48,12 @@ struct perf_pmu_alias {
47 48
48struct perf_pmu *perf_pmu__find(const char *name); 49struct perf_pmu *perf_pmu__find(const char *name);
49int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 50int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
50 struct list_head *head_terms); 51 struct list_head *head_terms,
52 struct parse_events_error *error);
51int perf_pmu__config_terms(struct list_head *formats, 53int perf_pmu__config_terms(struct list_head *formats,
52 struct perf_event_attr *attr, 54 struct perf_event_attr *attr,
53 struct list_head *head_terms, 55 struct list_head *head_terms,
54 bool zero); 56 bool zero, struct parse_events_error *error);
55int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 57int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
56 struct perf_pmu_info *info); 58 struct perf_pmu_info *info);
57struct list_head *perf_pmu__alias(struct perf_pmu *pmu, 59struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index d05b77cf35f7..076527b639bd 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -51,6 +51,7 @@
51#define PERFPROBE_GROUP "probe" 51#define PERFPROBE_GROUP "probe"
52 52
53bool probe_event_dry_run; /* Dry run flag */ 53bool probe_event_dry_run; /* Dry run flag */
54struct probe_conf probe_conf;
54 55
55#define semantic_error(msg ...) pr_err("Semantic error :" msg) 56#define semantic_error(msg ...) pr_err("Semantic error :" msg)
56 57
@@ -161,18 +162,18 @@ static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc)
161 162
162static struct map *kernel_get_module_map(const char *module) 163static struct map *kernel_get_module_map(const char *module)
163{ 164{
164 struct rb_node *nd;
165 struct map_groups *grp = &host_machine->kmaps; 165 struct map_groups *grp = &host_machine->kmaps;
166 struct maps *maps = &grp->maps[MAP__FUNCTION];
167 struct map *pos;
166 168
167 /* A file path -- this is an offline module */ 169 /* A file path -- this is an offline module */
168 if (module && strchr(module, '/')) 170 if (module && strchr(module, '/'))
169 return machine__new_module(host_machine, 0, module); 171 return machine__findnew_module_map(host_machine, 0, module);
170 172
171 if (!module) 173 if (!module)
172 module = "kernel"; 174 module = "kernel";
173 175
174 for (nd = rb_first(&grp->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) { 176 for (pos = maps__first(maps); pos; pos = map__next(pos)) {
175 struct map *pos = rb_entry(nd, struct map, rb_node);
176 if (strncmp(pos->dso->short_name + 1, module, 177 if (strncmp(pos->dso->short_name + 1, module,
177 pos->dso->short_name_len - 2) == 0) { 178 pos->dso->short_name_len - 2) == 0) {
178 return pos; 179 return pos;
@@ -194,52 +195,11 @@ static void put_target_map(struct map *map, bool user)
194{ 195{
195 if (map && user) { 196 if (map && user) {
196 /* Only the user map needs to be released */ 197 /* Only the user map needs to be released */
197 dso__delete(map->dso); 198 map__put(map);
198 map__delete(map);
199 } 199 }
200} 200}
201 201
202 202
203static struct dso *kernel_get_module_dso(const char *module)
204{
205 struct dso *dso;
206 struct map *map;
207 const char *vmlinux_name;
208
209 if (module) {
210 list_for_each_entry(dso, &host_machine->kernel_dsos.head,
211 node) {
212 if (strncmp(dso->short_name + 1, module,
213 dso->short_name_len - 2) == 0)
214 goto found;
215 }
216 pr_debug("Failed to find module %s.\n", module);
217 return NULL;
218 }
219
220 map = host_machine->vmlinux_maps[MAP__FUNCTION];
221 dso = map->dso;
222
223 vmlinux_name = symbol_conf.vmlinux_name;
224 if (vmlinux_name) {
225 if (dso__load_vmlinux(dso, map, vmlinux_name, false, NULL) <= 0)
226 return NULL;
227 } else {
228 if (dso__load_vmlinux_path(dso, map, NULL) <= 0) {
229 pr_debug("Failed to load kernel map.\n");
230 return NULL;
231 }
232 }
233found:
234 return dso;
235}
236
237const char *kernel_get_module_path(const char *module)
238{
239 struct dso *dso = kernel_get_module_dso(module);
240 return (dso) ? dso->long_name : NULL;
241}
242
243static int convert_exec_to_group(const char *exec, char **result) 203static int convert_exec_to_group(const char *exec, char **result)
244{ 204{
245 char *ptr1, *ptr2, *exec_copy; 205 char *ptr1, *ptr2, *exec_copy;
@@ -286,7 +246,55 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
286 clear_probe_trace_event(tevs + i); 246 clear_probe_trace_event(tevs + i);
287} 247}
288 248
249static bool kprobe_blacklist__listed(unsigned long address);
250static bool kprobe_warn_out_range(const char *symbol, unsigned long address)
251{
252 /* Get the address of _etext for checking non-probable text symbol */
253 if (kernel_get_symbol_address_by_name("_etext", false) < address)
254 pr_warning("%s is out of .text, skip it.\n", symbol);
255 else if (kprobe_blacklist__listed(address))
256 pr_warning("%s is blacklisted function, skip it.\n", symbol);
257 else
258 return false;
259
260 return true;
261}
262
289#ifdef HAVE_DWARF_SUPPORT 263#ifdef HAVE_DWARF_SUPPORT
264
265static int kernel_get_module_dso(const char *module, struct dso **pdso)
266{
267 struct dso *dso;
268 struct map *map;
269 const char *vmlinux_name;
270 int ret = 0;
271
272 if (module) {
273 list_for_each_entry(dso, &host_machine->dsos.head, node) {
274 if (!dso->kernel)
275 continue;
276 if (strncmp(dso->short_name + 1, module,
277 dso->short_name_len - 2) == 0)
278 goto found;
279 }
280 pr_debug("Failed to find module %s.\n", module);
281 return -ENOENT;
282 }
283
284 map = host_machine->vmlinux_maps[MAP__FUNCTION];
285 dso = map->dso;
286
287 vmlinux_name = symbol_conf.vmlinux_name;
288 dso->load_errno = 0;
289 if (vmlinux_name)
290 ret = dso__load_vmlinux(dso, map, vmlinux_name, false, NULL);
291 else
292 ret = dso__load_vmlinux_path(dso, map, NULL);
293found:
294 *pdso = dso;
295 return ret;
296}
297
290/* 298/*
291 * Some binaries like glibc have special symbols which are on the symbol 299 * Some binaries like glibc have special symbols which are on the symbol
292 * table, but not in the debuginfo. If we can find the address of the 300 * table, but not in the debuginfo. If we can find the address of the
@@ -344,15 +352,14 @@ out:
344 352
345static int get_alternative_probe_event(struct debuginfo *dinfo, 353static int get_alternative_probe_event(struct debuginfo *dinfo,
346 struct perf_probe_event *pev, 354 struct perf_probe_event *pev,
347 struct perf_probe_point *tmp, 355 struct perf_probe_point *tmp)
348 const char *target)
349{ 356{
350 int ret; 357 int ret;
351 358
352 memcpy(tmp, &pev->point, sizeof(*tmp)); 359 memcpy(tmp, &pev->point, sizeof(*tmp));
353 memset(&pev->point, 0, sizeof(pev->point)); 360 memset(&pev->point, 0, sizeof(pev->point));
354 ret = find_alternative_probe_point(dinfo, tmp, &pev->point, 361 ret = find_alternative_probe_point(dinfo, tmp, &pev->point,
355 target, pev->uprobes); 362 pev->target, pev->uprobes);
356 if (ret < 0) 363 if (ret < 0)
357 memcpy(&pev->point, tmp, sizeof(*tmp)); 364 memcpy(&pev->point, tmp, sizeof(*tmp));
358 365
@@ -390,16 +397,25 @@ static int get_alternative_line_range(struct debuginfo *dinfo,
390static struct debuginfo *open_debuginfo(const char *module, bool silent) 397static struct debuginfo *open_debuginfo(const char *module, bool silent)
391{ 398{
392 const char *path = module; 399 const char *path = module;
393 struct debuginfo *ret; 400 char reason[STRERR_BUFSIZE];
401 struct debuginfo *ret = NULL;
402 struct dso *dso = NULL;
403 int err;
394 404
395 if (!module || !strchr(module, '/')) { 405 if (!module || !strchr(module, '/')) {
396 path = kernel_get_module_path(module); 406 err = kernel_get_module_dso(module, &dso);
397 if (!path) { 407 if (err < 0) {
408 if (!dso || dso->load_errno == 0) {
409 if (!strerror_r(-err, reason, STRERR_BUFSIZE))
410 strcpy(reason, "(unknown)");
411 } else
412 dso__strerror_load(dso, reason, STRERR_BUFSIZE);
398 if (!silent) 413 if (!silent)
399 pr_err("Failed to find path of %s module.\n", 414 pr_err("Failed to find the path for %s: %s\n",
400 module ?: "kernel"); 415 module ?: "kernel", reason);
401 return NULL; 416 return NULL;
402 } 417 }
418 path = dso->long_name;
403 } 419 }
404 ret = debuginfo__new(path); 420 ret = debuginfo__new(path);
405 if (!ret && !silent) { 421 if (!ret && !silent) {
@@ -413,6 +429,41 @@ static struct debuginfo *open_debuginfo(const char *module, bool silent)
413 return ret; 429 return ret;
414} 430}
415 431
432/* For caching the last debuginfo */
433static struct debuginfo *debuginfo_cache;
434static char *debuginfo_cache_path;
435
436static struct debuginfo *debuginfo_cache__open(const char *module, bool silent)
437{
438 if ((debuginfo_cache_path && !strcmp(debuginfo_cache_path, module)) ||
439 (!debuginfo_cache_path && !module && debuginfo_cache))
440 goto out;
441
442 /* Copy module path */
443 free(debuginfo_cache_path);
444 if (module) {
445 debuginfo_cache_path = strdup(module);
446 if (!debuginfo_cache_path) {
447 debuginfo__delete(debuginfo_cache);
448 debuginfo_cache = NULL;
449 goto out;
450 }
451 }
452
453 debuginfo_cache = open_debuginfo(module, silent);
454 if (!debuginfo_cache)
455 zfree(&debuginfo_cache_path);
456out:
457 return debuginfo_cache;
458}
459
460static void debuginfo_cache__exit(void)
461{
462 debuginfo__delete(debuginfo_cache);
463 debuginfo_cache = NULL;
464 zfree(&debuginfo_cache_path);
465}
466
416 467
417static int get_text_start_address(const char *exec, unsigned long *address) 468static int get_text_start_address(const char *exec, unsigned long *address)
418{ 469{
@@ -474,12 +525,11 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
474 pr_debug("try to find information at %" PRIx64 " in %s\n", addr, 525 pr_debug("try to find information at %" PRIx64 " in %s\n", addr,
475 tp->module ? : "kernel"); 526 tp->module ? : "kernel");
476 527
477 dinfo = open_debuginfo(tp->module, verbose == 0); 528 dinfo = debuginfo_cache__open(tp->module, verbose == 0);
478 if (dinfo) { 529 if (dinfo)
479 ret = debuginfo__find_probe_point(dinfo, 530 ret = debuginfo__find_probe_point(dinfo,
480 (unsigned long)addr, pp); 531 (unsigned long)addr, pp);
481 debuginfo__delete(dinfo); 532 else
482 } else
483 ret = -ENOENT; 533 ret = -ENOENT;
484 534
485 if (ret > 0) { 535 if (ret > 0) {
@@ -558,7 +608,7 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,
558{ 608{
559 struct ref_reloc_sym *reloc_sym; 609 struct ref_reloc_sym *reloc_sym;
560 char *tmp; 610 char *tmp;
561 int i; 611 int i, skipped = 0;
562 612
563 if (uprobe) 613 if (uprobe)
564 return add_exec_to_probe_trace_events(tevs, ntevs, module); 614 return add_exec_to_probe_trace_events(tevs, ntevs, module);
@@ -574,31 +624,40 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,
574 } 624 }
575 625
576 for (i = 0; i < ntevs; i++) { 626 for (i = 0; i < ntevs; i++) {
577 if (tevs[i].point.address && !tevs[i].point.retprobe) { 627 if (!tevs[i].point.address || tevs[i].point.retprobe)
628 continue;
629 /* If we found a wrong one, mark it by NULL symbol */
630 if (kprobe_warn_out_range(tevs[i].point.symbol,
631 tevs[i].point.address)) {
632 tmp = NULL;
633 skipped++;
634 } else {
578 tmp = strdup(reloc_sym->name); 635 tmp = strdup(reloc_sym->name);
579 if (!tmp) 636 if (!tmp)
580 return -ENOMEM; 637 return -ENOMEM;
581 free(tevs[i].point.symbol);
582 tevs[i].point.symbol = tmp;
583 tevs[i].point.offset = tevs[i].point.address -
584 reloc_sym->unrelocated_addr;
585 } 638 }
639 /* If we have no realname, use symbol for it */
640 if (!tevs[i].point.realname)
641 tevs[i].point.realname = tevs[i].point.symbol;
642 else
643 free(tevs[i].point.symbol);
644 tevs[i].point.symbol = tmp;
645 tevs[i].point.offset = tevs[i].point.address -
646 reloc_sym->unrelocated_addr;
586 } 647 }
587 return 0; 648 return skipped;
588} 649}
589 650
590/* Try to find perf_probe_event with debuginfo */ 651/* Try to find perf_probe_event with debuginfo */
591static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 652static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
592 struct probe_trace_event **tevs, 653 struct probe_trace_event **tevs)
593 int max_tevs, const char *target)
594{ 654{
595 bool need_dwarf = perf_probe_event_need_dwarf(pev); 655 bool need_dwarf = perf_probe_event_need_dwarf(pev);
596 struct perf_probe_point tmp; 656 struct perf_probe_point tmp;
597 struct debuginfo *dinfo; 657 struct debuginfo *dinfo;
598 int ntevs, ret = 0; 658 int ntevs, ret = 0;
599 659
600 dinfo = open_debuginfo(target, !need_dwarf); 660 dinfo = open_debuginfo(pev->target, !need_dwarf);
601
602 if (!dinfo) { 661 if (!dinfo) {
603 if (need_dwarf) 662 if (need_dwarf)
604 return -ENOENT; 663 return -ENOENT;
@@ -608,13 +667,12 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
608 667
609 pr_debug("Try to find probe point from debuginfo.\n"); 668 pr_debug("Try to find probe point from debuginfo.\n");
610 /* Searching trace events corresponding to a probe event */ 669 /* Searching trace events corresponding to a probe event */
611 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs); 670 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs);
612 671
613 if (ntevs == 0) { /* Not found, retry with an alternative */ 672 if (ntevs == 0) { /* Not found, retry with an alternative */
614 ret = get_alternative_probe_event(dinfo, pev, &tmp, target); 673 ret = get_alternative_probe_event(dinfo, pev, &tmp);
615 if (!ret) { 674 if (!ret) {
616 ntevs = debuginfo__find_trace_events(dinfo, pev, 675 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs);
617 tevs, max_tevs);
618 /* 676 /*
619 * Write back to the original probe_event for 677 * Write back to the original probe_event for
620 * setting appropriate (user given) event name 678 * setting appropriate (user given) event name
@@ -629,12 +687,15 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
629 if (ntevs > 0) { /* Succeeded to find trace events */ 687 if (ntevs > 0) { /* Succeeded to find trace events */
630 pr_debug("Found %d probe_trace_events.\n", ntevs); 688 pr_debug("Found %d probe_trace_events.\n", ntevs);
631 ret = post_process_probe_trace_events(*tevs, ntevs, 689 ret = post_process_probe_trace_events(*tevs, ntevs,
632 target, pev->uprobes); 690 pev->target, pev->uprobes);
633 if (ret < 0) { 691 if (ret < 0 || ret == ntevs) {
634 clear_probe_trace_events(*tevs, ntevs); 692 clear_probe_trace_events(*tevs, ntevs);
635 zfree(tevs); 693 zfree(tevs);
636 } 694 }
637 return ret < 0 ? ret : ntevs; 695 if (ret != ntevs)
696 return ret < 0 ? ret : ntevs;
697 ntevs = 0;
698 /* Fall through */
638 } 699 }
639 700
640 if (ntevs == 0) { /* No error but failed to find probe point. */ 701 if (ntevs == 0) { /* No error but failed to find probe point. */
@@ -809,8 +870,7 @@ int show_line_range(struct line_range *lr, const char *module, bool user)
809 870
810static int show_available_vars_at(struct debuginfo *dinfo, 871static int show_available_vars_at(struct debuginfo *dinfo,
811 struct perf_probe_event *pev, 872 struct perf_probe_event *pev,
812 int max_vls, struct strfilter *_filter, 873 struct strfilter *_filter)
813 bool externs, const char *target)
814{ 874{
815 char *buf; 875 char *buf;
816 int ret, i, nvars; 876 int ret, i, nvars;
@@ -824,13 +884,12 @@ static int show_available_vars_at(struct debuginfo *dinfo,
824 return -EINVAL; 884 return -EINVAL;
825 pr_debug("Searching variables at %s\n", buf); 885 pr_debug("Searching variables at %s\n", buf);
826 886
827 ret = debuginfo__find_available_vars_at(dinfo, pev, &vls, 887 ret = debuginfo__find_available_vars_at(dinfo, pev, &vls);
828 max_vls, externs);
829 if (!ret) { /* Not found, retry with an alternative */ 888 if (!ret) { /* Not found, retry with an alternative */
830 ret = get_alternative_probe_event(dinfo, pev, &tmp, target); 889 ret = get_alternative_probe_event(dinfo, pev, &tmp);
831 if (!ret) { 890 if (!ret) {
832 ret = debuginfo__find_available_vars_at(dinfo, pev, 891 ret = debuginfo__find_available_vars_at(dinfo, pev,
833 &vls, max_vls, externs); 892 &vls);
834 /* Release the old probe_point */ 893 /* Release the old probe_point */
835 clear_perf_probe_point(&tmp); 894 clear_perf_probe_point(&tmp);
836 } 895 }
@@ -877,8 +936,7 @@ end:
877 936
878/* Show available variables on given probe point */ 937/* Show available variables on given probe point */
879int show_available_vars(struct perf_probe_event *pevs, int npevs, 938int show_available_vars(struct perf_probe_event *pevs, int npevs,
880 int max_vls, const char *module, 939 struct strfilter *_filter)
881 struct strfilter *_filter, bool externs)
882{ 940{
883 int i, ret = 0; 941 int i, ret = 0;
884 struct debuginfo *dinfo; 942 struct debuginfo *dinfo;
@@ -887,7 +945,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
887 if (ret < 0) 945 if (ret < 0)
888 return ret; 946 return ret;
889 947
890 dinfo = open_debuginfo(module, false); 948 dinfo = open_debuginfo(pevs->target, false);
891 if (!dinfo) { 949 if (!dinfo) {
892 ret = -ENOENT; 950 ret = -ENOENT;
893 goto out; 951 goto out;
@@ -896,8 +954,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
896 setup_pager(); 954 setup_pager();
897 955
898 for (i = 0; i < npevs && ret >= 0; i++) 956 for (i = 0; i < npevs && ret >= 0; i++)
899 ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter, 957 ret = show_available_vars_at(dinfo, &pevs[i], _filter);
900 externs, module);
901 958
902 debuginfo__delete(dinfo); 959 debuginfo__delete(dinfo);
903out: 960out:
@@ -907,6 +964,10 @@ out:
907 964
908#else /* !HAVE_DWARF_SUPPORT */ 965#else /* !HAVE_DWARF_SUPPORT */
909 966
967static void debuginfo_cache__exit(void)
968{
969}
970
910static int 971static int
911find_perf_probe_point_from_dwarf(struct probe_trace_point *tp __maybe_unused, 972find_perf_probe_point_from_dwarf(struct probe_trace_point *tp __maybe_unused,
912 struct perf_probe_point *pp __maybe_unused, 973 struct perf_probe_point *pp __maybe_unused,
@@ -916,9 +977,7 @@ find_perf_probe_point_from_dwarf(struct probe_trace_point *tp __maybe_unused,
916} 977}
917 978
918static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 979static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
919 struct probe_trace_event **tevs __maybe_unused, 980 struct probe_trace_event **tevs __maybe_unused)
920 int max_tevs __maybe_unused,
921 const char *target __maybe_unused)
922{ 981{
923 if (perf_probe_event_need_dwarf(pev)) { 982 if (perf_probe_event_need_dwarf(pev)) {
924 pr_warning("Debuginfo-analysis is not supported.\n"); 983 pr_warning("Debuginfo-analysis is not supported.\n");
@@ -937,10 +996,8 @@ int show_line_range(struct line_range *lr __maybe_unused,
937} 996}
938 997
939int show_available_vars(struct perf_probe_event *pevs __maybe_unused, 998int show_available_vars(struct perf_probe_event *pevs __maybe_unused,
940 int npevs __maybe_unused, int max_vls __maybe_unused, 999 int npevs __maybe_unused,
941 const char *module __maybe_unused, 1000 struct strfilter *filter __maybe_unused)
942 struct strfilter *filter __maybe_unused,
943 bool externs __maybe_unused)
944{ 1001{
945 pr_warning("Debuginfo-analysis is not supported.\n"); 1002 pr_warning("Debuginfo-analysis is not supported.\n");
946 return -ENOSYS; 1003 return -ENOSYS;
@@ -980,6 +1037,18 @@ static int parse_line_num(char **ptr, int *val, const char *what)
980 return 0; 1037 return 0;
981} 1038}
982 1039
1040/* Check the name is good for event, group or function */
1041static bool is_c_func_name(const char *name)
1042{
1043 if (!isalpha(*name) && *name != '_')
1044 return false;
1045 while (*++name != '\0') {
1046 if (!isalpha(*name) && !isdigit(*name) && *name != '_')
1047 return false;
1048 }
1049 return true;
1050}
1051
983/* 1052/*
984 * Stuff 'lr' according to the line range described by 'arg'. 1053 * Stuff 'lr' according to the line range described by 'arg'.
985 * The line range syntax is described by: 1054 * The line range syntax is described by:
@@ -1048,10 +1117,15 @@ int parse_line_range_desc(const char *arg, struct line_range *lr)
1048 goto err; 1117 goto err;
1049 } 1118 }
1050 lr->function = name; 1119 lr->function = name;
1051 } else if (strchr(name, '.')) 1120 } else if (strchr(name, '/') || strchr(name, '.'))
1052 lr->file = name; 1121 lr->file = name;
1053 else 1122 else if (is_c_func_name(name))/* We reuse it for checking funcname */
1054 lr->function = name; 1123 lr->function = name;
1124 else { /* Invalid name */
1125 semantic_error("'%s' is not a valid function name.\n", name);
1126 err = -EINVAL;
1127 goto err;
1128 }
1055 1129
1056 return 0; 1130 return 0;
1057err: 1131err:
@@ -1059,24 +1133,13 @@ err:
1059 return err; 1133 return err;
1060} 1134}
1061 1135
1062/* Check the name is good for event/group */
1063static bool check_event_name(const char *name)
1064{
1065 if (!isalpha(*name) && *name != '_')
1066 return false;
1067 while (*++name != '\0') {
1068 if (!isalpha(*name) && !isdigit(*name) && *name != '_')
1069 return false;
1070 }
1071 return true;
1072}
1073
1074/* Parse probepoint definition. */ 1136/* Parse probepoint definition. */
1075static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) 1137static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
1076{ 1138{
1077 struct perf_probe_point *pp = &pev->point; 1139 struct perf_probe_point *pp = &pev->point;
1078 char *ptr, *tmp; 1140 char *ptr, *tmp;
1079 char c, nc = 0; 1141 char c, nc = 0;
1142 bool file_spec = false;
1080 /* 1143 /*
1081 * <Syntax> 1144 * <Syntax>
1082 * perf probe [EVENT=]SRC[:LN|;PTN] 1145 * perf probe [EVENT=]SRC[:LN|;PTN]
@@ -1095,7 +1158,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
1095 semantic_error("Group name is not supported yet.\n"); 1158 semantic_error("Group name is not supported yet.\n");
1096 return -ENOTSUP; 1159 return -ENOTSUP;
1097 } 1160 }
1098 if (!check_event_name(arg)) { 1161 if (!is_c_func_name(arg)) {
1099 semantic_error("%s is bad for event name -it must " 1162 semantic_error("%s is bad for event name -it must "
1100 "follow C symbol-naming rule.\n", arg); 1163 "follow C symbol-naming rule.\n", arg);
1101 return -EINVAL; 1164 return -EINVAL;
@@ -1107,6 +1170,23 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
1107 arg = tmp; 1170 arg = tmp;
1108 } 1171 }
1109 1172
1173 /*
1174 * Check arg is function or file name and copy it.
1175 *
1176 * We consider arg to be a file spec if and only if it satisfies
1177 * all of the below criteria::
1178 * - it does not include any of "+@%",
1179 * - it includes one of ":;", and
1180 * - it has a period '.' in the name.
1181 *
1182 * Otherwise, we consider arg to be a function specification.
1183 */
1184 if (!strpbrk(arg, "+@%") && (ptr = strpbrk(arg, ";:")) != NULL) {
1185 /* This is a file spec if it includes a '.' before ; or : */
1186 if (memchr(arg, '.', ptr - arg))
1187 file_spec = true;
1188 }
1189
1110 ptr = strpbrk(arg, ";:+@%"); 1190 ptr = strpbrk(arg, ";:+@%");
1111 if (ptr) { 1191 if (ptr) {
1112 nc = *ptr; 1192 nc = *ptr;
@@ -1117,10 +1197,9 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
1117 if (tmp == NULL) 1197 if (tmp == NULL)
1118 return -ENOMEM; 1198 return -ENOMEM;
1119 1199
1120 /* Check arg is function or file and copy it */ 1200 if (file_spec)
1121 if (strchr(tmp, '.')) /* File */
1122 pp->file = tmp; 1201 pp->file = tmp;
1123 else /* Function */ 1202 else
1124 pp->function = tmp; 1203 pp->function = tmp;
1125 1204
1126 /* Parse other options */ 1205 /* Parse other options */
@@ -1762,8 +1841,7 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
1762 1841
1763out: 1842out:
1764 if (map && !is_kprobe) { 1843 if (map && !is_kprobe) {
1765 dso__delete(map->dso); 1844 map__put(map);
1766 map__delete(map);
1767 } 1845 }
1768 1846
1769 return ret; 1847 return ret;
@@ -1877,6 +1955,7 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
1877 free(tev->event); 1955 free(tev->event);
1878 free(tev->group); 1956 free(tev->group);
1879 free(tev->point.symbol); 1957 free(tev->point.symbol);
1958 free(tev->point.realname);
1880 free(tev->point.module); 1959 free(tev->point.module);
1881 for (i = 0; i < tev->nargs; i++) { 1960 for (i = 0; i < tev->nargs; i++) {
1882 free(tev->args[i].name); 1961 free(tev->args[i].name);
@@ -1954,7 +2033,7 @@ static int open_probe_events(const char *trace_file, bool readwrite)
1954 if (ret >= 0) { 2033 if (ret >= 0) {
1955 pr_debug("Opening %s write=%d\n", buf, readwrite); 2034 pr_debug("Opening %s write=%d\n", buf, readwrite);
1956 if (readwrite && !probe_event_dry_run) 2035 if (readwrite && !probe_event_dry_run)
1957 ret = open(buf, O_RDWR, O_APPEND); 2036 ret = open(buf, O_RDWR | O_APPEND, 0);
1958 else 2037 else
1959 ret = open(buf, O_RDONLY, 0); 2038 ret = open(buf, O_RDONLY, 0);
1960 2039
@@ -2095,9 +2174,31 @@ kprobe_blacklist__find_by_address(struct list_head *blacklist,
2095 return NULL; 2174 return NULL;
2096} 2175}
2097 2176
2098/* Show an event */ 2177static LIST_HEAD(kprobe_blacklist);
2099static int show_perf_probe_event(struct perf_probe_event *pev, 2178
2100 const char *module) 2179static void kprobe_blacklist__init(void)
2180{
2181 if (!list_empty(&kprobe_blacklist))
2182 return;
2183
2184 if (kprobe_blacklist__load(&kprobe_blacklist) < 0)
2185 pr_debug("No kprobe blacklist support, ignored\n");
2186}
2187
2188static void kprobe_blacklist__release(void)
2189{
2190 kprobe_blacklist__delete(&kprobe_blacklist);
2191}
2192
2193static bool kprobe_blacklist__listed(unsigned long address)
2194{
2195 return !!kprobe_blacklist__find_by_address(&kprobe_blacklist, address);
2196}
2197
2198static int perf_probe_event__sprintf(const char *group, const char *event,
2199 struct perf_probe_event *pev,
2200 const char *module,
2201 struct strbuf *result)
2101{ 2202{
2102 int i, ret; 2203 int i, ret;
2103 char buf[128]; 2204 char buf[128];
@@ -2108,30 +2209,67 @@ static int show_perf_probe_event(struct perf_probe_event *pev,
2108 if (!place) 2209 if (!place)
2109 return -EINVAL; 2210 return -EINVAL;
2110 2211
2111 ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event); 2212 ret = e_snprintf(buf, 128, "%s:%s", group, event);
2112 if (ret < 0) 2213 if (ret < 0)
2113 return ret; 2214 goto out;
2114 2215
2115 pr_info(" %-20s (on %s", buf, place); 2216 strbuf_addf(result, " %-20s (on %s", buf, place);
2116 if (module) 2217 if (module)
2117 pr_info(" in %s", module); 2218 strbuf_addf(result, " in %s", module);
2118 2219
2119 if (pev->nargs > 0) { 2220 if (pev->nargs > 0) {
2120 pr_info(" with"); 2221 strbuf_addstr(result, " with");
2121 for (i = 0; i < pev->nargs; i++) { 2222 for (i = 0; i < pev->nargs; i++) {
2122 ret = synthesize_perf_probe_arg(&pev->args[i], 2223 ret = synthesize_perf_probe_arg(&pev->args[i],
2123 buf, 128); 2224 buf, 128);
2124 if (ret < 0) 2225 if (ret < 0)
2125 break; 2226 goto out;
2126 pr_info(" %s", buf); 2227 strbuf_addf(result, " %s", buf);
2127 } 2228 }
2128 } 2229 }
2129 pr_info(")\n"); 2230 strbuf_addch(result, ')');
2231out:
2130 free(place); 2232 free(place);
2131 return ret; 2233 return ret;
2132} 2234}
2133 2235
2134static int __show_perf_probe_events(int fd, bool is_kprobe) 2236/* Show an event */
2237static int show_perf_probe_event(const char *group, const char *event,
2238 struct perf_probe_event *pev,
2239 const char *module, bool use_stdout)
2240{
2241 struct strbuf buf = STRBUF_INIT;
2242 int ret;
2243
2244 ret = perf_probe_event__sprintf(group, event, pev, module, &buf);
2245 if (ret >= 0) {
2246 if (use_stdout)
2247 printf("%s\n", buf.buf);
2248 else
2249 pr_info("%s\n", buf.buf);
2250 }
2251 strbuf_release(&buf);
2252
2253 return ret;
2254}
2255
2256static bool filter_probe_trace_event(struct probe_trace_event *tev,
2257 struct strfilter *filter)
2258{
2259 char tmp[128];
2260
2261 /* At first, check the event name itself */
2262 if (strfilter__compare(filter, tev->event))
2263 return true;
2264
2265 /* Next, check the combination of name and group */
2266 if (e_snprintf(tmp, 128, "%s:%s", tev->group, tev->event) < 0)
2267 return false;
2268 return strfilter__compare(filter, tmp);
2269}
2270
2271static int __show_perf_probe_events(int fd, bool is_kprobe,
2272 struct strfilter *filter)
2135{ 2273{
2136 int ret = 0; 2274 int ret = 0;
2137 struct probe_trace_event tev; 2275 struct probe_trace_event tev;
@@ -2149,24 +2287,31 @@ static int __show_perf_probe_events(int fd, bool is_kprobe)
2149 strlist__for_each(ent, rawlist) { 2287 strlist__for_each(ent, rawlist) {
2150 ret = parse_probe_trace_command(ent->s, &tev); 2288 ret = parse_probe_trace_command(ent->s, &tev);
2151 if (ret >= 0) { 2289 if (ret >= 0) {
2290 if (!filter_probe_trace_event(&tev, filter))
2291 goto next;
2152 ret = convert_to_perf_probe_event(&tev, &pev, 2292 ret = convert_to_perf_probe_event(&tev, &pev,
2153 is_kprobe); 2293 is_kprobe);
2154 if (ret >= 0) 2294 if (ret < 0)
2155 ret = show_perf_probe_event(&pev, 2295 goto next;
2156 tev.point.module); 2296 ret = show_perf_probe_event(pev.group, pev.event,
2297 &pev, tev.point.module,
2298 true);
2157 } 2299 }
2300next:
2158 clear_perf_probe_event(&pev); 2301 clear_perf_probe_event(&pev);
2159 clear_probe_trace_event(&tev); 2302 clear_probe_trace_event(&tev);
2160 if (ret < 0) 2303 if (ret < 0)
2161 break; 2304 break;
2162 } 2305 }
2163 strlist__delete(rawlist); 2306 strlist__delete(rawlist);
2307 /* Cleanup cached debuginfo if needed */
2308 debuginfo_cache__exit();
2164 2309
2165 return ret; 2310 return ret;
2166} 2311}
2167 2312
2168/* List up current perf-probe events */ 2313/* List up current perf-probe events */
2169int show_perf_probe_events(void) 2314int show_perf_probe_events(struct strfilter *filter)
2170{ 2315{
2171 int kp_fd, up_fd, ret; 2316 int kp_fd, up_fd, ret;
2172 2317
@@ -2178,7 +2323,7 @@ int show_perf_probe_events(void)
2178 2323
2179 kp_fd = open_kprobe_events(false); 2324 kp_fd = open_kprobe_events(false);
2180 if (kp_fd >= 0) { 2325 if (kp_fd >= 0) {
2181 ret = __show_perf_probe_events(kp_fd, true); 2326 ret = __show_perf_probe_events(kp_fd, true, filter);
2182 close(kp_fd); 2327 close(kp_fd);
2183 if (ret < 0) 2328 if (ret < 0)
2184 goto out; 2329 goto out;
@@ -2192,7 +2337,7 @@ int show_perf_probe_events(void)
2192 } 2337 }
2193 2338
2194 if (up_fd >= 0) { 2339 if (up_fd >= 0) {
2195 ret = __show_perf_probe_events(up_fd, false); 2340 ret = __show_perf_probe_events(up_fd, false, filter);
2196 close(up_fd); 2341 close(up_fd);
2197 } 2342 }
2198out: 2343out:
@@ -2266,6 +2411,10 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2266 struct strlist *namelist, bool allow_suffix) 2411 struct strlist *namelist, bool allow_suffix)
2267{ 2412{
2268 int i, ret; 2413 int i, ret;
2414 char *p;
2415
2416 if (*base == '.')
2417 base++;
2269 2418
2270 /* Try no suffix */ 2419 /* Try no suffix */
2271 ret = e_snprintf(buf, len, "%s", base); 2420 ret = e_snprintf(buf, len, "%s", base);
@@ -2273,6 +2422,10 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2273 pr_debug("snprintf() failed: %d\n", ret); 2422 pr_debug("snprintf() failed: %d\n", ret);
2274 return ret; 2423 return ret;
2275 } 2424 }
2425 /* Cut off the postfixes (e.g. .const, .isra)*/
2426 p = strchr(buf, '.');
2427 if (p && p != buf)
2428 *p = '\0';
2276 if (!strlist__has_entry(namelist, buf)) 2429 if (!strlist__has_entry(namelist, buf))
2277 return 0; 2430 return 0;
2278 2431
@@ -2328,10 +2481,9 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2328 int i, fd, ret; 2481 int i, fd, ret;
2329 struct probe_trace_event *tev = NULL; 2482 struct probe_trace_event *tev = NULL;
2330 char buf[64]; 2483 char buf[64];
2331 const char *event, *group; 2484 const char *event = NULL, *group = NULL;
2332 struct strlist *namelist; 2485 struct strlist *namelist;
2333 LIST_HEAD(blacklist); 2486 bool safename;
2334 struct kprobe_blacklist_node *node;
2335 2487
2336 if (pev->uprobes) 2488 if (pev->uprobes)
2337 fd = open_uprobe_events(true); 2489 fd = open_uprobe_events(true);
@@ -2347,34 +2499,26 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2347 namelist = get_probe_trace_event_names(fd, false); 2499 namelist = get_probe_trace_event_names(fd, false);
2348 if (!namelist) { 2500 if (!namelist) {
2349 pr_debug("Failed to get current event list.\n"); 2501 pr_debug("Failed to get current event list.\n");
2350 return -EIO; 2502 ret = -ENOMEM;
2351 } 2503 goto close_out;
2352 /* Get kprobe blacklist if exists */
2353 if (!pev->uprobes) {
2354 ret = kprobe_blacklist__load(&blacklist);
2355 if (ret < 0)
2356 pr_debug("No kprobe blacklist support, ignored\n");
2357 } 2504 }
2358 2505
2506 safename = (pev->point.function && !strisglob(pev->point.function));
2359 ret = 0; 2507 ret = 0;
2360 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":"); 2508 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
2361 for (i = 0; i < ntevs; i++) { 2509 for (i = 0; i < ntevs; i++) {
2362 tev = &tevs[i]; 2510 tev = &tevs[i];
2363 /* Ensure that the address is NOT blacklisted */ 2511 /* Skip if the symbol is out of .text or blacklisted */
2364 node = kprobe_blacklist__find_by_address(&blacklist, 2512 if (!tev->point.symbol)
2365 tev->point.address);
2366 if (node) {
2367 pr_warning("Warning: Skipped probing on blacklisted function: %s\n", node->symbol);
2368 continue; 2513 continue;
2369 }
2370 2514
2371 if (pev->event) 2515 if (pev->event)
2372 event = pev->event; 2516 event = pev->event;
2373 else 2517 else
2374 if (pev->point.function) 2518 if (safename)
2375 event = pev->point.function; 2519 event = pev->point.function;
2376 else 2520 else
2377 event = tev->point.symbol; 2521 event = tev->point.realname;
2378 if (pev->group) 2522 if (pev->group)
2379 group = pev->group; 2523 group = pev->group;
2380 else 2524 else
@@ -2399,15 +2543,12 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2399 /* Add added event name to namelist */ 2543 /* Add added event name to namelist */
2400 strlist__add(namelist, event); 2544 strlist__add(namelist, event);
2401 2545
2402 /* Trick here - save current event/group */ 2546 /* We use tev's name for showing new events */
2403 event = pev->event; 2547 show_perf_probe_event(tev->group, tev->event, pev,
2404 group = pev->group; 2548 tev->point.module, false);
2405 pev->event = tev->event; 2549 /* Save the last valid name */
2406 pev->group = tev->group; 2550 event = tev->event;
2407 show_perf_probe_event(pev, tev->point.module); 2551 group = tev->group;
2408 /* Trick here - restore current event/group */
2409 pev->event = (char *)event;
2410 pev->group = (char *)group;
2411 2552
2412 /* 2553 /*
2413 * Probes after the first probe which comes from same 2554 * Probes after the first probe which comes from same
@@ -2421,26 +2562,34 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2421 warn_uprobe_event_compat(tev); 2562 warn_uprobe_event_compat(tev);
2422 2563
2423 /* Note that it is possible to skip all events because of blacklist */ 2564 /* Note that it is possible to skip all events because of blacklist */
2424 if (ret >= 0 && tev->event) { 2565 if (ret >= 0 && event) {
2425 /* Show how to use the event. */ 2566 /* Show how to use the event. */
2426 pr_info("\nYou can now use it in all perf tools, such as:\n\n"); 2567 pr_info("\nYou can now use it in all perf tools, such as:\n\n");
2427 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 2568 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", group, event);
2428 tev->event);
2429 } 2569 }
2430 2570
2431 kprobe_blacklist__delete(&blacklist);
2432 strlist__delete(namelist); 2571 strlist__delete(namelist);
2572close_out:
2433 close(fd); 2573 close(fd);
2434 return ret; 2574 return ret;
2435} 2575}
2436 2576
2437static int find_probe_functions(struct map *map, char *name) 2577static int find_probe_functions(struct map *map, char *name,
2578 struct symbol **syms)
2438{ 2579{
2439 int found = 0; 2580 int found = 0;
2440 struct symbol *sym; 2581 struct symbol *sym;
2582 struct rb_node *tmp;
2583
2584 if (map__load(map, NULL) < 0)
2585 return 0;
2441 2586
2442 map__for_each_symbol_by_name(map, name, sym) { 2587 map__for_each_symbol(map, sym, tmp) {
2443 found++; 2588 if (strglobmatch(sym->name, name)) {
2589 found++;
2590 if (syms && found < probe_conf.max_probes)
2591 syms[found - 1] = sym;
2592 }
2444 } 2593 }
2445 2594
2446 return found; 2595 return found;
@@ -2449,42 +2598,52 @@ static int find_probe_functions(struct map *map, char *name)
2449#define strdup_or_goto(str, label) \ 2598#define strdup_or_goto(str, label) \
2450 ({ char *__p = strdup(str); if (!__p) goto label; __p; }) 2599 ({ char *__p = strdup(str); if (!__p) goto label; __p; })
2451 2600
2601void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
2602 struct probe_trace_event *tev __maybe_unused,
2603 struct map *map __maybe_unused) { }
2604
2452/* 2605/*
2453 * Find probe function addresses from map. 2606 * Find probe function addresses from map.
2454 * Return an error or the number of found probe_trace_event 2607 * Return an error or the number of found probe_trace_event
2455 */ 2608 */
2456static int find_probe_trace_events_from_map(struct perf_probe_event *pev, 2609static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2457 struct probe_trace_event **tevs, 2610 struct probe_trace_event **tevs)
2458 int max_tevs, const char *target)
2459{ 2611{
2460 struct map *map = NULL; 2612 struct map *map = NULL;
2461 struct ref_reloc_sym *reloc_sym = NULL; 2613 struct ref_reloc_sym *reloc_sym = NULL;
2462 struct symbol *sym; 2614 struct symbol *sym;
2615 struct symbol **syms = NULL;
2463 struct probe_trace_event *tev; 2616 struct probe_trace_event *tev;
2464 struct perf_probe_point *pp = &pev->point; 2617 struct perf_probe_point *pp = &pev->point;
2465 struct probe_trace_point *tp; 2618 struct probe_trace_point *tp;
2466 int num_matched_functions; 2619 int num_matched_functions;
2467 int ret, i; 2620 int ret, i, j, skipped = 0;
2468 2621
2469 map = get_target_map(target, pev->uprobes); 2622 map = get_target_map(pev->target, pev->uprobes);
2470 if (!map) { 2623 if (!map) {
2471 ret = -EINVAL; 2624 ret = -EINVAL;
2472 goto out; 2625 goto out;
2473 } 2626 }
2474 2627
2628 syms = malloc(sizeof(struct symbol *) * probe_conf.max_probes);
2629 if (!syms) {
2630 ret = -ENOMEM;
2631 goto out;
2632 }
2633
2475 /* 2634 /*
2476 * Load matched symbols: Since the different local symbols may have 2635 * Load matched symbols: Since the different local symbols may have
2477 * same name but different addresses, this lists all the symbols. 2636 * same name but different addresses, this lists all the symbols.
2478 */ 2637 */
2479 num_matched_functions = find_probe_functions(map, pp->function); 2638 num_matched_functions = find_probe_functions(map, pp->function, syms);
2480 if (num_matched_functions == 0) { 2639 if (num_matched_functions == 0) {
2481 pr_err("Failed to find symbol %s in %s\n", pp->function, 2640 pr_err("Failed to find symbol %s in %s\n", pp->function,
2482 target ? : "kernel"); 2641 pev->target ? : "kernel");
2483 ret = -ENOENT; 2642 ret = -ENOENT;
2484 goto out; 2643 goto out;
2485 } else if (num_matched_functions > max_tevs) { 2644 } else if (num_matched_functions > probe_conf.max_probes) {
2486 pr_err("Too many functions matched in %s\n", 2645 pr_err("Too many functions matched in %s\n",
2487 target ? : "kernel"); 2646 pev->target ? : "kernel");
2488 ret = -E2BIG; 2647 ret = -E2BIG;
2489 goto out; 2648 goto out;
2490 } 2649 }
@@ -2507,7 +2666,9 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2507 2666
2508 ret = 0; 2667 ret = 0;
2509 2668
2510 map__for_each_symbol_by_name(map, pp->function, sym) { 2669 for (j = 0; j < num_matched_functions; j++) {
2670 sym = syms[j];
2671
2511 tev = (*tevs) + ret; 2672 tev = (*tevs) + ret;
2512 tp = &tev->point; 2673 tp = &tev->point;
2513 if (ret == num_matched_functions) { 2674 if (ret == num_matched_functions) {
@@ -2524,16 +2685,24 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2524 } 2685 }
2525 /* Add one probe point */ 2686 /* Add one probe point */
2526 tp->address = map->unmap_ip(map, sym->start) + pp->offset; 2687 tp->address = map->unmap_ip(map, sym->start) + pp->offset;
2527 if (reloc_sym) { 2688 /* If we found a wrong one, mark it by NULL symbol */
2689 if (!pev->uprobes &&
2690 kprobe_warn_out_range(sym->name, tp->address)) {
2691 tp->symbol = NULL; /* Skip it */
2692 skipped++;
2693 } else if (reloc_sym) {
2528 tp->symbol = strdup_or_goto(reloc_sym->name, nomem_out); 2694 tp->symbol = strdup_or_goto(reloc_sym->name, nomem_out);
2529 tp->offset = tp->address - reloc_sym->addr; 2695 tp->offset = tp->address - reloc_sym->addr;
2530 } else { 2696 } else {
2531 tp->symbol = strdup_or_goto(sym->name, nomem_out); 2697 tp->symbol = strdup_or_goto(sym->name, nomem_out);
2532 tp->offset = pp->offset; 2698 tp->offset = pp->offset;
2533 } 2699 }
2700 tp->realname = strdup_or_goto(sym->name, nomem_out);
2701
2534 tp->retprobe = pp->retprobe; 2702 tp->retprobe = pp->retprobe;
2535 if (target) 2703 if (pev->target)
2536 tev->point.module = strdup_or_goto(target, nomem_out); 2704 tev->point.module = strdup_or_goto(pev->target,
2705 nomem_out);
2537 tev->uprobes = pev->uprobes; 2706 tev->uprobes = pev->uprobes;
2538 tev->nargs = pev->nargs; 2707 tev->nargs = pev->nargs;
2539 if (tev->nargs) { 2708 if (tev->nargs) {
@@ -2555,10 +2724,16 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2555 strdup_or_goto(pev->args[i].type, 2724 strdup_or_goto(pev->args[i].type,
2556 nomem_out); 2725 nomem_out);
2557 } 2726 }
2727 arch__fix_tev_from_maps(pev, tev, map);
2728 }
2729 if (ret == skipped) {
2730 ret = -ENOENT;
2731 goto err_out;
2558 } 2732 }
2559 2733
2560out: 2734out:
2561 put_target_map(map, pev->uprobes); 2735 put_target_map(map, pev->uprobes);
2736 free(syms);
2562 return ret; 2737 return ret;
2563 2738
2564nomem_out: 2739nomem_out:
@@ -2569,27 +2744,34 @@ err_out:
2569 goto out; 2744 goto out;
2570} 2745}
2571 2746
2747bool __weak arch__prefers_symtab(void) { return false; }
2748
2572static int convert_to_probe_trace_events(struct perf_probe_event *pev, 2749static int convert_to_probe_trace_events(struct perf_probe_event *pev,
2573 struct probe_trace_event **tevs, 2750 struct probe_trace_event **tevs)
2574 int max_tevs, const char *target)
2575{ 2751{
2576 int ret; 2752 int ret;
2577 2753
2578 if (pev->uprobes && !pev->group) { 2754 if (pev->uprobes && !pev->group) {
2579 /* Replace group name if not given */ 2755 /* Replace group name if not given */
2580 ret = convert_exec_to_group(target, &pev->group); 2756 ret = convert_exec_to_group(pev->target, &pev->group);
2581 if (ret != 0) { 2757 if (ret != 0) {
2582 pr_warning("Failed to make a group name.\n"); 2758 pr_warning("Failed to make a group name.\n");
2583 return ret; 2759 return ret;
2584 } 2760 }
2585 } 2761 }
2586 2762
2763 if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {
2764 ret = find_probe_trace_events_from_map(pev, tevs);
2765 if (ret > 0)
2766 return ret; /* Found in symbol table */
2767 }
2768
2587 /* Convert perf_probe_event with debuginfo */ 2769 /* Convert perf_probe_event with debuginfo */
2588 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target); 2770 ret = try_to_find_probe_trace_events(pev, tevs);
2589 if (ret != 0) 2771 if (ret != 0)
2590 return ret; /* Found in debuginfo or got an error */ 2772 return ret; /* Found in debuginfo or got an error */
2591 2773
2592 return find_probe_trace_events_from_map(pev, tevs, max_tevs, target); 2774 return find_probe_trace_events_from_map(pev, tevs);
2593} 2775}
2594 2776
2595struct __event_package { 2777struct __event_package {
@@ -2598,8 +2780,7 @@ struct __event_package {
2598 int ntevs; 2780 int ntevs;
2599}; 2781};
2600 2782
2601int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 2783int add_perf_probe_events(struct perf_probe_event *pevs, int npevs)
2602 int max_tevs, bool force_add)
2603{ 2784{
2604 int i, j, ret; 2785 int i, j, ret;
2605 struct __event_package *pkgs; 2786 struct __event_package *pkgs;
@@ -2619,20 +2800,24 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
2619 /* Loop 1: convert all events */ 2800 /* Loop 1: convert all events */
2620 for (i = 0; i < npevs; i++) { 2801 for (i = 0; i < npevs; i++) {
2621 pkgs[i].pev = &pevs[i]; 2802 pkgs[i].pev = &pevs[i];
2803 /* Init kprobe blacklist if needed */
2804 if (!pkgs[i].pev->uprobes)
2805 kprobe_blacklist__init();
2622 /* Convert with or without debuginfo */ 2806 /* Convert with or without debuginfo */
2623 ret = convert_to_probe_trace_events(pkgs[i].pev, 2807 ret = convert_to_probe_trace_events(pkgs[i].pev,
2624 &pkgs[i].tevs, 2808 &pkgs[i].tevs);
2625 max_tevs,
2626 pkgs[i].pev->target);
2627 if (ret < 0) 2809 if (ret < 0)
2628 goto end; 2810 goto end;
2629 pkgs[i].ntevs = ret; 2811 pkgs[i].ntevs = ret;
2630 } 2812 }
2813 /* This just release blacklist only if allocated */
2814 kprobe_blacklist__release();
2631 2815
2632 /* Loop 2: add all events */ 2816 /* Loop 2: add all events */
2633 for (i = 0; i < npevs; i++) { 2817 for (i = 0; i < npevs; i++) {
2634 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs, 2818 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
2635 pkgs[i].ntevs, force_add); 2819 pkgs[i].ntevs,
2820 probe_conf.force_add);
2636 if (ret < 0) 2821 if (ret < 0)
2637 break; 2822 break;
2638 } 2823 }
@@ -2684,40 +2869,39 @@ error:
2684 return ret; 2869 return ret;
2685} 2870}
2686 2871
2687static int del_trace_probe_event(int fd, const char *buf, 2872static int del_trace_probe_events(int fd, struct strfilter *filter,
2688 struct strlist *namelist) 2873 struct strlist *namelist)
2689{ 2874{
2690 struct str_node *ent, *n; 2875 struct str_node *ent;
2691 int ret = -1; 2876 const char *p;
2877 int ret = -ENOENT;
2692 2878
2693 if (strpbrk(buf, "*?")) { /* Glob-exp */ 2879 if (!namelist)
2694 strlist__for_each_safe(ent, n, namelist) 2880 return -ENOENT;
2695 if (strglobmatch(ent->s, buf)) { 2881
2696 ret = __del_trace_probe_event(fd, ent); 2882 strlist__for_each(ent, namelist) {
2697 if (ret < 0) 2883 p = strchr(ent->s, ':');
2698 break; 2884 if ((p && strfilter__compare(filter, p + 1)) ||
2699 strlist__remove(namelist, ent); 2885 strfilter__compare(filter, ent->s)) {
2700 }
2701 } else {
2702 ent = strlist__find(namelist, buf);
2703 if (ent) {
2704 ret = __del_trace_probe_event(fd, ent); 2886 ret = __del_trace_probe_event(fd, ent);
2705 if (ret >= 0) 2887 if (ret < 0)
2706 strlist__remove(namelist, ent); 2888 break;
2707 } 2889 }
2708 } 2890 }
2709 2891
2710 return ret; 2892 return ret;
2711} 2893}
2712 2894
2713int del_perf_probe_events(struct strlist *dellist) 2895int del_perf_probe_events(struct strfilter *filter)
2714{ 2896{
2715 int ret = -1, ufd = -1, kfd = -1; 2897 int ret, ret2, ufd = -1, kfd = -1;
2716 char buf[128];
2717 const char *group, *event;
2718 char *p, *str;
2719 struct str_node *ent;
2720 struct strlist *namelist = NULL, *unamelist = NULL; 2898 struct strlist *namelist = NULL, *unamelist = NULL;
2899 char *str = strfilter__string(filter);
2900
2901 if (!str)
2902 return -EINVAL;
2903
2904 pr_debug("Delete filter: \'%s\'\n", str);
2721 2905
2722 /* Get current event names */ 2906 /* Get current event names */
2723 kfd = open_kprobe_events(true); 2907 kfd = open_kprobe_events(true);
@@ -2730,49 +2914,23 @@ int del_perf_probe_events(struct strlist *dellist)
2730 2914
2731 if (kfd < 0 && ufd < 0) { 2915 if (kfd < 0 && ufd < 0) {
2732 print_both_open_warning(kfd, ufd); 2916 print_both_open_warning(kfd, ufd);
2917 ret = kfd;
2733 goto error; 2918 goto error;
2734 } 2919 }
2735 2920
2736 if (namelist == NULL && unamelist == NULL) 2921 ret = del_trace_probe_events(kfd, filter, namelist);
2922 if (ret < 0 && ret != -ENOENT)
2737 goto error; 2923 goto error;
2738 2924
2739 strlist__for_each(ent, dellist) { 2925 ret2 = del_trace_probe_events(ufd, filter, unamelist);
2740 str = strdup(ent->s); 2926 if (ret2 < 0 && ret2 != -ENOENT) {
2741 if (str == NULL) { 2927 ret = ret2;
2742 ret = -ENOMEM; 2928 goto error;
2743 goto error;
2744 }
2745 pr_debug("Parsing: %s\n", str);
2746 p = strchr(str, ':');
2747 if (p) {
2748 group = str;
2749 *p = '\0';
2750 event = p + 1;
2751 } else {
2752 group = "*";
2753 event = str;
2754 }
2755
2756 ret = e_snprintf(buf, 128, "%s:%s", group, event);
2757 if (ret < 0) {
2758 pr_err("Failed to copy event.");
2759 free(str);
2760 goto error;
2761 }
2762
2763 pr_debug("Group: %s, Event: %s\n", group, event);
2764
2765 if (namelist)
2766 ret = del_trace_probe_event(kfd, buf, namelist);
2767
2768 if (unamelist && ret != 0)
2769 ret = del_trace_probe_event(ufd, buf, unamelist);
2770
2771 if (ret != 0)
2772 pr_info("Info: Event \"%s\" does not exist.\n", buf);
2773
2774 free(str);
2775 } 2929 }
2930 if (ret == -ENOENT && ret2 == -ENOENT)
2931 pr_debug("\"%s\" does not hit any event.\n", str);
2932 /* Note that this is silently ignored */
2933 ret = 0;
2776 2934
2777error: 2935error:
2778 if (kfd >= 0) { 2936 if (kfd >= 0) {
@@ -2784,6 +2942,7 @@ error:
2784 strlist__delete(unamelist); 2942 strlist__delete(unamelist);
2785 close(ufd); 2943 close(ufd);
2786 } 2944 }
2945 free(str);
2787 2946
2788 return ret; 2947 return ret;
2789} 2948}
@@ -2837,8 +2996,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
2837 dso__fprintf_symbols_by_name(map->dso, map->type, stdout); 2996 dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
2838end: 2997end:
2839 if (user) { 2998 if (user) {
2840 dso__delete(map->dso); 2999 map__put(map);
2841 map__delete(map);
2842 } 3000 }
2843 exit_symbol_maps(); 3001 exit_symbol_maps();
2844 3002
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index d6b783447be9..31db6ee7db54 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -6,10 +6,20 @@
6#include "strlist.h" 6#include "strlist.h"
7#include "strfilter.h" 7#include "strfilter.h"
8 8
9/* Probe related configurations */
10struct probe_conf {
11 bool show_ext_vars;
12 bool show_location_range;
13 bool force_add;
14 bool no_inlines;
15 int max_probes;
16};
17extern struct probe_conf probe_conf;
9extern bool probe_event_dry_run; 18extern bool probe_event_dry_run;
10 19
11/* kprobe-tracer and uprobe-tracer tracing point */ 20/* kprobe-tracer and uprobe-tracer tracing point */
12struct probe_trace_point { 21struct probe_trace_point {
22 char *realname; /* function real name (if needed) */
13 char *symbol; /* Base symbol */ 23 char *symbol; /* Base symbol */
14 char *module; /* Module name */ 24 char *module; /* Module name */
15 unsigned long offset; /* Offset from symbol */ 25 unsigned long offset; /* Offset from symbol */
@@ -121,20 +131,18 @@ extern void line_range__clear(struct line_range *lr);
121/* Initialize line range */ 131/* Initialize line range */
122extern int line_range__init(struct line_range *lr); 132extern int line_range__init(struct line_range *lr);
123 133
124/* Internal use: Return kernel/module path */ 134extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs);
125extern const char *kernel_get_module_path(const char *module); 135extern int del_perf_probe_events(struct strfilter *filter);
126 136extern int show_perf_probe_events(struct strfilter *filter);
127extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
128 int max_probe_points, bool force_add);
129extern int del_perf_probe_events(struct strlist *dellist);
130extern int show_perf_probe_events(void);
131extern int show_line_range(struct line_range *lr, const char *module, 137extern int show_line_range(struct line_range *lr, const char *module,
132 bool user); 138 bool user);
133extern int show_available_vars(struct perf_probe_event *pevs, int npevs, 139extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
134 int max_probe_points, const char *module, 140 struct strfilter *filter);
135 struct strfilter *filter, bool externs);
136extern int show_available_funcs(const char *module, struct strfilter *filter, 141extern int show_available_funcs(const char *module, struct strfilter *filter,
137 bool user); 142 bool user);
143bool arch__prefers_symtab(void);
144void arch__fix_tev_from_maps(struct perf_probe_event *pev,
145 struct probe_trace_event *tev, struct map *map);
138 146
139/* Maximum index number of event-name postfix */ 147/* Maximum index number of event-name postfix */
140#define MAX_EVENT_INDEX 1024 148#define MAX_EVENT_INDEX 1024
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 2a76e14db732..2da65a710893 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -130,7 +130,7 @@ struct debuginfo *debuginfo__new(const char *path)
130 continue; 130 continue;
131 dinfo = __debuginfo__new(buf); 131 dinfo = __debuginfo__new(buf);
132 } 132 }
133 dso__delete(dso); 133 dso__put(dso);
134 134
135out: 135out:
136 /* if failed to open all distro debuginfo, open given binary */ 136 /* if failed to open all distro debuginfo, open given binary */
@@ -177,7 +177,7 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
177 Dwarf_Word offs = 0; 177 Dwarf_Word offs = 0;
178 bool ref = false; 178 bool ref = false;
179 const char *regs; 179 const char *regs;
180 int ret; 180 int ret, ret2 = 0;
181 181
182 if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL) 182 if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
183 goto static_var; 183 goto static_var;
@@ -187,9 +187,19 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
187 return -EINVAL; /* Broken DIE ? */ 187 return -EINVAL; /* Broken DIE ? */
188 if (dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0) { 188 if (dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0) {
189 ret = dwarf_entrypc(sp_die, &tmp); 189 ret = dwarf_entrypc(sp_die, &tmp);
190 if (ret || addr != tmp || 190 if (ret)
191 dwarf_tag(vr_die) != DW_TAG_formal_parameter || 191 return -ENOENT;
192 dwarf_highpc(sp_die, &tmp)) 192
193 if (probe_conf.show_location_range &&
194 (dwarf_tag(vr_die) == DW_TAG_variable)) {
195 ret2 = -ERANGE;
196 } else if (addr != tmp ||
197 dwarf_tag(vr_die) != DW_TAG_formal_parameter) {
198 return -ENOENT;
199 }
200
201 ret = dwarf_highpc(sp_die, &tmp);
202 if (ret)
193 return -ENOENT; 203 return -ENOENT;
194 /* 204 /*
195 * This is fuzzed by fentry mcount. We try to find the 205 * This is fuzzed by fentry mcount. We try to find the
@@ -210,7 +220,7 @@ found:
210 if (op->atom == DW_OP_addr) { 220 if (op->atom == DW_OP_addr) {
211static_var: 221static_var:
212 if (!tvar) 222 if (!tvar)
213 return 0; 223 return ret2;
214 /* Static variables on memory (not stack), make @varname */ 224 /* Static variables on memory (not stack), make @varname */
215 ret = strlen(dwarf_diename(vr_die)); 225 ret = strlen(dwarf_diename(vr_die));
216 tvar->value = zalloc(ret + 2); 226 tvar->value = zalloc(ret + 2);
@@ -220,7 +230,7 @@ static_var:
220 tvar->ref = alloc_trace_arg_ref((long)offs); 230 tvar->ref = alloc_trace_arg_ref((long)offs);
221 if (tvar->ref == NULL) 231 if (tvar->ref == NULL)
222 return -ENOMEM; 232 return -ENOMEM;
223 return 0; 233 return ret2;
224 } 234 }
225 235
226 /* If this is based on frame buffer, set the offset */ 236 /* If this is based on frame buffer, set the offset */
@@ -250,14 +260,14 @@ static_var:
250 } 260 }
251 261
252 if (!tvar) 262 if (!tvar)
253 return 0; 263 return ret2;
254 264
255 regs = get_arch_regstr(regn); 265 regs = get_arch_regstr(regn);
256 if (!regs) { 266 if (!regs) {
257 /* This should be a bug in DWARF or this tool */ 267 /* This should be a bug in DWARF or this tool */
258 pr_warning("Mapping for the register number %u " 268 pr_warning("Mapping for the register number %u "
259 "missing on this architecture.\n", regn); 269 "missing on this architecture.\n", regn);
260 return -ERANGE; 270 return -ENOTSUP;
261 } 271 }
262 272
263 tvar->value = strdup(regs); 273 tvar->value = strdup(regs);
@@ -269,7 +279,7 @@ static_var:
269 if (tvar->ref == NULL) 279 if (tvar->ref == NULL)
270 return -ENOMEM; 280 return -ENOMEM;
271 } 281 }
272 return 0; 282 return ret2;
273} 283}
274 284
275#define BYTES_TO_BITS(nb) ((nb) * BITS_PER_LONG / sizeof(long)) 285#define BYTES_TO_BITS(nb) ((nb) * BITS_PER_LONG / sizeof(long))
@@ -517,10 +527,12 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
517 527
518 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops, 528 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
519 &pf->sp_die, pf->tvar); 529 &pf->sp_die, pf->tvar);
520 if (ret == -ENOENT || ret == -EINVAL) 530 if (ret == -ENOENT || ret == -EINVAL) {
521 pr_err("Failed to find the location of %s at this address.\n" 531 pr_err("Failed to find the location of the '%s' variable at this address.\n"
522 " Perhaps, it has been optimized out.\n", pf->pvar->var); 532 " Perhaps it has been optimized out.\n"
523 else if (ret == -ENOTSUP) 533 " Use -V with the --range option to show '%s' location range.\n",
534 pf->pvar->var, pf->pvar->var);
535 } else if (ret == -ENOTSUP)
524 pr_err("Sorry, we don't support this variable location yet.\n"); 536 pr_err("Sorry, we don't support this variable location yet.\n");
525 else if (ret == 0 && pf->pvar->field) { 537 else if (ret == 0 && pf->pvar->field) {
526 ret = convert_variable_fields(vr_die, pf->pvar->var, 538 ret = convert_variable_fields(vr_die, pf->pvar->var,
@@ -662,9 +674,15 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
662 /* If not a real subprogram, find a real one */ 674 /* If not a real subprogram, find a real one */
663 if (!die_is_func_def(sc_die)) { 675 if (!die_is_func_def(sc_die)) {
664 if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) { 676 if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
665 pr_warning("Failed to find probe point in any " 677 if (die_find_tailfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
666 "functions.\n"); 678 pr_warning("Ignoring tail call from %s\n",
667 return -ENOENT; 679 dwarf_diename(&pf->sp_die));
680 return 0;
681 } else {
682 pr_warning("Failed to find probe point in any "
683 "functions.\n");
684 return -ENOENT;
685 }
668 } 686 }
669 } else 687 } else
670 memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die)); 688 memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die));
@@ -719,7 +737,7 @@ static int find_best_scope_cb(Dwarf_Die *fn_die, void *data)
719 } 737 }
720 /* If the function name is given, that's what user expects */ 738 /* If the function name is given, that's what user expects */
721 if (fsp->function) { 739 if (fsp->function) {
722 if (die_compare_name(fn_die, fsp->function)) { 740 if (die_match_name(fn_die, fsp->function)) {
723 memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die)); 741 memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
724 fsp->found = true; 742 fsp->found = true;
725 return 1; 743 return 1;
@@ -922,13 +940,14 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
922 940
923 /* Check tag and diename */ 941 /* Check tag and diename */
924 if (!die_is_func_def(sp_die) || 942 if (!die_is_func_def(sp_die) ||
925 !die_compare_name(sp_die, pp->function)) 943 !die_match_name(sp_die, pp->function))
926 return DWARF_CB_OK; 944 return DWARF_CB_OK;
927 945
928 /* Check declared file */ 946 /* Check declared file */
929 if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die))) 947 if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
930 return DWARF_CB_OK; 948 return DWARF_CB_OK;
931 949
950 pr_debug("Matched function: %s\n", dwarf_diename(sp_die));
932 pf->fname = dwarf_decl_file(sp_die); 951 pf->fname = dwarf_decl_file(sp_die);
933 if (pp->line) { /* Function relative line */ 952 if (pp->line) { /* Function relative line */
934 dwarf_decl_line(sp_die, &pf->lno); 953 dwarf_decl_line(sp_die, &pf->lno);
@@ -945,10 +964,20 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
945 /* TODO: Check the address in this function */ 964 /* TODO: Check the address in this function */
946 param->retval = call_probe_finder(sp_die, pf); 965 param->retval = call_probe_finder(sp_die, pf);
947 } 966 }
948 } else 967 } else if (!probe_conf.no_inlines) {
949 /* Inlined function: search instances */ 968 /* Inlined function: search instances */
950 param->retval = die_walk_instances(sp_die, 969 param->retval = die_walk_instances(sp_die,
951 probe_point_inline_cb, (void *)pf); 970 probe_point_inline_cb, (void *)pf);
971 /* This could be a non-existed inline definition */
972 if (param->retval == -ENOENT && strisglob(pp->function))
973 param->retval = 0;
974 }
975
976 /* We need to find other candidates */
977 if (strisglob(pp->function) && param->retval >= 0) {
978 param->retval = 0; /* We have to clear the result */
979 return DWARF_CB_OK;
980 }
952 981
953 return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */ 982 return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
954} 983}
@@ -977,7 +1006,7 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
977 if (dwarf_tag(param->sp_die) != DW_TAG_subprogram) 1006 if (dwarf_tag(param->sp_die) != DW_TAG_subprogram)
978 return DWARF_CB_OK; 1007 return DWARF_CB_OK;
979 1008
980 if (die_compare_name(param->sp_die, param->function)) { 1009 if (die_match_name(param->sp_die, param->function)) {
981 if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die)) 1010 if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die))
982 return DWARF_CB_OK; 1011 return DWARF_CB_OK;
983 1012
@@ -1030,7 +1059,7 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
1030 return -ENOMEM; 1059 return -ENOMEM;
1031 1060
1032 /* Fastpath: lookup by function name from .debug_pubnames section */ 1061 /* Fastpath: lookup by function name from .debug_pubnames section */
1033 if (pp->function) { 1062 if (pp->function && !strisglob(pp->function)) {
1034 struct pubname_callback_param pubname_param = { 1063 struct pubname_callback_param pubname_param = {
1035 .function = pp->function, 1064 .function = pp->function,
1036 .file = pp->file, 1065 .file = pp->file,
@@ -1089,6 +1118,7 @@ found:
1089struct local_vars_finder { 1118struct local_vars_finder {
1090 struct probe_finder *pf; 1119 struct probe_finder *pf;
1091 struct perf_probe_arg *args; 1120 struct perf_probe_arg *args;
1121 bool vars;
1092 int max_args; 1122 int max_args;
1093 int nargs; 1123 int nargs;
1094 int ret; 1124 int ret;
@@ -1103,7 +1133,7 @@ static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
1103 1133
1104 tag = dwarf_tag(die_mem); 1134 tag = dwarf_tag(die_mem);
1105 if (tag == DW_TAG_formal_parameter || 1135 if (tag == DW_TAG_formal_parameter ||
1106 tag == DW_TAG_variable) { 1136 (tag == DW_TAG_variable && vf->vars)) {
1107 if (convert_variable_location(die_mem, vf->pf->addr, 1137 if (convert_variable_location(die_mem, vf->pf->addr,
1108 vf->pf->fb_ops, &pf->sp_die, 1138 vf->pf->fb_ops, &pf->sp_die,
1109 NULL) == 0) { 1139 NULL) == 0) {
@@ -1129,26 +1159,28 @@ static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf,
1129 Dwarf_Die die_mem; 1159 Dwarf_Die die_mem;
1130 int i; 1160 int i;
1131 int n = 0; 1161 int n = 0;
1132 struct local_vars_finder vf = {.pf = pf, .args = args, 1162 struct local_vars_finder vf = {.pf = pf, .args = args, .vars = false,
1133 .max_args = MAX_PROBE_ARGS, .ret = 0}; 1163 .max_args = MAX_PROBE_ARGS, .ret = 0};
1134 1164
1135 for (i = 0; i < pf->pev->nargs; i++) { 1165 for (i = 0; i < pf->pev->nargs; i++) {
1136 /* var never be NULL */ 1166 /* var never be NULL */
1137 if (strcmp(pf->pev->args[i].var, "$vars") == 0) { 1167 if (strcmp(pf->pev->args[i].var, PROBE_ARG_VARS) == 0)
1138 pr_debug("Expanding $vars into:"); 1168 vf.vars = true;
1139 vf.nargs = n; 1169 else if (strcmp(pf->pev->args[i].var, PROBE_ARG_PARAMS) != 0) {
1140 /* Special local variables */
1141 die_find_child(sc_die, copy_variables_cb, (void *)&vf,
1142 &die_mem);
1143 pr_debug(" (%d)\n", vf.nargs - n);
1144 if (vf.ret < 0)
1145 return vf.ret;
1146 n = vf.nargs;
1147 } else {
1148 /* Copy normal argument */ 1170 /* Copy normal argument */
1149 args[n] = pf->pev->args[i]; 1171 args[n] = pf->pev->args[i];
1150 n++; 1172 n++;
1173 continue;
1151 } 1174 }
1175 pr_debug("Expanding %s into:", pf->pev->args[i].var);
1176 vf.nargs = n;
1177 /* Special local variables */
1178 die_find_child(sc_die, copy_variables_cb, (void *)&vf,
1179 &die_mem);
1180 pr_debug(" (%d)\n", vf.nargs - n);
1181 if (vf.ret < 0)
1182 return vf.ret;
1183 n = vf.nargs;
1152 } 1184 }
1153 return n; 1185 return n;
1154} 1186}
@@ -1176,6 +1208,10 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1176 if (ret < 0) 1208 if (ret < 0)
1177 return ret; 1209 return ret;
1178 1210
1211 tev->point.realname = strdup(dwarf_diename(sc_die));
1212 if (!tev->point.realname)
1213 return -ENOMEM;
1214
1179 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, 1215 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
1180 tev->point.offset); 1216 tev->point.offset);
1181 1217
@@ -1213,15 +1249,15 @@ end:
1213/* Find probe_trace_events specified by perf_probe_event from debuginfo */ 1249/* Find probe_trace_events specified by perf_probe_event from debuginfo */
1214int debuginfo__find_trace_events(struct debuginfo *dbg, 1250int debuginfo__find_trace_events(struct debuginfo *dbg,
1215 struct perf_probe_event *pev, 1251 struct perf_probe_event *pev,
1216 struct probe_trace_event **tevs, int max_tevs) 1252 struct probe_trace_event **tevs)
1217{ 1253{
1218 struct trace_event_finder tf = { 1254 struct trace_event_finder tf = {
1219 .pf = {.pev = pev, .callback = add_probe_trace_event}, 1255 .pf = {.pev = pev, .callback = add_probe_trace_event},
1220 .mod = dbg->mod, .max_tevs = max_tevs}; 1256 .max_tevs = probe_conf.max_probes, .mod = dbg->mod};
1221 int ret; 1257 int ret;
1222 1258
1223 /* Allocate result tevs array */ 1259 /* Allocate result tevs array */
1224 *tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs); 1260 *tevs = zalloc(sizeof(struct probe_trace_event) * tf.max_tevs);
1225 if (*tevs == NULL) 1261 if (*tevs == NULL)
1226 return -ENOMEM; 1262 return -ENOMEM;
1227 1263
@@ -1237,14 +1273,11 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,
1237 return (ret < 0) ? ret : tf.ntevs; 1273 return (ret < 0) ? ret : tf.ntevs;
1238} 1274}
1239 1275
1240#define MAX_VAR_LEN 64
1241
1242/* Collect available variables in this scope */ 1276/* Collect available variables in this scope */
1243static int collect_variables_cb(Dwarf_Die *die_mem, void *data) 1277static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1244{ 1278{
1245 struct available_var_finder *af = data; 1279 struct available_var_finder *af = data;
1246 struct variable_list *vl; 1280 struct variable_list *vl;
1247 char buf[MAX_VAR_LEN];
1248 int tag, ret; 1281 int tag, ret;
1249 1282
1250 vl = &af->vls[af->nvls - 1]; 1283 vl = &af->vls[af->nvls - 1];
@@ -1255,11 +1288,38 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1255 ret = convert_variable_location(die_mem, af->pf.addr, 1288 ret = convert_variable_location(die_mem, af->pf.addr,
1256 af->pf.fb_ops, &af->pf.sp_die, 1289 af->pf.fb_ops, &af->pf.sp_die,
1257 NULL); 1290 NULL);
1258 if (ret == 0) { 1291 if (ret == 0 || ret == -ERANGE) {
1259 ret = die_get_varname(die_mem, buf, MAX_VAR_LEN); 1292 int ret2;
1260 pr_debug2("Add new var: %s\n", buf); 1293 bool externs = !af->child;
1261 if (ret > 0) 1294 struct strbuf buf;
1262 strlist__add(vl->vars, buf); 1295
1296 strbuf_init(&buf, 64);
1297
1298 if (probe_conf.show_location_range) {
1299 if (!externs) {
1300 if (ret)
1301 strbuf_addf(&buf, "[INV]\t");
1302 else
1303 strbuf_addf(&buf, "[VAL]\t");
1304 } else
1305 strbuf_addf(&buf, "[EXT]\t");
1306 }
1307
1308 ret2 = die_get_varname(die_mem, &buf);
1309
1310 if (!ret2 && probe_conf.show_location_range &&
1311 !externs) {
1312 strbuf_addf(&buf, "\t");
1313 ret2 = die_get_var_range(&af->pf.sp_die,
1314 die_mem, &buf);
1315 }
1316
1317 pr_debug("Add new var: %s\n", buf.buf);
1318 if (ret2 == 0) {
1319 strlist__add(vl->vars,
1320 strbuf_detach(&buf, NULL));
1321 }
1322 strbuf_release(&buf);
1263 } 1323 }
1264 } 1324 }
1265 1325
@@ -1302,9 +1362,9 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
1302 die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem); 1362 die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem);
1303 1363
1304 /* Find external variables */ 1364 /* Find external variables */
1305 if (!af->externs) 1365 if (!probe_conf.show_ext_vars)
1306 goto out; 1366 goto out;
1307 /* Don't need to search child DIE for externs. */ 1367 /* Don't need to search child DIE for external vars. */
1308 af->child = false; 1368 af->child = false;
1309 die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem); 1369 die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem);
1310 1370
@@ -1324,17 +1384,16 @@ out:
1324 */ 1384 */
1325int debuginfo__find_available_vars_at(struct debuginfo *dbg, 1385int debuginfo__find_available_vars_at(struct debuginfo *dbg,
1326 struct perf_probe_event *pev, 1386 struct perf_probe_event *pev,
1327 struct variable_list **vls, 1387 struct variable_list **vls)
1328 int max_vls, bool externs)
1329{ 1388{
1330 struct available_var_finder af = { 1389 struct available_var_finder af = {
1331 .pf = {.pev = pev, .callback = add_available_vars}, 1390 .pf = {.pev = pev, .callback = add_available_vars},
1332 .mod = dbg->mod, 1391 .mod = dbg->mod,
1333 .max_vls = max_vls, .externs = externs}; 1392 .max_vls = probe_conf.max_probes};
1334 int ret; 1393 int ret;
1335 1394
1336 /* Allocate result vls array */ 1395 /* Allocate result vls array */
1337 *vls = zalloc(sizeof(struct variable_list) * max_vls); 1396 *vls = zalloc(sizeof(struct variable_list) * af.max_vls);
1338 if (*vls == NULL) 1397 if (*vls == NULL)
1339 return -ENOMEM; 1398 return -ENOMEM;
1340 1399
@@ -1535,7 +1594,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1535 return DWARF_CB_OK; 1594 return DWARF_CB_OK;
1536 1595
1537 if (die_is_func_def(sp_die) && 1596 if (die_is_func_def(sp_die) &&
1538 die_compare_name(sp_die, lr->function)) { 1597 die_match_name(sp_die, lr->function)) {
1539 lf->fname = dwarf_decl_file(sp_die); 1598 lf->fname = dwarf_decl_file(sp_die);
1540 dwarf_decl_line(sp_die, &lr->offset); 1599 dwarf_decl_line(sp_die, &lr->offset);
1541 pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset); 1600 pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index ebf8c8c81453..bed82716e1b4 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -10,6 +10,9 @@
10#define MAX_PROBES 128 10#define MAX_PROBES 128
11#define MAX_PROBE_ARGS 128 11#define MAX_PROBE_ARGS 128
12 12
13#define PROBE_ARG_VARS "$vars"
14#define PROBE_ARG_PARAMS "$params"
15
13static inline int is_c_varname(const char *name) 16static inline int is_c_varname(const char *name)
14{ 17{
15 /* TODO */ 18 /* TODO */
@@ -37,8 +40,7 @@ extern void debuginfo__delete(struct debuginfo *dbg);
37/* Find probe_trace_events specified by perf_probe_event from debuginfo */ 40/* Find probe_trace_events specified by perf_probe_event from debuginfo */
38extern int debuginfo__find_trace_events(struct debuginfo *dbg, 41extern int debuginfo__find_trace_events(struct debuginfo *dbg,
39 struct perf_probe_event *pev, 42 struct perf_probe_event *pev,
40 struct probe_trace_event **tevs, 43 struct probe_trace_event **tevs);
41 int max_tevs);
42 44
43/* Find a perf_probe_point from debuginfo */ 45/* Find a perf_probe_point from debuginfo */
44extern int debuginfo__find_probe_point(struct debuginfo *dbg, 46extern int debuginfo__find_probe_point(struct debuginfo *dbg,
@@ -52,8 +54,7 @@ extern int debuginfo__find_line_range(struct debuginfo *dbg,
52/* Find available variables */ 54/* Find available variables */
53extern int debuginfo__find_available_vars_at(struct debuginfo *dbg, 55extern int debuginfo__find_available_vars_at(struct debuginfo *dbg,
54 struct perf_probe_event *pev, 56 struct perf_probe_event *pev,
55 struct variable_list **vls, 57 struct variable_list **vls);
56 int max_points, bool externs);
57 58
58/* Find a src file from a DWARF tag path */ 59/* Find a src file from a DWARF tag path */
59int get_real_path(const char *raw_path, const char *comp_dir, 60int get_real_path(const char *raw_path, const char *comp_dir,
@@ -96,7 +97,6 @@ struct available_var_finder {
96 struct variable_list *vls; /* Found variable lists */ 97 struct variable_list *vls; /* Found variable lists */
97 int nvls; /* Number of variable lists */ 98 int nvls; /* Number of variable lists */
98 int max_vls; /* Max no. of variable lists */ 99 int max_vls; /* Max no. of variable lists */
99 bool externs; /* Find external vars too */
100 bool child; /* Search child scopes */ 100 bool child; /* Search child scopes */
101}; 101};
102 102
diff --git a/tools/perf/util/pstack.c b/tools/perf/util/pstack.c
index a126e6cc6e73..b234a6e3d0d4 100644
--- a/tools/perf/util/pstack.c
+++ b/tools/perf/util/pstack.c
@@ -74,3 +74,10 @@ void *pstack__pop(struct pstack *pstack)
74 pstack->entries[pstack->top] = NULL; 74 pstack->entries[pstack->top] = NULL;
75 return ret; 75 return ret;
76} 76}
77
78void *pstack__peek(struct pstack *pstack)
79{
80 if (pstack->top == 0)
81 return NULL;
82 return pstack->entries[pstack->top - 1];
83}
diff --git a/tools/perf/util/pstack.h b/tools/perf/util/pstack.h
index c3cb6584d527..ded7f2e36624 100644
--- a/tools/perf/util/pstack.h
+++ b/tools/perf/util/pstack.h
@@ -10,5 +10,6 @@ bool pstack__empty(const struct pstack *pstack);
10void pstack__remove(struct pstack *pstack, void *key); 10void pstack__remove(struct pstack *pstack, void *key);
11void pstack__push(struct pstack *pstack, void *key); 11void pstack__push(struct pstack *pstack, void *key);
12void *pstack__pop(struct pstack *pstack); 12void *pstack__pop(struct pstack *pstack);
13void *pstack__peek(struct pstack *pstack);
13 14
14#endif /* _PERF_PSTACK_ */ 15#endif /* _PERF_PSTACK_ */
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 4d28624a1eca..5925fec90562 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -16,6 +16,7 @@ util/util.c
16util/xyarray.c 16util/xyarray.c
17util/cgroup.c 17util/cgroup.c
18util/rblist.c 18util/rblist.c
19util/stat.c
19util/strlist.c 20util/strlist.c
20util/trace-event.c 21util/trace-event.c
21../../lib/rbtree.c 22../../lib/rbtree.c
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index 8acd0df88b5c..d457c523a33d 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -20,7 +20,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
20 if (!evlist) 20 if (!evlist)
21 return -ENOMEM; 21 return -ENOMEM;
22 22
23 if (parse_events(evlist, str)) 23 if (parse_events(evlist, str, NULL))
24 goto out_delete; 24 goto out_delete;
25 25
26 evsel = perf_evlist__first(evlist); 26 evsel = perf_evlist__first(evlist);
@@ -119,7 +119,16 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
119 evsel->attr.comm_exec = 1; 119 evsel->attr.comm_exec = 1;
120 } 120 }
121 121
122 if (evlist->nr_entries > 1) { 122 if (opts->full_auxtrace) {
123 /*
124 * Need to be able to synthesize and parse selected events with
125 * arbitrary sample types, which requires always being able to
126 * match the id.
127 */
128 use_sample_identifier = perf_can_sample_identifier();
129 evlist__for_each(evlist, evsel)
130 perf_evsel__set_sample_id(evsel, use_sample_identifier);
131 } else if (evlist->nr_entries > 1) {
123 struct perf_evsel *first = perf_evlist__first(evlist); 132 struct perf_evsel *first = perf_evlist__first(evlist);
124 133
125 evlist__for_each(evlist, evsel) { 134 evlist__for_each(evlist, evsel) {
@@ -207,7 +216,7 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
207 if (!temp_evlist) 216 if (!temp_evlist)
208 return false; 217 return false;
209 218
210 err = parse_events(temp_evlist, str); 219 err = parse_events(temp_evlist, str, NULL);
211 if (err) 220 if (err)
212 goto out_delete; 221 goto out_delete;
213 222
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0c74012575ac..aa482c10469d 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -15,12 +15,14 @@
15#include "cpumap.h" 15#include "cpumap.h"
16#include "perf_regs.h" 16#include "perf_regs.h"
17#include "asm/bug.h" 17#include "asm/bug.h"
18#include "auxtrace.h"
19#include "thread-stack.h"
18 20
19static int machines__deliver_event(struct machines *machines, 21static int perf_session__deliver_event(struct perf_session *session,
20 struct perf_evlist *evlist, 22 union perf_event *event,
21 union perf_event *event, 23 struct perf_sample *sample,
22 struct perf_sample *sample, 24 struct perf_tool *tool,
23 struct perf_tool *tool, u64 file_offset); 25 u64 file_offset);
24 26
25static int perf_session__open(struct perf_session *session) 27static int perf_session__open(struct perf_session *session)
26{ 28{
@@ -105,8 +107,8 @@ static int ordered_events__deliver_event(struct ordered_events *oe,
105 return ret; 107 return ret;
106 } 108 }
107 109
108 return machines__deliver_event(&session->machines, session->evlist, event->event, 110 return perf_session__deliver_event(session, event->event, &sample,
109 &sample, session->tool, event->file_offset); 111 session->tool, event->file_offset);
110} 112}
111 113
112struct perf_session *perf_session__new(struct perf_data_file *file, 114struct perf_session *perf_session__new(struct perf_data_file *file,
@@ -119,6 +121,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
119 121
120 session->repipe = repipe; 122 session->repipe = repipe;
121 session->tool = tool; 123 session->tool = tool;
124 INIT_LIST_HEAD(&session->auxtrace_index);
122 machines__init(&session->machines); 125 machines__init(&session->machines);
123 ordered_events__init(&session->ordered_events, ordered_events__deliver_event); 126 ordered_events__init(&session->ordered_events, ordered_events__deliver_event);
124 127
@@ -185,6 +188,8 @@ static void perf_session_env__delete(struct perf_session_env *env)
185 188
186void perf_session__delete(struct perf_session *session) 189void perf_session__delete(struct perf_session *session)
187{ 190{
191 auxtrace__free(session);
192 auxtrace_index__free(&session->auxtrace_index);
188 perf_session__destroy_kernel_maps(session); 193 perf_session__destroy_kernel_maps(session);
189 perf_session__delete_threads(session); 194 perf_session__delete_threads(session);
190 perf_session_env__delete(&session->header.env); 195 perf_session_env__delete(&session->header.env);
@@ -262,6 +267,49 @@ static int process_id_index_stub(struct perf_tool *tool __maybe_unused,
262 return 0; 267 return 0;
263} 268}
264 269
270static int process_event_auxtrace_info_stub(struct perf_tool *tool __maybe_unused,
271 union perf_event *event __maybe_unused,
272 struct perf_session *session __maybe_unused)
273{
274 dump_printf(": unhandled!\n");
275 return 0;
276}
277
278static int skipn(int fd, off_t n)
279{
280 char buf[4096];
281 ssize_t ret;
282
283 while (n > 0) {
284 ret = read(fd, buf, min(n, (off_t)sizeof(buf)));
285 if (ret <= 0)
286 return ret;
287 n -= ret;
288 }
289
290 return 0;
291}
292
293static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,
294 union perf_event *event,
295 struct perf_session *session
296 __maybe_unused)
297{
298 dump_printf(": unhandled!\n");
299 if (perf_data_file__is_pipe(session->file))
300 skipn(perf_data_file__fd(session->file), event->auxtrace.size);
301 return event->auxtrace.size;
302}
303
304static
305int process_event_auxtrace_error_stub(struct perf_tool *tool __maybe_unused,
306 union perf_event *event __maybe_unused,
307 struct perf_session *session __maybe_unused)
308{
309 dump_printf(": unhandled!\n");
310 return 0;
311}
312
265void perf_tool__fill_defaults(struct perf_tool *tool) 313void perf_tool__fill_defaults(struct perf_tool *tool)
266{ 314{
267 if (tool->sample == NULL) 315 if (tool->sample == NULL)
@@ -278,6 +326,12 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
278 tool->exit = process_event_stub; 326 tool->exit = process_event_stub;
279 if (tool->lost == NULL) 327 if (tool->lost == NULL)
280 tool->lost = perf_event__process_lost; 328 tool->lost = perf_event__process_lost;
329 if (tool->lost_samples == NULL)
330 tool->lost_samples = perf_event__process_lost_samples;
331 if (tool->aux == NULL)
332 tool->aux = perf_event__process_aux;
333 if (tool->itrace_start == NULL)
334 tool->itrace_start = perf_event__process_itrace_start;
281 if (tool->read == NULL) 335 if (tool->read == NULL)
282 tool->read = process_event_sample_stub; 336 tool->read = process_event_sample_stub;
283 if (tool->throttle == NULL) 337 if (tool->throttle == NULL)
@@ -298,6 +352,12 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
298 } 352 }
299 if (tool->id_index == NULL) 353 if (tool->id_index == NULL)
300 tool->id_index = process_id_index_stub; 354 tool->id_index = process_id_index_stub;
355 if (tool->auxtrace_info == NULL)
356 tool->auxtrace_info = process_event_auxtrace_info_stub;
357 if (tool->auxtrace == NULL)
358 tool->auxtrace = process_event_auxtrace_stub;
359 if (tool->auxtrace_error == NULL)
360 tool->auxtrace_error = process_event_auxtrace_error_stub;
301} 361}
302 362
303static void swap_sample_id_all(union perf_event *event, void *data) 363static void swap_sample_id_all(union perf_event *event, void *data)
@@ -390,6 +450,26 @@ static void perf_event__read_swap(union perf_event *event, bool sample_id_all)
390 swap_sample_id_all(event, &event->read + 1); 450 swap_sample_id_all(event, &event->read + 1);
391} 451}
392 452
453static void perf_event__aux_swap(union perf_event *event, bool sample_id_all)
454{
455 event->aux.aux_offset = bswap_64(event->aux.aux_offset);
456 event->aux.aux_size = bswap_64(event->aux.aux_size);
457 event->aux.flags = bswap_64(event->aux.flags);
458
459 if (sample_id_all)
460 swap_sample_id_all(event, &event->aux + 1);
461}
462
463static void perf_event__itrace_start_swap(union perf_event *event,
464 bool sample_id_all)
465{
466 event->itrace_start.pid = bswap_32(event->itrace_start.pid);
467 event->itrace_start.tid = bswap_32(event->itrace_start.tid);
468
469 if (sample_id_all)
470 swap_sample_id_all(event, &event->itrace_start + 1);
471}
472
393static void perf_event__throttle_swap(union perf_event *event, 473static void perf_event__throttle_swap(union perf_event *event,
394 bool sample_id_all) 474 bool sample_id_all)
395{ 475{
@@ -438,19 +518,42 @@ void perf_event__attr_swap(struct perf_event_attr *attr)
438{ 518{
439 attr->type = bswap_32(attr->type); 519 attr->type = bswap_32(attr->type);
440 attr->size = bswap_32(attr->size); 520 attr->size = bswap_32(attr->size);
441 attr->config = bswap_64(attr->config);
442 attr->sample_period = bswap_64(attr->sample_period);
443 attr->sample_type = bswap_64(attr->sample_type);
444 attr->read_format = bswap_64(attr->read_format);
445 attr->wakeup_events = bswap_32(attr->wakeup_events);
446 attr->bp_type = bswap_32(attr->bp_type);
447 attr->bp_addr = bswap_64(attr->bp_addr);
448 attr->bp_len = bswap_64(attr->bp_len);
449 attr->branch_sample_type = bswap_64(attr->branch_sample_type);
450 attr->sample_regs_user = bswap_64(attr->sample_regs_user);
451 attr->sample_stack_user = bswap_32(attr->sample_stack_user);
452 521
453 swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64)); 522#define bswap_safe(f, n) \
523 (attr->size > (offsetof(struct perf_event_attr, f) + \
524 sizeof(attr->f) * (n)))
525#define bswap_field(f, sz) \
526do { \
527 if (bswap_safe(f, 0)) \
528 attr->f = bswap_##sz(attr->f); \
529} while(0)
530#define bswap_field_32(f) bswap_field(f, 32)
531#define bswap_field_64(f) bswap_field(f, 64)
532
533 bswap_field_64(config);
534 bswap_field_64(sample_period);
535 bswap_field_64(sample_type);
536 bswap_field_64(read_format);
537 bswap_field_32(wakeup_events);
538 bswap_field_32(bp_type);
539 bswap_field_64(bp_addr);
540 bswap_field_64(bp_len);
541 bswap_field_64(branch_sample_type);
542 bswap_field_64(sample_regs_user);
543 bswap_field_32(sample_stack_user);
544 bswap_field_32(aux_watermark);
545
546 /*
547 * After read_format are bitfields. Check read_format because
548 * we are unable to use offsetof on bitfield.
549 */
550 if (bswap_safe(read_format, 1))
551 swap_bitfield((u8 *) (&attr->read_format + 1),
552 sizeof(u64));
553#undef bswap_field_64
554#undef bswap_field_32
555#undef bswap_field
556#undef bswap_safe
454} 557}
455 558
456static void perf_event__hdr_attr_swap(union perf_event *event, 559static void perf_event__hdr_attr_swap(union perf_event *event,
@@ -478,6 +581,40 @@ static void perf_event__tracing_data_swap(union perf_event *event,
478 event->tracing_data.size = bswap_32(event->tracing_data.size); 581 event->tracing_data.size = bswap_32(event->tracing_data.size);
479} 582}
480 583
584static void perf_event__auxtrace_info_swap(union perf_event *event,
585 bool sample_id_all __maybe_unused)
586{
587 size_t size;
588
589 event->auxtrace_info.type = bswap_32(event->auxtrace_info.type);
590
591 size = event->header.size;
592 size -= (void *)&event->auxtrace_info.priv - (void *)event;
593 mem_bswap_64(event->auxtrace_info.priv, size);
594}
595
596static void perf_event__auxtrace_swap(union perf_event *event,
597 bool sample_id_all __maybe_unused)
598{
599 event->auxtrace.size = bswap_64(event->auxtrace.size);
600 event->auxtrace.offset = bswap_64(event->auxtrace.offset);
601 event->auxtrace.reference = bswap_64(event->auxtrace.reference);
602 event->auxtrace.idx = bswap_32(event->auxtrace.idx);
603 event->auxtrace.tid = bswap_32(event->auxtrace.tid);
604 event->auxtrace.cpu = bswap_32(event->auxtrace.cpu);
605}
606
607static void perf_event__auxtrace_error_swap(union perf_event *event,
608 bool sample_id_all __maybe_unused)
609{
610 event->auxtrace_error.type = bswap_32(event->auxtrace_error.type);
611 event->auxtrace_error.code = bswap_32(event->auxtrace_error.code);
612 event->auxtrace_error.cpu = bswap_32(event->auxtrace_error.cpu);
613 event->auxtrace_error.pid = bswap_32(event->auxtrace_error.pid);
614 event->auxtrace_error.tid = bswap_32(event->auxtrace_error.tid);
615 event->auxtrace_error.ip = bswap_64(event->auxtrace_error.ip);
616}
617
481typedef void (*perf_event__swap_op)(union perf_event *event, 618typedef void (*perf_event__swap_op)(union perf_event *event,
482 bool sample_id_all); 619 bool sample_id_all);
483 620
@@ -492,11 +629,17 @@ static perf_event__swap_op perf_event__swap_ops[] = {
492 [PERF_RECORD_THROTTLE] = perf_event__throttle_swap, 629 [PERF_RECORD_THROTTLE] = perf_event__throttle_swap,
493 [PERF_RECORD_UNTHROTTLE] = perf_event__throttle_swap, 630 [PERF_RECORD_UNTHROTTLE] = perf_event__throttle_swap,
494 [PERF_RECORD_SAMPLE] = perf_event__all64_swap, 631 [PERF_RECORD_SAMPLE] = perf_event__all64_swap,
632 [PERF_RECORD_AUX] = perf_event__aux_swap,
633 [PERF_RECORD_ITRACE_START] = perf_event__itrace_start_swap,
634 [PERF_RECORD_LOST_SAMPLES] = perf_event__all64_swap,
495 [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap, 635 [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap,
496 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, 636 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
497 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, 637 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
498 [PERF_RECORD_HEADER_BUILD_ID] = NULL, 638 [PERF_RECORD_HEADER_BUILD_ID] = NULL,
499 [PERF_RECORD_ID_INDEX] = perf_event__all64_swap, 639 [PERF_RECORD_ID_INDEX] = perf_event__all64_swap,
640 [PERF_RECORD_AUXTRACE_INFO] = perf_event__auxtrace_info_swap,
641 [PERF_RECORD_AUXTRACE] = perf_event__auxtrace_swap,
642 [PERF_RECORD_AUXTRACE_ERROR] = perf_event__auxtrace_error_swap,
500 [PERF_RECORD_HEADER_MAX] = NULL, 643 [PERF_RECORD_HEADER_MAX] = NULL,
501}; 644};
502 645
@@ -921,6 +1064,8 @@ static int machines__deliver_event(struct machines *machines,
921 case PERF_RECORD_MMAP: 1064 case PERF_RECORD_MMAP:
922 return tool->mmap(tool, event, sample, machine); 1065 return tool->mmap(tool, event, sample, machine);
923 case PERF_RECORD_MMAP2: 1066 case PERF_RECORD_MMAP2:
1067 if (event->header.misc & PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT)
1068 ++evlist->stats.nr_proc_map_timeout;
924 return tool->mmap2(tool, event, sample, machine); 1069 return tool->mmap2(tool, event, sample, machine);
925 case PERF_RECORD_COMM: 1070 case PERF_RECORD_COMM:
926 return tool->comm(tool, event, sample, machine); 1071 return tool->comm(tool, event, sample, machine);
@@ -932,18 +1077,44 @@ static int machines__deliver_event(struct machines *machines,
932 if (tool->lost == perf_event__process_lost) 1077 if (tool->lost == perf_event__process_lost)
933 evlist->stats.total_lost += event->lost.lost; 1078 evlist->stats.total_lost += event->lost.lost;
934 return tool->lost(tool, event, sample, machine); 1079 return tool->lost(tool, event, sample, machine);
1080 case PERF_RECORD_LOST_SAMPLES:
1081 if (tool->lost_samples == perf_event__process_lost_samples)
1082 evlist->stats.total_lost_samples += event->lost_samples.lost;
1083 return tool->lost_samples(tool, event, sample, machine);
935 case PERF_RECORD_READ: 1084 case PERF_RECORD_READ:
936 return tool->read(tool, event, sample, evsel, machine); 1085 return tool->read(tool, event, sample, evsel, machine);
937 case PERF_RECORD_THROTTLE: 1086 case PERF_RECORD_THROTTLE:
938 return tool->throttle(tool, event, sample, machine); 1087 return tool->throttle(tool, event, sample, machine);
939 case PERF_RECORD_UNTHROTTLE: 1088 case PERF_RECORD_UNTHROTTLE:
940 return tool->unthrottle(tool, event, sample, machine); 1089 return tool->unthrottle(tool, event, sample, machine);
1090 case PERF_RECORD_AUX:
1091 return tool->aux(tool, event, sample, machine);
1092 case PERF_RECORD_ITRACE_START:
1093 return tool->itrace_start(tool, event, sample, machine);
941 default: 1094 default:
942 ++evlist->stats.nr_unknown_events; 1095 ++evlist->stats.nr_unknown_events;
943 return -1; 1096 return -1;
944 } 1097 }
945} 1098}
946 1099
1100static int perf_session__deliver_event(struct perf_session *session,
1101 union perf_event *event,
1102 struct perf_sample *sample,
1103 struct perf_tool *tool,
1104 u64 file_offset)
1105{
1106 int ret;
1107
1108 ret = auxtrace__process_event(session, event, sample, tool);
1109 if (ret < 0)
1110 return ret;
1111 if (ret > 0)
1112 return 0;
1113
1114 return machines__deliver_event(&session->machines, session->evlist,
1115 event, sample, tool, file_offset);
1116}
1117
947static s64 perf_session__process_user_event(struct perf_session *session, 1118static s64 perf_session__process_user_event(struct perf_session *session,
948 union perf_event *event, 1119 union perf_event *event,
949 u64 file_offset) 1120 u64 file_offset)
@@ -980,6 +1151,15 @@ static s64 perf_session__process_user_event(struct perf_session *session,
980 return tool->finished_round(tool, event, oe); 1151 return tool->finished_round(tool, event, oe);
981 case PERF_RECORD_ID_INDEX: 1152 case PERF_RECORD_ID_INDEX:
982 return tool->id_index(tool, event, session); 1153 return tool->id_index(tool, event, session);
1154 case PERF_RECORD_AUXTRACE_INFO:
1155 return tool->auxtrace_info(tool, event, session);
1156 case PERF_RECORD_AUXTRACE:
1157 /* setup for reading amidst mmap */
1158 lseek(fd, file_offset + event->header.size, SEEK_SET);
1159 return tool->auxtrace(tool, event, session);
1160 case PERF_RECORD_AUXTRACE_ERROR:
1161 perf_session__auxtrace_error_inc(session, event);
1162 return tool->auxtrace_error(tool, event, session);
983 default: 1163 default:
984 return -EINVAL; 1164 return -EINVAL;
985 } 1165 }
@@ -1034,7 +1214,7 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset,
1034 return -1; 1214 return -1;
1035 1215
1036 if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 || 1216 if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 ||
1037 readn(fd, &buf, hdr_sz) != (ssize_t)hdr_sz) 1217 readn(fd, buf, hdr_sz) != (ssize_t)hdr_sz)
1038 return -1; 1218 return -1;
1039 1219
1040 event = (union perf_event *)buf; 1220 event = (union perf_event *)buf;
@@ -1042,12 +1222,12 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset,
1042 if (session->header.needs_swap) 1222 if (session->header.needs_swap)
1043 perf_event_header__bswap(&event->header); 1223 perf_event_header__bswap(&event->header);
1044 1224
1045 if (event->header.size < hdr_sz) 1225 if (event->header.size < hdr_sz || event->header.size > buf_sz)
1046 return -1; 1226 return -1;
1047 1227
1048 rest = event->header.size - hdr_sz; 1228 rest = event->header.size - hdr_sz;
1049 1229
1050 if (readn(fd, &buf, rest) != (ssize_t)rest) 1230 if (readn(fd, buf, rest) != (ssize_t)rest)
1051 return -1; 1231 return -1;
1052 1232
1053 if (session->header.needs_swap) 1233 if (session->header.needs_swap)
@@ -1096,8 +1276,8 @@ static s64 perf_session__process_event(struct perf_session *session,
1096 return ret; 1276 return ret;
1097 } 1277 }
1098 1278
1099 return machines__deliver_event(&session->machines, evlist, event, 1279 return perf_session__deliver_event(session, event, &sample, tool,
1100 &sample, tool, file_offset); 1280 file_offset);
1101} 1281}
1102 1282
1103void perf_event_header__bswap(struct perf_event_header *hdr) 1283void perf_event_header__bswap(struct perf_event_header *hdr)
@@ -1138,6 +1318,18 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
1138 stats->nr_events[PERF_RECORD_LOST]); 1318 stats->nr_events[PERF_RECORD_LOST]);
1139 } 1319 }
1140 1320
1321 if (session->tool->lost_samples == perf_event__process_lost_samples) {
1322 double drop_rate;
1323
1324 drop_rate = (double)stats->total_lost_samples /
1325 (double) (stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples);
1326 if (drop_rate > 0.05) {
1327 ui__warning("Processed %" PRIu64 " samples and lost %3.2f%% samples!\n\n",
1328 stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples,
1329 drop_rate * 100.0);
1330 }
1331 }
1332
1141 if (stats->nr_unknown_events != 0) { 1333 if (stats->nr_unknown_events != 0) {
1142 ui__warning("Found %u unknown events!\n\n" 1334 ui__warning("Found %u unknown events!\n\n"
1143 "Is this an older tool processing a perf.data " 1335 "Is this an older tool processing a perf.data "
@@ -1168,6 +1360,32 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
1168 1360
1169 if (oe->nr_unordered_events != 0) 1361 if (oe->nr_unordered_events != 0)
1170 ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events); 1362 ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events);
1363
1364 events_stats__auxtrace_error_warn(stats);
1365
1366 if (stats->nr_proc_map_timeout != 0) {
1367 ui__warning("%d map information files for pre-existing threads were\n"
1368 "not processed, if there are samples for addresses they\n"
1369 "will not be resolved, you may find out which are these\n"
1370 "threads by running with -v and redirecting the output\n"
1371 "to a file.\n"
1372 "The time limit to process proc map is too short?\n"
1373 "Increase it by --proc-map-timeout\n",
1374 stats->nr_proc_map_timeout);
1375 }
1376}
1377
1378static int perf_session__flush_thread_stack(struct thread *thread,
1379 void *p __maybe_unused)
1380{
1381 return thread_stack__flush(thread);
1382}
1383
1384static int perf_session__flush_thread_stacks(struct perf_session *session)
1385{
1386 return machines__for_each_thread(&session->machines,
1387 perf_session__flush_thread_stack,
1388 NULL);
1171} 1389}
1172 1390
1173volatile int session_done; 1391volatile int session_done;
@@ -1256,10 +1474,17 @@ more:
1256done: 1474done:
1257 /* do the final flush for ordered samples */ 1475 /* do the final flush for ordered samples */
1258 err = ordered_events__flush(oe, OE_FLUSH__FINAL); 1476 err = ordered_events__flush(oe, OE_FLUSH__FINAL);
1477 if (err)
1478 goto out_err;
1479 err = auxtrace__flush_events(session, tool);
1480 if (err)
1481 goto out_err;
1482 err = perf_session__flush_thread_stacks(session);
1259out_err: 1483out_err:
1260 free(buf); 1484 free(buf);
1261 perf_session__warn_about_errors(session); 1485 perf_session__warn_about_errors(session);
1262 ordered_events__free(&session->ordered_events); 1486 ordered_events__free(&session->ordered_events);
1487 auxtrace__free_events(session);
1263 return err; 1488 return err;
1264} 1489}
1265 1490
@@ -1402,10 +1627,17 @@ more:
1402out: 1627out:
1403 /* do the final flush for ordered samples */ 1628 /* do the final flush for ordered samples */
1404 err = ordered_events__flush(oe, OE_FLUSH__FINAL); 1629 err = ordered_events__flush(oe, OE_FLUSH__FINAL);
1630 if (err)
1631 goto out_err;
1632 err = auxtrace__flush_events(session, tool);
1633 if (err)
1634 goto out_err;
1635 err = perf_session__flush_thread_stacks(session);
1405out_err: 1636out_err:
1406 ui_progress__finish(); 1637 ui_progress__finish();
1407 perf_session__warn_about_errors(session); 1638 perf_session__warn_about_errors(session);
1408 ordered_events__free(&session->ordered_events); 1639 ordered_events__free(&session->ordered_events);
1640 auxtrace__free_events(session);
1409 session->one_mmap = false; 1641 session->one_mmap = false;
1410 return err; 1642 return err;
1411} 1643}
@@ -1488,7 +1720,13 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp
1488 1720
1489size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) 1721size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1490{ 1722{
1491 size_t ret = fprintf(fp, "Aggregated stats:\n"); 1723 size_t ret;
1724 const char *msg = "";
1725
1726 if (perf_header__has_feat(&session->header, HEADER_AUXTRACE))
1727 msg = " (excludes AUX area (e.g. instruction trace) decoded / synthesized events)";
1728
1729 ret = fprintf(fp, "Aggregated stats:%s\n", msg);
1492 1730
1493 ret += events_stats__fprintf(&session->evlist->stats, fp); 1731 ret += events_stats__fprintf(&session->evlist->stats, fp);
1494 return ret; 1732 return ret;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index d5fa7b7916ef..b44afc75d1cc 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -15,10 +15,16 @@
15struct ip_callchain; 15struct ip_callchain;
16struct thread; 16struct thread;
17 17
18struct auxtrace;
19struct itrace_synth_opts;
20
18struct perf_session { 21struct perf_session {
19 struct perf_header header; 22 struct perf_header header;
20 struct machines machines; 23 struct machines machines;
21 struct perf_evlist *evlist; 24 struct perf_evlist *evlist;
25 struct auxtrace *auxtrace;
26 struct itrace_synth_opts *itrace_synth_opts;
27 struct list_head auxtrace_index;
22 struct trace_event tevent; 28 struct trace_event tevent;
23 bool repipe; 29 bool repipe;
24 bool one_mmap; 30 bool one_mmap;
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 4593f36ecc4c..4c65a143a34c 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -89,14 +89,14 @@ static int64_t
89sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) 89sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
90{ 90{
91 /* Compare the addr that should be unique among comm */ 91 /* Compare the addr that should be unique among comm */
92 return comm__str(right->comm) - comm__str(left->comm); 92 return strcmp(comm__str(right->comm), comm__str(left->comm));
93} 93}
94 94
95static int64_t 95static int64_t
96sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) 96sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
97{ 97{
98 /* Compare the addr that should be unique among comm */ 98 /* Compare the addr that should be unique among comm */
99 return comm__str(right->comm) - comm__str(left->comm); 99 return strcmp(comm__str(right->comm), comm__str(left->comm));
100} 100}
101 101
102static int64_t 102static int64_t
@@ -182,18 +182,16 @@ static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip)
182 182
183static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r) 183static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
184{ 184{
185 u64 ip_l, ip_r;
186
187 if (!sym_l || !sym_r) 185 if (!sym_l || !sym_r)
188 return cmp_null(sym_l, sym_r); 186 return cmp_null(sym_l, sym_r);
189 187
190 if (sym_l == sym_r) 188 if (sym_l == sym_r)
191 return 0; 189 return 0;
192 190
193 ip_l = sym_l->start; 191 if (sym_l->start != sym_r->start)
194 ip_r = sym_r->start; 192 return (int64_t)(sym_r->start - sym_l->start);
195 193
196 return (int64_t)(ip_r - ip_l); 194 return (int64_t)(sym_r->end - sym_l->end);
197} 195}
198 196
199static int64_t 197static int64_t
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 846036a921dc..e97cd476d336 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -58,15 +58,16 @@ struct he_stat {
58 58
59struct hist_entry_diff { 59struct hist_entry_diff {
60 bool computed; 60 bool computed;
61 union {
62 /* PERF_HPP__DELTA */
63 double period_ratio_delta;
61 64
62 /* PERF_HPP__DELTA */ 65 /* PERF_HPP__RATIO */
63 double period_ratio_delta; 66 double period_ratio;
64
65 /* PERF_HPP__RATIO */
66 double period_ratio;
67 67
68 /* HISTC_WEIGHTED_DIFF */ 68 /* HISTC_WEIGHTED_DIFF */
69 s64 wdiff; 69 s64 wdiff;
70 };
70}; 71};
71 72
72/** 73/**
@@ -92,21 +93,28 @@ struct hist_entry {
92 s32 cpu; 93 s32 cpu;
93 u8 cpumode; 94 u8 cpumode;
94 95
95 struct hist_entry_diff diff;
96
97 /* We are added by hists__add_dummy_entry. */ 96 /* We are added by hists__add_dummy_entry. */
98 bool dummy; 97 bool dummy;
99 98
100 /* XXX These two should move to some tree widget lib */
101 u16 row_offset;
102 u16 nr_rows;
103
104 bool init_have_children;
105 char level; 99 char level;
106 u8 filtered; 100 u8 filtered;
101 union {
102 /*
103 * Since perf diff only supports the stdio output, TUI
104 * fields are only accessed from perf report (or perf
105 * top). So make it an union to reduce memory usage.
106 */
107 struct hist_entry_diff diff;
108 struct /* for TUI */ {
109 u16 row_offset;
110 u16 nr_rows;
111 bool init_have_children;
112 bool unfolded;
113 bool has_children;
114 };
115 };
107 char *srcline; 116 char *srcline;
108 struct symbol *parent; 117 struct symbol *parent;
109 unsigned long position;
110 struct rb_root sorted_chain; 118 struct rb_root sorted_chain;
111 struct branch_info *branch_info; 119 struct branch_info *branch_info;
112 struct hists *hists; 120 struct hists *hists;
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
new file mode 100644
index 000000000000..53e8bb7bc852
--- /dev/null
+++ b/tools/perf/util/stat-shadow.c
@@ -0,0 +1,434 @@
1#include <stdio.h>
2#include "evsel.h"
3#include "stat.h"
4#include "color.h"
5
6enum {
7 CTX_BIT_USER = 1 << 0,
8 CTX_BIT_KERNEL = 1 << 1,
9 CTX_BIT_HV = 1 << 2,
10 CTX_BIT_HOST = 1 << 3,
11 CTX_BIT_IDLE = 1 << 4,
12 CTX_BIT_MAX = 1 << 5,
13};
14
15#define NUM_CTX CTX_BIT_MAX
16
17static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
18static struct stats runtime_cycles_stats[NUM_CTX][MAX_NR_CPUS];
19static struct stats runtime_stalled_cycles_front_stats[NUM_CTX][MAX_NR_CPUS];
20static struct stats runtime_stalled_cycles_back_stats[NUM_CTX][MAX_NR_CPUS];
21static struct stats runtime_branches_stats[NUM_CTX][MAX_NR_CPUS];
22static struct stats runtime_cacherefs_stats[NUM_CTX][MAX_NR_CPUS];
23static struct stats runtime_l1_dcache_stats[NUM_CTX][MAX_NR_CPUS];
24static struct stats runtime_l1_icache_stats[NUM_CTX][MAX_NR_CPUS];
25static struct stats runtime_ll_cache_stats[NUM_CTX][MAX_NR_CPUS];
26static struct stats runtime_itlb_cache_stats[NUM_CTX][MAX_NR_CPUS];
27static struct stats runtime_dtlb_cache_stats[NUM_CTX][MAX_NR_CPUS];
28static struct stats runtime_cycles_in_tx_stats[NUM_CTX][MAX_NR_CPUS];
29static struct stats runtime_transaction_stats[NUM_CTX][MAX_NR_CPUS];
30static struct stats runtime_elision_stats[NUM_CTX][MAX_NR_CPUS];
31
32struct stats walltime_nsecs_stats;
33
34static int evsel_context(struct perf_evsel *evsel)
35{
36 int ctx = 0;
37
38 if (evsel->attr.exclude_kernel)
39 ctx |= CTX_BIT_KERNEL;
40 if (evsel->attr.exclude_user)
41 ctx |= CTX_BIT_USER;
42 if (evsel->attr.exclude_hv)
43 ctx |= CTX_BIT_HV;
44 if (evsel->attr.exclude_host)
45 ctx |= CTX_BIT_HOST;
46 if (evsel->attr.exclude_idle)
47 ctx |= CTX_BIT_IDLE;
48
49 return ctx;
50}
51
52void perf_stat__reset_shadow_stats(void)
53{
54 memset(runtime_nsecs_stats, 0, sizeof(runtime_nsecs_stats));
55 memset(runtime_cycles_stats, 0, sizeof(runtime_cycles_stats));
56 memset(runtime_stalled_cycles_front_stats, 0, sizeof(runtime_stalled_cycles_front_stats));
57 memset(runtime_stalled_cycles_back_stats, 0, sizeof(runtime_stalled_cycles_back_stats));
58 memset(runtime_branches_stats, 0, sizeof(runtime_branches_stats));
59 memset(runtime_cacherefs_stats, 0, sizeof(runtime_cacherefs_stats));
60 memset(runtime_l1_dcache_stats, 0, sizeof(runtime_l1_dcache_stats));
61 memset(runtime_l1_icache_stats, 0, sizeof(runtime_l1_icache_stats));
62 memset(runtime_ll_cache_stats, 0, sizeof(runtime_ll_cache_stats));
63 memset(runtime_itlb_cache_stats, 0, sizeof(runtime_itlb_cache_stats));
64 memset(runtime_dtlb_cache_stats, 0, sizeof(runtime_dtlb_cache_stats));
65 memset(runtime_cycles_in_tx_stats, 0,
66 sizeof(runtime_cycles_in_tx_stats));
67 memset(runtime_transaction_stats, 0,
68 sizeof(runtime_transaction_stats));
69 memset(runtime_elision_stats, 0, sizeof(runtime_elision_stats));
70 memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats));
71}
72
73/*
74 * Update various tracking values we maintain to print
75 * more semantic information such as miss/hit ratios,
76 * instruction rates, etc:
77 */
78void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,
79 int cpu)
80{
81 int ctx = evsel_context(counter);
82
83 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
84 update_stats(&runtime_nsecs_stats[cpu], count[0]);
85 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
86 update_stats(&runtime_cycles_stats[ctx][cpu], count[0]);
87 else if (perf_stat_evsel__is(counter, CYCLES_IN_TX))
88 update_stats(&runtime_transaction_stats[ctx][cpu], count[0]);
89 else if (perf_stat_evsel__is(counter, TRANSACTION_START))
90 update_stats(&runtime_transaction_stats[ctx][cpu], count[0]);
91 else if (perf_stat_evsel__is(counter, ELISION_START))
92 update_stats(&runtime_elision_stats[ctx][cpu], count[0]);
93 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
94 update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count[0]);
95 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
96 update_stats(&runtime_stalled_cycles_back_stats[ctx][cpu], count[0]);
97 else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
98 update_stats(&runtime_branches_stats[ctx][cpu], count[0]);
99 else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES))
100 update_stats(&runtime_cacherefs_stats[ctx][cpu], count[0]);
101 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D))
102 update_stats(&runtime_l1_dcache_stats[ctx][cpu], count[0]);
103 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I))
104 update_stats(&runtime_ll_cache_stats[ctx][cpu], count[0]);
105 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL))
106 update_stats(&runtime_ll_cache_stats[ctx][cpu], count[0]);
107 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB))
108 update_stats(&runtime_dtlb_cache_stats[ctx][cpu], count[0]);
109 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB))
110 update_stats(&runtime_itlb_cache_stats[ctx][cpu], count[0]);
111}
112
113/* used for get_ratio_color() */
114enum grc_type {
115 GRC_STALLED_CYCLES_FE,
116 GRC_STALLED_CYCLES_BE,
117 GRC_CACHE_MISSES,
118 GRC_MAX_NR
119};
120
121static const char *get_ratio_color(enum grc_type type, double ratio)
122{
123 static const double grc_table[GRC_MAX_NR][3] = {
124 [GRC_STALLED_CYCLES_FE] = { 50.0, 30.0, 10.0 },
125 [GRC_STALLED_CYCLES_BE] = { 75.0, 50.0, 20.0 },
126 [GRC_CACHE_MISSES] = { 20.0, 10.0, 5.0 },
127 };
128 const char *color = PERF_COLOR_NORMAL;
129
130 if (ratio > grc_table[type][0])
131 color = PERF_COLOR_RED;
132 else if (ratio > grc_table[type][1])
133 color = PERF_COLOR_MAGENTA;
134 else if (ratio > grc_table[type][2])
135 color = PERF_COLOR_YELLOW;
136
137 return color;
138}
139
140static void print_stalled_cycles_frontend(FILE *out, int cpu,
141 struct perf_evsel *evsel
142 __maybe_unused, double avg)
143{
144 double total, ratio = 0.0;
145 const char *color;
146 int ctx = evsel_context(evsel);
147
148 total = avg_stats(&runtime_cycles_stats[ctx][cpu]);
149
150 if (total)
151 ratio = avg / total * 100.0;
152
153 color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio);
154
155 fprintf(out, " # ");
156 color_fprintf(out, color, "%6.2f%%", ratio);
157 fprintf(out, " frontend cycles idle ");
158}
159
160static void print_stalled_cycles_backend(FILE *out, int cpu,
161 struct perf_evsel *evsel
162 __maybe_unused, double avg)
163{
164 double total, ratio = 0.0;
165 const char *color;
166 int ctx = evsel_context(evsel);
167
168 total = avg_stats(&runtime_cycles_stats[ctx][cpu]);
169
170 if (total)
171 ratio = avg / total * 100.0;
172
173 color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio);
174
175 fprintf(out, " # ");
176 color_fprintf(out, color, "%6.2f%%", ratio);
177 fprintf(out, " backend cycles idle ");
178}
179
180static void print_branch_misses(FILE *out, int cpu,
181 struct perf_evsel *evsel __maybe_unused,
182 double avg)
183{
184 double total, ratio = 0.0;
185 const char *color;
186 int ctx = evsel_context(evsel);
187
188 total = avg_stats(&runtime_branches_stats[ctx][cpu]);
189
190 if (total)
191 ratio = avg / total * 100.0;
192
193 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
194
195 fprintf(out, " # ");
196 color_fprintf(out, color, "%6.2f%%", ratio);
197 fprintf(out, " of all branches ");
198}
199
200static void print_l1_dcache_misses(FILE *out, int cpu,
201 struct perf_evsel *evsel __maybe_unused,
202 double avg)
203{
204 double total, ratio = 0.0;
205 const char *color;
206 int ctx = evsel_context(evsel);
207
208 total = avg_stats(&runtime_l1_dcache_stats[ctx][cpu]);
209
210 if (total)
211 ratio = avg / total * 100.0;
212
213 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
214
215 fprintf(out, " # ");
216 color_fprintf(out, color, "%6.2f%%", ratio);
217 fprintf(out, " of all L1-dcache hits ");
218}
219
220static void print_l1_icache_misses(FILE *out, int cpu,
221 struct perf_evsel *evsel __maybe_unused,
222 double avg)
223{
224 double total, ratio = 0.0;
225 const char *color;
226 int ctx = evsel_context(evsel);
227
228 total = avg_stats(&runtime_l1_icache_stats[ctx][cpu]);
229
230 if (total)
231 ratio = avg / total * 100.0;
232
233 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
234
235 fprintf(out, " # ");
236 color_fprintf(out, color, "%6.2f%%", ratio);
237 fprintf(out, " of all L1-icache hits ");
238}
239
240static void print_dtlb_cache_misses(FILE *out, int cpu,
241 struct perf_evsel *evsel __maybe_unused,
242 double avg)
243{
244 double total, ratio = 0.0;
245 const char *color;
246 int ctx = evsel_context(evsel);
247
248 total = avg_stats(&runtime_dtlb_cache_stats[ctx][cpu]);
249
250 if (total)
251 ratio = avg / total * 100.0;
252
253 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
254
255 fprintf(out, " # ");
256 color_fprintf(out, color, "%6.2f%%", ratio);
257 fprintf(out, " of all dTLB cache hits ");
258}
259
260static void print_itlb_cache_misses(FILE *out, int cpu,
261 struct perf_evsel *evsel __maybe_unused,
262 double avg)
263{
264 double total, ratio = 0.0;
265 const char *color;
266 int ctx = evsel_context(evsel);
267
268 total = avg_stats(&runtime_itlb_cache_stats[ctx][cpu]);
269
270 if (total)
271 ratio = avg / total * 100.0;
272
273 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
274
275 fprintf(out, " # ");
276 color_fprintf(out, color, "%6.2f%%", ratio);
277 fprintf(out, " of all iTLB cache hits ");
278}
279
280static void print_ll_cache_misses(FILE *out, int cpu,
281 struct perf_evsel *evsel __maybe_unused,
282 double avg)
283{
284 double total, ratio = 0.0;
285 const char *color;
286 int ctx = evsel_context(evsel);
287
288 total = avg_stats(&runtime_ll_cache_stats[ctx][cpu]);
289
290 if (total)
291 ratio = avg / total * 100.0;
292
293 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
294
295 fprintf(out, " # ");
296 color_fprintf(out, color, "%6.2f%%", ratio);
297 fprintf(out, " of all LL-cache hits ");
298}
299
300void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel,
301 double avg, int cpu, enum aggr_mode aggr)
302{
303 double total, ratio = 0.0, total2;
304 int ctx = evsel_context(evsel);
305
306 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
307 total = avg_stats(&runtime_cycles_stats[ctx][cpu]);
308 if (total) {
309 ratio = avg / total;
310 fprintf(out, " # %5.2f insns per cycle ", ratio);
311 } else {
312 fprintf(out, " ");
313 }
314 total = avg_stats(&runtime_stalled_cycles_front_stats[ctx][cpu]);
315 total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[ctx][cpu]));
316
317 if (total && avg) {
318 ratio = total / avg;
319 fprintf(out, "\n");
320 if (aggr == AGGR_NONE)
321 fprintf(out, " ");
322 fprintf(out, " # %5.2f stalled cycles per insn", ratio);
323 }
324
325 } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
326 runtime_branches_stats[ctx][cpu].n != 0) {
327 print_branch_misses(out, cpu, evsel, avg);
328 } else if (
329 evsel->attr.type == PERF_TYPE_HW_CACHE &&
330 evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1D |
331 ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
332 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
333 runtime_l1_dcache_stats[ctx][cpu].n != 0) {
334 print_l1_dcache_misses(out, cpu, evsel, avg);
335 } else if (
336 evsel->attr.type == PERF_TYPE_HW_CACHE &&
337 evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1I |
338 ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
339 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
340 runtime_l1_icache_stats[ctx][cpu].n != 0) {
341 print_l1_icache_misses(out, cpu, evsel, avg);
342 } else if (
343 evsel->attr.type == PERF_TYPE_HW_CACHE &&
344 evsel->attr.config == ( PERF_COUNT_HW_CACHE_DTLB |
345 ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
346 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
347 runtime_dtlb_cache_stats[ctx][cpu].n != 0) {
348 print_dtlb_cache_misses(out, cpu, evsel, avg);
349 } else if (
350 evsel->attr.type == PERF_TYPE_HW_CACHE &&
351 evsel->attr.config == ( PERF_COUNT_HW_CACHE_ITLB |
352 ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
353 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
354 runtime_itlb_cache_stats[ctx][cpu].n != 0) {
355 print_itlb_cache_misses(out, cpu, evsel, avg);
356 } else if (
357 evsel->attr.type == PERF_TYPE_HW_CACHE &&
358 evsel->attr.config == ( PERF_COUNT_HW_CACHE_LL |
359 ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
360 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
361 runtime_ll_cache_stats[ctx][cpu].n != 0) {
362 print_ll_cache_misses(out, cpu, evsel, avg);
363 } else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES) &&
364 runtime_cacherefs_stats[ctx][cpu].n != 0) {
365 total = avg_stats(&runtime_cacherefs_stats[ctx][cpu]);
366
367 if (total)
368 ratio = avg * 100 / total;
369
370 fprintf(out, " # %8.3f %% of all cache refs ", ratio);
371
372 } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) {
373 print_stalled_cycles_frontend(out, cpu, evsel, avg);
374 } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) {
375 print_stalled_cycles_backend(out, cpu, evsel, avg);
376 } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
377 total = avg_stats(&runtime_nsecs_stats[cpu]);
378
379 if (total) {
380 ratio = avg / total;
381 fprintf(out, " # %8.3f GHz ", ratio);
382 } else {
383 fprintf(out, " ");
384 }
385 } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX)) {
386 total = avg_stats(&runtime_cycles_stats[ctx][cpu]);
387 if (total)
388 fprintf(out,
389 " # %5.2f%% transactional cycles ",
390 100.0 * (avg / total));
391 } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX_CP)) {
392 total = avg_stats(&runtime_cycles_stats[ctx][cpu]);
393 total2 = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]);
394 if (total2 < avg)
395 total2 = avg;
396 if (total)
397 fprintf(out,
398 " # %5.2f%% aborted cycles ",
399 100.0 * ((total2-avg) / total));
400 } else if (perf_stat_evsel__is(evsel, TRANSACTION_START) &&
401 avg > 0 &&
402 runtime_cycles_in_tx_stats[ctx][cpu].n != 0) {
403 total = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]);
404
405 if (total)
406 ratio = total / avg;
407
408 fprintf(out, " # %8.0f cycles / transaction ", ratio);
409 } else if (perf_stat_evsel__is(evsel, ELISION_START) &&
410 avg > 0 &&
411 runtime_cycles_in_tx_stats[ctx][cpu].n != 0) {
412 total = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]);
413
414 if (total)
415 ratio = total / avg;
416
417 fprintf(out, " # %8.0f cycles / elision ", ratio);
418 } else if (runtime_nsecs_stats[cpu].n != 0) {
419 char unit = 'M';
420
421 total = avg_stats(&runtime_nsecs_stats[cpu]);
422
423 if (total)
424 ratio = 1000.0 * avg / total;
425 if (ratio < 0.001) {
426 ratio *= 1000;
427 unit = 'K';
428 }
429
430 fprintf(out, " # %8.3f %c/sec ", ratio, unit);
431 } else {
432 fprintf(out, " ");
433 }
434}
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 6506b3dfb605..4014b709f956 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -1,6 +1,6 @@
1#include <math.h> 1#include <math.h>
2
3#include "stat.h" 2#include "stat.h"
3#include "evsel.h"
4 4
5void update_stats(struct stats *stats, u64 val) 5void update_stats(struct stats *stats, u64 val)
6{ 6{
@@ -61,3 +61,72 @@ double rel_stddev_stats(double stddev, double avg)
61 61
62 return pct; 62 return pct;
63} 63}
64
65bool __perf_evsel_stat__is(struct perf_evsel *evsel,
66 enum perf_stat_evsel_id id)
67{
68 struct perf_stat *ps = evsel->priv;
69
70 return ps->id == id;
71}
72
73#define ID(id, name) [PERF_STAT_EVSEL_ID__##id] = #name
74static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
75 ID(NONE, x),
76 ID(CYCLES_IN_TX, cpu/cycles-t/),
77 ID(TRANSACTION_START, cpu/tx-start/),
78 ID(ELISION_START, cpu/el-start/),
79 ID(CYCLES_IN_TX_CP, cpu/cycles-ct/),
80};
81#undef ID
82
83void perf_stat_evsel_id_init(struct perf_evsel *evsel)
84{
85 struct perf_stat *ps = evsel->priv;
86 int i;
87
88 /* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
89
90 for (i = 0; i < PERF_STAT_EVSEL_ID__MAX; i++) {
91 if (!strcmp(perf_evsel__name(evsel), id_str[i])) {
92 ps->id = i;
93 break;
94 }
95 }
96}
97
98struct perf_counts *perf_counts__new(int ncpus)
99{
100 int size = sizeof(struct perf_counts) +
101 ncpus * sizeof(struct perf_counts_values);
102
103 return zalloc(size);
104}
105
106void perf_counts__delete(struct perf_counts *counts)
107{
108 free(counts);
109}
110
111static void perf_counts__reset(struct perf_counts *counts, int ncpus)
112{
113 memset(counts, 0, (sizeof(*counts) +
114 (ncpus * sizeof(struct perf_counts_values))));
115}
116
117void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus)
118{
119 perf_counts__reset(evsel->counts, ncpus);
120}
121
122int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
123{
124 evsel->counts = perf_counts__new(ncpus);
125 return evsel->counts != NULL ? 0 : -ENOMEM;
126}
127
128void perf_evsel__free_counts(struct perf_evsel *evsel)
129{
130 perf_counts__delete(evsel->counts);
131 evsel->counts = NULL;
132}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 5667fc3e39cf..093dc3cb28dd 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -2,6 +2,7 @@
2#define __PERF_STATS_H 2#define __PERF_STATS_H
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include <stdio.h>
5 6
6struct stats 7struct stats
7{ 8{
@@ -9,6 +10,27 @@ struct stats
9 u64 max, min; 10 u64 max, min;
10}; 11};
11 12
13enum perf_stat_evsel_id {
14 PERF_STAT_EVSEL_ID__NONE = 0,
15 PERF_STAT_EVSEL_ID__CYCLES_IN_TX,
16 PERF_STAT_EVSEL_ID__TRANSACTION_START,
17 PERF_STAT_EVSEL_ID__ELISION_START,
18 PERF_STAT_EVSEL_ID__CYCLES_IN_TX_CP,
19 PERF_STAT_EVSEL_ID__MAX,
20};
21
22struct perf_stat {
23 struct stats res_stats[3];
24 enum perf_stat_evsel_id id;
25};
26
27enum aggr_mode {
28 AGGR_NONE,
29 AGGR_GLOBAL,
30 AGGR_SOCKET,
31 AGGR_CORE,
32};
33
12void update_stats(struct stats *stats, u64 val); 34void update_stats(struct stats *stats, u64 val);
13double avg_stats(struct stats *stats); 35double avg_stats(struct stats *stats);
14double stddev_stats(struct stats *stats); 36double stddev_stats(struct stats *stats);
@@ -22,4 +44,28 @@ static inline void init_stats(struct stats *stats)
22 stats->min = (u64) -1; 44 stats->min = (u64) -1;
23 stats->max = 0; 45 stats->max = 0;
24} 46}
47
48struct perf_evsel;
49bool __perf_evsel_stat__is(struct perf_evsel *evsel,
50 enum perf_stat_evsel_id id);
51
52#define perf_stat_evsel__is(evsel, id) \
53 __perf_evsel_stat__is(evsel, PERF_STAT_EVSEL_ID__ ## id)
54
55void perf_stat_evsel_id_init(struct perf_evsel *evsel);
56
57extern struct stats walltime_nsecs_stats;
58
59void perf_stat__reset_shadow_stats(void);
60void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,
61 int cpu);
62void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel,
63 double avg, int cpu, enum aggr_mode aggr);
64
65struct perf_counts *perf_counts__new(int ncpus);
66void perf_counts__delete(struct perf_counts *counts);
67
68void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
69int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
70void perf_evsel__free_counts(struct perf_evsel *evsel);
25#endif 71#endif
diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c
index 79a757a2a15c..bcae659b6546 100644
--- a/tools/perf/util/strfilter.c
+++ b/tools/perf/util/strfilter.c
@@ -170,6 +170,46 @@ struct strfilter *strfilter__new(const char *rules, const char **err)
170 return filter; 170 return filter;
171} 171}
172 172
173static int strfilter__append(struct strfilter *filter, bool _or,
174 const char *rules, const char **err)
175{
176 struct strfilter_node *right, *root;
177 const char *ep = NULL;
178
179 if (!filter || !rules)
180 return -EINVAL;
181
182 right = strfilter_node__new(rules, &ep);
183 if (!right || *ep != '\0') {
184 if (err)
185 *err = ep;
186 goto error;
187 }
188 root = strfilter_node__alloc(_or ? OP_or : OP_and, filter->root, right);
189 if (!root) {
190 ep = NULL;
191 goto error;
192 }
193
194 filter->root = root;
195 return 0;
196
197error:
198 strfilter_node__delete(right);
199 return ep ? -EINVAL : -ENOMEM;
200}
201
202int strfilter__or(struct strfilter *filter, const char *rules, const char **err)
203{
204 return strfilter__append(filter, true, rules, err);
205}
206
207int strfilter__and(struct strfilter *filter, const char *rules,
208 const char **err)
209{
210 return strfilter__append(filter, false, rules, err);
211}
212
173static bool strfilter_node__compare(struct strfilter_node *node, 213static bool strfilter_node__compare(struct strfilter_node *node,
174 const char *str) 214 const char *str)
175{ 215{
@@ -197,3 +237,70 @@ bool strfilter__compare(struct strfilter *filter, const char *str)
197 return false; 237 return false;
198 return strfilter_node__compare(filter->root, str); 238 return strfilter_node__compare(filter->root, str);
199} 239}
240
241static int strfilter_node__sprint(struct strfilter_node *node, char *buf);
242
243/* sprint node in parenthesis if needed */
244static int strfilter_node__sprint_pt(struct strfilter_node *node, char *buf)
245{
246 int len;
247 int pt = node->r ? 2 : 0; /* don't need to check node->l */
248
249 if (buf && pt)
250 *buf++ = '(';
251 len = strfilter_node__sprint(node, buf);
252 if (len < 0)
253 return len;
254 if (buf && pt)
255 *(buf + len) = ')';
256 return len + pt;
257}
258
259static int strfilter_node__sprint(struct strfilter_node *node, char *buf)
260{
261 int len = 0, rlen;
262
263 if (!node || !node->p)
264 return -EINVAL;
265
266 switch (*node->p) {
267 case '|':
268 case '&':
269 len = strfilter_node__sprint_pt(node->l, buf);
270 if (len < 0)
271 return len;
272 case '!':
273 if (buf) {
274 *(buf + len++) = *node->p;
275 buf += len;
276 } else
277 len++;
278 rlen = strfilter_node__sprint_pt(node->r, buf);
279 if (rlen < 0)
280 return rlen;
281 len += rlen;
282 break;
283 default:
284 len = strlen(node->p);
285 if (buf)
286 strcpy(buf, node->p);
287 }
288
289 return len;
290}
291
292char *strfilter__string(struct strfilter *filter)
293{
294 int len;
295 char *ret = NULL;
296
297 len = strfilter_node__sprint(filter->root, NULL);
298 if (len < 0)
299 return NULL;
300
301 ret = malloc(len + 1);
302 if (ret)
303 strfilter_node__sprint(filter->root, ret);
304
305 return ret;
306}
diff --git a/tools/perf/util/strfilter.h b/tools/perf/util/strfilter.h
index fe611f3c9e39..cff5eda88728 100644
--- a/tools/perf/util/strfilter.h
+++ b/tools/perf/util/strfilter.h
@@ -29,6 +29,32 @@ struct strfilter {
29struct strfilter *strfilter__new(const char *rules, const char **err); 29struct strfilter *strfilter__new(const char *rules, const char **err);
30 30
31/** 31/**
32 * strfilter__or - Append an additional rule by logical-or
33 * @filter: Original string filter
34 * @rules: Filter rule to be appended at left of the root of
35 * @filter by using logical-or.
36 * @err: Pointer which points an error detected on @rules
37 *
38 * Parse @rules and join it to the @filter by using logical-or.
39 * Return 0 if success, or return the error code.
40 */
41int strfilter__or(struct strfilter *filter,
42 const char *rules, const char **err);
43
44/**
45 * strfilter__add - Append an additional rule by logical-and
46 * @filter: Original string filter
47 * @rules: Filter rule to be appended at left of the root of
48 * @filter by using logical-and.
49 * @err: Pointer which points an error detected on @rules
50 *
51 * Parse @rules and join it to the @filter by using logical-and.
52 * Return 0 if success, or return the error code.
53 */
54int strfilter__and(struct strfilter *filter,
55 const char *rules, const char **err);
56
57/**
32 * strfilter__compare - compare given string and a string filter 58 * strfilter__compare - compare given string and a string filter
33 * @filter: String filter 59 * @filter: String filter
34 * @str: target string 60 * @str: target string
@@ -45,4 +71,13 @@ bool strfilter__compare(struct strfilter *filter, const char *str);
45 */ 71 */
46void strfilter__delete(struct strfilter *filter); 72void strfilter__delete(struct strfilter *filter);
47 73
74/**
75 * strfilter__string - Reconstruct a rule string from filter
76 * @filter: String filter to reconstruct
77 *
78 * Reconstruct a rule string from @filter. This will be good for
79 * debug messages. Note that returning string must be freed afterward.
80 */
81char *strfilter__string(struct strfilter *filter);
82
48#endif 83#endif
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index a7ab6063e038..65f7e389ae09 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -630,6 +630,11 @@ void symsrc__destroy(struct symsrc *ss)
630 close(ss->fd); 630 close(ss->fd);
631} 631}
632 632
633bool __weak elf__needs_adjust_symbols(GElf_Ehdr ehdr)
634{
635 return ehdr.e_type == ET_EXEC || ehdr.e_type == ET_REL;
636}
637
633int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, 638int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
634 enum dso_binary_type type) 639 enum dso_binary_type type)
635{ 640{
@@ -678,6 +683,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
678 } 683 }
679 684
680 if (!dso__build_id_equal(dso, build_id)) { 685 if (!dso__build_id_equal(dso, build_id)) {
686 pr_debug("%s: build id mismatch for %s.\n", __func__, name);
681 dso->load_errno = DSO_LOAD_ERRNO__MISMATCHING_BUILDID; 687 dso->load_errno = DSO_LOAD_ERRNO__MISMATCHING_BUILDID;
682 goto out_elf_end; 688 goto out_elf_end;
683 } 689 }
@@ -711,8 +717,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
711 ".gnu.prelink_undo", 717 ".gnu.prelink_undo",
712 NULL) != NULL); 718 NULL) != NULL);
713 } else { 719 } else {
714 ss->adjust_symbols = ehdr.e_type == ET_EXEC || 720 ss->adjust_symbols = elf__needs_adjust_symbols(ehdr);
715 ehdr.e_type == ET_REL;
716 } 721 }
717 722
718 ss->name = strdup(name); 723 ss->name = strdup(name);
@@ -771,6 +776,8 @@ static bool want_demangle(bool is_kernel_sym)
771 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle; 776 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
772} 777}
773 778
779void __weak arch__elf_sym_adjust(GElf_Sym *sym __maybe_unused) { }
780
774int dso__load_sym(struct dso *dso, struct map *map, 781int dso__load_sym(struct dso *dso, struct map *map,
775 struct symsrc *syms_ss, struct symsrc *runtime_ss, 782 struct symsrc *syms_ss, struct symsrc *runtime_ss,
776 symbol_filter_t filter, int kmodule) 783 symbol_filter_t filter, int kmodule)
@@ -935,6 +942,8 @@ int dso__load_sym(struct dso *dso, struct map *map,
935 (sym.st_value & 1)) 942 (sym.st_value & 1))
936 --sym.st_value; 943 --sym.st_value;
937 944
945 arch__elf_sym_adjust(&sym);
946
938 if (dso->kernel || kmodule) { 947 if (dso->kernel || kmodule) {
939 char dso_name[PATH_MAX]; 948 char dso_name[PATH_MAX];
940 949
@@ -963,8 +972,10 @@ int dso__load_sym(struct dso *dso, struct map *map,
963 map->unmap_ip = map__unmap_ip; 972 map->unmap_ip = map__unmap_ip;
964 /* Ensure maps are correctly ordered */ 973 /* Ensure maps are correctly ordered */
965 if (kmaps) { 974 if (kmaps) {
975 map__get(map);
966 map_groups__remove(kmaps, map); 976 map_groups__remove(kmaps, map);
967 map_groups__insert(kmaps, map); 977 map_groups__insert(kmaps, map);
978 map__put(map);
968 } 979 }
969 } 980 }
970 981
@@ -1005,7 +1016,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
1005 curr_map = map__new2(start, curr_dso, 1016 curr_map = map__new2(start, curr_dso,
1006 map->type); 1017 map->type);
1007 if (curr_map == NULL) { 1018 if (curr_map == NULL) {
1008 dso__delete(curr_dso); 1019 dso__put(curr_dso);
1009 goto out_elf_end; 1020 goto out_elf_end;
1010 } 1021 }
1011 if (adjust_kernel_syms) { 1022 if (adjust_kernel_syms) {
@@ -1020,11 +1031,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
1020 } 1031 }
1021 curr_dso->symtab_type = dso->symtab_type; 1032 curr_dso->symtab_type = dso->symtab_type;
1022 map_groups__insert(kmaps, curr_map); 1033 map_groups__insert(kmaps, curr_map);
1023 /* 1034 dsos__add(&map->groups->machine->dsos, curr_dso);
1024 * The new DSO should go to the kernel DSOS
1025 */
1026 dsos__add(&map->groups->machine->kernel_dsos,
1027 curr_dso);
1028 dso__set_loaded(curr_dso, map->type); 1035 dso__set_loaded(curr_dso, map->type);
1029 } else 1036 } else
1030 curr_dso = curr_map->dso; 1037 curr_dso = curr_map->dso;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 201f6c4ca738..504f2d73b7ee 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -85,8 +85,17 @@ static int prefix_underscores_count(const char *str)
85 return tail - str; 85 return tail - str;
86} 86}
87 87
88#define SYMBOL_A 0 88int __weak arch__choose_best_symbol(struct symbol *syma,
89#define SYMBOL_B 1 89 struct symbol *symb __maybe_unused)
90{
91 /* Avoid "SyS" kernel syscall aliases */
92 if (strlen(syma->name) >= 3 && !strncmp(syma->name, "SyS", 3))
93 return SYMBOL_B;
94 if (strlen(syma->name) >= 10 && !strncmp(syma->name, "compat_SyS", 10))
95 return SYMBOL_B;
96
97 return SYMBOL_A;
98}
90 99
91static int choose_best_symbol(struct symbol *syma, struct symbol *symb) 100static int choose_best_symbol(struct symbol *syma, struct symbol *symb)
92{ 101{
@@ -134,13 +143,7 @@ static int choose_best_symbol(struct symbol *syma, struct symbol *symb)
134 else if (na < nb) 143 else if (na < nb)
135 return SYMBOL_B; 144 return SYMBOL_B;
136 145
137 /* Avoid "SyS" kernel syscall aliases */ 146 return arch__choose_best_symbol(syma, symb);
138 if (na >= 3 && !strncmp(syma->name, "SyS", 3))
139 return SYMBOL_B;
140 if (na >= 10 && !strncmp(syma->name, "compat_SyS", 10))
141 return SYMBOL_B;
142
143 return SYMBOL_A;
144} 147}
145 148
146void symbols__fixup_duplicate(struct rb_root *symbols) 149void symbols__fixup_duplicate(struct rb_root *symbols)
@@ -199,18 +202,18 @@ void symbols__fixup_end(struct rb_root *symbols)
199 202
200void __map_groups__fixup_end(struct map_groups *mg, enum map_type type) 203void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
201{ 204{
202 struct map *prev, *curr; 205 struct maps *maps = &mg->maps[type];
203 struct rb_node *nd, *prevnd = rb_first(&mg->maps[type]); 206 struct map *next, *curr;
204 207
205 if (prevnd == NULL) 208 pthread_rwlock_wrlock(&maps->lock);
206 return;
207 209
208 curr = rb_entry(prevnd, struct map, rb_node); 210 curr = maps__first(maps);
211 if (curr == NULL)
212 goto out_unlock;
209 213
210 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) { 214 for (next = map__next(curr); next; next = map__next(curr)) {
211 prev = curr; 215 curr->end = next->start;
212 curr = rb_entry(nd, struct map, rb_node); 216 curr = next;
213 prev->end = curr->start;
214 } 217 }
215 218
216 /* 219 /*
@@ -218,6 +221,9 @@ void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
218 * last map final address. 221 * last map final address.
219 */ 222 */
220 curr->end = ~0ULL; 223 curr->end = ~0ULL;
224
225out_unlock:
226 pthread_rwlock_unlock(&maps->lock);
221} 227}
222 228
223struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name) 229struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name)
@@ -397,7 +403,7 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols,
397 const char *name) 403 const char *name)
398{ 404{
399 struct rb_node *n; 405 struct rb_node *n;
400 struct symbol_name_rb_node *s; 406 struct symbol_name_rb_node *s = NULL;
401 407
402 if (symbols == NULL) 408 if (symbols == NULL)
403 return NULL; 409 return NULL;
@@ -408,7 +414,7 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols,
408 int cmp; 414 int cmp;
409 415
410 s = rb_entry(n, struct symbol_name_rb_node, rb_node); 416 s = rb_entry(n, struct symbol_name_rb_node, rb_node);
411 cmp = strcmp(name, s->sym.name); 417 cmp = arch__compare_symbol_names(name, s->sym.name);
412 418
413 if (cmp < 0) 419 if (cmp < 0)
414 n = n->rb_left; 420 n = n->rb_left;
@@ -426,7 +432,7 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols,
426 struct symbol_name_rb_node *tmp; 432 struct symbol_name_rb_node *tmp;
427 433
428 tmp = rb_entry(n, struct symbol_name_rb_node, rb_node); 434 tmp = rb_entry(n, struct symbol_name_rb_node, rb_node);
429 if (strcmp(tmp->sym.name, s->sym.name)) 435 if (arch__compare_symbol_names(tmp->sym.name, s->sym.name))
430 break; 436 break;
431 437
432 s = tmp; 438 s = tmp;
@@ -653,14 +659,14 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
653 curr_map = map_groups__find(kmaps, map->type, pos->start); 659 curr_map = map_groups__find(kmaps, map->type, pos->start);
654 660
655 if (!curr_map || (filter && filter(curr_map, pos))) { 661 if (!curr_map || (filter && filter(curr_map, pos))) {
656 rb_erase(&pos->rb_node, root); 662 rb_erase_init(&pos->rb_node, root);
657 symbol__delete(pos); 663 symbol__delete(pos);
658 } else { 664 } else {
659 pos->start -= curr_map->start - curr_map->pgoff; 665 pos->start -= curr_map->start - curr_map->pgoff;
660 if (pos->end) 666 if (pos->end)
661 pos->end -= curr_map->start - curr_map->pgoff; 667 pos->end -= curr_map->start - curr_map->pgoff;
662 if (curr_map != map) { 668 if (curr_map != map) {
663 rb_erase(&pos->rb_node, root); 669 rb_erase_init(&pos->rb_node, root);
664 symbols__insert( 670 symbols__insert(
665 &curr_map->dso->symbols[curr_map->type], 671 &curr_map->dso->symbols[curr_map->type],
666 pos); 672 pos);
@@ -780,7 +786,7 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
780 786
781 curr_map = map__new2(pos->start, ndso, map->type); 787 curr_map = map__new2(pos->start, ndso, map->type);
782 if (curr_map == NULL) { 788 if (curr_map == NULL) {
783 dso__delete(ndso); 789 dso__put(ndso);
784 return -1; 790 return -1;
785 } 791 }
786 792
@@ -1167,20 +1173,23 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1167 /* Add new maps */ 1173 /* Add new maps */
1168 while (!list_empty(&md.maps)) { 1174 while (!list_empty(&md.maps)) {
1169 new_map = list_entry(md.maps.next, struct map, node); 1175 new_map = list_entry(md.maps.next, struct map, node);
1170 list_del(&new_map->node); 1176 list_del_init(&new_map->node);
1171 if (new_map == replacement_map) { 1177 if (new_map == replacement_map) {
1172 map->start = new_map->start; 1178 map->start = new_map->start;
1173 map->end = new_map->end; 1179 map->end = new_map->end;
1174 map->pgoff = new_map->pgoff; 1180 map->pgoff = new_map->pgoff;
1175 map->map_ip = new_map->map_ip; 1181 map->map_ip = new_map->map_ip;
1176 map->unmap_ip = new_map->unmap_ip; 1182 map->unmap_ip = new_map->unmap_ip;
1177 map__delete(new_map);
1178 /* Ensure maps are correctly ordered */ 1183 /* Ensure maps are correctly ordered */
1184 map__get(map);
1179 map_groups__remove(kmaps, map); 1185 map_groups__remove(kmaps, map);
1180 map_groups__insert(kmaps, map); 1186 map_groups__insert(kmaps, map);
1187 map__put(map);
1181 } else { 1188 } else {
1182 map_groups__insert(kmaps, new_map); 1189 map_groups__insert(kmaps, new_map);
1183 } 1190 }
1191
1192 map__put(new_map);
1184 } 1193 }
1185 1194
1186 /* 1195 /*
@@ -1205,8 +1214,8 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1205out_err: 1214out_err:
1206 while (!list_empty(&md.maps)) { 1215 while (!list_empty(&md.maps)) {
1207 map = list_entry(md.maps.next, struct map, node); 1216 map = list_entry(md.maps.next, struct map, node);
1208 list_del(&map->node); 1217 list_del_init(&map->node);
1209 map__delete(map); 1218 map__put(map);
1210 } 1219 }
1211 close(fd); 1220 close(fd);
1212 return -EINVAL; 1221 return -EINVAL;
@@ -1355,7 +1364,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
1355 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP: 1364 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
1356 /* 1365 /*
1357 * kernel modules know their symtab type - it's set when 1366 * kernel modules know their symtab type - it's set when
1358 * creating a module dso in machine__new_module(). 1367 * creating a module dso in machine__findnew_module_map().
1359 */ 1368 */
1360 return kmod && dso->symtab_type == type; 1369 return kmod && dso->symtab_type == type;
1361 1370
@@ -1380,12 +1389,22 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1380 struct symsrc *syms_ss = NULL, *runtime_ss = NULL; 1389 struct symsrc *syms_ss = NULL, *runtime_ss = NULL;
1381 bool kmod; 1390 bool kmod;
1382 1391
1383 dso__set_loaded(dso, map->type); 1392 pthread_mutex_lock(&dso->lock);
1393
1394 /* check again under the dso->lock */
1395 if (dso__loaded(dso, map->type)) {
1396 ret = 1;
1397 goto out;
1398 }
1384 1399
1385 if (dso->kernel == DSO_TYPE_KERNEL) 1400 if (dso->kernel) {
1386 return dso__load_kernel_sym(dso, map, filter); 1401 if (dso->kernel == DSO_TYPE_KERNEL)
1387 else if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1402 ret = dso__load_kernel_sym(dso, map, filter);
1388 return dso__load_guest_kernel_sym(dso, map, filter); 1403 else if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1404 ret = dso__load_guest_kernel_sym(dso, map, filter);
1405
1406 goto out;
1407 }
1389 1408
1390 if (map->groups && map->groups->machine) 1409 if (map->groups && map->groups->machine)
1391 machine = map->groups->machine; 1410 machine = map->groups->machine;
@@ -1398,18 +1417,18 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1398 struct stat st; 1417 struct stat st;
1399 1418
1400 if (lstat(dso->name, &st) < 0) 1419 if (lstat(dso->name, &st) < 0)
1401 return -1; 1420 goto out;
1402 1421
1403 if (st.st_uid && (st.st_uid != geteuid())) { 1422 if (st.st_uid && (st.st_uid != geteuid())) {
1404 pr_warning("File %s not owned by current user or root, " 1423 pr_warning("File %s not owned by current user or root, "
1405 "ignoring it.\n", dso->name); 1424 "ignoring it.\n", dso->name);
1406 return -1; 1425 goto out;
1407 } 1426 }
1408 1427
1409 ret = dso__load_perf_map(dso, map, filter); 1428 ret = dso__load_perf_map(dso, map, filter);
1410 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT : 1429 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT :
1411 DSO_BINARY_TYPE__NOT_FOUND; 1430 DSO_BINARY_TYPE__NOT_FOUND;
1412 return ret; 1431 goto out;
1413 } 1432 }
1414 1433
1415 if (machine) 1434 if (machine)
@@ -1417,7 +1436,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1417 1436
1418 name = malloc(PATH_MAX); 1437 name = malloc(PATH_MAX);
1419 if (!name) 1438 if (!name)
1420 return -1; 1439 goto out;
1421 1440
1422 kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || 1441 kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
1423 dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || 1442 dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
@@ -1498,23 +1517,32 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1498out_free: 1517out_free:
1499 free(name); 1518 free(name);
1500 if (ret < 0 && strstr(dso->name, " (deleted)") != NULL) 1519 if (ret < 0 && strstr(dso->name, " (deleted)") != NULL)
1501 return 0; 1520 ret = 0;
1521out:
1522 dso__set_loaded(dso, map->type);
1523 pthread_mutex_unlock(&dso->lock);
1524
1502 return ret; 1525 return ret;
1503} 1526}
1504 1527
1505struct map *map_groups__find_by_name(struct map_groups *mg, 1528struct map *map_groups__find_by_name(struct map_groups *mg,
1506 enum map_type type, const char *name) 1529 enum map_type type, const char *name)
1507{ 1530{
1508 struct rb_node *nd; 1531 struct maps *maps = &mg->maps[type];
1532 struct map *map;
1509 1533
1510 for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) { 1534 pthread_rwlock_rdlock(&maps->lock);
1511 struct map *map = rb_entry(nd, struct map, rb_node);
1512 1535
1536 for (map = maps__first(maps); map; map = map__next(map)) {
1513 if (map->dso && strcmp(map->dso->short_name, name) == 0) 1537 if (map->dso && strcmp(map->dso->short_name, name) == 0)
1514 return map; 1538 goto out_unlock;
1515 } 1539 }
1516 1540
1517 return NULL; 1541 map = NULL;
1542
1543out_unlock:
1544 pthread_rwlock_unlock(&maps->lock);
1545 return map;
1518} 1546}
1519 1547
1520int dso__load_vmlinux(struct dso *dso, struct map *map, 1548int dso__load_vmlinux(struct dso *dso, struct map *map,
@@ -1802,6 +1830,7 @@ static void vmlinux_path__exit(void)
1802{ 1830{
1803 while (--vmlinux_path__nr_entries >= 0) 1831 while (--vmlinux_path__nr_entries >= 0)
1804 zfree(&vmlinux_path[vmlinux_path__nr_entries]); 1832 zfree(&vmlinux_path[vmlinux_path__nr_entries]);
1833 vmlinux_path__nr_entries = 0;
1805 1834
1806 zfree(&vmlinux_path); 1835 zfree(&vmlinux_path);
1807} 1836}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 09561500164a..bef47ead1d9b 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -158,8 +158,6 @@ struct ref_reloc_sym {
158struct map_symbol { 158struct map_symbol {
159 struct map *map; 159 struct map *map;
160 struct symbol *sym; 160 struct symbol *sym;
161 bool unfolded;
162 bool has_children;
163}; 161};
164 162
165struct addr_map_symbol { 163struct addr_map_symbol {
@@ -303,4 +301,14 @@ int setup_list(struct strlist **list, const char *list_str,
303int setup_intlist(struct intlist **list, const char *list_str, 301int setup_intlist(struct intlist **list, const char *list_str,
304 const char *list_name); 302 const char *list_name);
305 303
304#ifdef HAVE_LIBELF_SUPPORT
305bool elf__needs_adjust_symbols(GElf_Ehdr ehdr);
306void arch__elf_sym_adjust(GElf_Sym *sym);
307#endif
308
309#define SYMBOL_A 0
310#define SYMBOL_B 1
311
312int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
313
306#endif /* __PERF_SYMBOL */ 314#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
index 9ed59a452d1f..679688e70ae7 100644
--- a/tools/perf/util/thread-stack.c
+++ b/tools/perf/util/thread-stack.c
@@ -219,7 +219,7 @@ static int thread_stack__call_return(struct thread *thread,
219 return crp->process(&cr, crp->data); 219 return crp->process(&cr, crp->data);
220} 220}
221 221
222static int thread_stack__flush(struct thread *thread, struct thread_stack *ts) 222static int __thread_stack__flush(struct thread *thread, struct thread_stack *ts)
223{ 223{
224 struct call_return_processor *crp = ts->crp; 224 struct call_return_processor *crp = ts->crp;
225 int err; 225 int err;
@@ -242,6 +242,14 @@ static int thread_stack__flush(struct thread *thread, struct thread_stack *ts)
242 return 0; 242 return 0;
243} 243}
244 244
245int thread_stack__flush(struct thread *thread)
246{
247 if (thread->ts)
248 return __thread_stack__flush(thread, thread->ts);
249
250 return 0;
251}
252
245int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip, 253int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
246 u64 to_ip, u16 insn_len, u64 trace_nr) 254 u64 to_ip, u16 insn_len, u64 trace_nr)
247{ 255{
@@ -264,7 +272,7 @@ int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
264 */ 272 */
265 if (trace_nr != thread->ts->trace_nr) { 273 if (trace_nr != thread->ts->trace_nr) {
266 if (thread->ts->trace_nr) 274 if (thread->ts->trace_nr)
267 thread_stack__flush(thread, thread->ts); 275 __thread_stack__flush(thread, thread->ts);
268 thread->ts->trace_nr = trace_nr; 276 thread->ts->trace_nr = trace_nr;
269 } 277 }
270 278
@@ -297,7 +305,7 @@ void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr)
297 305
298 if (trace_nr != thread->ts->trace_nr) { 306 if (trace_nr != thread->ts->trace_nr) {
299 if (thread->ts->trace_nr) 307 if (thread->ts->trace_nr)
300 thread_stack__flush(thread, thread->ts); 308 __thread_stack__flush(thread, thread->ts);
301 thread->ts->trace_nr = trace_nr; 309 thread->ts->trace_nr = trace_nr;
302 } 310 }
303} 311}
@@ -305,7 +313,7 @@ void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr)
305void thread_stack__free(struct thread *thread) 313void thread_stack__free(struct thread *thread)
306{ 314{
307 if (thread->ts) { 315 if (thread->ts) {
308 thread_stack__flush(thread, thread->ts); 316 __thread_stack__flush(thread, thread->ts);
309 zfree(&thread->ts->stack); 317 zfree(&thread->ts->stack);
310 zfree(&thread->ts); 318 zfree(&thread->ts);
311 } 319 }
@@ -689,7 +697,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
689 697
690 /* Flush stack on exec */ 698 /* Flush stack on exec */
691 if (ts->comm != comm && thread->pid_ == thread->tid) { 699 if (ts->comm != comm && thread->pid_ == thread->tid) {
692 err = thread_stack__flush(thread, ts); 700 err = __thread_stack__flush(thread, ts);
693 if (err) 701 if (err)
694 return err; 702 return err;
695 ts->comm = comm; 703 ts->comm = comm;
diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h
index b843bbef8ba2..e1528f1374c3 100644
--- a/tools/perf/util/thread-stack.h
+++ b/tools/perf/util/thread-stack.h
@@ -96,6 +96,7 @@ int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
96void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr); 96void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr);
97void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, 97void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
98 size_t sz, u64 ip); 98 size_t sz, u64 ip);
99int thread_stack__flush(struct thread *thread);
99void thread_stack__free(struct thread *thread); 100void thread_stack__free(struct thread *thread);
100 101
101struct call_return_processor * 102struct call_return_processor *
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 1c8fbc9588c5..28c4b746baa1 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -18,7 +18,7 @@ int thread__init_map_groups(struct thread *thread, struct machine *machine)
18 if (pid == thread->tid || pid == -1) { 18 if (pid == thread->tid || pid == -1) {
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 } 24 }
@@ -53,7 +53,8 @@ struct thread *thread__new(pid_t pid, pid_t tid)
53 goto err_thread; 53 goto err_thread;
54 54
55 list_add(&comm->list, &thread->comm_list); 55 list_add(&comm->list, &thread->comm_list);
56 56 atomic_set(&thread->refcnt, 0);
57 RB_CLEAR_NODE(&thread->rb_node);
57 } 58 }
58 59
59 return thread; 60 return thread;
@@ -67,6 +68,8 @@ void thread__delete(struct thread *thread)
67{ 68{
68 struct comm *comm, *tmp; 69 struct comm *comm, *tmp;
69 70
71 BUG_ON(!RB_EMPTY_NODE(&thread->rb_node));
72
70 thread_stack__free(thread); 73 thread_stack__free(thread);
71 74
72 if (thread->mg) { 75 if (thread->mg) {
@@ -84,13 +87,14 @@ void thread__delete(struct thread *thread)
84 87
85struct thread *thread__get(struct thread *thread) 88struct thread *thread__get(struct thread *thread)
86{ 89{
87 ++thread->refcnt; 90 if (thread)
91 atomic_inc(&thread->refcnt);
88 return thread; 92 return thread;
89} 93}
90 94
91void thread__put(struct thread *thread) 95void thread__put(struct thread *thread)
92{ 96{
93 if (thread && --thread->refcnt == 0) { 97 if (thread && atomic_dec_and_test(&thread->refcnt)) {
94 list_del_init(&thread->node); 98 list_del_init(&thread->node);
95 thread__delete(thread); 99 thread__delete(thread);
96 } 100 }
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 9b8a54dc34a8..a0ac0317affb 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -1,6 +1,7 @@
1#ifndef __PERF_THREAD_H 1#ifndef __PERF_THREAD_H
2#define __PERF_THREAD_H 2#define __PERF_THREAD_H
3 3
4#include <linux/atomic.h>
4#include <linux/rbtree.h> 5#include <linux/rbtree.h>
5#include <linux/list.h> 6#include <linux/list.h>
6#include <unistd.h> 7#include <unistd.h>
@@ -21,12 +22,12 @@ struct thread {
21 pid_t tid; 22 pid_t tid;
22 pid_t ppid; 23 pid_t ppid;
23 int cpu; 24 int cpu;
24 int refcnt; 25 atomic_t refcnt;
25 char shortname[3]; 26 char shortname[3];
26 bool comm_set; 27 bool comm_set;
28 int comm_len;
27 bool dead; /* if set thread has exited */ 29 bool dead; /* if set thread has exited */
28 struct list_head comm_list; 30 struct list_head comm_list;
29 int comm_len;
30 u64 db_id; 31 u64 db_id;
31 32
32 void *priv; 33 void *priv;
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index f93b9734735b..f4822bd03709 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -20,6 +20,15 @@ static int filter(const struct dirent *dir)
20 return 1; 20 return 1;
21} 21}
22 22
23static struct thread_map *thread_map__realloc(struct thread_map *map, int nr)
24{
25 size_t size = sizeof(*map) + sizeof(pid_t) * nr;
26
27 return realloc(map, size);
28}
29
30#define thread_map__alloc(__nr) thread_map__realloc(NULL, __nr)
31
23struct thread_map *thread_map__new_by_pid(pid_t pid) 32struct thread_map *thread_map__new_by_pid(pid_t pid)
24{ 33{
25 struct thread_map *threads; 34 struct thread_map *threads;
@@ -33,7 +42,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
33 if (items <= 0) 42 if (items <= 0)
34 return NULL; 43 return NULL;
35 44
36 threads = malloc(sizeof(*threads) + sizeof(pid_t) * items); 45 threads = thread_map__alloc(items);
37 if (threads != NULL) { 46 if (threads != NULL) {
38 for (i = 0; i < items; i++) 47 for (i = 0; i < items; i++)
39 threads->map[i] = atoi(namelist[i]->d_name); 48 threads->map[i] = atoi(namelist[i]->d_name);
@@ -49,7 +58,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
49 58
50struct thread_map *thread_map__new_by_tid(pid_t tid) 59struct thread_map *thread_map__new_by_tid(pid_t tid)
51{ 60{
52 struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t)); 61 struct thread_map *threads = thread_map__alloc(1);
53 62
54 if (threads != NULL) { 63 if (threads != NULL) {
55 threads->map[0] = tid; 64 threads->map[0] = tid;
@@ -65,8 +74,8 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
65 int max_threads = 32, items, i; 74 int max_threads = 32, items, i;
66 char path[256]; 75 char path[256];
67 struct dirent dirent, *next, **namelist = NULL; 76 struct dirent dirent, *next, **namelist = NULL;
68 struct thread_map *threads = malloc(sizeof(*threads) + 77 struct thread_map *threads = thread_map__alloc(max_threads);
69 max_threads * sizeof(pid_t)); 78
70 if (threads == NULL) 79 if (threads == NULL)
71 goto out; 80 goto out;
72 81
@@ -185,8 +194,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
185 goto out_free_threads; 194 goto out_free_threads;
186 195
187 total_tasks += items; 196 total_tasks += items;
188 nt = realloc(threads, (sizeof(*threads) + 197 nt = thread_map__realloc(threads, total_tasks);
189 sizeof(pid_t) * total_tasks));
190 if (nt == NULL) 198 if (nt == NULL)
191 goto out_free_namelist; 199 goto out_free_namelist;
192 200
@@ -216,7 +224,7 @@ out_free_threads:
216 224
217struct thread_map *thread_map__new_dummy(void) 225struct thread_map *thread_map__new_dummy(void)
218{ 226{
219 struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t)); 227 struct thread_map *threads = thread_map__alloc(1);
220 228
221 if (threads != NULL) { 229 if (threads != NULL) {
222 threads->map[0] = -1; 230 threads->map[0] = -1;
@@ -253,7 +261,7 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
253 continue; 261 continue;
254 262
255 ntasks++; 263 ntasks++;
256 nt = realloc(threads, sizeof(*threads) + sizeof(pid_t) * ntasks); 264 nt = thread_map__realloc(threads, ntasks);
257 265
258 if (nt == NULL) 266 if (nt == NULL)
259 goto out_free_threads; 267 goto out_free_threads;
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 51d9e56c0f84..c307dd438286 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -3,6 +3,8 @@
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5 5
6#include <linux/types.h>
7
6struct perf_session; 8struct perf_session;
7union perf_event; 9union perf_event;
8struct perf_evlist; 10struct perf_evlist;
@@ -29,6 +31,9 @@ typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event,
29typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event, 31typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event,
30 struct ordered_events *oe); 32 struct ordered_events *oe);
31 33
34typedef s64 (*event_op3)(struct perf_tool *tool, union perf_event *event,
35 struct perf_session *session);
36
32struct perf_tool { 37struct perf_tool {
33 event_sample sample, 38 event_sample sample,
34 read; 39 read;
@@ -38,13 +43,19 @@ struct perf_tool {
38 fork, 43 fork,
39 exit, 44 exit,
40 lost, 45 lost,
46 lost_samples,
47 aux,
48 itrace_start,
41 throttle, 49 throttle,
42 unthrottle; 50 unthrottle;
43 event_attr_op attr; 51 event_attr_op attr;
44 event_op2 tracing_data; 52 event_op2 tracing_data;
45 event_oe finished_round; 53 event_oe finished_round;
46 event_op2 build_id, 54 event_op2 build_id,
47 id_index; 55 id_index,
56 auxtrace_info,
57 auxtrace_error;
58 event_op3 auxtrace;
48 bool ordered_events; 59 bool ordered_events;
49 bool ordering_requires_timestamps; 60 bool ordering_requires_timestamps;
50}; 61};
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 25d6c737be3e..d4957418657e 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -173,7 +173,7 @@ void parse_ftrace_printk(struct pevent *pevent,
173 char *line; 173 char *line;
174 char *next = NULL; 174 char *next = NULL;
175 char *addr_str; 175 char *addr_str;
176 char *fmt; 176 char *fmt = NULL;
177 177
178 line = strtok_r(file, "\n", &next); 178 line = strtok_r(file, "\n", &next);
179 while (line) { 179 while (line) {
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 7b09a443a280..4c00507ee3fd 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -269,13 +269,14 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
269 u64 offset = dso->data.eh_frame_hdr_offset; 269 u64 offset = dso->data.eh_frame_hdr_offset;
270 270
271 if (offset == 0) { 271 if (offset == 0) {
272 fd = dso__data_fd(dso, machine); 272 fd = dso__data_get_fd(dso, machine);
273 if (fd < 0) 273 if (fd < 0)
274 return -EINVAL; 274 return -EINVAL;
275 275
276 /* Check the .eh_frame section for unwinding info */ 276 /* Check the .eh_frame section for unwinding info */
277 offset = elf_section_offset(fd, ".eh_frame_hdr"); 277 offset = elf_section_offset(fd, ".eh_frame_hdr");
278 dso->data.eh_frame_hdr_offset = offset; 278 dso->data.eh_frame_hdr_offset = offset;
279 dso__data_put_fd(dso);
279 } 280 }
280 281
281 if (offset) 282 if (offset)
@@ -294,13 +295,14 @@ static int read_unwind_spec_debug_frame(struct dso *dso,
294 u64 ofs = dso->data.debug_frame_offset; 295 u64 ofs = dso->data.debug_frame_offset;
295 296
296 if (ofs == 0) { 297 if (ofs == 0) {
297 fd = dso__data_fd(dso, machine); 298 fd = dso__data_get_fd(dso, machine);
298 if (fd < 0) 299 if (fd < 0)
299 return -EINVAL; 300 return -EINVAL;
300 301
301 /* Check the .debug_frame section for unwinding info */ 302 /* Check the .debug_frame section for unwinding info */
302 ofs = elf_section_offset(fd, ".debug_frame"); 303 ofs = elf_section_offset(fd, ".debug_frame");
303 dso->data.debug_frame_offset = ofs; 304 dso->data.debug_frame_offset = ofs;
305 dso__data_put_fd(dso);
304 } 306 }
305 307
306 *offset = ofs; 308 *offset = ofs;
@@ -353,10 +355,13 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
353#ifndef NO_LIBUNWIND_DEBUG_FRAME 355#ifndef NO_LIBUNWIND_DEBUG_FRAME
354 /* Check the .debug_frame section for unwinding info */ 356 /* Check the .debug_frame section for unwinding info */
355 if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { 357 if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
356 int fd = dso__data_fd(map->dso, ui->machine); 358 int fd = dso__data_get_fd(map->dso, ui->machine);
357 int is_exec = elf_is_exec(fd, map->dso->name); 359 int is_exec = elf_is_exec(fd, map->dso->name);
358 unw_word_t base = is_exec ? 0 : map->start; 360 unw_word_t base = is_exec ? 0 : map->start;
359 361
362 if (fd >= 0)
363 dso__data_put_fd(map->dso);
364
360 memset(&di, 0, sizeof(di)); 365 memset(&di, 0, sizeof(di));
361 if (dwarf_find_debug_frame(0, &di, ip, base, map->dso->name, 366 if (dwarf_find_debug_frame(0, &di, ip, base, map->dso->name,
362 map->start, map->end)) 367 map->start, map->end))
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 4ee6d0d4c993..edc2d633b332 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -72,20 +72,60 @@ int mkdir_p(char *path, mode_t mode)
72 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; 72 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
73} 73}
74 74
75static int slow_copyfile(const char *from, const char *to, mode_t mode) 75int rm_rf(char *path)
76{
77 DIR *dir;
78 int ret = 0;
79 struct dirent *d;
80 char namebuf[PATH_MAX];
81
82 dir = opendir(path);
83 if (dir == NULL)
84 return 0;
85
86 while ((d = readdir(dir)) != NULL && !ret) {
87 struct stat statbuf;
88
89 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
90 continue;
91
92 scnprintf(namebuf, sizeof(namebuf), "%s/%s",
93 path, d->d_name);
94
95 ret = stat(namebuf, &statbuf);
96 if (ret < 0) {
97 pr_debug("stat failed: %s\n", namebuf);
98 break;
99 }
100
101 if (S_ISREG(statbuf.st_mode))
102 ret = unlink(namebuf);
103 else if (S_ISDIR(statbuf.st_mode))
104 ret = rm_rf(namebuf);
105 else {
106 pr_debug("unknown file: %s\n", namebuf);
107 ret = -1;
108 }
109 }
110 closedir(dir);
111
112 if (ret < 0)
113 return ret;
114
115 return rmdir(path);
116}
117
118static int slow_copyfile(const char *from, const char *to)
76{ 119{
77 int err = -1; 120 int err = -1;
78 char *line = NULL; 121 char *line = NULL;
79 size_t n; 122 size_t n;
80 FILE *from_fp = fopen(from, "r"), *to_fp; 123 FILE *from_fp = fopen(from, "r"), *to_fp;
81 mode_t old_umask;
82 124
83 if (from_fp == NULL) 125 if (from_fp == NULL)
84 goto out; 126 goto out;
85 127
86 old_umask = umask(mode ^ 0777);
87 to_fp = fopen(to, "w"); 128 to_fp = fopen(to, "w");
88 umask(old_umask);
89 if (to_fp == NULL) 129 if (to_fp == NULL)
90 goto out_fclose_from; 130 goto out_fclose_from;
91 131
@@ -102,42 +142,81 @@ out:
102 return err; 142 return err;
103} 143}
104 144
145int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
146{
147 void *ptr;
148 loff_t pgoff;
149
150 pgoff = off_in & ~(page_size - 1);
151 off_in -= pgoff;
152
153 ptr = mmap(NULL, off_in + size, PROT_READ, MAP_PRIVATE, ifd, pgoff);
154 if (ptr == MAP_FAILED)
155 return -1;
156
157 while (size) {
158 ssize_t ret = pwrite(ofd, ptr + off_in, size, off_out);
159 if (ret < 0 && errno == EINTR)
160 continue;
161 if (ret <= 0)
162 break;
163
164 size -= ret;
165 off_in += ret;
166 off_out -= ret;
167 }
168 munmap(ptr, off_in + size);
169
170 return size ? -1 : 0;
171}
172
105int copyfile_mode(const char *from, const char *to, mode_t mode) 173int copyfile_mode(const char *from, const char *to, mode_t mode)
106{ 174{
107 int fromfd, tofd; 175 int fromfd, tofd;
108 struct stat st; 176 struct stat st;
109 void *addr;
110 int err = -1; 177 int err = -1;
178 char *tmp = NULL, *ptr = NULL;
111 179
112 if (stat(from, &st)) 180 if (stat(from, &st))
113 goto out; 181 goto out;
114 182
115 if (st.st_size == 0) /* /proc? do it slowly... */ 183 /* extra 'x' at the end is to reserve space for '.' */
116 return slow_copyfile(from, to, mode); 184 if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) {
117 185 tmp = NULL;
118 fromfd = open(from, O_RDONLY);
119 if (fromfd < 0)
120 goto out; 186 goto out;
187 }
188 ptr = strrchr(tmp, '/');
189 if (!ptr)
190 goto out;
191 ptr = memmove(ptr + 1, ptr, strlen(ptr) - 1);
192 *ptr = '.';
121 193
122 tofd = creat(to, mode); 194 tofd = mkstemp(tmp);
123 if (tofd < 0) 195 if (tofd < 0)
124 goto out_close_from; 196 goto out;
197
198 if (fchmod(tofd, mode))
199 goto out_close_to;
200
201 if (st.st_size == 0) { /* /proc? do it slowly... */
202 err = slow_copyfile(from, tmp);
203 goto out_close_to;
204 }
125 205
126 addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fromfd, 0); 206 fromfd = open(from, O_RDONLY);
127 if (addr == MAP_FAILED) 207 if (fromfd < 0)
128 goto out_close_to; 208 goto out_close_to;
129 209
130 if (write(tofd, addr, st.st_size) == st.st_size) 210 err = copyfile_offset(fromfd, 0, tofd, 0, st.st_size);
131 err = 0;
132 211
133 munmap(addr, st.st_size); 212 close(fromfd);
134out_close_to: 213out_close_to:
135 close(tofd); 214 close(tofd);
136 if (err) 215 if (!err)
137 unlink(to); 216 err = link(tmp, to);
138out_close_from: 217 unlink(tmp);
139 close(fromfd);
140out: 218out:
219 free(tmp);
141 return err; 220 return err;
142} 221}
143 222
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 1ff23e04ad27..8bce58b47a82 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -249,14 +249,20 @@ static inline int sane_case(int x, int high)
249} 249}
250 250
251int mkdir_p(char *path, mode_t mode); 251int mkdir_p(char *path, mode_t mode);
252int rm_rf(char *path);
252int copyfile(const char *from, const char *to); 253int copyfile(const char *from, const char *to);
253int copyfile_mode(const char *from, const char *to, mode_t mode); 254int copyfile_mode(const char *from, const char *to, mode_t mode);
255int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size);
254 256
255s64 perf_atoll(const char *str); 257s64 perf_atoll(const char *str);
256char **argv_split(const char *str, int *argcp); 258char **argv_split(const char *str, int *argcp);
257void argv_free(char **argv); 259void argv_free(char **argv);
258bool strglobmatch(const char *str, const char *pat); 260bool strglobmatch(const char *str, const char *pat);
259bool strlazymatch(const char *str, const char *pat); 261bool strlazymatch(const char *str, const char *pat);
262static inline bool strisglob(const char *str)
263{
264 return strpbrk(str, "*?[") != NULL;
265}
260int strtailcmp(const char *s1, const char *s2); 266int strtailcmp(const char *s1, const char *s2);
261char *strxfrchar(char *s, char from, char to); 267char *strxfrchar(char *s, char from, char to);
262unsigned long convert_unit(unsigned long value, char *unit); 268unsigned long convert_unit(unsigned long value, char *unit);
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c
index 5c7dd796979d..4b89118f158d 100644
--- a/tools/perf/util/vdso.c
+++ b/tools/perf/util/vdso.c
@@ -101,7 +101,7 @@ static char *get_file(struct vdso_file *vdso_file)
101 return vdso; 101 return vdso;
102} 102}
103 103
104void vdso__exit(struct machine *machine) 104void machine__exit_vdso(struct machine *machine)
105{ 105{
106 struct vdso_info *vdso_info = machine->vdso_info; 106 struct vdso_info *vdso_info = machine->vdso_info;
107 107
@@ -120,14 +120,14 @@ void vdso__exit(struct machine *machine)
120 zfree(&machine->vdso_info); 120 zfree(&machine->vdso_info);
121} 121}
122 122
123static struct dso *vdso__new(struct machine *machine, const char *short_name, 123static struct dso *__machine__addnew_vdso(struct machine *machine, const char *short_name,
124 const char *long_name) 124 const char *long_name)
125{ 125{
126 struct dso *dso; 126 struct dso *dso;
127 127
128 dso = dso__new(short_name); 128 dso = dso__new(short_name);
129 if (dso != NULL) { 129 if (dso != NULL) {
130 dsos__add(&machine->user_dsos, dso); 130 __dsos__add(&machine->dsos, dso);
131 dso__set_long_name(dso, long_name, false); 131 dso__set_long_name(dso, long_name, false);
132 } 132 }
133 133
@@ -230,27 +230,31 @@ static const char *vdso__get_compat_file(struct vdso_file *vdso_file)
230 return vdso_file->temp_file_name; 230 return vdso_file->temp_file_name;
231} 231}
232 232
233static struct dso *vdso__findnew_compat(struct machine *machine, 233static struct dso *__machine__findnew_compat(struct machine *machine,
234 struct vdso_file *vdso_file) 234 struct vdso_file *vdso_file)
235{ 235{
236 const char *file_name; 236 const char *file_name;
237 struct dso *dso; 237 struct dso *dso;
238 238
239 dso = dsos__find(&machine->user_dsos, vdso_file->dso_name, true); 239 pthread_rwlock_wrlock(&machine->dsos.lock);
240 dso = __dsos__find(&machine->dsos, vdso_file->dso_name, true);
240 if (dso) 241 if (dso)
241 return dso; 242 goto out_unlock;
242 243
243 file_name = vdso__get_compat_file(vdso_file); 244 file_name = vdso__get_compat_file(vdso_file);
244 if (!file_name) 245 if (!file_name)
245 return NULL; 246 goto out_unlock;
246 247
247 return vdso__new(machine, vdso_file->dso_name, file_name); 248 dso = __machine__addnew_vdso(machine, vdso_file->dso_name, file_name);
249out_unlock:
250 pthread_rwlock_unlock(&machine->dsos.lock);
251 return dso;
248} 252}
249 253
250static int vdso__dso_findnew_compat(struct machine *machine, 254static int __machine__findnew_vdso_compat(struct machine *machine,
251 struct thread *thread, 255 struct thread *thread,
252 struct vdso_info *vdso_info, 256 struct vdso_info *vdso_info,
253 struct dso **dso) 257 struct dso **dso)
254{ 258{
255 enum dso_type dso_type; 259 enum dso_type dso_type;
256 260
@@ -267,10 +271,10 @@ static int vdso__dso_findnew_compat(struct machine *machine,
267 271
268 switch (dso_type) { 272 switch (dso_type) {
269 case DSO__TYPE_32BIT: 273 case DSO__TYPE_32BIT:
270 *dso = vdso__findnew_compat(machine, &vdso_info->vdso32); 274 *dso = __machine__findnew_compat(machine, &vdso_info->vdso32);
271 return 1; 275 return 1;
272 case DSO__TYPE_X32BIT: 276 case DSO__TYPE_X32BIT:
273 *dso = vdso__findnew_compat(machine, &vdso_info->vdsox32); 277 *dso = __machine__findnew_compat(machine, &vdso_info->vdsox32);
274 return 1; 278 return 1;
275 case DSO__TYPE_UNKNOWN: 279 case DSO__TYPE_UNKNOWN:
276 case DSO__TYPE_64BIT: 280 case DSO__TYPE_64BIT:
@@ -281,35 +285,37 @@ static int vdso__dso_findnew_compat(struct machine *machine,
281 285
282#endif 286#endif
283 287
284struct dso *vdso__dso_findnew(struct machine *machine, 288struct dso *machine__findnew_vdso(struct machine *machine,
285 struct thread *thread __maybe_unused) 289 struct thread *thread __maybe_unused)
286{ 290{
287 struct vdso_info *vdso_info; 291 struct vdso_info *vdso_info;
288 struct dso *dso; 292 struct dso *dso = NULL;
289 293
294 pthread_rwlock_wrlock(&machine->dsos.lock);
290 if (!machine->vdso_info) 295 if (!machine->vdso_info)
291 machine->vdso_info = vdso_info__new(); 296 machine->vdso_info = vdso_info__new();
292 297
293 vdso_info = machine->vdso_info; 298 vdso_info = machine->vdso_info;
294 if (!vdso_info) 299 if (!vdso_info)
295 return NULL; 300 goto out_unlock;
296 301
297#if BITS_PER_LONG == 64 302#if BITS_PER_LONG == 64
298 if (vdso__dso_findnew_compat(machine, thread, vdso_info, &dso)) 303 if (__machine__findnew_vdso_compat(machine, thread, vdso_info, &dso))
299 return dso; 304 goto out_unlock;
300#endif 305#endif
301 306
302 dso = dsos__find(&machine->user_dsos, DSO__NAME_VDSO, true); 307 dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO, true);
303 if (!dso) { 308 if (!dso) {
304 char *file; 309 char *file;
305 310
306 file = get_file(&vdso_info->vdso); 311 file = get_file(&vdso_info->vdso);
307 if (!file) 312 if (file)
308 return NULL; 313 dso = __machine__addnew_vdso(machine, DSO__NAME_VDSO, file);
309
310 dso = vdso__new(machine, DSO__NAME_VDSO, file);
311 } 314 }
312 315
316out_unlock:
317 dso__get(dso);
318 pthread_rwlock_unlock(&machine->dsos.lock);
313 return dso; 319 return dso;
314} 320}
315 321
diff --git a/tools/perf/util/vdso.h b/tools/perf/util/vdso.h
index d97da1616f0c..cdc4fabfc212 100644
--- a/tools/perf/util/vdso.h
+++ b/tools/perf/util/vdso.h
@@ -23,7 +23,7 @@ bool dso__is_vdso(struct dso *dso);
23struct machine; 23struct machine;
24struct thread; 24struct thread;
25 25
26struct dso *vdso__dso_findnew(struct machine *machine, struct thread *thread); 26struct dso *machine__findnew_vdso(struct machine *machine, struct thread *thread);
27void vdso__exit(struct machine *machine); 27void machine__exit_vdso(struct machine *machine);
28 28
29#endif /* __PERF_VDSO__ */ 29#endif /* __PERF_VDSO__ */
diff --git a/tools/perf/util/xyarray.c b/tools/perf/util/xyarray.c
index 22afbf6c536a..c10ba41ef3f6 100644
--- a/tools/perf/util/xyarray.c
+++ b/tools/perf/util/xyarray.c
@@ -9,11 +9,19 @@ struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)
9 if (xy != NULL) { 9 if (xy != NULL) {
10 xy->entry_size = entry_size; 10 xy->entry_size = entry_size;
11 xy->row_size = row_size; 11 xy->row_size = row_size;
12 xy->entries = xlen * ylen;
12 } 13 }
13 14
14 return xy; 15 return xy;
15} 16}
16 17
18void xyarray__reset(struct xyarray *xy)
19{
20 size_t n = xy->entries * xy->entry_size;
21
22 memset(xy->contents, 0, n);
23}
24
17void xyarray__delete(struct xyarray *xy) 25void xyarray__delete(struct xyarray *xy)
18{ 26{
19 free(xy); 27 free(xy);
diff --git a/tools/perf/util/xyarray.h b/tools/perf/util/xyarray.h
index c488a07275dd..7f30af371b7e 100644
--- a/tools/perf/util/xyarray.h
+++ b/tools/perf/util/xyarray.h
@@ -6,11 +6,13 @@
6struct xyarray { 6struct xyarray {
7 size_t row_size; 7 size_t row_size;
8 size_t entry_size; 8 size_t entry_size;
9 size_t entries;
9 char contents[]; 10 char contents[];
10}; 11};
11 12
12struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size); 13struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size);
13void xyarray__delete(struct xyarray *xy); 14void xyarray__delete(struct xyarray *xy);
15void xyarray__reset(struct xyarray *xy);
14 16
15static inline void *xyarray__entry(struct xyarray *xy, int x, int y) 17static inline void *xyarray__entry(struct xyarray *xy, int x, int y)
16{ 18{