diff options
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[] = { | |||
69 | struct fs { | 69 | struct 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 | ||
15 | char tracing_mnt[PATH_MAX + 1] = "/sys/kernel/debug"; | 15 | char tracing_mnt[PATH_MAX] = "/sys/kernel/debug"; |
16 | char tracing_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing"; | 16 | char tracing_path[PATH_MAX] = "/sys/kernel/debug/tracing"; |
17 | char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events"; | 17 | char tracing_events_path[PATH_MAX] = "/sys/kernel/debug/tracing/events"; |
18 | 18 | ||
19 | 19 | ||
20 | static void __tracing_path_set(const char *tracing, const char *mountpoint) | 20 | static 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 | |||
30 | DESCRIPTION | 38 | DESCRIPTION |
31 | ----------- | 39 | ----------- |
32 | Performance counters for Linux are a new kernel-based subsystem | 40 | Performance 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 @@ | |||
1 | libperf-y += util/ | 1 | libperf-y += util/ |
2 | libperf-$(CONFIG_DWARF_UNWIND) += tests/ | 2 | libperf-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 */ | ||
5 | int test__rdpmc(void); | ||
6 | int test__perf_time_to_tsc(void); | ||
7 | int test__insn_x86(void); | ||
8 | int test__intel_cqm_count_nmi_context(void); | ||
9 | |||
10 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | ||
11 | struct thread; | ||
12 | struct perf_sample; | ||
13 | int test__arch_unwind_sample(struct perf_sample *sample, | ||
14 | struct thread *thread); | ||
15 | #endif | ||
16 | |||
17 | extern 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 @@ | |||
1 | libperf-y += regs_load.o | 1 | libperf-$(CONFIG_DWARF_UNWIND) += regs_load.o |
2 | libperf-y += dwarf-unwind.o | 2 | libperf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o |
3 | |||
4 | libperf-y += arch-tests.o | ||
5 | libperf-y += rdpmc.o | ||
6 | libperf-y += perf-time-to-tsc.o | ||
7 | libperf-$(CONFIG_AUXTRACE) += insn-x86.o | ||
8 | libperf-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 | |||
5 | struct 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 | |||
12 | static 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 | */ | ||
36 | int 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); | ||
121 | out: | ||
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 | ||
13 | static u64 rdpmc(unsigned int counter) | 12 | static 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 | |||
8 | perf-y += openat-syscall-tp-fields.o | 8 | perf-y += openat-syscall-tp-fields.o |
9 | perf-y += mmap-basic.o | 9 | perf-y += mmap-basic.o |
10 | perf-y += perf-record.o | 10 | perf-y += perf-record.o |
11 | perf-y += rdpmc.o | ||
12 | perf-y += evsel-roundtrip-name.o | 11 | perf-y += evsel-roundtrip-name.o |
13 | perf-y += evsel-tp-sched.o | 12 | perf-y += evsel-tp-sched.o |
14 | perf-y += fdarray.o | 13 | perf-y += fdarray.o |
@@ -35,11 +34,6 @@ perf-y += thread-map.o | |||
35 | perf-y += llvm.o | 34 | perf-y += llvm.o |
36 | perf-y += topology.o | 35 | perf-y += topology.o |
37 | 36 | ||
38 | perf-$(CONFIG_X86) += perf-time-to-tsc.o | ||
39 | ifdef CONFIG_AUXTRACE | ||
40 | perf-$(CONFIG_X86) += insn-x86.o | ||
41 | endif | ||
42 | |||
43 | ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64)) | 37 | ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64)) |
44 | perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o | 38 | perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o |
45 | endif | 39 | endif |
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 | ||
17 | static struct test { | 17 | struct test __weak arch_tests[] = { |
18 | const char *desc; | 18 | { |
19 | int (*func)(void); | 19 | .func = NULL, |
20 | } tests[] = { | 20 | }, |
21 | }; | ||
22 | |||
23 | static 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 | ||
173 | static struct test *tests[] = { | ||
174 | generic_tests, | ||
175 | arch_tests, | ||
176 | }; | ||
177 | |||
198 | static bool perf_test__matches(struct test *test, int curr, int argc, const char *argv[]) | 178 | static 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 | ||
254 | static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) | 236 | static 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 | ||
301 | static int perf_test__list(int argc, const char **argv) | 284 | static 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 | ||
1262 | static 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 | |||
1262 | static int count_tracepoints(void) | 1273 | static 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 | ||
1567 | static struct evlist_test test__events_pmu[] = { | 1583 | static 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 | ||
27 | struct test { | ||
28 | const char *desc; | ||
29 | int (*func)(void); | ||
30 | }; | ||
31 | |||
27 | /* Tests */ | 32 | /* Tests */ |
28 | int test__vmlinux_matches_kallsyms(void); | 33 | int test__vmlinux_matches_kallsyms(void); |
29 | int test__openat_syscall_event(void); | 34 | int test__openat_syscall_event(void); |
30 | int test__openat_syscall_event_on_all_cpus(void); | 35 | int test__openat_syscall_event_on_all_cpus(void); |
31 | int test__basic_mmap(void); | 36 | int test__basic_mmap(void); |
32 | int test__PERF_RECORD(void); | 37 | int test__PERF_RECORD(void); |
33 | int test__rdpmc(void); | ||
34 | int test__perf_evsel__roundtrip_name_test(void); | 38 | int test__perf_evsel__roundtrip_name_test(void); |
35 | int test__perf_evsel__tp_sched_test(void); | 39 | int test__perf_evsel__tp_sched_test(void); |
36 | int test__syscall_openat_tp_fields(void); | 40 | int test__syscall_openat_tp_fields(void); |
@@ -46,7 +50,6 @@ int test__bp_signal(void); | |||
46 | int test__bp_signal_overflow(void); | 50 | int test__bp_signal_overflow(void); |
47 | int test__task_exit(void); | 51 | int test__task_exit(void); |
48 | int test__sw_clock_freq(void); | 52 | int test__sw_clock_freq(void); |
49 | int test__perf_time_to_tsc(void); | ||
50 | int test__code_reading(void); | 53 | int test__code_reading(void); |
51 | int test__sample_parsing(void); | 54 | int test__sample_parsing(void); |
52 | int test__keep_tracking(void); | 55 | int test__keep_tracking(void); |
@@ -63,10 +66,9 @@ int test__fdarray__add(void); | |||
63 | int test__kmod_path__parse(void); | 66 | int test__kmod_path__parse(void); |
64 | int test__thread_map(void); | 67 | int test__thread_map(void); |
65 | int test__llvm(void); | 68 | int test__llvm(void); |
66 | int test__insn_x86(void); | ||
67 | int test_session_topology(void); | 69 | int 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 |
71 | struct thread; | 73 | struct thread; |
72 | struct perf_sample; | 74 | struct 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 @@ | |||
14 | struct ui_browser { | 14 | struct 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 | ||
864 | static int hists__scnprintf_headers(char *buf, size_t size, struct hists *hists) | 865 | static 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 | ||
208 | static void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr) | 208 | void 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 | ||
291 | void perf_evlist__set_tracking_event(struct perf_evlist *evlist, | 291 | void perf_evlist__set_tracking_event(struct perf_evlist *evlist, |
292 | struct perf_evsel *tracking_evsel); | 292 | struct perf_evsel *tracking_evsel); |
293 | |||
294 | void 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]+ | |||
122 | name [a-zA-Z_*?][a-zA-Z0-9_*?.]* | 122 | name [a-zA-Z_*?][a-zA-Z0-9_*?.]* |
123 | name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.]* | 123 | name_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() */ |
125 | modifier_event [ukhpGHSDI]+ | 125 | modifier_event [ukhpPGHSDI]+ |
126 | modifier_bp [rwx]{1,3} | 126 | modifier_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 | ||
657 | static int64_t | 657 | static int64_t |
658 | sort__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 | |||
670 | static 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 | |||
686 | static int64_t | ||
658 | sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right) | 687 | sort__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 | ||
1109 | struct 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 | |||
1080 | struct sort_entry sort_mem_daddr_dso = { | 1116 | struct 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 | ||
1300 | static struct sort_dimension memory_sort_dimensions[] = { | 1336 | static 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 | ||
19 | struct callchain_param callchain_param = { | 19 | struct 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 | ||