aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-10-06 03:04:10 -0400
committerIngo Molnar <mingo@kernel.org>2015-10-06 03:04:10 -0400
commit1c748dc2cbbe45d48572e395e11be677fbf7a28c (patch)
treedf5ec1da23e37e944805a4ca37021fdc2a9ac4aa
parente3b0ac1b7a8a590440a2030e7d10d48c59ab8a2a (diff)
parent27bf90bf0690f55c3679bcc4c325823cf1cfd19d (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: - Switch the default callchain output mode to 'graph,0.5,caller', to make it look like the default for other tools, reducing the learning curve for people used to 'caller' based viewing. (Arnaldo Carvalho de Melo) - Implement column based horizontal scrolling in the hists browser (top, report), making it possible to use the TUI for things like 'perf mem report' where there are many more columns than can fit in a terminal. (Arnaldo Carvalho de Melo) - Support sorting by symbol_iaddr with perf.data files produced by 'perf mem record'. (Don Zickus) - Display DATA_SRC sample type bit, i.e. when running 'perf evlist -v' the "DATA_SRC" wasn't appearing when set, fix it to look like: (Jiri Olsa) cpu/mem-loads/pp: ...SNIP... sample_type: IP|TID|TIME|ADDR|CPU|PERIOD|DATA_SRC - Introduce the 'P' event modifier, meaning 'max precision level, please', i.e.: $ perf record -e cycles:P usleep 1 Is now similar to: $ perf record usleep 1 Useful, for instance, when specifying multiple events. (Jiri Olsa) - Make 'perf -v' and 'perf -h' work. (Jiri Olsa) - Fail properly when pattern matching fails to find a tracepoint, i.e. '-e non:existent' was being correctly handled, with a proper error message about that not being a valid event, but '-e non:existent*' wasn't, fix it. (Jiri Olsa) Infrastructure changes: - Separate arch specific entries in 'perf test' and add an 'Intel CQM' one to be fun on x86 only. (Matt Fleming) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/lib/api/fs/fs.c2
-rw-r--r--tools/lib/api/fs/tracing_path.c6
-rw-r--r--tools/perf/Documentation/perf-list.txt1
-rw-r--r--tools/perf/Documentation/perf-report.txt2
-rw-r--r--tools/perf/Documentation/perf.txt8
-rw-r--r--tools/perf/arch/x86/Build2
-rw-r--r--tools/perf/arch/x86/include/arch-tests.h19
-rw-r--r--tools/perf/arch/x86/tests/Build10
-rw-r--r--tools/perf/arch/x86/tests/arch-tests.c34
-rw-r--r--tools/perf/arch/x86/tests/dwarf-unwind.c1
-rw-r--r--tools/perf/arch/x86/tests/gen-insn-x86-dat.awk (renamed from tools/perf/tests/gen-insn-x86-dat.awk)0
-rwxr-xr-xtools/perf/arch/x86/tests/gen-insn-x86-dat.sh (renamed from tools/perf/tests/gen-insn-x86-dat.sh)0
-rw-r--r--tools/perf/arch/x86/tests/insn-x86-dat-32.c (renamed from tools/perf/tests/insn-x86-dat-32.c)0
-rw-r--r--tools/perf/arch/x86/tests/insn-x86-dat-64.c (renamed from tools/perf/tests/insn-x86-dat-64.c)0
-rw-r--r--tools/perf/arch/x86/tests/insn-x86-dat-src.c (renamed from tools/perf/tests/insn-x86-dat-src.c)0
-rw-r--r--tools/perf/arch/x86/tests/insn-x86.c (renamed from tools/perf/tests/insn-x86.c)3
-rw-r--r--tools/perf/arch/x86/tests/intel-cqm.c124
-rw-r--r--tools/perf/arch/x86/tests/perf-time-to-tsc.c (renamed from tools/perf/tests/perf-time-to-tsc.c)4
-rw-r--r--tools/perf/arch/x86/tests/rdpmc.c (renamed from tools/perf/tests/rdpmc.c)7
-rw-r--r--tools/perf/builtin-report.c4
-rw-r--r--tools/perf/perf.c14
-rw-r--r--tools/perf/tests/Build6
-rw-r--r--tools/perf/tests/builtin-test.c56
-rw-r--r--tools/perf/tests/dwarf-unwind.c4
-rw-r--r--tools/perf/tests/parse-events.c16
-rw-r--r--tools/perf/tests/tests.h10
-rw-r--r--tools/perf/ui/browser.c14
-rw-r--r--tools/perf/ui/browser.h2
-rw-r--r--tools/perf/ui/browsers/hists.c22
-rw-r--r--tools/perf/util/annotate.h2
-rw-r--r--tools/perf/util/evlist.c2
-rw-r--r--tools/perf/util/evlist.h2
-rw-r--r--tools/perf/util/evsel.c5
-rw-r--r--tools/perf/util/evsel.h1
-rw-r--r--tools/perf/util/hist.c13
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/parse-events.c17
-rw-r--r--tools/perf/util/parse-events.l2
-rw-r--r--tools/perf/util/sort.c37
-rw-r--r--tools/perf/util/sort.h1
-rw-r--r--tools/perf/util/util.c4
41 files changed, 381 insertions, 77 deletions
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c
index 732dbef588b0..459599d1b6c4 100644
--- a/tools/lib/api/fs/fs.c
+++ b/tools/lib/api/fs/fs.c
@@ -69,7 +69,7 @@ static const char * const tracefs__known_mountpoints[] = {
69struct fs { 69struct fs {
70 const char *name; 70 const char *name;
71 const char * const *mounts; 71 const char * const *mounts;
72 char path[PATH_MAX + 1]; 72 char path[PATH_MAX];
73 bool found; 73 bool found;
74 long magic; 74 long magic;
75}; 75};
diff --git a/tools/lib/api/fs/tracing_path.c b/tools/lib/api/fs/tracing_path.c
index 0406a7d5c891..a26bb5ea8283 100644
--- a/tools/lib/api/fs/tracing_path.c
+++ b/tools/lib/api/fs/tracing_path.c
@@ -12,9 +12,9 @@
12#include "tracing_path.h" 12#include "tracing_path.h"
13 13
14 14
15char tracing_mnt[PATH_MAX + 1] = "/sys/kernel/debug"; 15char tracing_mnt[PATH_MAX] = "/sys/kernel/debug";
16char tracing_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing"; 16char tracing_path[PATH_MAX] = "/sys/kernel/debug/tracing";
17char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events"; 17char tracing_events_path[PATH_MAX] = "/sys/kernel/debug/tracing/events";
18 18
19 19
20static void __tracing_path_set(const char *tracing, const char *mountpoint) 20static void __tracing_path_set(const char *tracing, const char *mountpoint)
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index ad60c6ea1997..79483f40e991 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -30,6 +30,7 @@ counted. The following modifiers exist:
30 G - guest counting (in KVM guests) 30 G - guest counting (in KVM guests)
31 H - host counting (not in KVM guests) 31 H - host counting (not in KVM guests)
32 p - precise level 32 p - precise level
33 P - use maximum detected precise level
33 S - read sample value (PERF_SAMPLE_READ) 34 S - read sample value (PERF_SAMPLE_READ)
34 D - pin the event to the PMU 35 D - pin the event to the PMU
35 36
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index ce499035e6d8..e4fdeeb51123 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -192,7 +192,7 @@ OPTIONS
192 when available. Usually more convenient to use --branch-history 192 when available. Usually more convenient to use --branch-history
193 for this. 193 for this.
194 194
195 Default: fractal,0.5,callee,function. 195 Default: graph,0.5,caller
196 196
197--children:: 197--children::
198 Accumulate callchain of children to parent entry so that then can 198 Accumulate callchain of children to parent entry so that then can
diff --git a/tools/perf/Documentation/perf.txt b/tools/perf/Documentation/perf.txt
index 2b131776363e..864e37597252 100644
--- a/tools/perf/Documentation/perf.txt
+++ b/tools/perf/Documentation/perf.txt
@@ -27,6 +27,14 @@ OPTIONS
27 Setup buildid cache directory. It has higher priority than 27 Setup buildid cache directory. It has higher priority than
28 buildid.dir config file option. 28 buildid.dir config file option.
29 29
30-v::
31--version::
32 Display perf version.
33
34-h::
35--help::
36 Run perf help command.
37
30DESCRIPTION 38DESCRIPTION
31----------- 39-----------
32Performance counters for Linux are a new kernel-based subsystem 40Performance counters for Linux are a new kernel-based subsystem
diff --git a/tools/perf/arch/x86/Build b/tools/perf/arch/x86/Build
index 41bf61da476a..db52fa22d3a1 100644
--- a/tools/perf/arch/x86/Build
+++ b/tools/perf/arch/x86/Build
@@ -1,2 +1,2 @@
1libperf-y += util/ 1libperf-y += util/
2libperf-$(CONFIG_DWARF_UNWIND) += tests/ 2libperf-y += tests/
diff --git a/tools/perf/arch/x86/include/arch-tests.h b/tools/perf/arch/x86/include/arch-tests.h
new file mode 100644
index 000000000000..7ed00f4b0908
--- /dev/null
+++ b/tools/perf/arch/x86/include/arch-tests.h
@@ -0,0 +1,19 @@
1#ifndef ARCH_TESTS_H
2#define ARCH_TESTS_H
3
4/* Tests */
5int test__rdpmc(void);
6int test__perf_time_to_tsc(void);
7int test__insn_x86(void);
8int test__intel_cqm_count_nmi_context(void);
9
10#ifdef HAVE_DWARF_UNWIND_SUPPORT
11struct thread;
12struct perf_sample;
13int test__arch_unwind_sample(struct perf_sample *sample,
14 struct thread *thread);
15#endif
16
17extern struct test arch_tests[];
18
19#endif
diff --git a/tools/perf/arch/x86/tests/Build b/tools/perf/arch/x86/tests/Build
index b30eff9bcc83..cbb7e978166b 100644
--- a/tools/perf/arch/x86/tests/Build
+++ b/tools/perf/arch/x86/tests/Build
@@ -1,2 +1,8 @@
1libperf-y += regs_load.o 1libperf-$(CONFIG_DWARF_UNWIND) += regs_load.o
2libperf-y += dwarf-unwind.o 2libperf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
3
4libperf-y += arch-tests.o
5libperf-y += rdpmc.o
6libperf-y += perf-time-to-tsc.o
7libperf-$(CONFIG_AUXTRACE) += insn-x86.o
8libperf-y += intel-cqm.o
diff --git a/tools/perf/arch/x86/tests/arch-tests.c b/tools/perf/arch/x86/tests/arch-tests.c
new file mode 100644
index 000000000000..2218cb64f840
--- /dev/null
+++ b/tools/perf/arch/x86/tests/arch-tests.c
@@ -0,0 +1,34 @@
1#include <string.h>
2#include "tests/tests.h"
3#include "arch-tests.h"
4
5struct test arch_tests[] = {
6 {
7 .desc = "x86 rdpmc test",
8 .func = test__rdpmc,
9 },
10 {
11 .desc = "Test converting perf time to TSC",
12 .func = test__perf_time_to_tsc,
13 },
14#ifdef HAVE_DWARF_UNWIND_SUPPORT
15 {
16 .desc = "Test dwarf unwind",
17 .func = test__dwarf_unwind,
18 },
19#endif
20#ifdef HAVE_AUXTRACE_SUPPORT
21 {
22 .desc = "Test x86 instruction decoder - new instructions",
23 .func = test__insn_x86,
24 },
25#endif
26 {
27 .desc = "Test intel cqm nmi context read",
28 .func = test__intel_cqm_count_nmi_context,
29 },
30 {
31 .func = NULL,
32 },
33
34};
diff --git a/tools/perf/arch/x86/tests/dwarf-unwind.c b/tools/perf/arch/x86/tests/dwarf-unwind.c
index d8bbf7ad1681..7f209ce827bf 100644
--- a/tools/perf/arch/x86/tests/dwarf-unwind.c
+++ b/tools/perf/arch/x86/tests/dwarf-unwind.c
@@ -5,6 +5,7 @@
5#include "event.h" 5#include "event.h"
6#include "debug.h" 6#include "debug.h"
7#include "tests/tests.h" 7#include "tests/tests.h"
8#include "arch-tests.h"
8 9
9#define STACK_SIZE 8192 10#define STACK_SIZE 8192
10 11
diff --git a/tools/perf/tests/gen-insn-x86-dat.awk b/tools/perf/arch/x86/tests/gen-insn-x86-dat.awk
index a21454835cd4..a21454835cd4 100644
--- a/tools/perf/tests/gen-insn-x86-dat.awk
+++ b/tools/perf/arch/x86/tests/gen-insn-x86-dat.awk
diff --git a/tools/perf/tests/gen-insn-x86-dat.sh b/tools/perf/arch/x86/tests/gen-insn-x86-dat.sh
index 2d4ef94cff98..2d4ef94cff98 100755
--- a/tools/perf/tests/gen-insn-x86-dat.sh
+++ b/tools/perf/arch/x86/tests/gen-insn-x86-dat.sh
diff --git a/tools/perf/tests/insn-x86-dat-32.c b/tools/perf/arch/x86/tests/insn-x86-dat-32.c
index 3b491cfe204e..3b491cfe204e 100644
--- a/tools/perf/tests/insn-x86-dat-32.c
+++ b/tools/perf/arch/x86/tests/insn-x86-dat-32.c
diff --git a/tools/perf/tests/insn-x86-dat-64.c b/tools/perf/arch/x86/tests/insn-x86-dat-64.c
index 4fe7cce179c4..4fe7cce179c4 100644
--- a/tools/perf/tests/insn-x86-dat-64.c
+++ b/tools/perf/arch/x86/tests/insn-x86-dat-64.c
diff --git a/tools/perf/tests/insn-x86-dat-src.c b/tools/perf/arch/x86/tests/insn-x86-dat-src.c
index 41b1b1c62660..41b1b1c62660 100644
--- a/tools/perf/tests/insn-x86-dat-src.c
+++ b/tools/perf/arch/x86/tests/insn-x86-dat-src.c
diff --git a/tools/perf/tests/insn-x86.c b/tools/perf/arch/x86/tests/insn-x86.c
index 5c49eec81349..b6115dfd28f0 100644
--- a/tools/perf/tests/insn-x86.c
+++ b/tools/perf/arch/x86/tests/insn-x86.c
@@ -1,7 +1,8 @@
1#include <linux/types.h> 1#include <linux/types.h>
2 2
3#include "debug.h" 3#include "debug.h"
4#include "tests.h" 4#include "tests/tests.h"
5#include "arch-tests.h"
5 6
6#include "intel-pt-decoder/insn.h" 7#include "intel-pt-decoder/insn.h"
7#include "intel-pt-decoder/intel-pt-insn-decoder.h" 8#include "intel-pt-decoder/intel-pt-insn-decoder.h"
diff --git a/tools/perf/arch/x86/tests/intel-cqm.c b/tools/perf/arch/x86/tests/intel-cqm.c
new file mode 100644
index 000000000000..d28c1b6a3b54
--- /dev/null
+++ b/tools/perf/arch/x86/tests/intel-cqm.c
@@ -0,0 +1,124 @@
1#include "tests/tests.h"
2#include "perf.h"
3#include "cloexec.h"
4#include "debug.h"
5#include "evlist.h"
6#include "evsel.h"
7#include "arch-tests.h"
8
9#include <sys/mman.h>
10#include <string.h>
11
12static pid_t spawn(void)
13{
14 pid_t pid;
15
16 pid = fork();
17 if (pid)
18 return pid;
19
20 while(1);
21 sleep(5);
22 return 0;
23}
24
25/*
26 * Create an event group that contains both a sampled hardware
27 * (cpu-cycles) and software (intel_cqm/llc_occupancy/) event. We then
28 * wait for the hardware perf counter to overflow and generate a PMI,
29 * which triggers an event read for both of the events in the group.
30 *
31 * Since reading Intel CQM event counters requires sending SMP IPIs, the
32 * CQM pmu needs to handle the above situation gracefully, and return
33 * the last read counter value to avoid triggering a WARN_ON_ONCE() in
34 * smp_call_function_many() caused by sending IPIs from NMI context.
35 */
36int test__intel_cqm_count_nmi_context(void)
37{
38 struct perf_evlist *evlist = NULL;
39 struct perf_evsel *evsel = NULL;
40 struct perf_event_attr pe;
41 int i, fd[2], flag, ret;
42 size_t mmap_len;
43 void *event;
44 pid_t pid;
45 int err = TEST_FAIL;
46
47 flag = perf_event_open_cloexec_flag();
48
49 evlist = perf_evlist__new();
50 if (!evlist) {
51 pr_debug("perf_evlist__new failed\n");
52 return TEST_FAIL;
53 }
54
55 ret = parse_events(evlist, "intel_cqm/llc_occupancy/", NULL);
56 if (ret) {
57 pr_debug("parse_events failed\n");
58 err = TEST_SKIP;
59 goto out;
60 }
61
62 evsel = perf_evlist__first(evlist);
63 if (!evsel) {
64 pr_debug("perf_evlist__first failed\n");
65 goto out;
66 }
67
68 memset(&pe, 0, sizeof(pe));
69 pe.size = sizeof(pe);
70
71 pe.type = PERF_TYPE_HARDWARE;
72 pe.config = PERF_COUNT_HW_CPU_CYCLES;
73 pe.read_format = PERF_FORMAT_GROUP;
74
75 pe.sample_period = 128;
76 pe.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_READ;
77
78 pid = spawn();
79
80 fd[0] = sys_perf_event_open(&pe, pid, -1, -1, flag);
81 if (fd[0] < 0) {
82 pr_debug("failed to open event\n");
83 goto out;
84 }
85
86 memset(&pe, 0, sizeof(pe));
87 pe.size = sizeof(pe);
88
89 pe.type = evsel->attr.type;
90 pe.config = evsel->attr.config;
91
92 fd[1] = sys_perf_event_open(&pe, pid, -1, fd[0], flag);
93 if (fd[1] < 0) {
94 pr_debug("failed to open event\n");
95 goto out;
96 }
97
98 /*
99 * Pick a power-of-two number of pages + 1 for the meta-data
100 * page (struct perf_event_mmap_page). See tools/perf/design.txt.
101 */
102 mmap_len = page_size * 65;
103
104 event = mmap(NULL, mmap_len, PROT_READ, MAP_SHARED, fd[0], 0);
105 if (event == (void *)(-1)) {
106 pr_debug("failed to mmap %d\n", errno);
107 goto out;
108 }
109
110 sleep(1);
111
112 err = TEST_OK;
113
114 munmap(event, mmap_len);
115
116 for (i = 0; i < 2; i++)
117 close(fd[i]);
118
119 kill(pid, SIGKILL);
120 wait(NULL);
121out:
122 perf_evlist__delete(evlist);
123 return err;
124}
diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
index 5f49484f1abc..658cd200af74 100644
--- a/tools/perf/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -9,7 +9,9 @@
9#include "thread_map.h" 9#include "thread_map.h"
10#include "cpumap.h" 10#include "cpumap.h"
11#include "tsc.h" 11#include "tsc.h"
12#include "tests.h" 12#include "tests/tests.h"
13
14#include "arch-tests.h"
13 15
14#define CHECK__(x) { \ 16#define CHECK__(x) { \
15 while ((x) < 0) { \ 17 while ((x) < 0) { \
diff --git a/tools/perf/tests/rdpmc.c b/tools/perf/arch/x86/tests/rdpmc.c
index d31f2c4d9f64..e7688214c7cf 100644
--- a/tools/perf/tests/rdpmc.c
+++ b/tools/perf/arch/x86/tests/rdpmc.c
@@ -5,10 +5,9 @@
5#include <linux/types.h> 5#include <linux/types.h>
6#include "perf.h" 6#include "perf.h"
7#include "debug.h" 7#include "debug.h"
8#include "tests.h" 8#include "tests/tests.h"
9#include "cloexec.h" 9#include "cloexec.h"
10 10#include "arch-tests.h"
11#if defined(__x86_64__) || defined(__i386__)
12 11
13static u64 rdpmc(unsigned int counter) 12static u64 rdpmc(unsigned int counter)
14{ 13{
@@ -173,5 +172,3 @@ int test__rdpmc(void)
173 172
174 return 0; 173 return 0;
175} 174}
176
177#endif
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index b5623639f67d..3b23b25d1589 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -633,7 +633,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
633 bool has_br_stack = false; 633 bool has_br_stack = false;
634 int branch_mode = -1; 634 int branch_mode = -1;
635 bool branch_call_mode = false; 635 bool branch_call_mode = false;
636 char callchain_default_opt[] = "fractal,0.5,callee"; 636 char callchain_default_opt[] = "graph,0.5,caller";
637 const char * const report_usage[] = { 637 const char * const report_usage[] = {
638 "perf report [<options>]", 638 "perf report [<options>]",
639 NULL 639 NULL
@@ -701,7 +701,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
701 "Only display entries with parent-match"), 701 "Only display entries with parent-match"),
702 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order[,branch]", 702 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order[,branch]",
703 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address), add branches. " 703 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address), add branches. "
704 "Default: fractal,0.5,callee,function", &report_parse_callchain_opt, callchain_default_opt), 704 "Default: graph,0.5,caller", &report_parse_callchain_opt, callchain_default_opt),
705 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, 705 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
706 "Accumulate callchains of children and show total overhead as well"), 706 "Accumulate callchains of children and show total overhead as well"),
707 OPT_INTEGER(0, "max-stack", &report.max_stack, 707 OPT_INTEGER(0, "max-stack", &report.max_stack,
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 1fded922bcc8..543713422d14 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -162,6 +162,20 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
162 break; 162 break;
163 163
164 /* 164 /*
165 * Shortcut for '-h' and '-v' options to invoke help
166 * and version command.
167 */
168 if (!strcmp(cmd, "-h")) {
169 (*argv)[0] = "--help";
170 break;
171 }
172
173 if (!strcmp(cmd, "-v")) {
174 (*argv)[0] = "--version";
175 break;
176 }
177
178 /*
165 * Check remaining flags. 179 * Check remaining flags.
166 */ 180 */
167 if (!prefixcmp(cmd, CMD_EXEC_PATH)) { 181 if (!prefixcmp(cmd, CMD_EXEC_PATH)) {
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index c6f198ae65fb..50de2253cff6 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -8,7 +8,6 @@ perf-y += openat-syscall-all-cpus.o
8perf-y += openat-syscall-tp-fields.o 8perf-y += openat-syscall-tp-fields.o
9perf-y += mmap-basic.o 9perf-y += mmap-basic.o
10perf-y += perf-record.o 10perf-y += perf-record.o
11perf-y += rdpmc.o
12perf-y += evsel-roundtrip-name.o 11perf-y += evsel-roundtrip-name.o
13perf-y += evsel-tp-sched.o 12perf-y += evsel-tp-sched.o
14perf-y += fdarray.o 13perf-y += fdarray.o
@@ -35,11 +34,6 @@ perf-y += thread-map.o
35perf-y += llvm.o 34perf-y += llvm.o
36perf-y += topology.o 35perf-y += topology.o
37 36
38perf-$(CONFIG_X86) += perf-time-to-tsc.o
39ifdef CONFIG_AUXTRACE
40perf-$(CONFIG_X86) += insn-x86.o
41endif
42
43ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64)) 37ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64))
44perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o 38perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
45endif 39endif
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index d9bf51dc8cf5..66f72d3d6677 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -14,10 +14,13 @@
14#include "parse-options.h" 14#include "parse-options.h"
15#include "symbol.h" 15#include "symbol.h"
16 16
17static struct test { 17struct test __weak arch_tests[] = {
18 const char *desc; 18 {
19 int (*func)(void); 19 .func = NULL,
20} tests[] = { 20 },
21};
22
23static struct test generic_tests[] = {
21 { 24 {
22 .desc = "vmlinux symtab matches kallsyms", 25 .desc = "vmlinux symtab matches kallsyms",
23 .func = test__vmlinux_matches_kallsyms, 26 .func = test__vmlinux_matches_kallsyms,
@@ -38,12 +41,6 @@ static struct test {
38 .desc = "parse events tests", 41 .desc = "parse events tests",
39 .func = test__parse_events, 42 .func = test__parse_events,
40 }, 43 },
41#if defined(__x86_64__) || defined(__i386__)
42 {
43 .desc = "x86 rdpmc test",
44 .func = test__rdpmc,
45 },
46#endif
47 { 44 {
48 .desc = "Validate PERF_RECORD_* events & perf_sample fields", 45 .desc = "Validate PERF_RECORD_* events & perf_sample fields",
49 .func = test__PERF_RECORD, 46 .func = test__PERF_RECORD,
@@ -104,12 +101,6 @@ static struct test {
104 .desc = "Test software clock events have valid period values", 101 .desc = "Test software clock events have valid period values",
105 .func = test__sw_clock_freq, 102 .func = test__sw_clock_freq,
106 }, 103 },
107#if defined(__x86_64__) || defined(__i386__)
108 {
109 .desc = "Test converting perf time to TSC",
110 .func = test__perf_time_to_tsc,
111 },
112#endif
113 { 104 {
114 .desc = "Test object code reading", 105 .desc = "Test object code reading",
115 .func = test__code_reading, 106 .func = test__code_reading,
@@ -126,14 +117,6 @@ static struct test {
126 .desc = "Test parsing with no sample_id_all bit set", 117 .desc = "Test parsing with no sample_id_all bit set",
127 .func = test__parse_no_sample_id_all, 118 .func = test__parse_no_sample_id_all,
128 }, 119 },
129#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)
130#ifdef HAVE_DWARF_UNWIND_SUPPORT
131 {
132 .desc = "Test dwarf unwind",
133 .func = test__dwarf_unwind,
134 },
135#endif
136#endif
137 { 120 {
138 .desc = "Test filtering hist entries", 121 .desc = "Test filtering hist entries",
139 .func = test__hists_filter, 122 .func = test__hists_filter,
@@ -178,14 +161,6 @@ static struct test {
178 .desc = "Test LLVM searching and compiling", 161 .desc = "Test LLVM searching and compiling",
179 .func = test__llvm, 162 .func = test__llvm,
180 }, 163 },
181#ifdef HAVE_AUXTRACE_SUPPORT
182#if defined(__x86_64__) || defined(__i386__)
183 {
184 .desc = "Test x86 instruction decoder - new instructions",
185 .func = test__insn_x86,
186 },
187#endif
188#endif
189 { 164 {
190 .desc = "Test topology in session", 165 .desc = "Test topology in session",
191 .func = test_session_topology, 166 .func = test_session_topology,
@@ -195,6 +170,11 @@ static struct test {
195 }, 170 },
196}; 171};
197 172
173static struct test *tests[] = {
174 generic_tests,
175 arch_tests,
176};
177
198static bool perf_test__matches(struct test *test, int curr, int argc, const char *argv[]) 178static bool perf_test__matches(struct test *test, int curr, int argc, const char *argv[])
199{ 179{
200 int i; 180 int i;
@@ -249,22 +229,25 @@ static int run_test(struct test *test)
249 return err; 229 return err;
250} 230}
251 231
252#define for_each_test(t) for (t = &tests[0]; t->func; t++) 232#define for_each_test(j, t) \
233 for (j = 0; j < ARRAY_SIZE(tests); j++) \
234 for (t = &tests[j][0]; t->func; t++)
253 235
254static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) 236static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
255{ 237{
256 struct test *t; 238 struct test *t;
239 unsigned int j;
257 int i = 0; 240 int i = 0;
258 int width = 0; 241 int width = 0;
259 242
260 for_each_test(t) { 243 for_each_test(j, t) {
261 int len = strlen(t->desc); 244 int len = strlen(t->desc);
262 245
263 if (width < len) 246 if (width < len)
264 width = len; 247 width = len;
265 } 248 }
266 249
267 for_each_test(t) { 250 for_each_test(j, t) {
268 int curr = i++, err; 251 int curr = i++, err;
269 252
270 if (!perf_test__matches(t, curr, argc, argv)) 253 if (!perf_test__matches(t, curr, argc, argv))
@@ -300,10 +283,11 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
300 283
301static int perf_test__list(int argc, const char **argv) 284static int perf_test__list(int argc, const char **argv)
302{ 285{
286 unsigned int j;
303 struct test *t; 287 struct test *t;
304 int i = 0; 288 int i = 0;
305 289
306 for_each_test(t) { 290 for_each_test(j, t) {
307 if (argc > 1 && !strstr(t->desc, argv[1])) 291 if (argc > 1 && !strstr(t->desc, argv[1]))
308 continue; 292 continue;
309 293
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 40b36c462427..07221793a3ac 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -11,6 +11,10 @@
11#include "thread.h" 11#include "thread.h"
12#include "callchain.h" 12#include "callchain.h"
13 13
14#if defined (__x86_64__) || defined (__i386__)
15#include "arch-tests.h"
16#endif
17
14/* For bsearch. We try to unwind functions in shared object. */ 18/* For bsearch. We try to unwind functions in shared object. */
15#include <stdlib.h> 19#include <stdlib.h>
16 20
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 3a2ebe666192..0648b84a9171 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -1259,6 +1259,17 @@ test__checkevent_breakpoint_len_rw_modifier(struct perf_evlist *evlist)
1259 return test__checkevent_breakpoint_rw(evlist); 1259 return test__checkevent_breakpoint_rw(evlist);
1260} 1260}
1261 1261
1262static int test__checkevent_precise_max_modifier(struct perf_evlist *evlist)
1263{
1264 struct perf_evsel *evsel = perf_evlist__first(evlist);
1265
1266 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
1267 TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type);
1268 TEST_ASSERT_VAL("wrong config",
1269 PERF_COUNT_SW_TASK_CLOCK == evsel->attr.config);
1270 return 0;
1271}
1272
1262static int count_tracepoints(void) 1273static int count_tracepoints(void)
1263{ 1274{
1264 struct dirent *events_ent; 1275 struct dirent *events_ent;
@@ -1562,6 +1573,11 @@ static struct evlist_test test__events[] = {
1562 .check = test__checkevent_exclude_idle_modifier_1, 1573 .check = test__checkevent_exclude_idle_modifier_1,
1563 .id = 46, 1574 .id = 46,
1564 }, 1575 },
1576 {
1577 .name = "task-clock:P,cycles",
1578 .check = test__checkevent_precise_max_modifier,
1579 .id = 47,
1580 },
1565}; 1581};
1566 1582
1567static struct evlist_test test__events_pmu[] = { 1583static struct evlist_test test__events_pmu[] = {
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 0b3549672c16..c80486969f83 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -24,13 +24,17 @@ enum {
24 TEST_SKIP = -2, 24 TEST_SKIP = -2,
25}; 25};
26 26
27struct test {
28 const char *desc;
29 int (*func)(void);
30};
31
27/* Tests */ 32/* Tests */
28int test__vmlinux_matches_kallsyms(void); 33int test__vmlinux_matches_kallsyms(void);
29int test__openat_syscall_event(void); 34int test__openat_syscall_event(void);
30int test__openat_syscall_event_on_all_cpus(void); 35int test__openat_syscall_event_on_all_cpus(void);
31int test__basic_mmap(void); 36int test__basic_mmap(void);
32int test__PERF_RECORD(void); 37int test__PERF_RECORD(void);
33int test__rdpmc(void);
34int test__perf_evsel__roundtrip_name_test(void); 38int test__perf_evsel__roundtrip_name_test(void);
35int test__perf_evsel__tp_sched_test(void); 39int test__perf_evsel__tp_sched_test(void);
36int test__syscall_openat_tp_fields(void); 40int test__syscall_openat_tp_fields(void);
@@ -46,7 +50,6 @@ int test__bp_signal(void);
46int test__bp_signal_overflow(void); 50int test__bp_signal_overflow(void);
47int test__task_exit(void); 51int test__task_exit(void);
48int test__sw_clock_freq(void); 52int test__sw_clock_freq(void);
49int test__perf_time_to_tsc(void);
50int test__code_reading(void); 53int test__code_reading(void);
51int test__sample_parsing(void); 54int test__sample_parsing(void);
52int test__keep_tracking(void); 55int test__keep_tracking(void);
@@ -63,10 +66,9 @@ int test__fdarray__add(void);
63int test__kmod_path__parse(void); 66int test__kmod_path__parse(void);
64int test__thread_map(void); 67int test__thread_map(void);
65int test__llvm(void); 68int test__llvm(void);
66int test__insn_x86(void);
67int test_session_topology(void); 69int test_session_topology(void);
68 70
69#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__) 71#if defined(__arm__) || defined(__aarch64__)
70#ifdef HAVE_DWARF_UNWIND_SUPPORT 72#ifdef HAVE_DWARF_UNWIND_SUPPORT
71struct thread; 73struct thread;
72struct perf_sample; 74struct perf_sample;
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index c6c7e5189214..e9703c0829f1 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -393,6 +393,7 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs)
393 393
394 if (browser->use_navkeypressed && !browser->navkeypressed) { 394 if (browser->use_navkeypressed && !browser->navkeypressed) {
395 if (key == K_DOWN || key == K_UP || 395 if (key == K_DOWN || key == K_UP ||
396 (browser->columns && (key == K_LEFT || key == K_RIGHT)) ||
396 key == K_PGDN || key == K_PGUP || 397 key == K_PGDN || key == K_PGUP ||
397 key == K_HOME || key == K_END || 398 key == K_HOME || key == K_END ||
398 key == ' ') { 399 key == ' ') {
@@ -421,6 +422,18 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs)
421 browser->seek(browser, -1, SEEK_CUR); 422 browser->seek(browser, -1, SEEK_CUR);
422 } 423 }
423 break; 424 break;
425 case K_RIGHT:
426 if (!browser->columns)
427 goto out;
428 if (browser->horiz_scroll < browser->columns - 1)
429 ++browser->horiz_scroll;
430 break;
431 case K_LEFT:
432 if (!browser->columns)
433 goto out;
434 if (browser->horiz_scroll != 0)
435 --browser->horiz_scroll;
436 break;
424 case K_PGDN: 437 case K_PGDN:
425 case ' ': 438 case ' ':
426 if (browser->top_idx + browser->rows > browser->nr_entries - 1) 439 if (browser->top_idx + browser->rows > browser->nr_entries - 1)
@@ -459,6 +472,7 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs)
459 browser->seek(browser, -offset, SEEK_END); 472 browser->seek(browser, -offset, SEEK_END);
460 break; 473 break;
461 default: 474 default:
475 out:
462 return key; 476 return key;
463 } 477 }
464 } 478 }
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index f3cef564de02..01781de59532 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -14,7 +14,7 @@
14struct ui_browser { 14struct ui_browser {
15 u64 index, top_idx; 15 u64 index, top_idx;
16 void *top, *entries; 16 void *top, *entries;
17 u16 y, x, width, height, rows; 17 u16 y, x, width, height, rows, columns, horiz_scroll;
18 int current_color; 18 int current_color;
19 void *priv; 19 void *priv;
20 const char *title; 20 const char *title;
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index a4e9b370c037..9b7346a881cf 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -784,11 +784,12 @@ static int hist_browser__show_entry(struct hist_browser *browser,
784 .size = sizeof(s), 784 .size = sizeof(s),
785 .ptr = &arg, 785 .ptr = &arg,
786 }; 786 };
787 int column = 0;
787 788
788 hist_browser__gotorc(browser, row, 0); 789 hist_browser__gotorc(browser, row, 0);
789 790
790 perf_hpp__for_each_format(fmt) { 791 perf_hpp__for_each_format(fmt) {
791 if (perf_hpp__should_skip(fmt)) 792 if (perf_hpp__should_skip(fmt) || column++ < browser->b.horiz_scroll)
792 continue; 793 continue;
793 794
794 if (current_entry && browser->b.navkeypressed) { 795 if (current_entry && browser->b.navkeypressed) {
@@ -861,14 +862,16 @@ static int advance_hpp_check(struct perf_hpp *hpp, int inc)
861 return hpp->size <= 0; 862 return hpp->size <= 0;
862} 863}
863 864
864static int hists__scnprintf_headers(char *buf, size_t size, struct hists *hists) 865static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *buf, size_t size)
865{ 866{
867 struct hists *hists = browser->hists;
866 struct perf_hpp dummy_hpp = { 868 struct perf_hpp dummy_hpp = {
867 .buf = buf, 869 .buf = buf,
868 .size = size, 870 .size = size,
869 }; 871 };
870 struct perf_hpp_fmt *fmt; 872 struct perf_hpp_fmt *fmt;
871 size_t ret = 0; 873 size_t ret = 0;
874 int column = 0;
872 875
873 if (symbol_conf.use_callchain) { 876 if (symbol_conf.use_callchain) {
874 ret = scnprintf(buf, size, " "); 877 ret = scnprintf(buf, size, " ");
@@ -877,7 +880,7 @@ static int hists__scnprintf_headers(char *buf, size_t size, struct hists *hists)
877 } 880 }
878 881
879 perf_hpp__for_each_format(fmt) { 882 perf_hpp__for_each_format(fmt) {
880 if (perf_hpp__should_skip(fmt)) 883 if (perf_hpp__should_skip(fmt) || column++ < browser->b.horiz_scroll)
881 continue; 884 continue;
882 885
883 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 886 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
@@ -896,7 +899,7 @@ static void hist_browser__show_headers(struct hist_browser *browser)
896{ 899{
897 char headers[1024]; 900 char headers[1024];
898 901
899 hists__scnprintf_headers(headers, sizeof(headers), browser->hists); 902 hists_browser__scnprintf_headers(browser, headers, sizeof(headers));
900 ui_browser__gotorc(&browser->b, 0, 0); 903 ui_browser__gotorc(&browser->b, 0, 0);
901 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); 904 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT);
902 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); 905 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1);
@@ -1806,8 +1809,17 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1806 memset(options, 0, sizeof(options)); 1809 memset(options, 0, sizeof(options));
1807 memset(actions, 0, sizeof(actions)); 1810 memset(actions, 0, sizeof(actions));
1808 1811
1809 perf_hpp__for_each_format(fmt) 1812 perf_hpp__for_each_format(fmt) {
1810 perf_hpp__reset_width(fmt, hists); 1813 perf_hpp__reset_width(fmt, hists);
1814 /*
1815 * This is done just once, and activates the horizontal scrolling
1816 * code in the ui_browser code, it would be better to have a the
1817 * counter in the perf_hpp code, but I couldn't find doing it here
1818 * works, FIXME by setting this in hist_browser__new, for now, be
1819 * clever 8-)
1820 */
1821 ++browser->b.columns;
1822 }
1811 1823
1812 if (symbol_conf.col_width_list_str) 1824 if (symbol_conf.col_width_list_str)
1813 perf_hpp__set_user_width(symbol_conf.col_width_list_str); 1825 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index e9996092a093..cea323d9ee7e 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -122,7 +122,7 @@ struct annotated_source {
122 struct list_head source; 122 struct list_head source;
123 struct source_line *lines; 123 struct source_line *lines;
124 int nr_histograms; 124 int nr_histograms;
125 int sizeof_sym_hist; 125 size_t sizeof_sym_hist;
126 struct cyc_hist *cycles_hist; 126 struct cyc_hist *cycles_hist;
127 struct sym_hist histograms[0]; 127 struct sym_hist histograms[0];
128}; 128};
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index e7e195d867ea..d1392194a9a9 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -205,7 +205,7 @@ void perf_evlist__set_leader(struct perf_evlist *evlist)
205 } 205 }
206} 206}
207 207
208static void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr) 208void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr)
209{ 209{
210 attr->precise_ip = 3; 210 attr->precise_ip = 3;
211 211
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 66bc9d4c0869..a459fe71b452 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -290,4 +290,6 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
290 290
291void perf_evlist__set_tracking_event(struct perf_evlist *evlist, 291void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
292 struct perf_evsel *tracking_evsel); 292 struct perf_evsel *tracking_evsel);
293
294void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr);
293#endif /* __PERF_EVLIST_H */ 295#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 58890044d835..8be867ccefe9 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -882,6 +882,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
882 attr->clockid = opts->clockid; 882 attr->clockid = opts->clockid;
883 } 883 }
884 884
885 if (evsel->precise_max)
886 perf_event_attr__set_max_precise_ip(attr);
887
885 /* 888 /*
886 * Apply event specific term settings, 889 * Apply event specific term settings,
887 * it overloads any global configuration. 890 * it overloads any global configuration.
@@ -1178,7 +1181,7 @@ static void __p_sample_type(char *buf, size_t size, u64 value)
1178 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), 1181 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
1179 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), 1182 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
1180 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), 1183 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
1181 bit_name(IDENTIFIER), bit_name(REGS_INTR), 1184 bit_name(IDENTIFIER), bit_name(REGS_INTR), bit_name(DATA_SRC),
1182 { .name = NULL, } 1185 { .name = NULL, }
1183 }; 1186 };
1184#undef bit_name 1187#undef bit_name
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 7906666580da..02a5fed8d924 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -111,6 +111,7 @@ struct perf_evsel {
111 bool system_wide; 111 bool system_wide;
112 bool tracking; 112 bool tracking;
113 bool per_pkg; 113 bool per_pkg;
114 bool precise_max;
114 /* parse modifier helper */ 115 /* parse modifier helper */
115 int exclude_GH; 116 int exclude_GH;
116 int nr_members; 117 int nr_members;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index c346b331b892..4fd37d6708cb 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -132,6 +132,18 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
132 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, 132 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
133 symlen); 133 symlen);
134 } 134 }
135
136 if (h->mem_info->iaddr.sym) {
137 symlen = (int)h->mem_info->iaddr.sym->namelen + 4
138 + unresolved_col_width + 2;
139 hists__new_col_len(hists, HISTC_MEM_IADDR_SYMBOL,
140 symlen);
141 } else {
142 symlen = unresolved_col_width + 4 + 2;
143 hists__new_col_len(hists, HISTC_MEM_IADDR_SYMBOL,
144 symlen);
145 }
146
135 if (h->mem_info->daddr.map) { 147 if (h->mem_info->daddr.map) {
136 symlen = dso__name_len(h->mem_info->daddr.map->dso); 148 symlen = dso__name_len(h->mem_info->daddr.map->dso);
137 hists__new_col_len(hists, HISTC_MEM_DADDR_DSO, 149 hists__new_col_len(hists, HISTC_MEM_DADDR_DSO,
@@ -143,6 +155,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
143 } else { 155 } else {
144 symlen = unresolved_col_width + 4 + 2; 156 symlen = unresolved_col_width + 4 + 2;
145 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen); 157 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen);
158 hists__new_col_len(hists, HISTC_MEM_IADDR_SYMBOL, symlen);
146 hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO); 159 hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
147 } 160 }
148 161
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 8c20a8f6b214..a48a2078d288 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -49,6 +49,7 @@ enum hist_column {
49 HISTC_MEM_LVL, 49 HISTC_MEM_LVL,
50 HISTC_MEM_SNOOP, 50 HISTC_MEM_SNOOP,
51 HISTC_MEM_DCACHELINE, 51 HISTC_MEM_DCACHELINE,
52 HISTC_MEM_IADDR_SYMBOL,
52 HISTC_TRANSACTION, 53 HISTC_TRANSACTION,
53 HISTC_CYCLES, 54 HISTC_CYCLES,
54 HISTC_NR_COLS, /* Last entry */ 55 HISTC_NR_COLS, /* Last entry */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 5d0cfce2599b..991bbd469bea 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -449,7 +449,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
449 char evt_path[MAXPATHLEN]; 449 char evt_path[MAXPATHLEN];
450 struct dirent *evt_ent; 450 struct dirent *evt_ent;
451 DIR *evt_dir; 451 DIR *evt_dir;
452 int ret = 0; 452 int ret = 0, found = 0;
453 453
454 snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name); 454 snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
455 evt_dir = opendir(evt_path); 455 evt_dir = opendir(evt_path);
@@ -468,10 +468,17 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
468 if (!strglobmatch(evt_ent->d_name, evt_name)) 468 if (!strglobmatch(evt_ent->d_name, evt_name))
469 continue; 469 continue;
470 470
471 found++;
472
471 ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name, 473 ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name,
472 err, head_config); 474 err, head_config);
473 } 475 }
474 476
477 if (!found) {
478 tracepoint_error(err, ENOENT, sys_name, evt_name);
479 ret = -1;
480 }
481
475 closedir(evt_dir); 482 closedir(evt_dir);
476 return ret; 483 return ret;
477} 484}
@@ -923,6 +930,7 @@ struct event_modifier {
923 int eG; 930 int eG;
924 int eI; 931 int eI;
925 int precise; 932 int precise;
933 int precise_max;
926 int exclude_GH; 934 int exclude_GH;
927 int sample_read; 935 int sample_read;
928 int pinned; 936 int pinned;
@@ -938,6 +946,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
938 int eG = evsel ? evsel->attr.exclude_guest : 0; 946 int eG = evsel ? evsel->attr.exclude_guest : 0;
939 int eI = evsel ? evsel->attr.exclude_idle : 0; 947 int eI = evsel ? evsel->attr.exclude_idle : 0;
940 int precise = evsel ? evsel->attr.precise_ip : 0; 948 int precise = evsel ? evsel->attr.precise_ip : 0;
949 int precise_max = 0;
941 int sample_read = 0; 950 int sample_read = 0;
942 int pinned = evsel ? evsel->attr.pinned : 0; 951 int pinned = evsel ? evsel->attr.pinned : 0;
943 952
@@ -974,6 +983,8 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
974 /* use of precise requires exclude_guest */ 983 /* use of precise requires exclude_guest */
975 if (!exclude_GH) 984 if (!exclude_GH)
976 eG = 1; 985 eG = 1;
986 } else if (*str == 'P') {
987 precise_max = 1;
977 } else if (*str == 'S') { 988 } else if (*str == 'S') {
978 sample_read = 1; 989 sample_read = 1;
979 } else if (*str == 'D') { 990 } else if (*str == 'D') {
@@ -1004,6 +1015,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
1004 mod->eG = eG; 1015 mod->eG = eG;
1005 mod->eI = eI; 1016 mod->eI = eI;
1006 mod->precise = precise; 1017 mod->precise = precise;
1018 mod->precise_max = precise_max;
1007 mod->exclude_GH = exclude_GH; 1019 mod->exclude_GH = exclude_GH;
1008 mod->sample_read = sample_read; 1020 mod->sample_read = sample_read;
1009 mod->pinned = pinned; 1021 mod->pinned = pinned;
@@ -1020,7 +1032,7 @@ static int check_modifier(char *str)
1020 char *p = str; 1032 char *p = str;
1021 1033
1022 /* The sizeof includes 0 byte as well. */ 1034 /* The sizeof includes 0 byte as well. */
1023 if (strlen(str) > (sizeof("ukhGHpppSDI") - 1)) 1035 if (strlen(str) > (sizeof("ukhGHpppPSDI") - 1))
1024 return -1; 1036 return -1;
1025 1037
1026 while (*p) { 1038 while (*p) {
@@ -1059,6 +1071,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
1059 evsel->attr.exclude_idle = mod.eI; 1071 evsel->attr.exclude_idle = mod.eI;
1060 evsel->exclude_GH = mod.exclude_GH; 1072 evsel->exclude_GH = mod.exclude_GH;
1061 evsel->sample_read = mod.sample_read; 1073 evsel->sample_read = mod.sample_read;
1074 evsel->precise_max = mod.precise_max;
1062 1075
1063 if (perf_evsel__is_group_leader(evsel)) 1076 if (perf_evsel__is_group_leader(evsel))
1064 evsel->attr.pinned = mod.pinned; 1077 evsel->attr.pinned = mod.pinned;
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index c29832bce496..be244573a02e 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -122,7 +122,7 @@ num_raw_hex [a-fA-F0-9]+
122name [a-zA-Z_*?][a-zA-Z0-9_*?.]* 122name [a-zA-Z_*?][a-zA-Z0-9_*?.]*
123name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.]* 123name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.]*
124/* If you add a modifier you need to update check_modifier() */ 124/* If you add a modifier you need to update check_modifier() */
125modifier_event [ukhpGHSDI]+ 125modifier_event [ukhpPGHSDI]+
126modifier_bp [rwx]{1,3} 126modifier_bp [rwx]{1,3}
127 127
128%% 128%%
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 6b9556d298c9..ee94b728fca4 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -655,6 +655,35 @@ static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
655} 655}
656 656
657static int64_t 657static int64_t
658sort__iaddr_cmp(struct hist_entry *left, struct hist_entry *right)
659{
660 uint64_t l = 0, r = 0;
661
662 if (left->mem_info)
663 l = left->mem_info->iaddr.addr;
664 if (right->mem_info)
665 r = right->mem_info->iaddr.addr;
666
667 return (int64_t)(r - l);
668}
669
670static int hist_entry__iaddr_snprintf(struct hist_entry *he, char *bf,
671 size_t size, unsigned int width)
672{
673 uint64_t addr = 0;
674 struct map *map = NULL;
675 struct symbol *sym = NULL;
676
677 if (he->mem_info) {
678 addr = he->mem_info->iaddr.addr;
679 map = he->mem_info->iaddr.map;
680 sym = he->mem_info->iaddr.sym;
681 }
682 return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
683 width);
684}
685
686static int64_t
658sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right) 687sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
659{ 688{
660 struct map *map_l = NULL; 689 struct map *map_l = NULL;
@@ -1077,6 +1106,13 @@ struct sort_entry sort_mem_daddr_sym = {
1077 .se_width_idx = HISTC_MEM_DADDR_SYMBOL, 1106 .se_width_idx = HISTC_MEM_DADDR_SYMBOL,
1078}; 1107};
1079 1108
1109struct sort_entry sort_mem_iaddr_sym = {
1110 .se_header = "Code Symbol",
1111 .se_cmp = sort__iaddr_cmp,
1112 .se_snprintf = hist_entry__iaddr_snprintf,
1113 .se_width_idx = HISTC_MEM_IADDR_SYMBOL,
1114};
1115
1080struct sort_entry sort_mem_daddr_dso = { 1116struct sort_entry sort_mem_daddr_dso = {
1081 .se_header = "Data Object", 1117 .se_header = "Data Object",
1082 .se_cmp = sort__dso_daddr_cmp, 1118 .se_cmp = sort__dso_daddr_cmp,
@@ -1299,6 +1335,7 @@ static struct sort_dimension bstack_sort_dimensions[] = {
1299 1335
1300static struct sort_dimension memory_sort_dimensions[] = { 1336static struct sort_dimension memory_sort_dimensions[] = {
1301 DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym), 1337 DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym),
1338 DIM(SORT_MEM_IADDR_SYMBOL, "symbol_iaddr", sort_mem_iaddr_sym),
1302 DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso), 1339 DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso),
1303 DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked), 1340 DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked),
1304 DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb), 1341 DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb),
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index c06b75746613..33b3d30e18d3 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -201,6 +201,7 @@ enum sort_type {
201 SORT_MEM_LVL, 201 SORT_MEM_LVL,
202 SORT_MEM_SNOOP, 202 SORT_MEM_SNOOP,
203 SORT_MEM_DCACHELINE, 203 SORT_MEM_DCACHELINE,
204 SORT_MEM_IADDR_SYMBOL,
204}; 205};
205 206
206/* 207/*
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index ce465b259e52..c1bf9ff210b0 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -17,9 +17,9 @@
17#include "callchain.h" 17#include "callchain.h"
18 18
19struct callchain_param callchain_param = { 19struct callchain_param callchain_param = {
20 .mode = CHAIN_GRAPH_REL, 20 .mode = CHAIN_GRAPH_ABS,
21 .min_percent = 0.5, 21 .min_percent = 0.5,
22 .order = ORDER_CALLEE, 22 .order = ORDER_CALLER,
23 .key = CCKEY_FUNCTION 23 .key = CCKEY_FUNCTION
24}; 24};
25 25