aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2014-07-18 00:16:06 -0400
committerIngo Molnar <mingo@kernel.org>2014-07-18 00:16:06 -0400
commitec6dbcb7ade2a616675cbe3185cf299ee1615c9f (patch)
tree4953f7eca477e011aa9e16cdb236220ed9cec4be
parentff2ebe46e15bd49d52b9c2f3fc77f3a9d94eac7b (diff)
parent0b437860818dc717f6a9e8a5089223a8414f5fff (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: User visible changes: o Support S/390 in 'perf kvm stat' (Alexander Yarygin) Developer Stuff: o Various fixes and prep work related to supporting Intel PT (Adrian Hunter) o Introduce multiple debug variables control (Jiri Olsa) o Add callchain and additional sample information for python scripts (Joseph Schuchart) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/s390/include/uapi/asm/Kbuild1
-rw-r--r--arch/s390/include/uapi/asm/kvm_perf.h25
-rw-r--r--arch/x86/include/uapi/asm/Kbuild1
-rw-r--r--arch/x86/include/uapi/asm/kvm_perf.h16
-rw-r--r--tools/perf/Documentation/perf-kvm.txt16
-rw-r--r--tools/perf/Documentation/perf.txt10
-rw-r--r--tools/perf/MANIFEST3
-rw-r--r--tools/perf/Makefile.perf3
-rw-r--r--tools/perf/arch/s390/Makefile2
-rw-r--r--tools/perf/arch/s390/util/kvm-stat.c105
-rw-r--r--tools/perf/arch/x86/Makefile1
-rw-r--r--tools/perf/arch/x86/tests/dwarf-unwind.c1
-rw-r--r--tools/perf/arch/x86/util/kvm-stat.c156
-rw-r--r--tools/perf/arch/x86/util/tsc.c22
-rw-r--r--tools/perf/arch/x86/util/tsc.h3
-rw-r--r--tools/perf/arch/x86/util/unwind-libunwind.c1
-rw-r--r--tools/perf/builtin-buildid-cache.c8
-rw-r--r--tools/perf/builtin-evlist.c1
-rw-r--r--tools/perf/builtin-help.c1
-rw-r--r--tools/perf/builtin-inject.c3
-rw-r--r--tools/perf/builtin-kvm.c384
-rw-r--r--tools/perf/builtin-sched.c12
-rw-r--r--tools/perf/builtin-timechart.c1
-rw-r--r--tools/perf/config/Makefile6
-rw-r--r--tools/perf/config/feature-checks/Makefile4
-rw-r--r--tools/perf/config/feature-checks/test-all.c5
-rw-r--r--tools/perf/config/feature-checks/test-sync-compare-and-swap.c14
-rw-r--r--tools/perf/perf.c13
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py3
-rw-r--r--tools/perf/scripts/python/check-perf-trace.py4
-rw-r--r--tools/perf/scripts/python/failed-syscalls-by-pid.py2
-rw-r--r--tools/perf/scripts/python/futex-contention.py4
-rwxr-xr-xtools/perf/scripts/python/net_dropmonitor.py2
-rw-r--r--tools/perf/scripts/python/netdev-times.py26
-rw-r--r--tools/perf/scripts/python/sched-migration.py41
-rw-r--r--tools/perf/scripts/python/sctop.py2
-rw-r--r--tools/perf/scripts/python/syscall-counts-by-pid.py2
-rw-r--r--tools/perf/scripts/python/syscall-counts.py2
-rw-r--r--tools/perf/tests/dso-data.c1
-rw-r--r--tools/perf/tests/evsel-roundtrip-name.c1
-rw-r--r--tools/perf/tests/evsel-tp-sched.c1
-rw-r--r--tools/perf/tests/open-syscall-tp-fields.c1
-rw-r--r--tools/perf/tests/parse-events.c1
-rw-r--r--tools/perf/tests/parse-no-sample-id-all.c1
-rw-r--r--tools/perf/tests/perf-time-to-tsc.c3
-rw-r--r--tools/perf/tests/sample-parsing.c1
-rw-r--r--tools/perf/tests/thread-mg-share.c1
-rw-r--r--tools/perf/ui/stdio/hist.c2
-rw-r--r--tools/perf/util/callchain.c2
-rw-r--r--tools/perf/util/data.c1
-rw-r--r--tools/perf/util/debug.c56
-rw-r--r--tools/perf/util/debug.h22
-rw-r--r--tools/perf/util/dso.c1
-rw-r--r--tools/perf/util/dso.h1
-rw-r--r--tools/perf/util/event.c10
-rw-r--r--tools/perf/util/evlist.c46
-rw-r--r--tools/perf/util/evsel.c14
-rw-r--r--tools/perf/util/evsel.h2
-rw-r--r--tools/perf/util/include/linux/kernel.h21
-rw-r--r--tools/perf/util/kvm-stat.h140
-rw-r--r--tools/perf/util/machine.c63
-rw-r--r--tools/perf/util/map.c38
-rw-r--r--tools/perf/util/map.h10
-rw-r--r--tools/perf/util/parse-options.h5
-rw-r--r--tools/perf/util/probe-finder.c1
-rw-r--r--tools/perf/util/pstack.c1
-rw-r--r--tools/perf/util/python.c4
-rw-r--r--tools/perf/util/record.c18
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c1
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c140
-rw-r--r--tools/perf/util/session.c14
-rw-r--r--tools/perf/util/session.h3
-rw-r--r--tools/perf/util/symbol-elf.c6
-rw-r--r--tools/perf/util/symbol-minimal.c22
-rw-r--r--tools/perf/util/symbol.c20
-rw-r--r--tools/perf/util/symbol.h4
-rw-r--r--tools/perf/util/thread.c12
-rw-r--r--tools/perf/util/trace-event-info.c1
-rw-r--r--tools/perf/util/trace-event-read.c2
-rw-r--r--tools/perf/util/tsc.c25
-rw-r--r--tools/perf/util/tsc.h11
-rw-r--r--tools/perf/util/unwind-libdw.c1
-rw-r--r--tools/perf/util/unwind-libunwind.c1
-rw-r--r--tools/perf/util/util.c1
-rw-r--r--tools/perf/util/vdso.c1
85 files changed, 1170 insertions, 470 deletions
diff --git a/arch/s390/include/uapi/asm/Kbuild b/arch/s390/include/uapi/asm/Kbuild
index 6a9a9eb645f5..0e2b54db82bc 100644
--- a/arch/s390/include/uapi/asm/Kbuild
+++ b/arch/s390/include/uapi/asm/Kbuild
@@ -16,6 +16,7 @@ header-y += ioctls.h
16header-y += ipcbuf.h 16header-y += ipcbuf.h
17header-y += kvm.h 17header-y += kvm.h
18header-y += kvm_para.h 18header-y += kvm_para.h
19header-y += kvm_perf.h
19header-y += kvm_virtio.h 20header-y += kvm_virtio.h
20header-y += mman.h 21header-y += mman.h
21header-y += monwriter.h 22header-y += monwriter.h
diff --git a/arch/s390/include/uapi/asm/kvm_perf.h b/arch/s390/include/uapi/asm/kvm_perf.h
new file mode 100644
index 000000000000..397282727e21
--- /dev/null
+++ b/arch/s390/include/uapi/asm/kvm_perf.h
@@ -0,0 +1,25 @@
1/*
2 * Definitions for perf-kvm on s390
3 *
4 * Copyright 2014 IBM Corp.
5 * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License (version 2 only)
9 * as published by the Free Software Foundation.
10 */
11
12#ifndef __LINUX_KVM_PERF_S390_H
13#define __LINUX_KVM_PERF_S390_H
14
15#include <asm/sie.h>
16
17#define DECODE_STR_LEN 40
18
19#define VCPU_ID "id"
20
21#define KVM_ENTRY_TRACE "kvm:kvm_s390_sie_enter"
22#define KVM_EXIT_TRACE "kvm:kvm_s390_sie_exit"
23#define KVM_EXIT_REASON "icptcode"
24
25#endif
diff --git a/arch/x86/include/uapi/asm/Kbuild b/arch/x86/include/uapi/asm/Kbuild
index 09409c44f9a5..3dec769cadf7 100644
--- a/arch/x86/include/uapi/asm/Kbuild
+++ b/arch/x86/include/uapi/asm/Kbuild
@@ -22,6 +22,7 @@ header-y += ipcbuf.h
22header-y += ist.h 22header-y += ist.h
23header-y += kvm.h 23header-y += kvm.h
24header-y += kvm_para.h 24header-y += kvm_para.h
25header-y += kvm_perf.h
25header-y += ldt.h 26header-y += ldt.h
26header-y += mce.h 27header-y += mce.h
27header-y += mman.h 28header-y += mman.h
diff --git a/arch/x86/include/uapi/asm/kvm_perf.h b/arch/x86/include/uapi/asm/kvm_perf.h
new file mode 100644
index 000000000000..3bb964f88aa1
--- /dev/null
+++ b/arch/x86/include/uapi/asm/kvm_perf.h
@@ -0,0 +1,16 @@
1#ifndef _ASM_X86_KVM_PERF_H
2#define _ASM_X86_KVM_PERF_H
3
4#include <asm/svm.h>
5#include <asm/vmx.h>
6#include <asm/kvm.h>
7
8#define DECODE_STR_LEN 20
9
10#define VCPU_ID "vcpu_id"
11
12#define KVM_ENTRY_TRACE "kvm:kvm_entry"
13#define KVM_EXIT_TRACE "kvm:kvm_exit"
14#define KVM_EXIT_REASON "exit_reason"
15
16#endif /* _ASM_X86_KVM_PERF_H */
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index 52276a6d2b75..6e689dc89a2f 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -51,9 +51,9 @@ There are a couple of variants of perf kvm:
51 'perf kvm stat <command>' to run a command and gather performance counter 51 'perf kvm stat <command>' to run a command and gather performance counter
52 statistics. 52 statistics.
53 Especially, perf 'kvm stat record/report' generates a statistical analysis 53 Especially, perf 'kvm stat record/report' generates a statistical analysis
54 of KVM events. Currently, vmexit, mmio and ioport events are supported. 54 of KVM events. Currently, vmexit, mmio (x86 only) and ioport (x86 only)
55 'perf kvm stat record <command>' records kvm events and the events between 55 events are supported. 'perf kvm stat record <command>' records kvm events
56 start and end <command>. 56 and the events between start and end <command>.
57 And this command produces a file which contains tracing results of kvm 57 And this command produces a file which contains tracing results of kvm
58 events. 58 events.
59 59
@@ -103,8 +103,8 @@ STAT REPORT OPTIONS
103 analyze events which occures on this vcpu. (default: all vcpus) 103 analyze events which occures on this vcpu. (default: all vcpus)
104 104
105--event=<value>:: 105--event=<value>::
106 event to be analyzed. Possible values: vmexit, mmio, ioport. 106 event to be analyzed. Possible values: vmexit, mmio (x86 only),
107 (default: vmexit) 107 ioport (x86 only). (default: vmexit)
108-k:: 108-k::
109--key=<value>:: 109--key=<value>::
110 Sorting key. Possible values: sample (default, sort by samples 110 Sorting key. Possible values: sample (default, sort by samples
@@ -138,7 +138,8 @@ STAT LIVE OPTIONS
138 138
139 139
140--event=<value>:: 140--event=<value>::
141 event to be analyzed. Possible values: vmexit, mmio, ioport. 141 event to be analyzed. Possible values: vmexit,
142 mmio (x86 only), ioport (x86 only).
142 (default: vmexit) 143 (default: vmexit)
143 144
144-k:: 145-k::
@@ -147,7 +148,8 @@ STAT LIVE OPTIONS
147 number), time (sort by average time). 148 number), time (sort by average time).
148 149
149--duration=<value>:: 150--duration=<value>::
150 Show events other than HLT that take longer than duration usecs. 151 Show events other than HLT (x86 only) or Wait state (s390 only)
152 that take longer than duration usecs.
151 153
152SEE ALSO 154SEE ALSO
153-------- 155--------
diff --git a/tools/perf/Documentation/perf.txt b/tools/perf/Documentation/perf.txt
index 0eeb247dc7d2..d240bb2e5b22 100644
--- a/tools/perf/Documentation/perf.txt
+++ b/tools/perf/Documentation/perf.txt
@@ -8,7 +8,15 @@ perf - Performance analysis tools for Linux
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf' [--version] [--help] COMMAND [ARGS] 11'perf' [--version] [--help] [OPTIONS] COMMAND [ARGS]
12
13OPTIONS
14-------
15--debug::
16 Setup debug variable (just verbose for now) in value
17 range (0, 10). Use like:
18 --debug verbose # sets verbose = 1
19 --debug verbose=2 # sets verbose = 2
12 20
13DESCRIPTION 21DESCRIPTION
14----------- 22-----------
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 45da209b6ed3..344c4d3d0a4a 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -37,3 +37,6 @@ arch/x86/include/asm/kvm_host.h
37arch/x86/include/uapi/asm/svm.h 37arch/x86/include/uapi/asm/svm.h
38arch/x86/include/uapi/asm/vmx.h 38arch/x86/include/uapi/asm/vmx.h
39arch/x86/include/uapi/asm/kvm.h 39arch/x86/include/uapi/asm/kvm.h
40arch/x86/include/uapi/asm/kvm_perf.h
41arch/s390/include/uapi/asm/sie.h
42arch/s390/include/uapi/asm/kvm_perf.h
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 9670a16fa577..3308b22a1660 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -295,11 +295,13 @@ LIB_H += util/intlist.h
295LIB_H += util/perf_regs.h 295LIB_H += util/perf_regs.h
296LIB_H += util/unwind.h 296LIB_H += util/unwind.h
297LIB_H += util/vdso.h 297LIB_H += util/vdso.h
298LIB_H += util/tsc.h
298LIB_H += ui/helpline.h 299LIB_H += ui/helpline.h
299LIB_H += ui/progress.h 300LIB_H += ui/progress.h
300LIB_H += ui/util.h 301LIB_H += ui/util.h
301LIB_H += ui/ui.h 302LIB_H += ui/ui.h
302LIB_H += util/data.h 303LIB_H += util/data.h
304LIB_H += util/kvm-stat.h
303 305
304LIB_OBJS += $(OUTPUT)util/abspath.o 306LIB_OBJS += $(OUTPUT)util/abspath.o
305LIB_OBJS += $(OUTPUT)util/alias.o 307LIB_OBJS += $(OUTPUT)util/alias.o
@@ -373,6 +375,7 @@ LIB_OBJS += $(OUTPUT)util/stat.o
373LIB_OBJS += $(OUTPUT)util/record.o 375LIB_OBJS += $(OUTPUT)util/record.o
374LIB_OBJS += $(OUTPUT)util/srcline.o 376LIB_OBJS += $(OUTPUT)util/srcline.o
375LIB_OBJS += $(OUTPUT)util/data.o 377LIB_OBJS += $(OUTPUT)util/data.o
378LIB_OBJS += $(OUTPUT)util/tsc.o
376 379
377LIB_OBJS += $(OUTPUT)ui/setup.o 380LIB_OBJS += $(OUTPUT)ui/setup.o
378LIB_OBJS += $(OUTPUT)ui/helpline.o 381LIB_OBJS += $(OUTPUT)ui/helpline.o
diff --git a/tools/perf/arch/s390/Makefile b/tools/perf/arch/s390/Makefile
index 744e629797be..798ac7379c5f 100644
--- a/tools/perf/arch/s390/Makefile
+++ b/tools/perf/arch/s390/Makefile
@@ -3,3 +3,5 @@ PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o 3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif 4endif
5LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o 5LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
6HAVE_KVM_STAT_SUPPORT := 1
7LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/kvm-stat.o
diff --git a/tools/perf/arch/s390/util/kvm-stat.c b/tools/perf/arch/s390/util/kvm-stat.c
new file mode 100644
index 000000000000..a5dbc07ec9dc
--- /dev/null
+++ b/tools/perf/arch/s390/util/kvm-stat.c
@@ -0,0 +1,105 @@
1/*
2 * Arch specific functions for perf kvm stat.
3 *
4 * Copyright 2014 IBM Corp.
5 * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License (version 2 only)
9 * as published by the Free Software Foundation.
10 */
11
12#include "../../util/kvm-stat.h"
13#include <asm/kvm_perf.h>
14
15define_exit_reasons_table(sie_exit_reasons, sie_intercept_code);
16define_exit_reasons_table(sie_icpt_insn_codes, icpt_insn_codes);
17define_exit_reasons_table(sie_sigp_order_codes, sigp_order_codes);
18define_exit_reasons_table(sie_diagnose_codes, diagnose_codes);
19define_exit_reasons_table(sie_icpt_prog_codes, icpt_prog_codes);
20
21static void event_icpt_insn_get_key(struct perf_evsel *evsel,
22 struct perf_sample *sample,
23 struct event_key *key)
24{
25 unsigned long insn;
26
27 insn = perf_evsel__intval(evsel, sample, "instruction");
28 key->key = icpt_insn_decoder(insn);
29 key->exit_reasons = sie_icpt_insn_codes;
30}
31
32static void event_sigp_get_key(struct perf_evsel *evsel,
33 struct perf_sample *sample,
34 struct event_key *key)
35{
36 key->key = perf_evsel__intval(evsel, sample, "order_code");
37 key->exit_reasons = sie_sigp_order_codes;
38}
39
40static void event_diag_get_key(struct perf_evsel *evsel,
41 struct perf_sample *sample,
42 struct event_key *key)
43{
44 key->key = perf_evsel__intval(evsel, sample, "code");
45 key->exit_reasons = sie_diagnose_codes;
46}
47
48static void event_icpt_prog_get_key(struct perf_evsel *evsel,
49 struct perf_sample *sample,
50 struct event_key *key)
51{
52 key->key = perf_evsel__intval(evsel, sample, "code");
53 key->exit_reasons = sie_icpt_prog_codes;
54}
55
56static struct child_event_ops child_events[] = {
57 { .name = "kvm:kvm_s390_intercept_instruction",
58 .get_key = event_icpt_insn_get_key },
59 { .name = "kvm:kvm_s390_handle_sigp",
60 .get_key = event_sigp_get_key },
61 { .name = "kvm:kvm_s390_handle_diag",
62 .get_key = event_diag_get_key },
63 { .name = "kvm:kvm_s390_intercept_prog",
64 .get_key = event_icpt_prog_get_key },
65 { NULL, NULL },
66};
67
68static struct kvm_events_ops exit_events = {
69 .is_begin_event = exit_event_begin,
70 .is_end_event = exit_event_end,
71 .child_ops = child_events,
72 .decode_key = exit_event_decode_key,
73 .name = "VM-EXIT"
74};
75
76const char * const kvm_events_tp[] = {
77 "kvm:kvm_s390_sie_enter",
78 "kvm:kvm_s390_sie_exit",
79 "kvm:kvm_s390_intercept_instruction",
80 "kvm:kvm_s390_handle_sigp",
81 "kvm:kvm_s390_handle_diag",
82 "kvm:kvm_s390_intercept_prog",
83 NULL,
84};
85
86struct kvm_reg_events_ops kvm_reg_events_ops[] = {
87 { .name = "vmexit", .ops = &exit_events },
88 { NULL, NULL },
89};
90
91const char * const kvm_skip_events[] = {
92 "Wait state",
93 NULL,
94};
95
96int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid)
97{
98 if (strstr(cpuid, "IBM/S390")) {
99 kvm->exit_reasons = sie_exit_reasons;
100 kvm->exit_reasons_isa = "SIE";
101 } else
102 return -ENOTSUP;
103
104 return 0;
105}
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index d3939014a877..9b21881db52f 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -16,3 +16,4 @@ LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
16LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o 16LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o
17LIB_H += arch/$(ARCH)/util/tsc.h 17LIB_H += arch/$(ARCH)/util/tsc.h
18HAVE_KVM_STAT_SUPPORT := 1 18HAVE_KVM_STAT_SUPPORT := 1
19LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/kvm-stat.o
diff --git a/tools/perf/arch/x86/tests/dwarf-unwind.c b/tools/perf/arch/x86/tests/dwarf-unwind.c
index 9f89f899ccc7..d8bbf7ad1681 100644
--- a/tools/perf/arch/x86/tests/dwarf-unwind.c
+++ b/tools/perf/arch/x86/tests/dwarf-unwind.c
@@ -3,6 +3,7 @@
3#include "thread.h" 3#include "thread.h"
4#include "map.h" 4#include "map.h"
5#include "event.h" 5#include "event.h"
6#include "debug.h"
6#include "tests/tests.h" 7#include "tests/tests.h"
7 8
8#define STACK_SIZE 8192 9#define STACK_SIZE 8192
diff --git a/tools/perf/arch/x86/util/kvm-stat.c b/tools/perf/arch/x86/util/kvm-stat.c
new file mode 100644
index 000000000000..14e4e668fad7
--- /dev/null
+++ b/tools/perf/arch/x86/util/kvm-stat.c
@@ -0,0 +1,156 @@
1#include "../../util/kvm-stat.h"
2#include <asm/kvm_perf.h>
3
4define_exit_reasons_table(vmx_exit_reasons, VMX_EXIT_REASONS);
5define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS);
6
7static struct kvm_events_ops exit_events = {
8 .is_begin_event = exit_event_begin,
9 .is_end_event = exit_event_end,
10 .decode_key = exit_event_decode_key,
11 .name = "VM-EXIT"
12};
13
14/*
15 * For the mmio events, we treat:
16 * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry
17 * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...).
18 */
19static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample,
20 struct event_key *key)
21{
22 key->key = perf_evsel__intval(evsel, sample, "gpa");
23 key->info = perf_evsel__intval(evsel, sample, "type");
24}
25
26#define KVM_TRACE_MMIO_READ_UNSATISFIED 0
27#define KVM_TRACE_MMIO_READ 1
28#define KVM_TRACE_MMIO_WRITE 2
29
30static bool mmio_event_begin(struct perf_evsel *evsel,
31 struct perf_sample *sample, struct event_key *key)
32{
33 /* MMIO read begin event in kernel. */
34 if (kvm_exit_event(evsel))
35 return true;
36
37 /* MMIO write begin event in kernel. */
38 if (!strcmp(evsel->name, "kvm:kvm_mmio") &&
39 perf_evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_WRITE) {
40 mmio_event_get_key(evsel, sample, key);
41 return true;
42 }
43
44 return false;
45}
46
47static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample,
48 struct event_key *key)
49{
50 /* MMIO write end event in kernel. */
51 if (kvm_entry_event(evsel))
52 return true;
53
54 /* MMIO read end event in kernel.*/
55 if (!strcmp(evsel->name, "kvm:kvm_mmio") &&
56 perf_evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_READ) {
57 mmio_event_get_key(evsel, sample, key);
58 return true;
59 }
60
61 return false;
62}
63
64static void mmio_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
65 struct event_key *key,
66 char *decode)
67{
68 scnprintf(decode, DECODE_STR_LEN, "%#lx:%s",
69 (unsigned long)key->key,
70 key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R");
71}
72
73static struct kvm_events_ops mmio_events = {
74 .is_begin_event = mmio_event_begin,
75 .is_end_event = mmio_event_end,
76 .decode_key = mmio_event_decode_key,
77 .name = "MMIO Access"
78};
79
80 /* The time of emulation pio access is from kvm_pio to kvm_entry. */
81static void ioport_event_get_key(struct perf_evsel *evsel,
82 struct perf_sample *sample,
83 struct event_key *key)
84{
85 key->key = perf_evsel__intval(evsel, sample, "port");
86 key->info = perf_evsel__intval(evsel, sample, "rw");
87}
88
89static bool ioport_event_begin(struct perf_evsel *evsel,
90 struct perf_sample *sample,
91 struct event_key *key)
92{
93 if (!strcmp(evsel->name, "kvm:kvm_pio")) {
94 ioport_event_get_key(evsel, sample, key);
95 return true;
96 }
97
98 return false;
99}
100
101static bool ioport_event_end(struct perf_evsel *evsel,
102 struct perf_sample *sample __maybe_unused,
103 struct event_key *key __maybe_unused)
104{
105 return kvm_entry_event(evsel);
106}
107
108static void ioport_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
109 struct event_key *key,
110 char *decode)
111{
112 scnprintf(decode, DECODE_STR_LEN, "%#llx:%s",
113 (unsigned long long)key->key,
114 key->info ? "POUT" : "PIN");
115}
116
117static struct kvm_events_ops ioport_events = {
118 .is_begin_event = ioport_event_begin,
119 .is_end_event = ioport_event_end,
120 .decode_key = ioport_event_decode_key,
121 .name = "IO Port Access"
122};
123
124const char * const kvm_events_tp[] = {
125 "kvm:kvm_entry",
126 "kvm:kvm_exit",
127 "kvm:kvm_mmio",
128 "kvm:kvm_pio",
129 NULL,
130};
131
132struct kvm_reg_events_ops kvm_reg_events_ops[] = {
133 { .name = "vmexit", .ops = &exit_events },
134 { .name = "mmio", .ops = &mmio_events },
135 { .name = "ioport", .ops = &ioport_events },
136 { NULL, NULL },
137};
138
139const char * const kvm_skip_events[] = {
140 "HLT",
141 NULL,
142};
143
144int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid)
145{
146 if (strstr(cpuid, "Intel")) {
147 kvm->exit_reasons = vmx_exit_reasons;
148 kvm->exit_reasons_isa = "VMX";
149 } else if (strstr(cpuid, "AMD")) {
150 kvm->exit_reasons = svm_exit_reasons;
151 kvm->exit_reasons_isa = "SVM";
152 } else
153 return -ENOTSUP;
154
155 return 0;
156}
diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c
index 40021fa3129b..3655f24c3170 100644
--- a/tools/perf/arch/x86/util/tsc.c
+++ b/tools/perf/arch/x86/util/tsc.c
@@ -6,29 +6,9 @@
6#include "../../perf.h" 6#include "../../perf.h"
7#include <linux/types.h> 7#include <linux/types.h>
8#include "../../util/debug.h" 8#include "../../util/debug.h"
9#include "../../util/tsc.h"
9#include "tsc.h" 10#include "tsc.h"
10 11
11u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc)
12{
13 u64 t, quot, rem;
14
15 t = ns - tc->time_zero;
16 quot = t / tc->time_mult;
17 rem = t % tc->time_mult;
18 return (quot << tc->time_shift) +
19 (rem << tc->time_shift) / tc->time_mult;
20}
21
22u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc)
23{
24 u64 quot, rem;
25
26 quot = cyc >> tc->time_shift;
27 rem = cyc & ((1 << tc->time_shift) - 1);
28 return tc->time_zero + quot * tc->time_mult +
29 ((rem * tc->time_mult) >> tc->time_shift);
30}
31
32int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, 12int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
33 struct perf_tsc_conversion *tc) 13 struct perf_tsc_conversion *tc)
34{ 14{
diff --git a/tools/perf/arch/x86/util/tsc.h b/tools/perf/arch/x86/util/tsc.h
index 2affe0366b59..2edc4d31065c 100644
--- a/tools/perf/arch/x86/util/tsc.h
+++ b/tools/perf/arch/x86/util/tsc.h
@@ -14,7 +14,4 @@ struct perf_event_mmap_page;
14int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, 14int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
15 struct perf_tsc_conversion *tc); 15 struct perf_tsc_conversion *tc);
16 16
17u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc);
18u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc);
19
20#endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */ 17#endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */
diff --git a/tools/perf/arch/x86/util/unwind-libunwind.c b/tools/perf/arch/x86/util/unwind-libunwind.c
index 3261f68c6a7c..db25e93d989c 100644
--- a/tools/perf/arch/x86/util/unwind-libunwind.c
+++ b/tools/perf/arch/x86/util/unwind-libunwind.c
@@ -3,6 +3,7 @@
3#include <libunwind.h> 3#include <libunwind.h>
4#include "perf_regs.h" 4#include "perf_regs.h"
5#include "../../util/unwind.h" 5#include "../../util/unwind.h"
6#include "../../util/debug.h"
6 7
7#ifdef HAVE_ARCH_X86_64_SUPPORT 8#ifdef HAVE_ARCH_X86_64_SUPPORT
8int libunwind__arch_reg_id(int regnum) 9int libunwind__arch_reg_id(int regnum)
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index b22dbb16f877..2a2c78f80876 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -125,7 +125,8 @@ static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
125 return ret; 125 return ret;
126} 126}
127 127
128static int build_id_cache__add_kcore(const char *filename, const char *debugdir) 128static int build_id_cache__add_kcore(const char *filename, const char *debugdir,
129 bool force)
129{ 130{
130 char dir[32], sbuildid[BUILD_ID_SIZE * 2 + 1]; 131 char dir[32], sbuildid[BUILD_ID_SIZE * 2 + 1];
131 char from_dir[PATH_MAX], to_dir[PATH_MAX]; 132 char from_dir[PATH_MAX], to_dir[PATH_MAX];
@@ -144,7 +145,8 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir)
144 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s", 145 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s",
145 debugdir, sbuildid); 146 debugdir, sbuildid);
146 147
147 if (!build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) { 148 if (!force &&
149 !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) {
148 pr_debug("same kcore found in %s\n", to_dir); 150 pr_debug("same kcore found in %s\n", to_dir);
149 return 0; 151 return 0;
150 } 152 }
@@ -389,7 +391,7 @@ int cmd_buildid_cache(int argc, const char **argv,
389 } 391 }
390 392
391 if (kcore_filename && 393 if (kcore_filename &&
392 build_id_cache__add_kcore(kcore_filename, debugdir)) 394 build_id_cache__add_kcore(kcore_filename, debugdir, force))
393 pr_warning("Couldn't add %s\n", kcore_filename); 395 pr_warning("Couldn't add %s\n", kcore_filename);
394 396
395 return ret; 397 return ret;
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index c99e0de7e54a..66e12f55c052 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -15,6 +15,7 @@
15#include "util/parse-options.h" 15#include "util/parse-options.h"
16#include "util/session.h" 16#include "util/session.h"
17#include "util/data.h" 17#include "util/data.h"
18#include "util/debug.h"
18 19
19static int __cmd_evlist(const char *file_name, struct perf_attr_details *details) 20static int __cmd_evlist(const char *file_name, struct perf_attr_details *details)
20{ 21{
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 178b88ae3d2f..0384d930480b 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -11,6 +11,7 @@
11#include "util/parse-options.h" 11#include "util/parse-options.h"
12#include "util/run-command.h" 12#include "util/run-command.h"
13#include "util/help.h" 13#include "util/help.h"
14#include "util/debug.h"
14 15
15static struct man_viewer_list { 16static struct man_viewer_list {
16 struct man_viewer_list *next; 17 struct man_viewer_list *next;
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 16c7c11ad06e..cf6a605a13e8 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -389,6 +389,9 @@ static int __cmd_inject(struct perf_inject *inject)
389 ret = perf_session__process_events(session, &inject->tool); 389 ret = perf_session__process_events(session, &inject->tool);
390 390
391 if (!file_out->is_pipe) { 391 if (!file_out->is_pipe) {
392 if (inject->build_ids)
393 perf_header__set_feat(&session->header,
394 HEADER_BUILD_ID);
392 session->header.data_size = inject->bytes_written; 395 session->header.data_size = inject->bytes_written;
393 perf_session__write_header(session, session->evlist, file_out->fd, true); 396 perf_session__write_header(session, session->evlist, file_out->fd, true);
394 } 397 }
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 41dbeaf8cc11..43367eb00510 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -30,112 +30,24 @@
30#include <math.h> 30#include <math.h>
31 31
32#ifdef HAVE_KVM_STAT_SUPPORT 32#ifdef HAVE_KVM_STAT_SUPPORT
33#include <asm/svm.h> 33#include <asm/kvm_perf.h>
34#include <asm/vmx.h> 34#include "util/kvm-stat.h"
35#include <asm/kvm.h>
36
37struct event_key {
38 #define INVALID_KEY (~0ULL)
39 u64 key;
40 int info;
41};
42
43struct kvm_event_stats {
44 u64 time;
45 struct stats stats;
46};
47
48struct kvm_event {
49 struct list_head hash_entry;
50 struct rb_node rb;
51
52 struct event_key key;
53
54 struct kvm_event_stats total;
55
56 #define DEFAULT_VCPU_NUM 8
57 int max_vcpu;
58 struct kvm_event_stats *vcpu;
59};
60
61typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int);
62
63struct kvm_event_key {
64 const char *name;
65 key_cmp_fun key;
66};
67
68
69struct perf_kvm_stat;
70
71struct kvm_events_ops {
72 bool (*is_begin_event)(struct perf_evsel *evsel,
73 struct perf_sample *sample,
74 struct event_key *key);
75 bool (*is_end_event)(struct perf_evsel *evsel,
76 struct perf_sample *sample, struct event_key *key);
77 void (*decode_key)(struct perf_kvm_stat *kvm, struct event_key *key,
78 char decode[20]);
79 const char *name;
80};
81
82struct exit_reasons_table {
83 unsigned long exit_code;
84 const char *reason;
85};
86
87#define EVENTS_BITS 12
88#define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS)
89
90struct perf_kvm_stat {
91 struct perf_tool tool;
92 struct record_opts opts;
93 struct perf_evlist *evlist;
94 struct perf_session *session;
95
96 const char *file_name;
97 const char *report_event;
98 const char *sort_key;
99 int trace_vcpu;
100
101 struct exit_reasons_table *exit_reasons;
102 const char *exit_reasons_isa;
103
104 struct kvm_events_ops *events_ops;
105 key_cmp_fun compare;
106 struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
107
108 u64 total_time;
109 u64 total_count;
110 u64 lost_events;
111 u64 duration;
112
113 const char *pid_str;
114 struct intlist *pid_list;
115 35
116 struct rb_root result; 36void exit_event_get_key(struct perf_evsel *evsel,
117 37 struct perf_sample *sample,
118 int timerfd; 38 struct event_key *key)
119 unsigned int display_time;
120 bool live;
121};
122
123
124static void exit_event_get_key(struct perf_evsel *evsel,
125 struct perf_sample *sample,
126 struct event_key *key)
127{ 39{
128 key->info = 0; 40 key->info = 0;
129 key->key = perf_evsel__intval(evsel, sample, "exit_reason"); 41 key->key = perf_evsel__intval(evsel, sample, KVM_EXIT_REASON);
130} 42}
131 43
132static bool kvm_exit_event(struct perf_evsel *evsel) 44bool kvm_exit_event(struct perf_evsel *evsel)
133{ 45{
134 return !strcmp(evsel->name, "kvm:kvm_exit"); 46 return !strcmp(evsel->name, KVM_EXIT_TRACE);
135} 47}
136 48
137static bool exit_event_begin(struct perf_evsel *evsel, 49bool exit_event_begin(struct perf_evsel *evsel,
138 struct perf_sample *sample, struct event_key *key) 50 struct perf_sample *sample, struct event_key *key)
139{ 51{
140 if (kvm_exit_event(evsel)) { 52 if (kvm_exit_event(evsel)) {
141 exit_event_get_key(evsel, sample, key); 53 exit_event_get_key(evsel, sample, key);
@@ -145,26 +57,18 @@ static bool exit_event_begin(struct perf_evsel *evsel,
145 return false; 57 return false;
146} 58}
147 59
148static bool kvm_entry_event(struct perf_evsel *evsel) 60bool kvm_entry_event(struct perf_evsel *evsel)
149{ 61{
150 return !strcmp(evsel->name, "kvm:kvm_entry"); 62 return !strcmp(evsel->name, KVM_ENTRY_TRACE);
151} 63}
152 64
153static bool exit_event_end(struct perf_evsel *evsel, 65bool exit_event_end(struct perf_evsel *evsel,
154 struct perf_sample *sample __maybe_unused, 66 struct perf_sample *sample __maybe_unused,
155 struct event_key *key __maybe_unused) 67 struct event_key *key __maybe_unused)
156{ 68{
157 return kvm_entry_event(evsel); 69 return kvm_entry_event(evsel);
158} 70}
159 71
160#define define_exit_reasons_table(name, symbols) \
161 static struct exit_reasons_table name[] = { \
162 symbols, { -1, NULL } \
163 }
164
165define_exit_reasons_table(vmx_exit_reasons, VMX_EXIT_REASONS);
166define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS);
167
168static const char *get_exit_reason(struct perf_kvm_stat *kvm, 72static const char *get_exit_reason(struct perf_kvm_stat *kvm,
169 struct exit_reasons_table *tbl, 73 struct exit_reasons_table *tbl,
170 u64 exit_code) 74 u64 exit_code)
@@ -180,149 +84,30 @@ static const char *get_exit_reason(struct perf_kvm_stat *kvm,
180 return "UNKNOWN"; 84 return "UNKNOWN";
181} 85}
182 86
183static void exit_event_decode_key(struct perf_kvm_stat *kvm, 87void exit_event_decode_key(struct perf_kvm_stat *kvm,
184 struct event_key *key, 88 struct event_key *key,
185 char decode[20]) 89 char *decode)
186{ 90{
187 const char *exit_reason = get_exit_reason(kvm, kvm->exit_reasons, 91 const char *exit_reason = get_exit_reason(kvm, key->exit_reasons,
188 key->key); 92 key->key);
189 93
190 scnprintf(decode, 20, "%s", exit_reason); 94 scnprintf(decode, DECODE_STR_LEN, "%s", exit_reason);
191} 95}
192 96
193static struct kvm_events_ops exit_events = { 97static bool register_kvm_events_ops(struct perf_kvm_stat *kvm)
194 .is_begin_event = exit_event_begin,
195 .is_end_event = exit_event_end,
196 .decode_key = exit_event_decode_key,
197 .name = "VM-EXIT"
198};
199
200/*
201 * For the mmio events, we treat:
202 * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry
203 * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...).
204 */
205static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample,
206 struct event_key *key)
207{
208 key->key = perf_evsel__intval(evsel, sample, "gpa");
209 key->info = perf_evsel__intval(evsel, sample, "type");
210}
211
212#define KVM_TRACE_MMIO_READ_UNSATISFIED 0
213#define KVM_TRACE_MMIO_READ 1
214#define KVM_TRACE_MMIO_WRITE 2
215
216static bool mmio_event_begin(struct perf_evsel *evsel,
217 struct perf_sample *sample, struct event_key *key)
218{
219 /* MMIO read begin event in kernel. */
220 if (kvm_exit_event(evsel))
221 return true;
222
223 /* MMIO write begin event in kernel. */
224 if (!strcmp(evsel->name, "kvm:kvm_mmio") &&
225 perf_evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_WRITE) {
226 mmio_event_get_key(evsel, sample, key);
227 return true;
228 }
229
230 return false;
231}
232
233static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample,
234 struct event_key *key)
235{
236 /* MMIO write end event in kernel. */
237 if (kvm_entry_event(evsel))
238 return true;
239
240 /* MMIO read end event in kernel.*/
241 if (!strcmp(evsel->name, "kvm:kvm_mmio") &&
242 perf_evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_READ) {
243 mmio_event_get_key(evsel, sample, key);
244 return true;
245 }
246
247 return false;
248}
249
250static void mmio_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
251 struct event_key *key,
252 char decode[20])
253{
254 scnprintf(decode, 20, "%#lx:%s", (unsigned long)key->key,
255 key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R");
256}
257
258static struct kvm_events_ops mmio_events = {
259 .is_begin_event = mmio_event_begin,
260 .is_end_event = mmio_event_end,
261 .decode_key = mmio_event_decode_key,
262 .name = "MMIO Access"
263};
264
265 /* The time of emulation pio access is from kvm_pio to kvm_entry. */
266static void ioport_event_get_key(struct perf_evsel *evsel,
267 struct perf_sample *sample,
268 struct event_key *key)
269{ 98{
270 key->key = perf_evsel__intval(evsel, sample, "port"); 99 struct kvm_reg_events_ops *events_ops = kvm_reg_events_ops;
271 key->info = perf_evsel__intval(evsel, sample, "rw");
272}
273 100
274static bool ioport_event_begin(struct perf_evsel *evsel, 101 for (events_ops = kvm_reg_events_ops; events_ops->name; events_ops++) {
275 struct perf_sample *sample, 102 if (!strcmp(events_ops->name, kvm->report_event)) {
276 struct event_key *key) 103 kvm->events_ops = events_ops->ops;
277{ 104 return true;
278 if (!strcmp(evsel->name, "kvm:kvm_pio")) { 105 }
279 ioport_event_get_key(evsel, sample, key);
280 return true;
281 } 106 }
282 107
283 return false; 108 return false;
284} 109}
285 110
286static bool ioport_event_end(struct perf_evsel *evsel,
287 struct perf_sample *sample __maybe_unused,
288 struct event_key *key __maybe_unused)
289{
290 return kvm_entry_event(evsel);
291}
292
293static void ioport_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
294 struct event_key *key,
295 char decode[20])
296{
297 scnprintf(decode, 20, "%#llx:%s", (unsigned long long)key->key,
298 key->info ? "POUT" : "PIN");
299}
300
301static struct kvm_events_ops ioport_events = {
302 .is_begin_event = ioport_event_begin,
303 .is_end_event = ioport_event_end,
304 .decode_key = ioport_event_decode_key,
305 .name = "IO Port Access"
306};
307
308static bool register_kvm_events_ops(struct perf_kvm_stat *kvm)
309{
310 bool ret = true;
311
312 if (!strcmp(kvm->report_event, "vmexit"))
313 kvm->events_ops = &exit_events;
314 else if (!strcmp(kvm->report_event, "mmio"))
315 kvm->events_ops = &mmio_events;
316 else if (!strcmp(kvm->report_event, "ioport"))
317 kvm->events_ops = &ioport_events;
318 else {
319 pr_err("Unknown report event:%s\n", kvm->report_event);
320 ret = false;
321 }
322
323 return ret;
324}
325
326struct vcpu_event_record { 111struct vcpu_event_record {
327 int vcpu_id; 112 int vcpu_id;
328 u64 start_time; 113 u64 start_time;
@@ -476,6 +261,54 @@ static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
476 return true; 261 return true;
477} 262}
478 263
264static bool is_child_event(struct perf_kvm_stat *kvm,
265 struct perf_evsel *evsel,
266 struct perf_sample *sample,
267 struct event_key *key)
268{
269 struct child_event_ops *child_ops;
270
271 child_ops = kvm->events_ops->child_ops;
272
273 if (!child_ops)
274 return false;
275
276 for (; child_ops->name; child_ops++) {
277 if (!strcmp(evsel->name, child_ops->name)) {
278 child_ops->get_key(evsel, sample, key);
279 return true;
280 }
281 }
282
283 return false;
284}
285
286static bool handle_child_event(struct perf_kvm_stat *kvm,
287 struct vcpu_event_record *vcpu_record,
288 struct event_key *key,
289 struct perf_sample *sample __maybe_unused)
290{
291 struct kvm_event *event = NULL;
292
293 if (key->key != INVALID_KEY)
294 event = find_create_kvm_event(kvm, key);
295
296 vcpu_record->last_event = event;
297
298 return true;
299}
300
301static bool skip_event(const char *event)
302{
303 const char * const *skip_events;
304
305 for (skip_events = kvm_skip_events; *skip_events; skip_events++)
306 if (!strcmp(event, *skip_events))
307 return true;
308
309 return false;
310}
311
479static bool handle_end_event(struct perf_kvm_stat *kvm, 312static bool handle_end_event(struct perf_kvm_stat *kvm,
480 struct vcpu_event_record *vcpu_record, 313 struct vcpu_event_record *vcpu_record,
481 struct event_key *key, 314 struct event_key *key,
@@ -524,10 +357,10 @@ static bool handle_end_event(struct perf_kvm_stat *kvm,
524 time_diff = sample->time - time_begin; 357 time_diff = sample->time - time_begin;
525 358
526 if (kvm->duration && time_diff > kvm->duration) { 359 if (kvm->duration && time_diff > kvm->duration) {
527 char decode[32]; 360 char decode[DECODE_STR_LEN];
528 361
529 kvm->events_ops->decode_key(kvm, &event->key, decode); 362 kvm->events_ops->decode_key(kvm, &event->key, decode);
530 if (strcmp(decode, "HLT")) { 363 if (!skip_event(decode)) {
531 pr_info("%" PRIu64 " VM %d, vcpu %d: %s event took %" PRIu64 "usec\n", 364 pr_info("%" PRIu64 " VM %d, vcpu %d: %s event took %" PRIu64 "usec\n",
532 sample->time, sample->pid, vcpu_record->vcpu_id, 365 sample->time, sample->pid, vcpu_record->vcpu_id,
533 decode, time_diff/1000); 366 decode, time_diff/1000);
@@ -552,7 +385,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
552 return NULL; 385 return NULL;
553 } 386 }
554 387
555 vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, "vcpu_id"); 388 vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, VCPU_ID);
556 thread->priv = vcpu_record; 389 thread->priv = vcpu_record;
557 } 390 }
558 391
@@ -565,7 +398,8 @@ static bool handle_kvm_event(struct perf_kvm_stat *kvm,
565 struct perf_sample *sample) 398 struct perf_sample *sample)
566{ 399{
567 struct vcpu_event_record *vcpu_record; 400 struct vcpu_event_record *vcpu_record;
568 struct event_key key = {.key = INVALID_KEY}; 401 struct event_key key = { .key = INVALID_KEY,
402 .exit_reasons = kvm->exit_reasons };
569 403
570 vcpu_record = per_vcpu_record(thread, evsel, sample); 404 vcpu_record = per_vcpu_record(thread, evsel, sample);
571 if (!vcpu_record) 405 if (!vcpu_record)
@@ -579,6 +413,9 @@ static bool handle_kvm_event(struct perf_kvm_stat *kvm,
579 if (kvm->events_ops->is_begin_event(evsel, sample, &key)) 413 if (kvm->events_ops->is_begin_event(evsel, sample, &key))
580 return handle_begin_event(kvm, vcpu_record, &key, sample->time); 414 return handle_begin_event(kvm, vcpu_record, &key, sample->time);
581 415
416 if (is_child_event(kvm, evsel, sample, &key))
417 return handle_child_event(kvm, vcpu_record, &key, sample);
418
582 if (kvm->events_ops->is_end_event(evsel, sample, &key)) 419 if (kvm->events_ops->is_end_event(evsel, sample, &key))
583 return handle_end_event(kvm, vcpu_record, &key, sample); 420 return handle_end_event(kvm, vcpu_record, &key, sample);
584 421
@@ -739,7 +576,7 @@ static void show_timeofday(void)
739 576
740static void print_result(struct perf_kvm_stat *kvm) 577static void print_result(struct perf_kvm_stat *kvm)
741{ 578{
742 char decode[20]; 579 char decode[DECODE_STR_LEN];
743 struct kvm_event *event; 580 struct kvm_event *event;
744 int vcpu = kvm->trace_vcpu; 581 int vcpu = kvm->trace_vcpu;
745 582
@@ -750,7 +587,7 @@ static void print_result(struct perf_kvm_stat *kvm)
750 587
751 pr_info("\n\n"); 588 pr_info("\n\n");
752 print_vcpu_info(kvm); 589 print_vcpu_info(kvm);
753 pr_info("%20s ", kvm->events_ops->name); 590 pr_info("%*s ", DECODE_STR_LEN, kvm->events_ops->name);
754 pr_info("%10s ", "Samples"); 591 pr_info("%10s ", "Samples");
755 pr_info("%9s ", "Samples%"); 592 pr_info("%9s ", "Samples%");
756 593
@@ -769,7 +606,7 @@ static void print_result(struct perf_kvm_stat *kvm)
769 min = get_event_min(event, vcpu); 606 min = get_event_min(event, vcpu);
770 607
771 kvm->events_ops->decode_key(kvm, &event->key, decode); 608 kvm->events_ops->decode_key(kvm, &event->key, decode);
772 pr_info("%20s ", decode); 609 pr_info("%*s ", DECODE_STR_LEN, decode);
773 pr_info("%10llu ", (unsigned long long)ecount); 610 pr_info("%10llu ", (unsigned long long)ecount);
774 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100); 611 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
775 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100); 612 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
@@ -835,20 +672,6 @@ static int process_sample_event(struct perf_tool *tool,
835 return 0; 672 return 0;
836} 673}
837 674
838static int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid)
839{
840 if (strstr(cpuid, "Intel")) {
841 kvm->exit_reasons = vmx_exit_reasons;
842 kvm->exit_reasons_isa = "VMX";
843 } else if (strstr(cpuid, "AMD")) {
844 kvm->exit_reasons = svm_exit_reasons;
845 kvm->exit_reasons_isa = "SVM";
846 } else
847 return -ENOTSUP;
848
849 return 0;
850}
851
852static int cpu_isa_config(struct perf_kvm_stat *kvm) 675static int cpu_isa_config(struct perf_kvm_stat *kvm)
853{ 676{
854 char buf[64], *cpuid; 677 char buf[64], *cpuid;
@@ -1307,13 +1130,6 @@ exit:
1307 return ret; 1130 return ret;
1308} 1131}
1309 1132
1310static const char * const kvm_events_tp[] = {
1311 "kvm:kvm_entry",
1312 "kvm:kvm_exit",
1313 "kvm:kvm_mmio",
1314 "kvm:kvm_pio",
1315};
1316
1317#define STRDUP_FAIL_EXIT(s) \ 1133#define STRDUP_FAIL_EXIT(s) \
1318 ({ char *_p; \ 1134 ({ char *_p; \
1319 _p = strdup(s); \ 1135 _p = strdup(s); \
@@ -1325,7 +1141,7 @@ static const char * const kvm_events_tp[] = {
1325static int 1141static int
1326kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv) 1142kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
1327{ 1143{
1328 unsigned int rec_argc, i, j; 1144 unsigned int rec_argc, i, j, events_tp_size;
1329 const char **rec_argv; 1145 const char **rec_argv;
1330 const char * const record_args[] = { 1146 const char * const record_args[] = {
1331 "record", 1147 "record",
@@ -1333,9 +1149,14 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
1333 "-m", "1024", 1149 "-m", "1024",
1334 "-c", "1", 1150 "-c", "1",
1335 }; 1151 };
1152 const char * const *events_tp;
1153 events_tp_size = 0;
1154
1155 for (events_tp = kvm_events_tp; *events_tp; events_tp++)
1156 events_tp_size++;
1336 1157
1337 rec_argc = ARRAY_SIZE(record_args) + argc + 2 + 1158 rec_argc = ARRAY_SIZE(record_args) + argc + 2 +
1338 2 * ARRAY_SIZE(kvm_events_tp); 1159 2 * events_tp_size;
1339 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1160 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1340 1161
1341 if (rec_argv == NULL) 1162 if (rec_argv == NULL)
@@ -1344,7 +1165,7 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
1344 for (i = 0; i < ARRAY_SIZE(record_args); i++) 1165 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1345 rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]); 1166 rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]);
1346 1167
1347 for (j = 0; j < ARRAY_SIZE(kvm_events_tp); j++) { 1168 for (j = 0; j < events_tp_size; j++) {
1348 rec_argv[i++] = "-e"; 1169 rec_argv[i++] = "-e";
1349 rec_argv[i++] = STRDUP_FAIL_EXIT(kvm_events_tp[j]); 1170 rec_argv[i++] = STRDUP_FAIL_EXIT(kvm_events_tp[j]);
1350 } 1171 }
@@ -1363,7 +1184,8 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1363{ 1184{
1364 const struct option kvm_events_report_options[] = { 1185 const struct option kvm_events_report_options[] = {
1365 OPT_STRING(0, "event", &kvm->report_event, "report event", 1186 OPT_STRING(0, "event", &kvm->report_event, "report event",
1366 "event for reporting: vmexit, mmio, ioport"), 1187 "event for reporting: vmexit, "
1188 "mmio (x86 only), ioport (x86 only)"),
1367 OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu, 1189 OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu,
1368 "vcpu id to report"), 1190 "vcpu id to report"),
1369 OPT_STRING('k', "key", &kvm->sort_key, "sort-key", 1191 OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
@@ -1398,16 +1220,16 @@ static struct perf_evlist *kvm_live_event_list(void)
1398{ 1220{
1399 struct perf_evlist *evlist; 1221 struct perf_evlist *evlist;
1400 char *tp, *name, *sys; 1222 char *tp, *name, *sys;
1401 unsigned int j;
1402 int err = -1; 1223 int err = -1;
1224 const char * const *events_tp;
1403 1225
1404 evlist = perf_evlist__new(); 1226 evlist = perf_evlist__new();
1405 if (evlist == NULL) 1227 if (evlist == NULL)
1406 return NULL; 1228 return NULL;
1407 1229
1408 for (j = 0; j < ARRAY_SIZE(kvm_events_tp); j++) { 1230 for (events_tp = kvm_events_tp; *events_tp; events_tp++) {
1409 1231
1410 tp = strdup(kvm_events_tp[j]); 1232 tp = strdup(*events_tp);
1411 if (tp == NULL) 1233 if (tp == NULL)
1412 goto out; 1234 goto out;
1413 1235
@@ -1416,7 +1238,7 @@ static struct perf_evlist *kvm_live_event_list(void)
1416 name = strchr(tp, ':'); 1238 name = strchr(tp, ':');
1417 if (name == NULL) { 1239 if (name == NULL) {
1418 pr_err("Error parsing %s tracepoint: subsystem delimiter not found\n", 1240 pr_err("Error parsing %s tracepoint: subsystem delimiter not found\n",
1419 kvm_events_tp[j]); 1241 *events_tp);
1420 free(tp); 1242 free(tp);
1421 goto out; 1243 goto out;
1422 } 1244 }
@@ -1424,7 +1246,7 @@ static struct perf_evlist *kvm_live_event_list(void)
1424 name++; 1246 name++;
1425 1247
1426 if (perf_evlist__add_newtp(evlist, sys, name, NULL)) { 1248 if (perf_evlist__add_newtp(evlist, sys, name, NULL)) {
1427 pr_err("Failed to add %s tracepoint to the list\n", kvm_events_tp[j]); 1249 pr_err("Failed to add %s tracepoint to the list\n", *events_tp);
1428 free(tp); 1250 free(tp);
1429 goto out; 1251 goto out;
1430 } 1252 }
@@ -1469,7 +1291,9 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1469 "key for sorting: sample(sort by samples number)" 1291 "key for sorting: sample(sort by samples number)"
1470 " time (sort by avg time)"), 1292 " time (sort by avg time)"),
1471 OPT_U64(0, "duration", &kvm->duration, 1293 OPT_U64(0, "duration", &kvm->duration,
1472 "show events other than HALT that take longer than duration usecs"), 1294 "show events other than"
1295 " HLT (x86 only) or Wait state (s390 only)"
1296 " that take longer than duration usecs"),
1473 OPT_END() 1297 OPT_END()
1474 }; 1298 };
1475 const char * const live_usage[] = { 1299 const char * const live_usage[] = {
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index c38d06c04775..b7f555add0c8 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -935,8 +935,8 @@ static int latency_switch_event(struct perf_sched *sched,
935 return -1; 935 return -1;
936 } 936 }
937 937
938 sched_out = machine__findnew_thread(machine, 0, prev_pid); 938 sched_out = machine__findnew_thread(machine, -1, prev_pid);
939 sched_in = machine__findnew_thread(machine, 0, next_pid); 939 sched_in = machine__findnew_thread(machine, -1, next_pid);
940 940
941 out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid); 941 out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid);
942 if (!out_events) { 942 if (!out_events) {
@@ -979,7 +979,7 @@ static int latency_runtime_event(struct perf_sched *sched,
979{ 979{
980 const u32 pid = perf_evsel__intval(evsel, sample, "pid"); 980 const u32 pid = perf_evsel__intval(evsel, sample, "pid");
981 const u64 runtime = perf_evsel__intval(evsel, sample, "runtime"); 981 const u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
982 struct thread *thread = machine__findnew_thread(machine, 0, pid); 982 struct thread *thread = machine__findnew_thread(machine, -1, pid);
983 struct work_atoms *atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid); 983 struct work_atoms *atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid);
984 u64 timestamp = sample->time; 984 u64 timestamp = sample->time;
985 int cpu = sample->cpu; 985 int cpu = sample->cpu;
@@ -1012,7 +1012,7 @@ static int latency_wakeup_event(struct perf_sched *sched,
1012 struct thread *wakee; 1012 struct thread *wakee;
1013 u64 timestamp = sample->time; 1013 u64 timestamp = sample->time;
1014 1014
1015 wakee = machine__findnew_thread(machine, 0, pid); 1015 wakee = machine__findnew_thread(machine, -1, pid);
1016 atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid); 1016 atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid);
1017 if (!atoms) { 1017 if (!atoms) {
1018 if (thread_atoms_insert(sched, wakee)) 1018 if (thread_atoms_insert(sched, wakee))
@@ -1072,7 +1072,7 @@ static int latency_migrate_task_event(struct perf_sched *sched,
1072 if (sched->profile_cpu == -1) 1072 if (sched->profile_cpu == -1)
1073 return 0; 1073 return 0;
1074 1074
1075 migrant = machine__findnew_thread(machine, 0, pid); 1075 migrant = machine__findnew_thread(machine, -1, pid);
1076 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); 1076 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid);
1077 if (!atoms) { 1077 if (!atoms) {
1078 if (thread_atoms_insert(sched, migrant)) 1078 if (thread_atoms_insert(sched, migrant))
@@ -1290,7 +1290,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1290 return -1; 1290 return -1;
1291 } 1291 }
1292 1292
1293 sched_in = machine__findnew_thread(machine, 0, next_pid); 1293 sched_in = machine__findnew_thread(machine, -1, next_pid);
1294 1294
1295 sched->curr_thread[this_cpu] = sched_in; 1295 sched->curr_thread[this_cpu] = sched_in;
1296 1296
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 04c9c53becad..2f1a5220c090 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -37,6 +37,7 @@
37#include "util/svghelper.h" 37#include "util/svghelper.h"
38#include "util/tool.h" 38#include "util/tool.h"
39#include "util/data.h" 39#include "util/data.h"
40#include "util/debug.h"
40 41
41#define SUPPORT_OLD_POWER_EVENTS 1 42#define SUPPORT_OLD_POWER_EVENTS 1
42#define PWR_EVENT_EXIT -1 43#define PWR_EVENT_EXIT -1
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index b7f42d577c4e..1f67aa02d240 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -164,6 +164,7 @@ CORE_FEATURE_TESTS = \
164 backtrace \ 164 backtrace \
165 dwarf \ 165 dwarf \
166 fortify-source \ 166 fortify-source \
167 sync-compare-and-swap \
167 glibc \ 168 glibc \
168 gtk2 \ 169 gtk2 \
169 gtk2-infobar \ 170 gtk2-infobar \
@@ -199,6 +200,7 @@ LIB_FEATURE_TESTS = \
199VF_FEATURE_TESTS = \ 200VF_FEATURE_TESTS = \
200 backtrace \ 201 backtrace \
201 fortify-source \ 202 fortify-source \
203 sync-compare-and-swap \
202 gtk2-infobar \ 204 gtk2-infobar \
203 libelf-getphdrnum \ 205 libelf-getphdrnum \
204 libelf-mmap \ 206 libelf-mmap \
@@ -272,6 +274,10 @@ CFLAGS += -I$(LIB_INCLUDE)
272 274
273CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE 275CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
274 276
277ifeq ($(feature-sync-compare-and-swap), 1)
278 CFLAGS += -DHAVE_SYNC_COMPARE_AND_SWAP_SUPPORT
279endif
280
275ifndef NO_BIONIC 281ifndef NO_BIONIC
276 $(call feature_check,bionic) 282 $(call feature_check,bionic)
277 ifeq ($(feature-bionic), 1) 283 ifeq ($(feature-bionic), 1)
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 64c84e5f0514..6088f8d8a434 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -5,6 +5,7 @@ FILES= \
5 test-bionic.bin \ 5 test-bionic.bin \
6 test-dwarf.bin \ 6 test-dwarf.bin \
7 test-fortify-source.bin \ 7 test-fortify-source.bin \
8 test-sync-compare-and-swap.bin \
8 test-glibc.bin \ 9 test-glibc.bin \
9 test-gtk2.bin \ 10 test-gtk2.bin \
10 test-gtk2-infobar.bin \ 11 test-gtk2-infobar.bin \
@@ -141,6 +142,9 @@ test-timerfd.bin:
141test-libdw-dwarf-unwind.bin: 142test-libdw-dwarf-unwind.bin:
142 $(BUILD) 143 $(BUILD)
143 144
145test-sync-compare-and-swap.bin:
146 $(BUILD) -Werror
147
144-include *.d 148-include *.d
145 149
146############################### 150###############################
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
index fe5c1e5c952f..a7d022e161c0 100644
--- a/tools/perf/config/feature-checks/test-all.c
+++ b/tools/perf/config/feature-checks/test-all.c
@@ -89,6 +89,10 @@
89# include "test-libdw-dwarf-unwind.c" 89# include "test-libdw-dwarf-unwind.c"
90#undef main 90#undef main
91 91
92#define main main_test_sync_compare_and_swap
93# include "test-sync-compare-and-swap.c"
94#undef main
95
92int main(int argc, char *argv[]) 96int main(int argc, char *argv[])
93{ 97{
94 main_test_libpython(); 98 main_test_libpython();
@@ -111,6 +115,7 @@ int main(int argc, char *argv[])
111 main_test_timerfd(); 115 main_test_timerfd();
112 main_test_stackprotector_all(); 116 main_test_stackprotector_all();
113 main_test_libdw_dwarf_unwind(); 117 main_test_libdw_dwarf_unwind();
118 main_test_sync_compare_and_swap(argc, argv);
114 119
115 return 0; 120 return 0;
116} 121}
diff --git a/tools/perf/config/feature-checks/test-sync-compare-and-swap.c b/tools/perf/config/feature-checks/test-sync-compare-and-swap.c
new file mode 100644
index 000000000000..c34d4ca4af56
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-sync-compare-and-swap.c
@@ -0,0 +1,14 @@
1#include <stdint.h>
2
3volatile uint64_t x;
4
5int main(int argc, char *argv[])
6{
7 uint64_t old, new = argc;
8
9 argv = argv;
10 do {
11 old = __sync_val_compare_and_swap(&x, 0, 0);
12 } while (!__sync_bool_compare_and_swap(&x, old, new));
13 return old == new;
14}
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 95c58fc15284..eed3fb2a3af0 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -13,11 +13,12 @@
13#include "util/quote.h" 13#include "util/quote.h"
14#include "util/run-command.h" 14#include "util/run-command.h"
15#include "util/parse-events.h" 15#include "util/parse-events.h"
16#include "util/debug.h"
16#include <api/fs/debugfs.h> 17#include <api/fs/debugfs.h>
17#include <pthread.h> 18#include <pthread.h>
18 19
19const char perf_usage_string[] = 20const char perf_usage_string[] =
20 "perf [--version] [--help] COMMAND [ARGS]"; 21 "perf [--version] [--debug variable[=VALUE]] [--help] COMMAND [ARGS]";
21 22
22const char perf_more_info_string[] = 23const char perf_more_info_string[] =
23 "See 'perf help COMMAND' for more information on a specific command."; 24 "See 'perf help COMMAND' for more information on a specific command.";
@@ -212,6 +213,16 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
212 printf("%s ", p->cmd); 213 printf("%s ", p->cmd);
213 } 214 }
214 exit(0); 215 exit(0);
216 } else if (!strcmp(cmd, "--debug")) {
217 if (*argc < 2) {
218 fprintf(stderr, "No variable specified for --debug.\n");
219 usage(perf_usage_string);
220 }
221 if (perf_debug_option((*argv)[1]))
222 usage(perf_usage_string);
223
224 (*argv)++;
225 (*argc)--;
215 } else { 226 } else {
216 fprintf(stderr, "Unknown option: %s\n", cmd); 227 fprintf(stderr, "Unknown option: %s\n", cmd);
217 usage(perf_usage_string); 228 usage(perf_usage_string);
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
index de7211e4fa47..38dfb720fb6f 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
@@ -107,12 +107,13 @@ def taskState(state):
107 107
108class EventHeaders: 108class EventHeaders:
109 def __init__(self, common_cpu, common_secs, common_nsecs, 109 def __init__(self, common_cpu, common_secs, common_nsecs,
110 common_pid, common_comm): 110 common_pid, common_comm, common_callchain):
111 self.cpu = common_cpu 111 self.cpu = common_cpu
112 self.secs = common_secs 112 self.secs = common_secs
113 self.nsecs = common_nsecs 113 self.nsecs = common_nsecs
114 self.pid = common_pid 114 self.pid = common_pid
115 self.comm = common_comm 115 self.comm = common_comm
116 self.callchain = common_callchain
116 117
117 def ts(self): 118 def ts(self):
118 return (self.secs * (10 ** 9)) + self.nsecs 119 return (self.secs * (10 ** 9)) + self.nsecs
diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
index 4647a7694cf6..334599c6032c 100644
--- a/tools/perf/scripts/python/check-perf-trace.py
+++ b/tools/perf/scripts/python/check-perf-trace.py
@@ -27,7 +27,7 @@ def trace_end():
27 27
28def irq__softirq_entry(event_name, context, common_cpu, 28def irq__softirq_entry(event_name, context, common_cpu,
29 common_secs, common_nsecs, common_pid, common_comm, 29 common_secs, common_nsecs, common_pid, common_comm,
30 vec): 30 common_callchain, vec):
31 print_header(event_name, common_cpu, common_secs, common_nsecs, 31 print_header(event_name, common_cpu, common_secs, common_nsecs,
32 common_pid, common_comm) 32 common_pid, common_comm)
33 33
@@ -38,7 +38,7 @@ def irq__softirq_entry(event_name, context, common_cpu,
38 38
39def kmem__kmalloc(event_name, context, common_cpu, 39def kmem__kmalloc(event_name, context, common_cpu,
40 common_secs, common_nsecs, common_pid, common_comm, 40 common_secs, common_nsecs, common_pid, common_comm,
41 call_site, ptr, bytes_req, bytes_alloc, 41 common_callchain, call_site, ptr, bytes_req, bytes_alloc,
42 gfp_flags): 42 gfp_flags):
43 print_header(event_name, common_cpu, common_secs, common_nsecs, 43 print_header(event_name, common_cpu, common_secs, common_nsecs,
44 common_pid, common_comm) 44 common_pid, common_comm)
diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
index 266a8364bce5..cafeff3d74db 100644
--- a/tools/perf/scripts/python/failed-syscalls-by-pid.py
+++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py
@@ -39,7 +39,7 @@ def trace_end():
39 39
40def raw_syscalls__sys_exit(event_name, context, common_cpu, 40def raw_syscalls__sys_exit(event_name, context, common_cpu,
41 common_secs, common_nsecs, common_pid, common_comm, 41 common_secs, common_nsecs, common_pid, common_comm,
42 id, ret): 42 common_callchain, id, ret):
43 if (for_comm and common_comm != for_comm) or \ 43 if (for_comm and common_comm != for_comm) or \
44 (for_pid and common_pid != for_pid ): 44 (for_pid and common_pid != for_pid ):
45 return 45 return
diff --git a/tools/perf/scripts/python/futex-contention.py b/tools/perf/scripts/python/futex-contention.py
index 11e70a388d41..0f5cf437b602 100644
--- a/tools/perf/scripts/python/futex-contention.py
+++ b/tools/perf/scripts/python/futex-contention.py
@@ -21,7 +21,7 @@ thread_blocktime = {}
21lock_waits = {} # long-lived stats on (tid,lock) blockage elapsed time 21lock_waits = {} # long-lived stats on (tid,lock) blockage elapsed time
22process_names = {} # long-lived pid-to-execname mapping 22process_names = {} # long-lived pid-to-execname mapping
23 23
24def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, 24def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
25 nr, uaddr, op, val, utime, uaddr2, val3): 25 nr, uaddr, op, val, utime, uaddr2, val3):
26 cmd = op & FUTEX_CMD_MASK 26 cmd = op & FUTEX_CMD_MASK
27 if cmd != FUTEX_WAIT: 27 if cmd != FUTEX_WAIT:
@@ -31,7 +31,7 @@ def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
31 thread_thislock[tid] = uaddr 31 thread_thislock[tid] = uaddr
32 thread_blocktime[tid] = nsecs(s, ns) 32 thread_blocktime[tid] = nsecs(s, ns)
33 33
34def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, 34def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
35 nr, ret): 35 nr, ret):
36 if thread_blocktime.has_key(tid): 36 if thread_blocktime.has_key(tid):
37 elapsed = nsecs(s, ns) - thread_blocktime[tid] 37 elapsed = nsecs(s, ns) - thread_blocktime[tid]
diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py
index b5740599aabd..0b6ce8c253e8 100755
--- a/tools/perf/scripts/python/net_dropmonitor.py
+++ b/tools/perf/scripts/python/net_dropmonitor.py
@@ -66,7 +66,7 @@ def trace_end():
66 print_drop_table() 66 print_drop_table()
67 67
68# called from perf, when it finds a correspoinding event 68# called from perf, when it finds a correspoinding event
69def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, 69def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
70 skbaddr, location, protocol): 70 skbaddr, location, protocol):
71 slocation = str(location) 71 slocation = str(location)
72 try: 72 try:
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
index 9aa0a32972e8..4d21ef2d601d 100644
--- a/tools/perf/scripts/python/netdev-times.py
+++ b/tools/perf/scripts/python/netdev-times.py
@@ -224,75 +224,75 @@ def trace_end():
224 (len(rx_skb_list), of_count_rx_skb_list) 224 (len(rx_skb_list), of_count_rx_skb_list)
225 225
226# called from perf, when it finds a correspoinding event 226# called from perf, when it finds a correspoinding event
227def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, vec): 227def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
228 if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX": 228 if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
229 return 229 return
230 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec) 230 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
231 all_event_list.append(event_info) 231 all_event_list.append(event_info)
232 232
233def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, vec): 233def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
234 if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX": 234 if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
235 return 235 return
236 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec) 236 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
237 all_event_list.append(event_info) 237 all_event_list.append(event_info)
238 238
239def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, vec): 239def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
240 if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX": 240 if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
241 return 241 return
242 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec) 242 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
243 all_event_list.append(event_info) 243 all_event_list.append(event_info)
244 244
245def irq__irq_handler_entry(name, context, cpu, sec, nsec, pid, comm, 245def irq__irq_handler_entry(name, context, cpu, sec, nsec, pid, comm,
246 irq, irq_name): 246 callchain, irq, irq_name):
247 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 247 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
248 irq, irq_name) 248 irq, irq_name)
249 all_event_list.append(event_info) 249 all_event_list.append(event_info)
250 250
251def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, irq, ret): 251def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, irq, ret):
252 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret) 252 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret)
253 all_event_list.append(event_info) 253 all_event_list.append(event_info)
254 254
255def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, napi, dev_name): 255def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, dev_name):
256 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 256 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
257 napi, dev_name) 257 napi, dev_name)
258 all_event_list.append(event_info) 258 all_event_list.append(event_info)
259 259
260def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr, 260def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
261 skblen, dev_name): 261 skblen, dev_name):
262 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 262 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
263 skbaddr, skblen, dev_name) 263 skbaddr, skblen, dev_name)
264 all_event_list.append(event_info) 264 all_event_list.append(event_info)
265 265
266def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, skbaddr, 266def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
267 skblen, dev_name): 267 skblen, dev_name):
268 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 268 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
269 skbaddr, skblen, dev_name) 269 skbaddr, skblen, dev_name)
270 all_event_list.append(event_info) 270 all_event_list.append(event_info)
271 271
272def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm, 272def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm, callchain,
273 skbaddr, skblen, dev_name): 273 skbaddr, skblen, dev_name):
274 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 274 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
275 skbaddr, skblen, dev_name) 275 skbaddr, skblen, dev_name)
276 all_event_list.append(event_info) 276 all_event_list.append(event_info)
277 277
278def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm, 278def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm, callchain,
279 skbaddr, skblen, rc, dev_name): 279 skbaddr, skblen, rc, dev_name):
280 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 280 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
281 skbaddr, skblen, rc ,dev_name) 281 skbaddr, skblen, rc ,dev_name)
282 all_event_list.append(event_info) 282 all_event_list.append(event_info)
283 283
284def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, 284def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
285 skbaddr, protocol, location): 285 skbaddr, protocol, location):
286 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 286 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
287 skbaddr, protocol, location) 287 skbaddr, protocol, location)
288 all_event_list.append(event_info) 288 all_event_list.append(event_info)
289 289
290def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr): 290def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr):
291 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 291 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
292 skbaddr) 292 skbaddr)
293 all_event_list.append(event_info) 293 all_event_list.append(event_info)
294 294
295def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm, 295def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm, callchain,
296 skbaddr, skblen): 296 skbaddr, skblen):
297 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 297 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
298 skbaddr, skblen) 298 skbaddr, skblen)
diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py
index 74d55ec08aed..de66cb3b72c9 100644
--- a/tools/perf/scripts/python/sched-migration.py
+++ b/tools/perf/scripts/python/sched-migration.py
@@ -369,93 +369,92 @@ def trace_end():
369 369
370def sched__sched_stat_runtime(event_name, context, common_cpu, 370def sched__sched_stat_runtime(event_name, context, common_cpu,
371 common_secs, common_nsecs, common_pid, common_comm, 371 common_secs, common_nsecs, common_pid, common_comm,
372 comm, pid, runtime, vruntime): 372 common_callchain, comm, pid, runtime, vruntime):
373 pass 373 pass
374 374
375def sched__sched_stat_iowait(event_name, context, common_cpu, 375def sched__sched_stat_iowait(event_name, context, common_cpu,
376 common_secs, common_nsecs, common_pid, common_comm, 376 common_secs, common_nsecs, common_pid, common_comm,
377 comm, pid, delay): 377 common_callchain, comm, pid, delay):
378 pass 378 pass
379 379
380def sched__sched_stat_sleep(event_name, context, common_cpu, 380def sched__sched_stat_sleep(event_name, context, common_cpu,
381 common_secs, common_nsecs, common_pid, common_comm, 381 common_secs, common_nsecs, common_pid, common_comm,
382 comm, pid, delay): 382 common_callchain, comm, pid, delay):
383 pass 383 pass
384 384
385def sched__sched_stat_wait(event_name, context, common_cpu, 385def sched__sched_stat_wait(event_name, context, common_cpu,
386 common_secs, common_nsecs, common_pid, common_comm, 386 common_secs, common_nsecs, common_pid, common_comm,
387 comm, pid, delay): 387 common_callchain, comm, pid, delay):
388 pass 388 pass
389 389
390def sched__sched_process_fork(event_name, context, common_cpu, 390def sched__sched_process_fork(event_name, context, common_cpu,
391 common_secs, common_nsecs, common_pid, common_comm, 391 common_secs, common_nsecs, common_pid, common_comm,
392 parent_comm, parent_pid, child_comm, child_pid): 392 common_callchain, parent_comm, parent_pid, child_comm, child_pid):
393 pass 393 pass
394 394
395def sched__sched_process_wait(event_name, context, common_cpu, 395def sched__sched_process_wait(event_name, context, common_cpu,
396 common_secs, common_nsecs, common_pid, common_comm, 396 common_secs, common_nsecs, common_pid, common_comm,
397 comm, pid, prio): 397 common_callchain, comm, pid, prio):
398 pass 398 pass
399 399
400def sched__sched_process_exit(event_name, context, common_cpu, 400def sched__sched_process_exit(event_name, context, common_cpu,
401 common_secs, common_nsecs, common_pid, common_comm, 401 common_secs, common_nsecs, common_pid, common_comm,
402 comm, pid, prio): 402 common_callchain, comm, pid, prio):
403 pass 403 pass
404 404
405def sched__sched_process_free(event_name, context, common_cpu, 405def sched__sched_process_free(event_name, context, common_cpu,
406 common_secs, common_nsecs, common_pid, common_comm, 406 common_secs, common_nsecs, common_pid, common_comm,
407 comm, pid, prio): 407 common_callchain, comm, pid, prio):
408 pass 408 pass
409 409
410def sched__sched_migrate_task(event_name, context, common_cpu, 410def sched__sched_migrate_task(event_name, context, common_cpu,
411 common_secs, common_nsecs, common_pid, common_comm, 411 common_secs, common_nsecs, common_pid, common_comm,
412 comm, pid, prio, orig_cpu, 412 common_callchain, comm, pid, prio, orig_cpu,
413 dest_cpu): 413 dest_cpu):
414 headers = EventHeaders(common_cpu, common_secs, common_nsecs, 414 headers = EventHeaders(common_cpu, common_secs, common_nsecs,
415 common_pid, common_comm) 415 common_pid, common_comm, common_callchain)
416 parser.migrate(headers, pid, prio, orig_cpu, dest_cpu) 416 parser.migrate(headers, pid, prio, orig_cpu, dest_cpu)
417 417
418def sched__sched_switch(event_name, context, common_cpu, 418def sched__sched_switch(event_name, context, common_cpu,
419 common_secs, common_nsecs, common_pid, common_comm, 419 common_secs, common_nsecs, common_pid, common_comm, common_callchain,
420 prev_comm, prev_pid, prev_prio, prev_state, 420 prev_comm, prev_pid, prev_prio, prev_state,
421 next_comm, next_pid, next_prio): 421 next_comm, next_pid, next_prio):
422 422
423 headers = EventHeaders(common_cpu, common_secs, common_nsecs, 423 headers = EventHeaders(common_cpu, common_secs, common_nsecs,
424 common_pid, common_comm) 424 common_pid, common_comm, common_callchain)
425 parser.sched_switch(headers, prev_comm, prev_pid, prev_prio, prev_state, 425 parser.sched_switch(headers, prev_comm, prev_pid, prev_prio, prev_state,
426 next_comm, next_pid, next_prio) 426 next_comm, next_pid, next_prio)
427 427
428def sched__sched_wakeup_new(event_name, context, common_cpu, 428def sched__sched_wakeup_new(event_name, context, common_cpu,
429 common_secs, common_nsecs, common_pid, common_comm, 429 common_secs, common_nsecs, common_pid, common_comm,
430 comm, pid, prio, success, 430 common_callchain, comm, pid, prio, success,
431 target_cpu): 431 target_cpu):
432 headers = EventHeaders(common_cpu, common_secs, common_nsecs, 432 headers = EventHeaders(common_cpu, common_secs, common_nsecs,
433 common_pid, common_comm) 433 common_pid, common_comm, common_callchain)
434 parser.wake_up(headers, comm, pid, success, target_cpu, 1) 434 parser.wake_up(headers, comm, pid, success, target_cpu, 1)
435 435
436def sched__sched_wakeup(event_name, context, common_cpu, 436def sched__sched_wakeup(event_name, context, common_cpu,
437 common_secs, common_nsecs, common_pid, common_comm, 437 common_secs, common_nsecs, common_pid, common_comm,
438 comm, pid, prio, success, 438 common_callchain, comm, pid, prio, success,
439 target_cpu): 439 target_cpu):
440 headers = EventHeaders(common_cpu, common_secs, common_nsecs, 440 headers = EventHeaders(common_cpu, common_secs, common_nsecs,
441 common_pid, common_comm) 441 common_pid, common_comm, common_callchain)
442 parser.wake_up(headers, comm, pid, success, target_cpu, 0) 442 parser.wake_up(headers, comm, pid, success, target_cpu, 0)
443 443
444def sched__sched_wait_task(event_name, context, common_cpu, 444def sched__sched_wait_task(event_name, context, common_cpu,
445 common_secs, common_nsecs, common_pid, common_comm, 445 common_secs, common_nsecs, common_pid, common_comm,
446 comm, pid, prio): 446 common_callchain, comm, pid, prio):
447 pass 447 pass
448 448
449def sched__sched_kthread_stop_ret(event_name, context, common_cpu, 449def sched__sched_kthread_stop_ret(event_name, context, common_cpu,
450 common_secs, common_nsecs, common_pid, common_comm, 450 common_secs, common_nsecs, common_pid, common_comm,
451 ret): 451 common_callchain, ret):
452 pass 452 pass
453 453
454def sched__sched_kthread_stop(event_name, context, common_cpu, 454def sched__sched_kthread_stop(event_name, context, common_cpu,
455 common_secs, common_nsecs, common_pid, common_comm, 455 common_secs, common_nsecs, common_pid, common_comm,
456 comm, pid): 456 common_callchain, comm, pid):
457 pass 457 pass
458 458
459def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs, 459def trace_unhandled(event_name, context, event_fields_dict):
460 common_pid, common_comm):
461 pass 460 pass
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
index c9f3058b7dd4..61621b93affb 100644
--- a/tools/perf/scripts/python/sctop.py
+++ b/tools/perf/scripts/python/sctop.py
@@ -44,7 +44,7 @@ def trace_begin():
44 44
45def raw_syscalls__sys_enter(event_name, context, common_cpu, 45def raw_syscalls__sys_enter(event_name, context, common_cpu,
46 common_secs, common_nsecs, common_pid, common_comm, 46 common_secs, common_nsecs, common_pid, common_comm,
47 id, args): 47 common_callchain, id, args):
48 if for_comm is not None: 48 if for_comm is not None:
49 if common_comm != for_comm: 49 if common_comm != for_comm:
50 return 50 return
diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
index cf2054c529c9..daf314cc5dd3 100644
--- a/tools/perf/scripts/python/syscall-counts-by-pid.py
+++ b/tools/perf/scripts/python/syscall-counts-by-pid.py
@@ -38,7 +38,7 @@ def trace_end():
38 38
39def raw_syscalls__sys_enter(event_name, context, common_cpu, 39def raw_syscalls__sys_enter(event_name, context, common_cpu,
40 common_secs, common_nsecs, common_pid, common_comm, 40 common_secs, common_nsecs, common_pid, common_comm,
41 id, args): 41 common_callchain, id, args):
42 42
43 if (for_comm and common_comm != for_comm) or \ 43 if (for_comm and common_comm != for_comm) or \
44 (for_pid and common_pid != for_pid ): 44 (for_pid and common_pid != for_pid ):
diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py
index 92b29381bd39..e66a7730aeb5 100644
--- a/tools/perf/scripts/python/syscall-counts.py
+++ b/tools/perf/scripts/python/syscall-counts.py
@@ -35,7 +35,7 @@ def trace_end():
35 35
36def raw_syscalls__sys_enter(event_name, context, common_cpu, 36def raw_syscalls__sys_enter(event_name, context, common_cpu,
37 common_secs, common_nsecs, common_pid, common_comm, 37 common_secs, common_nsecs, common_pid, common_comm,
38 id, args): 38 common_callchain, id, args):
39 if for_comm is not None: 39 if for_comm is not None:
40 if common_comm != for_comm: 40 if common_comm != for_comm:
41 return 41 return
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index 630808cd7cc2..caaf37f079b1 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -10,6 +10,7 @@
10#include "machine.h" 10#include "machine.h"
11#include "symbol.h" 11#include "symbol.h"
12#include "tests.h" 12#include "tests.h"
13#include "debug.h"
13 14
14static char *test_file(int size) 15static char *test_file(int size)
15{ 16{
diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c
index 465cdbc345cf..b8d8341b383e 100644
--- a/tools/perf/tests/evsel-roundtrip-name.c
+++ b/tools/perf/tests/evsel-roundtrip-name.c
@@ -2,6 +2,7 @@
2#include "evsel.h" 2#include "evsel.h"
3#include "parse-events.h" 3#include "parse-events.h"
4#include "tests.h" 4#include "tests.h"
5#include "debug.h"
5 6
6static int perf_evsel__roundtrip_cache_name_test(void) 7static int perf_evsel__roundtrip_cache_name_test(void)
7{ 8{
diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c
index 35d7fdb2328d..52162425c969 100644
--- a/tools/perf/tests/evsel-tp-sched.c
+++ b/tools/perf/tests/evsel-tp-sched.c
@@ -1,6 +1,7 @@
1#include <traceevent/event-parse.h> 1#include <traceevent/event-parse.h>
2#include "evsel.h" 2#include "evsel.h"
3#include "tests.h" 3#include "tests.h"
4#include "debug.h"
4 5
5static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, 6static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
6 int size, bool should_be_signed) 7 int size, bool should_be_signed)
diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c
index c505ef2af245..0785b64ffd6c 100644
--- a/tools/perf/tests/open-syscall-tp-fields.c
+++ b/tools/perf/tests/open-syscall-tp-fields.c
@@ -3,6 +3,7 @@
3#include "evsel.h" 3#include "evsel.h"
4#include "thread_map.h" 4#include "thread_map.h"
5#include "tests.h" 5#include "tests.h"
6#include "debug.h"
6 7
7int test__syscall_open_tp_fields(void) 8int test__syscall_open_tp_fields(void)
8{ 9{
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index deba66955f8c..5941927a4b7f 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -5,6 +5,7 @@
5#include <api/fs/fs.h> 5#include <api/fs/fs.h>
6#include <api/fs/debugfs.h> 6#include <api/fs/debugfs.h>
7#include "tests.h" 7#include "tests.h"
8#include "debug.h"
8#include <linux/hw_breakpoint.h> 9#include <linux/hw_breakpoint.h>
9 10
10#define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \ 11#define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \
diff --git a/tools/perf/tests/parse-no-sample-id-all.c b/tools/perf/tests/parse-no-sample-id-all.c
index 905019f9b740..2c63ea658541 100644
--- a/tools/perf/tests/parse-no-sample-id-all.c
+++ b/tools/perf/tests/parse-no-sample-id-all.c
@@ -7,6 +7,7 @@
7#include "evlist.h" 7#include "evlist.h"
8#include "header.h" 8#include "header.h"
9#include "util.h" 9#include "util.h"
10#include "debug.h"
10 11
11static int process_event(struct perf_evlist **pevlist, union perf_event *event) 12static int process_event(struct perf_evlist **pevlist, union perf_event *event)
12{ 13{
diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c
index 3b7cd4d32dcb..0372f6edca20 100644
--- a/tools/perf/tests/perf-time-to-tsc.c
+++ b/tools/perf/tests/perf-time-to-tsc.c
@@ -8,10 +8,9 @@
8#include "evsel.h" 8#include "evsel.h"
9#include "thread_map.h" 9#include "thread_map.h"
10#include "cpumap.h" 10#include "cpumap.h"
11#include "tsc.h"
11#include "tests.h" 12#include "tests.h"
12 13
13#include "../arch/x86/util/tsc.h"
14
15#define CHECK__(x) { \ 14#define CHECK__(x) { \
16 while ((x) < 0) { \ 15 while ((x) < 0) { \
17 pr_debug(#x " failed!\n"); \ 16 pr_debug(#x " failed!\n"); \
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index 7ae8d17db3d9..ca292f9a4ae2 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -4,6 +4,7 @@
4#include "util.h" 4#include "util.h"
5#include "event.h" 5#include "event.h"
6#include "evsel.h" 6#include "evsel.h"
7#include "debug.h"
7 8
8#include "tests.h" 9#include "tests.h"
9 10
diff --git a/tools/perf/tests/thread-mg-share.c b/tools/perf/tests/thread-mg-share.c
index 2b2e0dbe114f..b028499dd3cf 100644
--- a/tools/perf/tests/thread-mg-share.c
+++ b/tools/perf/tests/thread-mg-share.c
@@ -2,6 +2,7 @@
2#include "machine.h" 2#include "machine.h"
3#include "thread.h" 3#include "thread.h"
4#include "map.h" 4#include "map.h"
5#include "debug.h"
5 6
6int test__thread_mg_share(void) 7int test__thread_mg_share(void)
7{ 8{
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 90122abd3721..40af0acb4fe9 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -479,7 +479,7 @@ print_entries:
479 479
480 if (h->ms.map == NULL && verbose > 1) { 480 if (h->ms.map == NULL && verbose > 1) {
481 __map_groups__fprintf_maps(h->thread->mg, 481 __map_groups__fprintf_maps(h->thread->mg,
482 MAP__FUNCTION, verbose, fp); 482 MAP__FUNCTION, fp);
483 fprintf(fp, "%.10s end\n", graph_dotted_line); 483 fprintf(fp, "%.10s end\n", graph_dotted_line);
484 } 484 }
485 } 485 }
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 48b6d3f50012..437ee09727e6 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -626,7 +626,7 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent
626 626
627int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample) 627int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
628{ 628{
629 if (!symbol_conf.use_callchain) 629 if (!symbol_conf.use_callchain || sample->callchain == NULL)
630 return 0; 630 return 0;
631 return callchain_append(he->callchain, &callchain_cursor, sample->period); 631 return callchain_append(he->callchain, &callchain_cursor, sample->period);
632} 632}
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index ee370a7f2444..29d720cf5844 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -7,6 +7,7 @@
7 7
8#include "data.h" 8#include "data.h"
9#include "util.h" 9#include "util.h"
10#include "debug.h"
10 11
11static bool check_pipe(struct perf_data_file *file) 12static bool check_pipe(struct perf_data_file *file)
12{ 13{
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 299b55586502..71d419362634 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -16,11 +16,11 @@
16int verbose; 16int verbose;
17bool dump_trace = false, quiet = false; 17bool dump_trace = false, quiet = false;
18 18
19static int _eprintf(int level, const char *fmt, va_list args) 19static int _eprintf(int level, int var, const char *fmt, va_list args)
20{ 20{
21 int ret = 0; 21 int ret = 0;
22 22
23 if (verbose >= level) { 23 if (var >= level) {
24 if (use_browser >= 1) 24 if (use_browser >= 1)
25 ui_helpline__vshow(fmt, args); 25 ui_helpline__vshow(fmt, args);
26 else 26 else
@@ -30,13 +30,13 @@ static int _eprintf(int level, const char *fmt, va_list args)
30 return ret; 30 return ret;
31} 31}
32 32
33int eprintf(int level, const char *fmt, ...) 33int eprintf(int level, int var, const char *fmt, ...)
34{ 34{
35 va_list args; 35 va_list args;
36 int ret; 36 int ret;
37 37
38 va_start(args, fmt); 38 va_start(args, fmt);
39 ret = _eprintf(level, fmt, args); 39 ret = _eprintf(level, var, fmt, args);
40 va_end(args); 40 va_end(args);
41 41
42 return ret; 42 return ret;
@@ -51,9 +51,9 @@ void pr_stat(const char *fmt, ...)
51 va_list args; 51 va_list args;
52 52
53 va_start(args, fmt); 53 va_start(args, fmt);
54 _eprintf(1, fmt, args); 54 _eprintf(1, verbose, fmt, args);
55 va_end(args); 55 va_end(args);
56 eprintf(1, "\n"); 56 eprintf(1, verbose, "\n");
57} 57}
58 58
59int dump_printf(const char *fmt, ...) 59int dump_printf(const char *fmt, ...)
@@ -105,3 +105,47 @@ void trace_event(union perf_event *event)
105 } 105 }
106 printf(".\n"); 106 printf(".\n");
107} 107}
108
109static struct debug_variable {
110 const char *name;
111 int *ptr;
112} debug_variables[] = {
113 { .name = "verbose", .ptr = &verbose },
114 { .name = NULL, }
115};
116
117int perf_debug_option(const char *str)
118{
119 struct debug_variable *var = &debug_variables[0];
120 char *vstr, *s = strdup(str);
121 int v = 1;
122
123 vstr = strchr(s, '=');
124 if (vstr)
125 *vstr++ = 0;
126
127 while (var->name) {
128 if (!strcmp(s, var->name))
129 break;
130 var++;
131 }
132
133 if (!var->name) {
134 pr_err("Unknown debug variable name '%s'\n", s);
135 free(s);
136 return -1;
137 }
138
139 if (vstr) {
140 v = atoi(vstr);
141 /*
142 * Allow only values in range (0, 10),
143 * otherwise set 0.
144 */
145 v = (v < 0) || (v > 10) ? 0 : v;
146 }
147
148 *var->ptr = v;
149 free(s);
150 return 0;
151}
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 443694c36b03..89fb6b0f7ab2 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -11,6 +11,24 @@
11extern int verbose; 11extern int verbose;
12extern bool quiet, dump_trace; 12extern bool quiet, dump_trace;
13 13
14#ifndef pr_fmt
15#define pr_fmt(fmt) fmt
16#endif
17
18#define pr_err(fmt, ...) \
19 eprintf(0, verbose, pr_fmt(fmt), ##__VA_ARGS__)
20#define pr_warning(fmt, ...) \
21 eprintf(0, verbose, pr_fmt(fmt), ##__VA_ARGS__)
22#define pr_info(fmt, ...) \
23 eprintf(0, verbose, pr_fmt(fmt), ##__VA_ARGS__)
24#define pr_debug(fmt, ...) \
25 eprintf(1, verbose, pr_fmt(fmt), ##__VA_ARGS__)
26#define pr_debugN(n, fmt, ...) \
27 eprintf(n, verbose, pr_fmt(fmt), ##__VA_ARGS__)
28#define pr_debug2(fmt, ...) pr_debugN(2, pr_fmt(fmt), ##__VA_ARGS__)
29#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
30#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
31
14int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 32int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
15void trace_event(union perf_event *event); 33void trace_event(union perf_event *event);
16 34
@@ -19,4 +37,8 @@ int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
19 37
20void pr_stat(const char *fmt, ...); 38void pr_stat(const char *fmt, ...);
21 39
40int eprintf(int level, int var, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
41
42int perf_debug_option(const char *str);
43
22#endif /* __PERF_DEBUG_H */ 44#endif /* __PERF_DEBUG_H */
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 819f10414f08..fc006fed8877 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -703,6 +703,7 @@ struct dso *dso__new(const char *name)
703 dso->data.fd = -1; 703 dso->data.fd = -1;
704 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND; 704 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
705 dso->binary_type = DSO_BINARY_TYPE__NOT_FOUND; 705 dso->binary_type = DSO_BINARY_TYPE__NOT_FOUND;
706 dso->is_64_bit = (sizeof(void *) == 8);
706 dso->loaded = 0; 707 dso->loaded = 0;
707 dso->rel = 0; 708 dso->rel = 0;
708 dso->sorted_by_name = 0; 709 dso->sorted_by_name = 0;
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index ad553ba257bf..c239e86541a3 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -90,6 +90,7 @@ struct dso {
90 u8 annotate_warned:1; 90 u8 annotate_warned:1;
91 u8 short_name_allocated:1; 91 u8 short_name_allocated:1;
92 u8 long_name_allocated:1; 92 u8 long_name_allocated:1;
93 u8 is_64_bit:1;
93 u8 sorted_by_name; 94 u8 sorted_by_name;
94 u8 loaded; 95 u8 loaded;
95 u8 rel; 96 u8 rel;
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index d0281bdfa582..7e0e8ae568ec 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -603,7 +603,14 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
603 603
604size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp) 604size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
605{ 605{
606 return fprintf(fp, ": %s:%d\n", event->comm.comm, event->comm.tid); 606 const char *s;
607
608 if (event->header.misc & PERF_RECORD_MISC_COMM_EXEC)
609 s = " exec";
610 else
611 s = "";
612
613 return fprintf(fp, "%s: %s:%d\n", s, event->comm.comm, event->comm.tid);
607} 614}
608 615
609int perf_event__process_comm(struct perf_tool *tool __maybe_unused, 616int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
@@ -781,6 +788,7 @@ try_again:
781 cpumode == PERF_RECORD_MISC_USER && 788 cpumode == PERF_RECORD_MISC_USER &&
782 machine && mg != &machine->kmaps) { 789 machine && mg != &machine->kmaps) {
783 mg = &machine->kmaps; 790 mg = &machine->kmaps;
791 load_map = true;
784 goto try_again; 792 goto try_again;
785 } 793 }
786 } else { 794 } else {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index c51223ac25f4..814e954c1318 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -606,12 +606,17 @@ static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
606 return evlist->mmap != NULL ? 0 : -ENOMEM; 606 return evlist->mmap != NULL ? 0 : -ENOMEM;
607} 607}
608 608
609static int __perf_evlist__mmap(struct perf_evlist *evlist, 609struct mmap_params {
610 int idx, int prot, int mask, int fd) 610 int prot;
611 int mask;
612};
613
614static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
615 struct mmap_params *mp, int fd)
611{ 616{
612 evlist->mmap[idx].prev = 0; 617 evlist->mmap[idx].prev = 0;
613 evlist->mmap[idx].mask = mask; 618 evlist->mmap[idx].mask = mp->mask;
614 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, 619 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot,
615 MAP_SHARED, fd, 0); 620 MAP_SHARED, fd, 0);
616 if (evlist->mmap[idx].base == MAP_FAILED) { 621 if (evlist->mmap[idx].base == MAP_FAILED) {
617 pr_debug2("failed to mmap perf event ring buffer, error %d\n", 622 pr_debug2("failed to mmap perf event ring buffer, error %d\n",
@@ -625,8 +630,8 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist,
625} 630}
626 631
627static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, 632static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
628 int prot, int mask, int cpu, int thread, 633 struct mmap_params *mp, int cpu,
629 int *output) 634 int thread, int *output)
630{ 635{
631 struct perf_evsel *evsel; 636 struct perf_evsel *evsel;
632 637
@@ -635,8 +640,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
635 640
636 if (*output == -1) { 641 if (*output == -1) {
637 *output = fd; 642 *output = fd;
638 if (__perf_evlist__mmap(evlist, idx, prot, mask, 643 if (__perf_evlist__mmap(evlist, idx, mp, *output) < 0)
639 *output) < 0)
640 return -1; 644 return -1;
641 } else { 645 } else {
642 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) 646 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
@@ -651,8 +655,8 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
651 return 0; 655 return 0;
652} 656}
653 657
654static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, 658static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist,
655 int mask) 659 struct mmap_params *mp)
656{ 660{
657 int cpu, thread; 661 int cpu, thread;
658 int nr_cpus = cpu_map__nr(evlist->cpus); 662 int nr_cpus = cpu_map__nr(evlist->cpus);
@@ -663,8 +667,8 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot,
663 int output = -1; 667 int output = -1;
664 668
665 for (thread = 0; thread < nr_threads; thread++) { 669 for (thread = 0; thread < nr_threads; thread++) {
666 if (perf_evlist__mmap_per_evsel(evlist, cpu, prot, mask, 670 if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu,
667 cpu, thread, &output)) 671 thread, &output))
668 goto out_unmap; 672 goto out_unmap;
669 } 673 }
670 } 674 }
@@ -677,8 +681,8 @@ out_unmap:
677 return -1; 681 return -1;
678} 682}
679 683
680static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, 684static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist,
681 int mask) 685 struct mmap_params *mp)
682{ 686{
683 int thread; 687 int thread;
684 int nr_threads = thread_map__nr(evlist->threads); 688 int nr_threads = thread_map__nr(evlist->threads);
@@ -687,8 +691,8 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot,
687 for (thread = 0; thread < nr_threads; thread++) { 691 for (thread = 0; thread < nr_threads; thread++) {
688 int output = -1; 692 int output = -1;
689 693
690 if (perf_evlist__mmap_per_evsel(evlist, thread, prot, mask, 0, 694 if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread,
691 thread, &output)) 695 &output))
692 goto out_unmap; 696 goto out_unmap;
693 } 697 }
694 698
@@ -793,7 +797,9 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
793 struct perf_evsel *evsel; 797 struct perf_evsel *evsel;
794 const struct cpu_map *cpus = evlist->cpus; 798 const struct cpu_map *cpus = evlist->cpus;
795 const struct thread_map *threads = evlist->threads; 799 const struct thread_map *threads = evlist->threads;
796 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask; 800 struct mmap_params mp = {
801 .prot = PROT_READ | (overwrite ? 0 : PROT_WRITE),
802 };
797 803
798 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 804 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
799 return -ENOMEM; 805 return -ENOMEM;
@@ -804,7 +810,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
804 evlist->overwrite = overwrite; 810 evlist->overwrite = overwrite;
805 evlist->mmap_len = perf_evlist__mmap_size(pages); 811 evlist->mmap_len = perf_evlist__mmap_size(pages);
806 pr_debug("mmap size %zuB\n", evlist->mmap_len); 812 pr_debug("mmap size %zuB\n", evlist->mmap_len);
807 mask = evlist->mmap_len - page_size - 1; 813 mp.mask = evlist->mmap_len - page_size - 1;
808 814
809 evlist__for_each(evlist, evsel) { 815 evlist__for_each(evlist, evsel) {
810 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 816 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
@@ -814,9 +820,9 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
814 } 820 }
815 821
816 if (cpu_map__empty(cpus)) 822 if (cpu_map__empty(cpus))
817 return perf_evlist__mmap_per_thread(evlist, prot, mask); 823 return perf_evlist__mmap_per_thread(evlist, &mp);
818 824
819 return perf_evlist__mmap_per_cpu(evlist, prot, mask); 825 return perf_evlist__mmap_per_cpu(evlist, &mp);
820} 826}
821 827
822int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) 828int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 8606175fe1e8..90f58cdd0fb0 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -623,7 +623,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
623 attr->mmap_data = track; 623 attr->mmap_data = track;
624 } 624 }
625 625
626 if (opts->call_graph_enabled) 626 if (opts->call_graph_enabled && !evsel->no_aux_samples)
627 perf_evsel__config_callgraph(evsel, opts); 627 perf_evsel__config_callgraph(evsel, opts);
628 628
629 if (target__has_cpu(&opts->target)) 629 if (target__has_cpu(&opts->target))
@@ -637,7 +637,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
637 target__has_cpu(&opts->target) || per_cpu)) 637 target__has_cpu(&opts->target) || per_cpu))
638 perf_evsel__set_sample_bit(evsel, TIME); 638 perf_evsel__set_sample_bit(evsel, TIME);
639 639
640 if (opts->raw_samples) { 640 if (opts->raw_samples && !evsel->no_aux_samples) {
641 perf_evsel__set_sample_bit(evsel, TIME); 641 perf_evsel__set_sample_bit(evsel, TIME);
642 perf_evsel__set_sample_bit(evsel, RAW); 642 perf_evsel__set_sample_bit(evsel, RAW);
643 perf_evsel__set_sample_bit(evsel, CPU); 643 perf_evsel__set_sample_bit(evsel, CPU);
@@ -650,7 +650,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
650 attr->watermark = 0; 650 attr->watermark = 0;
651 attr->wakeup_events = 1; 651 attr->wakeup_events = 1;
652 } 652 }
653 if (opts->branch_stack) { 653 if (opts->branch_stack && !evsel->no_aux_samples) {
654 perf_evsel__set_sample_bit(evsel, BRANCH_STACK); 654 perf_evsel__set_sample_bit(evsel, BRANCH_STACK);
655 attr->branch_sample_type = opts->branch_stack; 655 attr->branch_sample_type = opts->branch_stack;
656 } 656 }
@@ -681,6 +681,11 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
681 if (target__none(&opts->target) && perf_evsel__is_group_leader(evsel) && 681 if (target__none(&opts->target) && perf_evsel__is_group_leader(evsel) &&
682 !opts->initial_delay) 682 !opts->initial_delay)
683 attr->enable_on_exec = 1; 683 attr->enable_on_exec = 1;
684
685 if (evsel->immediate) {
686 attr->disabled = 0;
687 attr->enable_on_exec = 0;
688 }
684} 689}
685 690
686int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 691int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
@@ -960,6 +965,7 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
960 ret += PRINT_ATTR2(exclude_user, exclude_kernel); 965 ret += PRINT_ATTR2(exclude_user, exclude_kernel);
961 ret += PRINT_ATTR2(exclude_hv, exclude_idle); 966 ret += PRINT_ATTR2(exclude_hv, exclude_idle);
962 ret += PRINT_ATTR2(mmap, comm); 967 ret += PRINT_ATTR2(mmap, comm);
968 ret += PRINT_ATTR2(mmap2, comm_exec);
963 ret += PRINT_ATTR2(freq, inherit_stat); 969 ret += PRINT_ATTR2(freq, inherit_stat);
964 ret += PRINT_ATTR2(enable_on_exec, task); 970 ret += PRINT_ATTR2(enable_on_exec, task);
965 ret += PRINT_ATTR2(watermark, precise_ip); 971 ret += PRINT_ATTR2(watermark, precise_ip);
@@ -967,7 +973,6 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
967 ret += PRINT_ATTR2(exclude_host, exclude_guest); 973 ret += PRINT_ATTR2(exclude_host, exclude_guest);
968 ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel, 974 ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel,
969 "excl.callchain_user", exclude_callchain_user); 975 "excl.callchain_user", exclude_callchain_user);
970 ret += PRINT_ATTR_U32(mmap2);
971 976
972 ret += PRINT_ATTR_U32(wakeup_events); 977 ret += PRINT_ATTR_U32(wakeup_events);
973 ret += PRINT_ATTR_U32(wakeup_watermark); 978 ret += PRINT_ATTR_U32(wakeup_watermark);
@@ -1940,6 +1945,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
1940 if_print(mmap); 1945 if_print(mmap);
1941 if_print(mmap2); 1946 if_print(mmap2);
1942 if_print(comm); 1947 if_print(comm);
1948 if_print(comm_exec);
1943 if_print(freq); 1949 if_print(freq);
1944 if_print(inherit_stat); 1950 if_print(inherit_stat);
1945 if_print(enable_on_exec); 1951 if_print(enable_on_exec);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index a52e9a5bb2d0..d7f93ce0ebc1 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -83,6 +83,8 @@ struct perf_evsel {
83 int is_pos; 83 int is_pos;
84 bool supported; 84 bool supported;
85 bool needs_swap; 85 bool needs_swap;
86 bool no_aux_samples;
87 bool immediate;
86 /* parse modifier helper */ 88 /* parse modifier helper */
87 int exclude_GH; 89 int exclude_GH;
88 int nr_members; 90 int nr_members;
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h
index 9844c31b7c2b..09e8e7aea7c6 100644
--- a/tools/perf/util/include/linux/kernel.h
+++ b/tools/perf/util/include/linux/kernel.h
@@ -94,27 +94,6 @@ static inline int scnprintf(char * buf, size_t size, const char * fmt, ...)
94 return (i >= ssize) ? (ssize - 1) : i; 94 return (i >= ssize) ? (ssize - 1) : i;
95} 95}
96 96
97int eprintf(int level,
98 const char *fmt, ...) __attribute__((format(printf, 2, 3)));
99
100#ifndef pr_fmt
101#define pr_fmt(fmt) fmt
102#endif
103
104#define pr_err(fmt, ...) \
105 eprintf(0, pr_fmt(fmt), ##__VA_ARGS__)
106#define pr_warning(fmt, ...) \
107 eprintf(0, pr_fmt(fmt), ##__VA_ARGS__)
108#define pr_info(fmt, ...) \
109 eprintf(0, pr_fmt(fmt), ##__VA_ARGS__)
110#define pr_debug(fmt, ...) \
111 eprintf(1, pr_fmt(fmt), ##__VA_ARGS__)
112#define pr_debugN(n, fmt, ...) \
113 eprintf(n, pr_fmt(fmt), ##__VA_ARGS__)
114#define pr_debug2(fmt, ...) pr_debugN(2, pr_fmt(fmt), ##__VA_ARGS__)
115#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
116#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
117
118/* 97/*
119 * This looks more complex than it should be. But we need to 98 * This looks more complex than it should be. But we need to
120 * get the type for the ~ right in round_down (it needs to be 99 * get the type for the ~ right in round_down (it needs to be
diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h
new file mode 100644
index 000000000000..0b5a8cd2ee79
--- /dev/null
+++ b/tools/perf/util/kvm-stat.h
@@ -0,0 +1,140 @@
1#ifndef __PERF_KVM_STAT_H
2#define __PERF_KVM_STAT_H
3
4#include "../perf.h"
5#include "evsel.h"
6#include "evlist.h"
7#include "session.h"
8#include "tool.h"
9#include "stat.h"
10
11struct event_key {
12 #define INVALID_KEY (~0ULL)
13 u64 key;
14 int info;
15 struct exit_reasons_table *exit_reasons;
16};
17
18struct kvm_event_stats {
19 u64 time;
20 struct stats stats;
21};
22
23struct kvm_event {
24 struct list_head hash_entry;
25 struct rb_node rb;
26
27 struct event_key key;
28
29 struct kvm_event_stats total;
30
31 #define DEFAULT_VCPU_NUM 8
32 int max_vcpu;
33 struct kvm_event_stats *vcpu;
34};
35
36typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int);
37
38struct kvm_event_key {
39 const char *name;
40 key_cmp_fun key;
41};
42
43struct perf_kvm_stat;
44
45struct child_event_ops {
46 void (*get_key)(struct perf_evsel *evsel,
47 struct perf_sample *sample,
48 struct event_key *key);
49 const char *name;
50};
51
52struct kvm_events_ops {
53 bool (*is_begin_event)(struct perf_evsel *evsel,
54 struct perf_sample *sample,
55 struct event_key *key);
56 bool (*is_end_event)(struct perf_evsel *evsel,
57 struct perf_sample *sample, struct event_key *key);
58 struct child_event_ops *child_ops;
59 void (*decode_key)(struct perf_kvm_stat *kvm, struct event_key *key,
60 char *decode);
61 const char *name;
62};
63
64struct exit_reasons_table {
65 unsigned long exit_code;
66 const char *reason;
67};
68
69#define EVENTS_BITS 12
70#define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS)
71
72struct perf_kvm_stat {
73 struct perf_tool tool;
74 struct record_opts opts;
75 struct perf_evlist *evlist;
76 struct perf_session *session;
77
78 const char *file_name;
79 const char *report_event;
80 const char *sort_key;
81 int trace_vcpu;
82
83 struct exit_reasons_table *exit_reasons;
84 const char *exit_reasons_isa;
85
86 struct kvm_events_ops *events_ops;
87 key_cmp_fun compare;
88 struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
89
90 u64 total_time;
91 u64 total_count;
92 u64 lost_events;
93 u64 duration;
94
95 const char *pid_str;
96 struct intlist *pid_list;
97
98 struct rb_root result;
99
100 int timerfd;
101 unsigned int display_time;
102 bool live;
103};
104
105struct kvm_reg_events_ops {
106 const char *name;
107 struct kvm_events_ops *ops;
108};
109
110void exit_event_get_key(struct perf_evsel *evsel,
111 struct perf_sample *sample,
112 struct event_key *key);
113bool exit_event_begin(struct perf_evsel *evsel,
114 struct perf_sample *sample,
115 struct event_key *key);
116bool exit_event_end(struct perf_evsel *evsel,
117 struct perf_sample *sample,
118 struct event_key *key);
119void exit_event_decode_key(struct perf_kvm_stat *kvm,
120 struct event_key *key,
121 char *decode);
122
123bool kvm_exit_event(struct perf_evsel *evsel);
124bool kvm_entry_event(struct perf_evsel *evsel);
125
126#define define_exit_reasons_table(name, symbols) \
127 static struct exit_reasons_table name[] = { \
128 symbols, { -1, NULL } \
129 }
130
131/*
132 * arch specific callbacks and data structures
133 */
134int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid);
135
136extern const char * const kvm_events_tp[];
137extern struct kvm_reg_events_ops kvm_reg_events_ops[];
138extern const char * const kvm_skip_events[];
139
140#endif /* __PERF_KVM_STAT_H */
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index e9b943acaa5e..93c8b6fbc799 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -34,7 +34,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
34 return -ENOMEM; 34 return -ENOMEM;
35 35
36 if (pid != HOST_KERNEL_ID) { 36 if (pid != HOST_KERNEL_ID) {
37 struct thread *thread = machine__findnew_thread(machine, 0, 37 struct thread *thread = machine__findnew_thread(machine, -1,
38 pid); 38 pid);
39 char comm[64]; 39 char comm[64];
40 40
@@ -272,6 +272,52 @@ void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size)
272 return; 272 return;
273} 273}
274 274
275static void machine__update_thread_pid(struct machine *machine,
276 struct thread *th, pid_t pid)
277{
278 struct thread *leader;
279
280 if (pid == th->pid_ || pid == -1 || th->pid_ != -1)
281 return;
282
283 th->pid_ = pid;
284
285 if (th->pid_ == th->tid)
286 return;
287
288 leader = machine__findnew_thread(machine, th->pid_, th->pid_);
289 if (!leader)
290 goto out_err;
291
292 if (!leader->mg)
293 leader->mg = map_groups__new();
294
295 if (!leader->mg)
296 goto out_err;
297
298 if (th->mg == leader->mg)
299 return;
300
301 if (th->mg) {
302 /*
303 * Maps are created from MMAP events which provide the pid and
304 * tid. Consequently there never should be any maps on a thread
305 * with an unknown pid. Just print an error if there are.
306 */
307 if (!map_groups__empty(th->mg))
308 pr_err("Discarding thread maps for %d:%d\n",
309 th->pid_, th->tid);
310 map_groups__delete(th->mg);
311 }
312
313 th->mg = map_groups__get(leader->mg);
314
315 return;
316
317out_err:
318 pr_err("Failed to join map groups for %d:%d\n", th->pid_, th->tid);
319}
320
275static struct thread *__machine__findnew_thread(struct machine *machine, 321static struct thread *__machine__findnew_thread(struct machine *machine,
276 pid_t pid, pid_t tid, 322 pid_t pid, pid_t tid,
277 bool create) 323 bool create)
@@ -285,10 +331,10 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
285 * so most of the time we dont have to look up 331 * so most of the time we dont have to look up
286 * the full rbtree: 332 * the full rbtree:
287 */ 333 */
288 if (machine->last_match && machine->last_match->tid == tid) { 334 th = machine->last_match;
289 if (pid && pid != machine->last_match->pid_) 335 if (th && th->tid == tid) {
290 machine->last_match->pid_ = pid; 336 machine__update_thread_pid(machine, th, pid);
291 return machine->last_match; 337 return th;
292 } 338 }
293 339
294 while (*p != NULL) { 340 while (*p != NULL) {
@@ -297,8 +343,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
297 343
298 if (th->tid == tid) { 344 if (th->tid == tid) {
299 machine->last_match = th; 345 machine->last_match = th;
300 if (pid && pid != th->pid_) 346 machine__update_thread_pid(machine, th, pid);
301 th->pid_ = pid;
302 return th; 347 return th;
303 } 348 }
304 349
@@ -325,8 +370,10 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
325 * within thread__init_map_groups to find the thread 370 * within thread__init_map_groups to find the thread
326 * leader and that would screwed the rb tree. 371 * leader and that would screwed the rb tree.
327 */ 372 */
328 if (thread__init_map_groups(th, machine)) 373 if (thread__init_map_groups(th, machine)) {
374 thread__delete(th);
329 return NULL; 375 return NULL;
376 }
330 } 377 }
331 378
332 return th; 379 return th;
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 25c571f4cba6..845f627e45f4 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -12,6 +12,7 @@
12#include "vdso.h" 12#include "vdso.h"
13#include "build-id.h" 13#include "build-id.h"
14#include "util.h" 14#include "util.h"
15#include "debug.h"
15#include <linux/string.h> 16#include <linux/string.h>
16 17
17const char *map_type__name[MAP__NR_TYPES] = { 18const char *map_type__name[MAP__NR_TYPES] = {
@@ -454,6 +455,20 @@ void map_groups__exit(struct map_groups *mg)
454 } 455 }
455} 456}
456 457
458bool map_groups__empty(struct map_groups *mg)
459{
460 int i;
461
462 for (i = 0; i < MAP__NR_TYPES; ++i) {
463 if (maps__first(&mg->maps[i]))
464 return false;
465 if (!list_empty(&mg->removed_maps[i]))
466 return false;
467 }
468
469 return true;
470}
471
457struct map_groups *map_groups__new(void) 472struct map_groups *map_groups__new(void)
458{ 473{
459 struct map_groups *mg = malloc(sizeof(*mg)); 474 struct map_groups *mg = malloc(sizeof(*mg));
@@ -554,8 +569,8 @@ int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter)
554 return ams->sym ? 0 : -1; 569 return ams->sym ? 0 : -1;
555} 570}
556 571
557size_t __map_groups__fprintf_maps(struct map_groups *mg, 572size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type,
558 enum map_type type, int verbose, FILE *fp) 573 FILE *fp)
559{ 574{
560 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); 575 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
561 struct rb_node *nd; 576 struct rb_node *nd;
@@ -573,17 +588,16 @@ size_t __map_groups__fprintf_maps(struct map_groups *mg,
573 return printed; 588 return printed;
574} 589}
575 590
576size_t map_groups__fprintf_maps(struct map_groups *mg, int verbose, FILE *fp) 591static size_t map_groups__fprintf_maps(struct map_groups *mg, FILE *fp)
577{ 592{
578 size_t printed = 0, i; 593 size_t printed = 0, i;
579 for (i = 0; i < MAP__NR_TYPES; ++i) 594 for (i = 0; i < MAP__NR_TYPES; ++i)
580 printed += __map_groups__fprintf_maps(mg, i, verbose, fp); 595 printed += __map_groups__fprintf_maps(mg, i, fp);
581 return printed; 596 return printed;
582} 597}
583 598
584static size_t __map_groups__fprintf_removed_maps(struct map_groups *mg, 599static size_t __map_groups__fprintf_removed_maps(struct map_groups *mg,
585 enum map_type type, 600 enum map_type type, FILE *fp)
586 int verbose, FILE *fp)
587{ 601{
588 struct map *pos; 602 struct map *pos;
589 size_t printed = 0; 603 size_t printed = 0;
@@ -600,23 +614,23 @@ static size_t __map_groups__fprintf_removed_maps(struct map_groups *mg,
600} 614}
601 615
602static size_t map_groups__fprintf_removed_maps(struct map_groups *mg, 616static size_t map_groups__fprintf_removed_maps(struct map_groups *mg,
603 int verbose, FILE *fp) 617 FILE *fp)
604{ 618{
605 size_t printed = 0, i; 619 size_t printed = 0, i;
606 for (i = 0; i < MAP__NR_TYPES; ++i) 620 for (i = 0; i < MAP__NR_TYPES; ++i)
607 printed += __map_groups__fprintf_removed_maps(mg, i, verbose, fp); 621 printed += __map_groups__fprintf_removed_maps(mg, i, fp);
608 return printed; 622 return printed;
609} 623}
610 624
611size_t map_groups__fprintf(struct map_groups *mg, int verbose, FILE *fp) 625size_t map_groups__fprintf(struct map_groups *mg, FILE *fp)
612{ 626{
613 size_t printed = map_groups__fprintf_maps(mg, verbose, fp); 627 size_t printed = map_groups__fprintf_maps(mg, fp);
614 printed += fprintf(fp, "Removed maps:\n"); 628 printed += fprintf(fp, "Removed maps:\n");
615 return printed + map_groups__fprintf_removed_maps(mg, verbose, fp); 629 return printed + map_groups__fprintf_removed_maps(mg, fp);
616} 630}
617 631
618int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, 632int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
619 int verbose, FILE *fp) 633 FILE *fp)
620{ 634{
621 struct rb_root *root = &mg->maps[map->type]; 635 struct rb_root *root = &mg->maps[map->type];
622 struct rb_node *next = rb_first(root); 636 struct rb_node *next = rb_first(root);
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 7758c72522ef..22d13a219590 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -66,6 +66,7 @@ struct map_groups {
66 66
67struct map_groups *map_groups__new(void); 67struct map_groups *map_groups__new(void);
68void map_groups__delete(struct map_groups *mg); 68void map_groups__delete(struct map_groups *mg);
69bool map_groups__empty(struct map_groups *mg);
69 70
70static inline struct map_groups *map_groups__get(struct map_groups *mg) 71static inline struct map_groups *map_groups__get(struct map_groups *mg)
71{ 72{
@@ -141,8 +142,8 @@ void map__fixup_end(struct map *map);
141 142
142void map__reloc_vmlinux(struct map *map); 143void map__reloc_vmlinux(struct map *map);
143 144
144size_t __map_groups__fprintf_maps(struct map_groups *mg, 145size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type,
145 enum map_type type, int verbose, FILE *fp); 146 FILE *fp);
146void maps__insert(struct rb_root *maps, struct map *map); 147void maps__insert(struct rb_root *maps, struct map *map);
147void maps__remove(struct rb_root *maps, struct map *map); 148void maps__remove(struct rb_root *maps, struct map *map);
148struct map *maps__find(struct rb_root *maps, u64 addr); 149struct map *maps__find(struct rb_root *maps, u64 addr);
@@ -152,8 +153,7 @@ void map_groups__init(struct map_groups *mg);
152void map_groups__exit(struct map_groups *mg); 153void map_groups__exit(struct map_groups *mg);
153int map_groups__clone(struct map_groups *mg, 154int map_groups__clone(struct map_groups *mg,
154 struct map_groups *parent, enum map_type type); 155 struct map_groups *parent, enum map_type type);
155size_t map_groups__fprintf(struct map_groups *mg, int verbose, FILE *fp); 156size_t map_groups__fprintf(struct map_groups *mg, FILE *fp);
156size_t map_groups__fprintf_maps(struct map_groups *mg, int verbose, FILE *fp);
157 157
158int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name, 158int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name,
159 u64 addr); 159 u64 addr);
@@ -210,7 +210,7 @@ struct symbol *map_groups__find_function_by_name(struct map_groups *mg,
210} 210}
211 211
212int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, 212int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
213 int verbose, FILE *fp); 213 FILE *fp);
214 214
215struct map *map_groups__find_by_name(struct map_groups *mg, 215struct map *map_groups__find_by_name(struct map_groups *mg,
216 enum map_type type, const char *name); 216 enum map_type type, const char *name);
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index d8dac8ac5f37..b59ba858e73d 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -98,6 +98,7 @@ struct option {
98 parse_opt_cb *callback; 98 parse_opt_cb *callback;
99 intptr_t defval; 99 intptr_t defval;
100 bool *set; 100 bool *set;
101 void *data;
101}; 102};
102 103
103#define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v ) 104#define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v )
@@ -131,6 +132,10 @@ struct option {
131 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\ 132 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\
132 .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\ 133 .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\
133 .flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG} 134 .flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG}
135#define OPT_CALLBACK_OPTARG(s, l, v, d, a, h, f) \
136 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \
137 .value = (v), (a), .help = (h), .callback = (f), \
138 .flags = PARSE_OPT_OPTARG, .data = (d) }
134 139
135/* parse_options() will filter out the processed options and leave the 140/* parse_options() will filter out the processed options and leave the
136 * non-option argments in argv[]. 141 * non-option argments in argv[].
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 98e304766416..dca9145d704c 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -26,7 +26,6 @@
26#include <errno.h> 26#include <errno.h>
27#include <stdio.h> 27#include <stdio.h>
28#include <unistd.h> 28#include <unistd.h>
29#include <getopt.h>
30#include <stdlib.h> 29#include <stdlib.h>
31#include <string.h> 30#include <string.h>
32#include <stdarg.h> 31#include <stdarg.h>
diff --git a/tools/perf/util/pstack.c b/tools/perf/util/pstack.c
index daa17aeb6c63..a126e6cc6e73 100644
--- a/tools/perf/util/pstack.c
+++ b/tools/perf/util/pstack.c
@@ -6,6 +6,7 @@
6 6
7#include "util.h" 7#include "util.h"
8#include "pstack.h" 8#include "pstack.h"
9#include "debug.h"
9#include <linux/kernel.h> 10#include <linux/kernel.h>
10#include <stdlib.h> 11#include <stdlib.h>
11 12
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 122669c18ff4..12aa9b0d0ba1 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -14,12 +14,12 @@
14 */ 14 */
15int verbose; 15int verbose;
16 16
17int eprintf(int level, const char *fmt, ...) 17int eprintf(int level, int var, const char *fmt, ...)
18{ 18{
19 va_list args; 19 va_list args;
20 int ret = 0; 20 int ret = 0;
21 21
22 if (verbose >= level) { 22 if (var >= level) {
23 va_start(args, fmt); 23 va_start(args, fmt);
24 ret = vfprintf(stderr, fmt, args); 24 ret = vfprintf(stderr, fmt, args);
25 va_end(args); 25 va_end(args);
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index 049e0a09ccd3..165723152cfb 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -69,15 +69,26 @@ static void perf_probe_sample_identifier(struct perf_evsel *evsel)
69 evsel->attr.sample_type |= PERF_SAMPLE_IDENTIFIER; 69 evsel->attr.sample_type |= PERF_SAMPLE_IDENTIFIER;
70} 70}
71 71
72static void perf_probe_comm_exec(struct perf_evsel *evsel)
73{
74 evsel->attr.comm_exec = 1;
75}
76
72bool perf_can_sample_identifier(void) 77bool perf_can_sample_identifier(void)
73{ 78{
74 return perf_probe_api(perf_probe_sample_identifier); 79 return perf_probe_api(perf_probe_sample_identifier);
75} 80}
76 81
82static bool perf_can_comm_exec(void)
83{
84 return perf_probe_api(perf_probe_comm_exec);
85}
86
77void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts) 87void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
78{ 88{
79 struct perf_evsel *evsel; 89 struct perf_evsel *evsel;
80 bool use_sample_identifier = false; 90 bool use_sample_identifier = false;
91 bool use_comm_exec;
81 92
82 /* 93 /*
83 * Set the evsel leader links before we configure attributes, 94 * Set the evsel leader links before we configure attributes,
@@ -89,8 +100,13 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
89 if (evlist->cpus->map[0] < 0) 100 if (evlist->cpus->map[0] < 0)
90 opts->no_inherit = true; 101 opts->no_inherit = true;
91 102
92 evlist__for_each(evlist, evsel) 103 use_comm_exec = perf_can_comm_exec();
104
105 evlist__for_each(evlist, evsel) {
93 perf_evsel__config(evsel, opts); 106 perf_evsel__config(evsel, opts);
107 if (!evsel->idx && use_comm_exec)
108 evsel->attr.comm_exec = 1;
109 }
94 110
95 if (evlist->nr_entries > 1) { 111 if (evlist->nr_entries > 1) {
96 struct perf_evsel *first = perf_evlist__first(evlist); 112 struct perf_evsel *first = perf_evlist__first(evlist);
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index af7da565a750..b2dba9c0a3a1 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -34,6 +34,7 @@
34#include "../event.h" 34#include "../event.h"
35#include "../trace-event.h" 35#include "../trace-event.h"
36#include "../evsel.h" 36#include "../evsel.h"
37#include "../debug.h"
37 38
38void boot_Perf__Trace__Context(pTHX_ CV *cv); 39void boot_Perf__Trace__Context(pTHX_ CV *cv);
39void boot_DynaLoader(pTHX_ CV *cv); 40void boot_DynaLoader(pTHX_ CV *cv);
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index e55b65a65558..cbce2545da45 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -27,11 +27,13 @@
27#include <errno.h> 27#include <errno.h>
28 28
29#include "../../perf.h" 29#include "../../perf.h"
30#include "../debug.h"
30#include "../evsel.h" 31#include "../evsel.h"
31#include "../util.h" 32#include "../util.h"
32#include "../event.h" 33#include "../event.h"
33#include "../thread.h" 34#include "../thread.h"
34#include "../trace-event.h" 35#include "../trace-event.h"
36#include "../machine.h"
35 37
36PyMODINIT_FUNC initperf_trace_context(void); 38PyMODINIT_FUNC initperf_trace_context(void);
37 39
@@ -50,10 +52,14 @@ static int zero_flag_atom;
50 52
51static PyObject *main_module, *main_dict; 53static PyObject *main_module, *main_dict;
52 54
55static void handler_call_die(const char *handler_name) NORETURN;
53static void handler_call_die(const char *handler_name) 56static void handler_call_die(const char *handler_name)
54{ 57{
55 PyErr_Print(); 58 PyErr_Print();
56 Py_FatalError("problem in Python trace event handler"); 59 Py_FatalError("problem in Python trace event handler");
60 // Py_FatalError does not return
61 // but we have to make the compiler happy
62 abort();
57} 63}
58 64
59/* 65/*
@@ -97,6 +103,7 @@ static void define_value(enum print_arg_type field_type,
97 retval = PyObject_CallObject(handler, t); 103 retval = PyObject_CallObject(handler, t);
98 if (retval == NULL) 104 if (retval == NULL)
99 handler_call_die(handler_name); 105 handler_call_die(handler_name);
106 Py_DECREF(retval);
100 } 107 }
101 108
102 Py_DECREF(t); 109 Py_DECREF(t);
@@ -143,6 +150,7 @@ static void define_field(enum print_arg_type field_type,
143 retval = PyObject_CallObject(handler, t); 150 retval = PyObject_CallObject(handler, t);
144 if (retval == NULL) 151 if (retval == NULL)
145 handler_call_die(handler_name); 152 handler_call_die(handler_name);
153 Py_DECREF(retval);
146 } 154 }
147 155
148 Py_DECREF(t); 156 Py_DECREF(t);
@@ -272,12 +280,90 @@ static PyObject *get_field_numeric_entry(struct event_format *event,
272 return obj; 280 return obj;
273} 281}
274 282
283
284static PyObject *python_process_callchain(struct perf_sample *sample,
285 struct perf_evsel *evsel,
286 struct addr_location *al)
287{
288 PyObject *pylist;
289
290 pylist = PyList_New(0);
291 if (!pylist)
292 Py_FatalError("couldn't create Python list");
293
294 if (!symbol_conf.use_callchain || !sample->callchain)
295 goto exit;
296
297 if (machine__resolve_callchain(al->machine, evsel, al->thread,
298 sample, NULL, NULL,
299 PERF_MAX_STACK_DEPTH) != 0) {
300 pr_err("Failed to resolve callchain. Skipping\n");
301 goto exit;
302 }
303 callchain_cursor_commit(&callchain_cursor);
304
305
306 while (1) {
307 PyObject *pyelem;
308 struct callchain_cursor_node *node;
309 node = callchain_cursor_current(&callchain_cursor);
310 if (!node)
311 break;
312
313 pyelem = PyDict_New();
314 if (!pyelem)
315 Py_FatalError("couldn't create Python dictionary");
316
317
318 pydict_set_item_string_decref(pyelem, "ip",
319 PyLong_FromUnsignedLongLong(node->ip));
320
321 if (node->sym) {
322 PyObject *pysym = PyDict_New();
323 if (!pysym)
324 Py_FatalError("couldn't create Python dictionary");
325 pydict_set_item_string_decref(pysym, "start",
326 PyLong_FromUnsignedLongLong(node->sym->start));
327 pydict_set_item_string_decref(pysym, "end",
328 PyLong_FromUnsignedLongLong(node->sym->end));
329 pydict_set_item_string_decref(pysym, "binding",
330 PyInt_FromLong(node->sym->binding));
331 pydict_set_item_string_decref(pysym, "name",
332 PyString_FromStringAndSize(node->sym->name,
333 node->sym->namelen));
334 pydict_set_item_string_decref(pyelem, "sym", pysym);
335 }
336
337 if (node->map) {
338 struct map *map = node->map;
339 const char *dsoname = "[unknown]";
340 if (map && map->dso && (map->dso->name || map->dso->long_name)) {
341 if (symbol_conf.show_kernel_path && map->dso->long_name)
342 dsoname = map->dso->long_name;
343 else if (map->dso->name)
344 dsoname = map->dso->name;
345 }
346 pydict_set_item_string_decref(pyelem, "dso",
347 PyString_FromString(dsoname));
348 }
349
350 callchain_cursor_advance(&callchain_cursor);
351 PyList_Append(pylist, pyelem);
352 Py_DECREF(pyelem);
353 }
354
355exit:
356 return pylist;
357}
358
359
275static void python_process_tracepoint(struct perf_sample *sample, 360static void python_process_tracepoint(struct perf_sample *sample,
276 struct perf_evsel *evsel, 361 struct perf_evsel *evsel,
277 struct thread *thread, 362 struct thread *thread,
278 struct addr_location *al) 363 struct addr_location *al)
279{ 364{
280 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; 365 PyObject *handler, *retval, *context, *t, *obj, *callchain;
366 PyObject *dict = NULL;
281 static char handler_name[256]; 367 static char handler_name[256];
282 struct format_field *field; 368 struct format_field *field;
283 unsigned long s, ns; 369 unsigned long s, ns;
@@ -320,18 +406,23 @@ static void python_process_tracepoint(struct perf_sample *sample,
320 PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); 406 PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
321 PyTuple_SetItem(t, n++, context); 407 PyTuple_SetItem(t, n++, context);
322 408
409 /* ip unwinding */
410 callchain = python_process_callchain(sample, evsel, al);
411
323 if (handler) { 412 if (handler) {
324 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 413 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
325 PyTuple_SetItem(t, n++, PyInt_FromLong(s)); 414 PyTuple_SetItem(t, n++, PyInt_FromLong(s));
326 PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); 415 PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
327 PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); 416 PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
328 PyTuple_SetItem(t, n++, PyString_FromString(comm)); 417 PyTuple_SetItem(t, n++, PyString_FromString(comm));
418 PyTuple_SetItem(t, n++, callchain);
329 } else { 419 } else {
330 pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); 420 pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu));
331 pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); 421 pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s));
332 pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); 422 pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns));
333 pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); 423 pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid));
334 pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); 424 pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm));
425 pydict_set_item_string_decref(dict, "common_callchain", callchain);
335 } 426 }
336 for (field = event->format.fields; field; field = field->next) { 427 for (field = event->format.fields; field; field = field->next) {
337 if (field->flags & FIELD_IS_STRING) { 428 if (field->flags & FIELD_IS_STRING) {
@@ -351,6 +442,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
351 pydict_set_item_string_decref(dict, field->name, obj); 442 pydict_set_item_string_decref(dict, field->name, obj);
352 443
353 } 444 }
445
354 if (!handler) 446 if (!handler)
355 PyTuple_SetItem(t, n++, dict); 447 PyTuple_SetItem(t, n++, dict);
356 448
@@ -361,6 +453,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
361 retval = PyObject_CallObject(handler, t); 453 retval = PyObject_CallObject(handler, t);
362 if (retval == NULL) 454 if (retval == NULL)
363 handler_call_die(handler_name); 455 handler_call_die(handler_name);
456 Py_DECREF(retval);
364 } else { 457 } else {
365 handler = PyDict_GetItemString(main_dict, "trace_unhandled"); 458 handler = PyDict_GetItemString(main_dict, "trace_unhandled");
366 if (handler && PyCallable_Check(handler)) { 459 if (handler && PyCallable_Check(handler)) {
@@ -368,6 +461,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
368 retval = PyObject_CallObject(handler, t); 461 retval = PyObject_CallObject(handler, t);
369 if (retval == NULL) 462 if (retval == NULL)
370 handler_call_die("trace_unhandled"); 463 handler_call_die("trace_unhandled");
464 Py_DECREF(retval);
371 } 465 }
372 Py_DECREF(dict); 466 Py_DECREF(dict);
373 } 467 }
@@ -380,7 +474,7 @@ static void python_process_general_event(struct perf_sample *sample,
380 struct thread *thread, 474 struct thread *thread,
381 struct addr_location *al) 475 struct addr_location *al)
382{ 476{
383 PyObject *handler, *retval, *t, *dict; 477 PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample;
384 static char handler_name[64]; 478 static char handler_name[64];
385 unsigned n = 0; 479 unsigned n = 0;
386 480
@@ -396,6 +490,10 @@ static void python_process_general_event(struct perf_sample *sample,
396 if (!dict) 490 if (!dict)
397 Py_FatalError("couldn't create Python dictionary"); 491 Py_FatalError("couldn't create Python dictionary");
398 492
493 dict_sample = PyDict_New();
494 if (!dict_sample)
495 Py_FatalError("couldn't create Python dictionary");
496
399 snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); 497 snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
400 498
401 handler = PyDict_GetItemString(main_dict, handler_name); 499 handler = PyDict_GetItemString(main_dict, handler_name);
@@ -405,8 +503,21 @@ static void python_process_general_event(struct perf_sample *sample,
405 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); 503 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
406 pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( 504 pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
407 (const char *)&evsel->attr, sizeof(evsel->attr))); 505 (const char *)&evsel->attr, sizeof(evsel->attr)));
408 pydict_set_item_string_decref(dict, "sample", PyString_FromStringAndSize( 506
409 (const char *)sample, sizeof(*sample))); 507 pydict_set_item_string_decref(dict_sample, "pid",
508 PyInt_FromLong(sample->pid));
509 pydict_set_item_string_decref(dict_sample, "tid",
510 PyInt_FromLong(sample->tid));
511 pydict_set_item_string_decref(dict_sample, "cpu",
512 PyInt_FromLong(sample->cpu));
513 pydict_set_item_string_decref(dict_sample, "ip",
514 PyLong_FromUnsignedLongLong(sample->ip));
515 pydict_set_item_string_decref(dict_sample, "time",
516 PyLong_FromUnsignedLongLong(sample->time));
517 pydict_set_item_string_decref(dict_sample, "period",
518 PyLong_FromUnsignedLongLong(sample->period));
519 pydict_set_item_string_decref(dict, "sample", dict_sample);
520
410 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( 521 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
411 (const char *)sample->raw_data, sample->raw_size)); 522 (const char *)sample->raw_data, sample->raw_size));
412 pydict_set_item_string_decref(dict, "comm", 523 pydict_set_item_string_decref(dict, "comm",
@@ -420,6 +531,10 @@ static void python_process_general_event(struct perf_sample *sample,
420 PyString_FromString(al->sym->name)); 531 PyString_FromString(al->sym->name));
421 } 532 }
422 533
534 /* ip unwinding */
535 callchain = python_process_callchain(sample, evsel, al);
536 pydict_set_item_string_decref(dict, "callchain", callchain);
537
423 PyTuple_SetItem(t, n++, dict); 538 PyTuple_SetItem(t, n++, dict);
424 if (_PyTuple_Resize(&t, n) == -1) 539 if (_PyTuple_Resize(&t, n) == -1)
425 Py_FatalError("error resizing Python tuple"); 540 Py_FatalError("error resizing Python tuple");
@@ -427,6 +542,7 @@ static void python_process_general_event(struct perf_sample *sample,
427 retval = PyObject_CallObject(handler, t); 542 retval = PyObject_CallObject(handler, t);
428 if (retval == NULL) 543 if (retval == NULL)
429 handler_call_die(handler_name); 544 handler_call_die(handler_name);
545 Py_DECREF(retval);
430exit: 546exit:
431 Py_DECREF(dict); 547 Py_DECREF(dict);
432 Py_DECREF(t); 548 Py_DECREF(t);
@@ -548,8 +664,7 @@ static int python_stop_script(void)
548 retval = PyObject_CallObject(handler, NULL); 664 retval = PyObject_CallObject(handler, NULL);
549 if (retval == NULL) 665 if (retval == NULL)
550 handler_call_die("trace_end"); 666 handler_call_die("trace_end");
551 else 667 Py_DECREF(retval);
552 Py_DECREF(retval);
553out: 668out:
554 Py_XDECREF(main_dict); 669 Py_XDECREF(main_dict);
555 Py_XDECREF(main_module); 670 Py_XDECREF(main_module);
@@ -616,6 +731,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
616 fprintf(ofp, "common_nsecs, "); 731 fprintf(ofp, "common_nsecs, ");
617 fprintf(ofp, "common_pid, "); 732 fprintf(ofp, "common_pid, ");
618 fprintf(ofp, "common_comm,\n\t"); 733 fprintf(ofp, "common_comm,\n\t");
734 fprintf(ofp, "common_callchain, ");
619 735
620 not_first = 0; 736 not_first = 0;
621 count = 0; 737 count = 0;
@@ -659,7 +775,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
659 fprintf(ofp, "%%u"); 775 fprintf(ofp, "%%u");
660 } 776 }
661 777
662 fprintf(ofp, "\\n\" %% \\\n\t\t("); 778 fprintf(ofp, "\" %% \\\n\t\t(");
663 779
664 not_first = 0; 780 not_first = 0;
665 count = 0; 781 count = 0;
@@ -695,7 +811,15 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
695 fprintf(ofp, "%s", f->name); 811 fprintf(ofp, "%s", f->name);
696 } 812 }
697 813
698 fprintf(ofp, "),\n\n"); 814 fprintf(ofp, ")\n\n");
815
816 fprintf(ofp, "\t\tfor node in common_callchain:");
817 fprintf(ofp, "\n\t\t\tif 'sym' in node:");
818 fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])");
819 fprintf(ofp, "\n\t\t\telse:");
820 fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n");
821 fprintf(ofp, "\t\tprint \"\\n\"\n\n");
822
699 } 823 }
700 824
701 fprintf(ofp, "def trace_unhandled(event_name, context, " 825 fprintf(ofp, "def trace_unhandled(event_name, context, "
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 64a186edc7be..eac14ce0ae8d 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1083,13 +1083,14 @@ void perf_event_header__bswap(struct perf_event_header *hdr)
1083 1083
1084struct thread *perf_session__findnew(struct perf_session *session, pid_t pid) 1084struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
1085{ 1085{
1086 return machine__findnew_thread(&session->machines.host, 0, pid); 1086 return machine__findnew_thread(&session->machines.host, -1, pid);
1087} 1087}
1088 1088
1089static struct thread *perf_session__register_idle_thread(struct perf_session *session) 1089static struct thread *perf_session__register_idle_thread(struct perf_session *session)
1090{ 1090{
1091 struct thread *thread = perf_session__findnew(session, 0); 1091 struct thread *thread;
1092 1092
1093 thread = machine__findnew_thread(&session->machines.host, 0, 0);
1093 if (thread == NULL || thread__set_comm(thread, "swapper", 0)) { 1094 if (thread == NULL || thread__set_comm(thread, "swapper", 0)) {
1094 pr_err("problem inserting idle task.\n"); 1095 pr_err("problem inserting idle task.\n");
1095 thread = NULL; 1096 thread = NULL;
@@ -1296,8 +1297,10 @@ int __perf_session__process_events(struct perf_session *session,
1296 ui_progress__init(&prog, file_size, "Processing events..."); 1297 ui_progress__init(&prog, file_size, "Processing events...");
1297 1298
1298 mmap_size = MMAP_SIZE; 1299 mmap_size = MMAP_SIZE;
1299 if (mmap_size > file_size) 1300 if (mmap_size > file_size) {
1300 mmap_size = file_size; 1301 mmap_size = file_size;
1302 session->one_mmap = true;
1303 }
1301 1304
1302 memset(mmaps, 0, sizeof(mmaps)); 1305 memset(mmaps, 0, sizeof(mmaps));
1303 1306
@@ -1319,6 +1322,10 @@ remap:
1319 mmaps[map_idx] = buf; 1322 mmaps[map_idx] = buf;
1320 map_idx = (map_idx + 1) & (ARRAY_SIZE(mmaps) - 1); 1323 map_idx = (map_idx + 1) & (ARRAY_SIZE(mmaps) - 1);
1321 file_pos = file_offset + head; 1324 file_pos = file_offset + head;
1325 if (session->one_mmap) {
1326 session->one_mmap_addr = buf;
1327 session->one_mmap_offset = file_offset;
1328 }
1322 1329
1323more: 1330more:
1324 event = fetch_mmaped_event(session, head, mmap_size, buf); 1331 event = fetch_mmaped_event(session, head, mmap_size, buf);
@@ -1364,6 +1371,7 @@ out_err:
1364 ui_progress__finish(); 1371 ui_progress__finish();
1365 perf_session__warn_about_errors(session, tool); 1372 perf_session__warn_about_errors(session, tool);
1366 perf_session_free_sample_buffers(session); 1373 perf_session_free_sample_buffers(session);
1374 session->one_mmap = false;
1367 return err; 1375 return err;
1368} 1376}
1369 1377
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 3140f8ae6148..0321013bd9fd 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -36,6 +36,9 @@ struct perf_session {
36 struct trace_event tevent; 36 struct trace_event tevent;
37 struct events_stats stats; 37 struct events_stats stats;
38 bool repipe; 38 bool repipe;
39 bool one_mmap;
40 void *one_mmap_addr;
41 u64 one_mmap_offset;
39 struct ordered_samples ordered_samples; 42 struct ordered_samples ordered_samples;
40 struct perf_data_file *file; 43 struct perf_data_file *file;
41}; 44};
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 6864661a79dd..cef8f426356e 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -49,7 +49,8 @@ static inline uint8_t elf_sym__type(const GElf_Sym *sym)
49 49
50static inline int elf_sym__is_function(const GElf_Sym *sym) 50static inline int elf_sym__is_function(const GElf_Sym *sym)
51{ 51{
52 return elf_sym__type(sym) == STT_FUNC && 52 return (elf_sym__type(sym) == STT_FUNC ||
53 elf_sym__type(sym) == STT_GNU_IFUNC) &&
53 sym->st_name != 0 && 54 sym->st_name != 0 &&
54 sym->st_shndx != SHN_UNDEF; 55 sym->st_shndx != SHN_UNDEF;
55} 56}
@@ -598,6 +599,8 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
598 goto out_elf_end; 599 goto out_elf_end;
599 } 600 }
600 601
602 ss->is_64_bit = (gelf_getclass(elf) == ELFCLASS64);
603
601 ss->symtab = elf_section_by_name(elf, &ehdr, &ss->symshdr, ".symtab", 604 ss->symtab = elf_section_by_name(elf, &ehdr, &ss->symshdr, ".symtab",
602 NULL); 605 NULL);
603 if (ss->symshdr.sh_type != SHT_SYMTAB) 606 if (ss->symshdr.sh_type != SHT_SYMTAB)
@@ -698,6 +701,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
698 bool remap_kernel = false, adjust_kernel_syms = false; 701 bool remap_kernel = false, adjust_kernel_syms = false;
699 702
700 dso->symtab_type = syms_ss->type; 703 dso->symtab_type = syms_ss->type;
704 dso->is_64_bit = syms_ss->is_64_bit;
701 dso->rel = syms_ss->ehdr.e_type == ET_REL; 705 dso->rel = syms_ss->ehdr.e_type == ET_REL;
702 706
703 /* 707 /*
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index bd15f490d04f..101f55d407d0 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -288,6 +288,23 @@ int dso__synthesize_plt_symbols(struct dso *dso __maybe_unused,
288 return 0; 288 return 0;
289} 289}
290 290
291static int fd__is_64_bit(int fd)
292{
293 u8 e_ident[EI_NIDENT];
294
295 if (lseek(fd, 0, SEEK_SET))
296 return -1;
297
298 if (readn(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident))
299 return -1;
300
301 if (memcmp(e_ident, ELFMAG, SELFMAG) ||
302 e_ident[EI_VERSION] != EV_CURRENT)
303 return -1;
304
305 return e_ident[EI_CLASS] == ELFCLASS64;
306}
307
291int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, 308int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
292 struct symsrc *ss, 309 struct symsrc *ss,
293 struct symsrc *runtime_ss __maybe_unused, 310 struct symsrc *runtime_ss __maybe_unused,
@@ -295,6 +312,11 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
295 int kmodule __maybe_unused) 312 int kmodule __maybe_unused)
296{ 313{
297 unsigned char *build_id[BUILD_ID_SIZE]; 314 unsigned char *build_id[BUILD_ID_SIZE];
315 int ret;
316
317 ret = fd__is_64_bit(ss->fd);
318 if (ret >= 0)
319 dso->is_64_bit = ret;
298 320
299 if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) { 321 if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) {
300 dso__set_build_id(dso, build_id); 322 dso__set_build_id(dso, build_id);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 2e6a2e219eb9..eb06746b06b2 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -342,6 +342,16 @@ static struct symbol *symbols__first(struct rb_root *symbols)
342 return NULL; 342 return NULL;
343} 343}
344 344
345static struct symbol *symbols__next(struct symbol *sym)
346{
347 struct rb_node *n = rb_next(&sym->rb_node);
348
349 if (n)
350 return rb_entry(n, struct symbol, rb_node);
351
352 return NULL;
353}
354
345struct symbol_name_rb_node { 355struct symbol_name_rb_node {
346 struct rb_node rb_node; 356 struct rb_node rb_node;
347 struct symbol sym; 357 struct symbol sym;
@@ -412,11 +422,16 @@ struct symbol *dso__find_symbol(struct dso *dso,
412 return symbols__find(&dso->symbols[type], addr); 422 return symbols__find(&dso->symbols[type], addr);
413} 423}
414 424
415static struct symbol *dso__first_symbol(struct dso *dso, enum map_type type) 425struct symbol *dso__first_symbol(struct dso *dso, enum map_type type)
416{ 426{
417 return symbols__first(&dso->symbols[type]); 427 return symbols__first(&dso->symbols[type]);
418} 428}
419 429
430struct symbol *dso__next_symbol(struct symbol *sym)
431{
432 return symbols__next(sym);
433}
434
420struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 435struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
421 const char *name) 436 const char *name)
422{ 437{
@@ -1065,6 +1080,7 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1065 &is_64_bit); 1080 &is_64_bit);
1066 if (err) 1081 if (err)
1067 goto out_err; 1082 goto out_err;
1083 dso->is_64_bit = is_64_bit;
1068 1084
1069 if (list_empty(&md.maps)) { 1085 if (list_empty(&md.maps)) {
1070 err = -EINVAL; 1086 err = -EINVAL;
@@ -1663,6 +1679,7 @@ do_kallsyms:
1663 free(kallsyms_allocated_filename); 1679 free(kallsyms_allocated_filename);
1664 1680
1665 if (err > 0 && !dso__is_kcore(dso)) { 1681 if (err > 0 && !dso__is_kcore(dso)) {
1682 dso->binary_type = DSO_BINARY_TYPE__KALLSYMS;
1666 dso__set_long_name(dso, "[kernel.kallsyms]", false); 1683 dso__set_long_name(dso, "[kernel.kallsyms]", false);
1667 map__fixup_start(map); 1684 map__fixup_start(map);
1668 map__fixup_end(map); 1685 map__fixup_end(map);
@@ -1710,6 +1727,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1710 if (err > 0) 1727 if (err > 0)
1711 pr_debug("Using %s for symbols\n", kallsyms_filename); 1728 pr_debug("Using %s for symbols\n", kallsyms_filename);
1712 if (err > 0 && !dso__is_kcore(dso)) { 1729 if (err > 0 && !dso__is_kcore(dso)) {
1730 dso->binary_type = DSO_BINARY_TYPE__GUEST_KALLSYMS;
1713 machine__mmap_name(machine, path, sizeof(path)); 1731 machine__mmap_name(machine, path, sizeof(path));
1714 dso__set_long_name(dso, strdup(path), true); 1732 dso__set_long_name(dso, strdup(path), true);
1715 map__fixup_start(map); 1733 map__fixup_start(map);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index a81877b1dee0..ee2d3ccd3ad1 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -216,6 +216,7 @@ struct symsrc {
216 GElf_Shdr dynshdr; 216 GElf_Shdr dynshdr;
217 217
218 bool adjust_symbols; 218 bool adjust_symbols;
219 bool is_64_bit;
219#endif 220#endif
220}; 221};
221 222
@@ -239,6 +240,9 @@ struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,
239struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 240struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
240 const char *name); 241 const char *name);
241 242
243struct symbol *dso__first_symbol(struct dso *dso, enum map_type type);
244struct symbol *dso__next_symbol(struct symbol *sym);
245
242int filename__read_build_id(const char *filename, void *bf, size_t size); 246int filename__read_build_id(const char *filename, void *bf, size_t size);
243int sysfs__read_build_id(const char *filename, void *bf, size_t size); 247int sysfs__read_build_id(const char *filename, void *bf, size_t size);
244int modules__parse(const char *filename, void *arg, 248int modules__parse(const char *filename, void *arg,
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 2fde0d5e40b5..9692c06a9e21 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -13,7 +13,7 @@ int thread__init_map_groups(struct thread *thread, struct machine *machine)
13 struct thread *leader; 13 struct thread *leader;
14 pid_t pid = thread->pid_; 14 pid_t pid = thread->pid_;
15 15
16 if (pid == thread->tid) { 16 if (pid == thread->tid || pid == -1) {
17 thread->mg = map_groups__new(); 17 thread->mg = map_groups__new();
18 } else { 18 } else {
19 leader = machine__findnew_thread(machine, pid, pid); 19 leader = machine__findnew_thread(machine, pid, pid);
@@ -60,8 +60,10 @@ void thread__delete(struct thread *thread)
60{ 60{
61 struct comm *comm, *tmp; 61 struct comm *comm, *tmp;
62 62
63 map_groups__put(thread->mg); 63 if (thread->mg) {
64 thread->mg = NULL; 64 map_groups__put(thread->mg);
65 thread->mg = NULL;
66 }
65 list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) { 67 list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) {
66 list_del(&comm->list); 68 list_del(&comm->list);
67 comm__free(comm); 69 comm__free(comm);
@@ -127,12 +129,12 @@ int thread__comm_len(struct thread *thread)
127size_t thread__fprintf(struct thread *thread, FILE *fp) 129size_t thread__fprintf(struct thread *thread, FILE *fp)
128{ 130{
129 return fprintf(fp, "Thread %d %s\n", thread->tid, thread__comm_str(thread)) + 131 return fprintf(fp, "Thread %d %s\n", thread->tid, thread__comm_str(thread)) +
130 map_groups__fprintf(thread->mg, verbose, fp); 132 map_groups__fprintf(thread->mg, fp);
131} 133}
132 134
133void thread__insert_map(struct thread *thread, struct map *map) 135void thread__insert_map(struct thread *thread, struct map *map)
134{ 136{
135 map_groups__fixup_overlappings(thread->mg, map, verbose, stderr); 137 map_groups__fixup_overlappings(thread->mg, map, stderr);
136 map_groups__insert(thread->mg, map); 138 map_groups__insert(thread->mg, map);
137} 139}
138 140
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index c3bba883f5c3..eb72716017ac 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -40,6 +40,7 @@
40#include "trace-event.h" 40#include "trace-event.h"
41#include <api/fs/debugfs.h> 41#include <api/fs/debugfs.h>
42#include "evsel.h" 42#include "evsel.h"
43#include "debug.h"
43 44
44#define VERSION "0.5" 45#define VERSION "0.5"
45 46
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index e113e180c48f..54d9e9b548a8 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -22,7 +22,6 @@
22#include <stdio.h> 22#include <stdio.h>
23#include <stdlib.h> 23#include <stdlib.h>
24#include <string.h> 24#include <string.h>
25#include <getopt.h>
26#include <stdarg.h> 25#include <stdarg.h>
27#include <sys/types.h> 26#include <sys/types.h>
28#include <sys/stat.h> 27#include <sys/stat.h>
@@ -36,6 +35,7 @@
36#include "../perf.h" 35#include "../perf.h"
37#include "util.h" 36#include "util.h"
38#include "trace-event.h" 37#include "trace-event.h"
38#include "debug.h"
39 39
40static int input_fd; 40static int input_fd;
41 41
diff --git a/tools/perf/util/tsc.c b/tools/perf/util/tsc.c
new file mode 100644
index 000000000000..ef4749836ce9
--- /dev/null
+++ b/tools/perf/util/tsc.c
@@ -0,0 +1,25 @@
1#include <linux/compiler.h>
2#include <linux/types.h>
3
4#include "tsc.h"
5
6u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc)
7{
8 u64 t, quot, rem;
9
10 t = ns - tc->time_zero;
11 quot = t / tc->time_mult;
12 rem = t % tc->time_mult;
13 return (quot << tc->time_shift) +
14 (rem << tc->time_shift) / tc->time_mult;
15}
16
17u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc)
18{
19 u64 quot, rem;
20
21 quot = cyc >> tc->time_shift;
22 rem = cyc & ((1 << tc->time_shift) - 1);
23 return tc->time_zero + quot * tc->time_mult +
24 ((rem * tc->time_mult) >> tc->time_shift);
25}
diff --git a/tools/perf/util/tsc.h b/tools/perf/util/tsc.h
new file mode 100644
index 000000000000..4eca84887c8a
--- /dev/null
+++ b/tools/perf/util/tsc.h
@@ -0,0 +1,11 @@
1#ifndef __PERF_TSC_H
2#define __PERF_TSC_H
3
4#include <linux/types.h>
5
6#include "../arch/x86/util/tsc.h"
7
8u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc);
9u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc);
10
11#endif
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index 5ec80a575b50..7419768c38b1 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -3,6 +3,7 @@
3#include <elfutils/libdwfl.h> 3#include <elfutils/libdwfl.h>
4#include <inttypes.h> 4#include <inttypes.h>
5#include <errno.h> 5#include <errno.h>
6#include "debug.h"
6#include "unwind.h" 7#include "unwind.h"
7#include "unwind-libdw.h" 8#include "unwind-libdw.h"
8#include "machine.h" 9#include "machine.h"
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 25578b98f5c5..92b56db52471 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -30,6 +30,7 @@
30#include "unwind.h" 30#include "unwind.h"
31#include "symbol.h" 31#include "symbol.h"
32#include "util.h" 32#include "util.h"
33#include "debug.h"
33 34
34extern int 35extern int
35UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, 36UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index e4132aeeb780..e52e7461911b 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,5 +1,6 @@
1#include "../perf.h" 1#include "../perf.h"
2#include "util.h" 2#include "util.h"
3#include "debug.h"
3#include <api/fs/fs.h> 4#include <api/fs/fs.h>
4#include <sys/mman.h> 5#include <sys/mman.h>
5#ifdef HAVE_BACKTRACE_SUPPORT 6#ifdef HAVE_BACKTRACE_SUPPORT
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c
index 0ddb3b8a89ec..290582452da3 100644
--- a/tools/perf/util/vdso.c
+++ b/tools/perf/util/vdso.c
@@ -12,6 +12,7 @@
12#include "util.h" 12#include "util.h"
13#include "symbol.h" 13#include "symbol.h"
14#include "linux/string.h" 14#include "linux/string.h"
15#include "debug.h"
15 16
16static bool vdso_found; 17static bool vdso_found;
17static char vdso_file[] = "/tmp/perf-vdso.so-XXXXXX"; 18static char vdso_file[] = "/tmp/perf-vdso.so-XXXXXX";