aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-09-03 19:15:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-03 19:15:41 -0400
commit79b0691d0c1d3d4a976e3304a1512e6eca9671ec (patch)
tree23185e0f096a0924b3e2eafd823c83644c06d998 /tools/perf
parentca520cab25e0e8da717c596ccaa2c2b3650cfa09 (diff)
parent5b923564ccf43f92969c9e0fd199c8c5db657039 (diff)
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar: "Tooling fixes plus a handful of late arriving tooling changes" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf tools: Fix link time error with sample_reg_masks on non x86 perf build: Fix Intel PT instruction decoder dependency problem perf dwarf: Fix potential array out of bounds access perf record: Add ability to name registers to record perf/x86: Add list of register names perf script: Enable printing of interrupted machine state perf evlist: Open event on evsel cpus and threads bpf tools: New API to get name from a BPF object perf tools: Fix build on powerpc broken by pt/bts
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-record.txt6
-rw-r--r--tools/perf/Documentation/perf-script.txt2
-rw-r--r--tools/perf/arch/sh/util/dwarf-regs.c2
-rw-r--r--tools/perf/arch/sparc/util/dwarf-regs.c2
-rw-r--r--tools/perf/arch/x86/util/Build1
-rw-r--r--tools/perf/arch/x86/util/dwarf-regs.c2
-rw-r--r--tools/perf/arch/x86/util/perf_regs.c28
-rw-r--r--tools/perf/builtin-record.c9
-rw-r--r--tools/perf/builtin-script.c31
-rw-r--r--tools/perf/perf.h2
-rw-r--r--tools/perf/tests/llvm.c2
-rw-r--r--tools/perf/util/Build2
-rw-r--r--tools/perf/util/evlist.c4
-rw-r--r--tools/perf/util/evsel.c2
-rw-r--r--tools/perf/util/intel-pt-decoder/Build1
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c3
-rw-r--r--tools/perf/util/parse-regs-options.c71
-rw-r--r--tools/perf/util/parse-regs-options.h5
-rw-r--r--tools/perf/util/perf_regs.c4
-rw-r--r--tools/perf/util/perf_regs.h9
20 files changed, 176 insertions, 12 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 347a27322ed8..2e9ce77b5e14 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -276,7 +276,11 @@ filter out the startup phase of the program, which is often very different.
276--intr-regs:: 276--intr-regs::
277Capture machine state (registers) at interrupt, i.e., on counter overflows for 277Capture machine state (registers) at interrupt, i.e., on counter overflows for
278each sample. List of captured registers depends on the architecture. This option 278each sample. List of captured registers depends on the architecture. This option
279is off by default. 279is off by default. It is possible to select the registers to sample using their
280symbolic names, e.g. on x86, ax, si. To list the available registers use
281--intr-regs=\?. To name registers, pass a comma separated list such as
282--intr-regs=ax,bx. The list of register is architecture dependent.
283
280 284
281--running-time:: 285--running-time::
282Record running and enabled time for read events (:S) 286Record running and enabled time for read events (:S)
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 614b2c7b0293..dc3ec783b7bd 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -116,7 +116,7 @@ OPTIONS
116--fields:: 116--fields::
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
119 srcline, period, flags. 119 srcline, period, iregs, flags.
120 Field list can be prepended with the type, trace, sw or hw, 120 Field list can be prepended with the type, trace, sw or hw,
121 to indicate to which event type the field list applies. 121 to indicate to which event type the field list applies.
122 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace 122 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
diff --git a/tools/perf/arch/sh/util/dwarf-regs.c b/tools/perf/arch/sh/util/dwarf-regs.c
index 0d0897f57a10..f8dfa89696f4 100644
--- a/tools/perf/arch/sh/util/dwarf-regs.c
+++ b/tools/perf/arch/sh/util/dwarf-regs.c
@@ -51,5 +51,5 @@ const char *sh_regs_table[SH_MAX_REGS] = {
51/* Return architecture dependent register string (for kprobe-tracer) */ 51/* Return architecture dependent register string (for kprobe-tracer) */
52const char *get_arch_regstr(unsigned int n) 52const char *get_arch_regstr(unsigned int n)
53{ 53{
54 return (n <= SH_MAX_REGS) ? sh_regs_table[n] : NULL; 54 return (n < SH_MAX_REGS) ? sh_regs_table[n] : NULL;
55} 55}
diff --git a/tools/perf/arch/sparc/util/dwarf-regs.c b/tools/perf/arch/sparc/util/dwarf-regs.c
index 92eda412fed3..b704fdb9237a 100644
--- a/tools/perf/arch/sparc/util/dwarf-regs.c
+++ b/tools/perf/arch/sparc/util/dwarf-regs.c
@@ -39,5 +39,5 @@ const char *sparc_regs_table[SPARC_MAX_REGS] = {
39 */ 39 */
40const char *get_arch_regstr(unsigned int n) 40const char *get_arch_regstr(unsigned int n)
41{ 41{
42 return (n <= SPARC_MAX_REGS) ? sparc_regs_table[n] : NULL; 42 return (n < SPARC_MAX_REGS) ? sparc_regs_table[n] : NULL;
43} 43}
diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build
index 2c55e1b336c5..ff63649fa9ac 100644
--- a/tools/perf/arch/x86/util/Build
+++ b/tools/perf/arch/x86/util/Build
@@ -2,6 +2,7 @@ libperf-y += header.o
2libperf-y += tsc.o 2libperf-y += tsc.o
3libperf-y += pmu.o 3libperf-y += pmu.o
4libperf-y += kvm-stat.o 4libperf-y += kvm-stat.o
5libperf-y += perf_regs.o
5 6
6libperf-$(CONFIG_DWARF) += dwarf-regs.o 7libperf-$(CONFIG_DWARF) += dwarf-regs.o
7 8
diff --git a/tools/perf/arch/x86/util/dwarf-regs.c b/tools/perf/arch/x86/util/dwarf-regs.c
index be22dd463232..a08de0a35b83 100644
--- a/tools/perf/arch/x86/util/dwarf-regs.c
+++ b/tools/perf/arch/x86/util/dwarf-regs.c
@@ -71,5 +71,5 @@ const char *x86_64_regs_table[X86_64_MAX_REGS] = {
71/* Return architecture dependent register string (for kprobe-tracer) */ 71/* Return architecture dependent register string (for kprobe-tracer) */
72const char *get_arch_regstr(unsigned int n) 72const char *get_arch_regstr(unsigned int n)
73{ 73{
74 return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL; 74 return (n < ARCH_MAX_REGS) ? arch_regs_table[n] : NULL;
75} 75}
diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
new file mode 100644
index 000000000000..c5db14f36cc7
--- /dev/null
+++ b/tools/perf/arch/x86/util/perf_regs.c
@@ -0,0 +1,28 @@
1#include "../../perf.h"
2#include "../../util/perf_regs.h"
3
4const struct sample_reg sample_reg_masks[] = {
5 SMPL_REG(AX, PERF_REG_X86_AX),
6 SMPL_REG(BX, PERF_REG_X86_BX),
7 SMPL_REG(CX, PERF_REG_X86_CX),
8 SMPL_REG(DX, PERF_REG_X86_DX),
9 SMPL_REG(SI, PERF_REG_X86_SI),
10 SMPL_REG(DI, PERF_REG_X86_DI),
11 SMPL_REG(BP, PERF_REG_X86_BP),
12 SMPL_REG(SP, PERF_REG_X86_SP),
13 SMPL_REG(IP, PERF_REG_X86_IP),
14 SMPL_REG(FLAGS, PERF_REG_X86_FLAGS),
15 SMPL_REG(CS, PERF_REG_X86_CS),
16 SMPL_REG(SS, PERF_REG_X86_SS),
17#ifdef HAVE_ARCH_X86_64_SUPPORT
18 SMPL_REG(R8, PERF_REG_X86_R8),
19 SMPL_REG(R9, PERF_REG_X86_R9),
20 SMPL_REG(R10, PERF_REG_X86_R10),
21 SMPL_REG(R11, PERF_REG_X86_R11),
22 SMPL_REG(R12, PERF_REG_X86_R12),
23 SMPL_REG(R13, PERF_REG_X86_R13),
24 SMPL_REG(R14, PERF_REG_X86_R14),
25 SMPL_REG(R15, PERF_REG_X86_R15),
26#endif
27 SMPL_REG_END
28};
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a660022f2c92..142eeb341b29 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -27,8 +27,10 @@
27#include "util/cpumap.h" 27#include "util/cpumap.h"
28#include "util/thread_map.h" 28#include "util/thread_map.h"
29#include "util/data.h" 29#include "util/data.h"
30#include "util/perf_regs.h"
30#include "util/auxtrace.h" 31#include "util/auxtrace.h"
31#include "util/parse-branch-options.h" 32#include "util/parse-branch-options.h"
33#include "util/parse-regs-options.h"
32 34
33#include <unistd.h> 35#include <unistd.h>
34#include <sched.h> 36#include <sched.h>
@@ -279,7 +281,7 @@ static int record__open(struct record *rec)
279 281
280 evlist__for_each(evlist, pos) { 282 evlist__for_each(evlist, pos) {
281try_again: 283try_again:
282 if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { 284 if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
283 if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 285 if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
284 if (verbose) 286 if (verbose)
285 ui__warning("%s\n", msg); 287 ui__warning("%s\n", msg);
@@ -1080,8 +1082,9 @@ struct option __record_options[] = {
1080 "sample transaction flags (special events only)"), 1082 "sample transaction flags (special events only)"),
1081 OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 1083 OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
1082 "use per-thread mmaps"), 1084 "use per-thread mmaps"),
1083 OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs, 1085 OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
1084 "Sample machine registers on interrupt"), 1086 "sample selected machine registers on interrupt,"
1087 " use -I ? to list register names", parse_regs),
1085 OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 1088 OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
1086 "Record running/enabled time of read (:S) events"), 1089 "Record running/enabled time of read (:S) events"),
1087 OPT_CALLBACK('k', "clockid", &record.opts, 1090 OPT_CALLBACK('k', "clockid", &record.opts,
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 4430340292c0..eb51325e8ad9 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -6,6 +6,7 @@
6#include "util/exec_cmd.h" 6#include "util/exec_cmd.h"
7#include "util/header.h" 7#include "util/header.h"
8#include "util/parse-options.h" 8#include "util/parse-options.h"
9#include "util/perf_regs.h"
9#include "util/session.h" 10#include "util/session.h"
10#include "util/tool.h" 11#include "util/tool.h"
11#include "util/symbol.h" 12#include "util/symbol.h"
@@ -46,6 +47,7 @@ enum perf_output_field {
46 PERF_OUTPUT_SYMOFFSET = 1U << 11, 47 PERF_OUTPUT_SYMOFFSET = 1U << 11,
47 PERF_OUTPUT_SRCLINE = 1U << 12, 48 PERF_OUTPUT_SRCLINE = 1U << 12,
48 PERF_OUTPUT_PERIOD = 1U << 13, 49 PERF_OUTPUT_PERIOD = 1U << 13,
50 PERF_OUTPUT_IREGS = 1U << 14,
49}; 51};
50 52
51struct output_option { 53struct output_option {
@@ -66,6 +68,7 @@ struct output_option {
66 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, 68 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
67 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, 69 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
68 {.str = "period", .field = PERF_OUTPUT_PERIOD}, 70 {.str = "period", .field = PERF_OUTPUT_PERIOD},
71 {.str = "iregs", .field = PERF_OUTPUT_IREGS},
69}; 72};
70 73
71/* default set to maintain compatibility with current format */ 74/* default set to maintain compatibility with current format */
@@ -255,6 +258,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
255 PERF_OUTPUT_PERIOD)) 258 PERF_OUTPUT_PERIOD))
256 return -EINVAL; 259 return -EINVAL;
257 260
261 if (PRINT_FIELD(IREGS) &&
262 perf_evsel__check_stype(evsel, PERF_SAMPLE_REGS_INTR, "IREGS",
263 PERF_OUTPUT_IREGS))
264 return -EINVAL;
265
258 return 0; 266 return 0;
259} 267}
260 268
@@ -352,6 +360,24 @@ out:
352 return 0; 360 return 0;
353} 361}
354 362
363static void print_sample_iregs(union perf_event *event __maybe_unused,
364 struct perf_sample *sample,
365 struct thread *thread __maybe_unused,
366 struct perf_event_attr *attr)
367{
368 struct regs_dump *regs = &sample->intr_regs;
369 uint64_t mask = attr->sample_regs_intr;
370 unsigned i = 0, r;
371
372 if (!regs)
373 return;
374
375 for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) {
376 u64 val = regs->regs[i++];
377 printf("%5s:0x%"PRIx64" ", perf_reg_name(r), val);
378 }
379}
380
355static void print_sample_start(struct perf_sample *sample, 381static void print_sample_start(struct perf_sample *sample,
356 struct thread *thread, 382 struct thread *thread,
357 struct perf_evsel *evsel) 383 struct perf_evsel *evsel)
@@ -525,6 +551,9 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
525 PERF_MAX_STACK_DEPTH); 551 PERF_MAX_STACK_DEPTH);
526 } 552 }
527 553
554 if (PRINT_FIELD(IREGS))
555 print_sample_iregs(event, sample, thread, attr);
556
528 printf("\n"); 557 printf("\n");
529} 558}
530 559
@@ -1643,7 +1672,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1643 "comma separated output fields prepend with 'type:'. " 1672 "comma separated output fields prepend with 'type:'. "
1644 "Valid types: hw,sw,trace,raw. " 1673 "Valid types: hw,sw,trace,raw. "
1645 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 1674 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
1646 "addr,symoff,period,flags", parse_output_fields), 1675 "addr,symoff,period,iregs,flags", parse_output_fields),
1647 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1676 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1648 "system-wide collection from all CPUs"), 1677 "system-wide collection from all CPUs"),
1649 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 1678 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index cccb4cf575d3..90129accffbe 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -54,7 +54,6 @@ struct record_opts {
54 bool sample_time_set; 54 bool sample_time_set;
55 bool callgraph_set; 55 bool callgraph_set;
56 bool period; 56 bool period;
57 bool sample_intr_regs;
58 bool running_time; 57 bool running_time;
59 bool full_auxtrace; 58 bool full_auxtrace;
60 bool auxtrace_snapshot_mode; 59 bool auxtrace_snapshot_mode;
@@ -64,6 +63,7 @@ struct record_opts {
64 unsigned int auxtrace_mmap_pages; 63 unsigned int auxtrace_mmap_pages;
65 unsigned int user_freq; 64 unsigned int user_freq;
66 u64 branch_stack; 65 u64 branch_stack;
66 u64 sample_intr_regs;
67 u64 default_interval; 67 u64 default_interval;
68 u64 user_interval; 68 u64 user_interval;
69 size_t auxtrace_snapshot_size; 69 size_t auxtrace_snapshot_size;
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index a337356fd979..52d55971f66f 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -26,7 +26,7 @@ static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
26{ 26{
27 struct bpf_object *obj; 27 struct bpf_object *obj;
28 28
29 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz); 29 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, NULL);
30 if (!obj) 30 if (!obj)
31 return -1; 31 return -1;
32 bpf_object__close(obj); 32 bpf_object__close(obj);
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index e912856cc4e5..349bc96ca1fe 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -75,6 +75,7 @@ libperf-y += record.o
75libperf-y += srcline.o 75libperf-y += srcline.o
76libperf-y += data.o 76libperf-y += data.o
77libperf-$(CONFIG_X86) += tsc.o 77libperf-$(CONFIG_X86) += tsc.o
78libperf-$(CONFIG_AUXTRACE) += tsc.o
78libperf-y += cloexec.o 79libperf-y += cloexec.o
79libperf-y += thread-stack.o 80libperf-y += thread-stack.o
80libperf-$(CONFIG_AUXTRACE) += auxtrace.o 81libperf-$(CONFIG_AUXTRACE) += auxtrace.o
@@ -82,6 +83,7 @@ libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/
82libperf-$(CONFIG_AUXTRACE) += intel-pt.o 83libperf-$(CONFIG_AUXTRACE) += intel-pt.o
83libperf-$(CONFIG_AUXTRACE) += intel-bts.o 84libperf-$(CONFIG_AUXTRACE) += intel-bts.o
84libperf-y += parse-branch-options.o 85libperf-y += parse-branch-options.o
86libperf-y += parse-regs-options.o
85 87
86libperf-$(CONFIG_LIBELF) += symbol-elf.o 88libperf-$(CONFIG_LIBELF) += symbol-elf.o
87libperf-$(CONFIG_LIBELF) += probe-file.o 89libperf-$(CONFIG_LIBELF) += probe-file.o
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 8d00039d6a20..d51a5200c8af 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1181,6 +1181,10 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **e
1181 if (evsel->filter == NULL) 1181 if (evsel->filter == NULL)
1182 continue; 1182 continue;
1183 1183
1184 /*
1185 * filters only work for tracepoint event, which doesn't have cpu limit.
1186 * So evlist and evsel should always be same.
1187 */
1184 err = perf_evsel__apply_filter(evsel, ncpus, nthreads, evsel->filter); 1188 err = perf_evsel__apply_filter(evsel, ncpus, nthreads, evsel->filter);
1185 if (err) { 1189 if (err) {
1186 *err_evsel = evsel; 1190 *err_evsel = evsel;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index bac25f41a751..c53f79123b37 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -787,7 +787,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
787 perf_evsel__config_callgraph(evsel, opts, &callchain_param); 787 perf_evsel__config_callgraph(evsel, opts, &callchain_param);
788 788
789 if (opts->sample_intr_regs) { 789 if (opts->sample_intr_regs) {
790 attr->sample_regs_intr = PERF_REGS_MASK; 790 attr->sample_regs_intr = opts->sample_intr_regs;
791 perf_evsel__set_sample_bit(evsel, REGS_INTR); 791 perf_evsel__set_sample_bit(evsel, REGS_INTR);
792 } 792 }
793 793
diff --git a/tools/perf/util/intel-pt-decoder/Build b/tools/perf/util/intel-pt-decoder/Build
index 240730d682c1..2386322ece4f 100644
--- a/tools/perf/util/intel-pt-decoder/Build
+++ b/tools/perf/util/intel-pt-decoder/Build
@@ -4,6 +4,7 @@ inat_tables_script = util/intel-pt-decoder/gen-insn-attr-x86.awk
4inat_tables_maps = util/intel-pt-decoder/x86-opcode-map.txt 4inat_tables_maps = util/intel-pt-decoder/x86-opcode-map.txt
5 5
6$(OUTPUT)util/intel-pt-decoder/inat-tables.c: $(inat_tables_script) $(inat_tables_maps) 6$(OUTPUT)util/intel-pt-decoder/inat-tables.c: $(inat_tables_script) $(inat_tables_maps)
7 $(call rule_mkdir)
7 @$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@ || rm -f $@ 8 @$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@ || rm -f $@
8 9
9$(OUTPUT)util/intel-pt-decoder/intel-pt-insn-decoder.o: util/intel-pt-decoder/inat.c $(OUTPUT)util/intel-pt-decoder/inat-tables.c 10$(OUTPUT)util/intel-pt-decoder/intel-pt-insn-decoder.o: util/intel-pt-decoder/inat.c $(OUTPUT)util/intel-pt-decoder/inat-tables.c
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
index 9e4eb8fcd559..d23138c06665 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
@@ -146,6 +146,9 @@ static void intel_pt_insn_decoder(struct insn *insn,
146 case 4: 146 case 4:
147 intel_pt_insn->rel = bswap_32(insn->immediate.value); 147 intel_pt_insn->rel = bswap_32(insn->immediate.value);
148 break; 148 break;
149 default:
150 intel_pt_insn->rel = 0;
151 break;
149 } 152 }
150#else 153#else
151 intel_pt_insn->rel = insn->immediate.value; 154 intel_pt_insn->rel = insn->immediate.value;
diff --git a/tools/perf/util/parse-regs-options.c b/tools/perf/util/parse-regs-options.c
new file mode 100644
index 000000000000..4f2c1c255d81
--- /dev/null
+++ b/tools/perf/util/parse-regs-options.c
@@ -0,0 +1,71 @@
1#include "perf.h"
2#include "util/util.h"
3#include "util/debug.h"
4#include "util/parse-options.h"
5#include "util/parse-regs-options.h"
6
7int
8parse_regs(const struct option *opt, const char *str, int unset)
9{
10 uint64_t *mode = (uint64_t *)opt->value;
11 const struct sample_reg *r;
12 char *s, *os = NULL, *p;
13 int ret = -1;
14
15 if (unset)
16 return 0;
17
18 /*
19 * cannot set it twice
20 */
21 if (*mode)
22 return -1;
23
24 /* str may be NULL in case no arg is passed to -I */
25 if (str) {
26 /* because str is read-only */
27 s = os = strdup(str);
28 if (!s)
29 return -1;
30
31 for (;;) {
32 p = strchr(s, ',');
33 if (p)
34 *p = '\0';
35
36 if (!strcmp(s, "?")) {
37 fprintf(stderr, "available registers: ");
38 for (r = sample_reg_masks; r->name; r++) {
39 fprintf(stderr, "%s ", r->name);
40 }
41 fputc('\n', stderr);
42 /* just printing available regs */
43 return -1;
44 }
45 for (r = sample_reg_masks; r->name; r++) {
46 if (!strcasecmp(s, r->name))
47 break;
48 }
49 if (!r->name) {
50 ui__warning("unknown register %s,"
51 " check man page\n", s);
52 goto error;
53 }
54
55 *mode |= r->mask;
56
57 if (!p)
58 break;
59
60 s = p + 1;
61 }
62 }
63 ret = 0;
64
65 /* default to all possible regs */
66 if (*mode == 0)
67 *mode = PERF_REGS_MASK;
68error:
69 free(os);
70 return ret;
71}
diff --git a/tools/perf/util/parse-regs-options.h b/tools/perf/util/parse-regs-options.h
new file mode 100644
index 000000000000..7d762b188007
--- /dev/null
+++ b/tools/perf/util/parse-regs-options.h
@@ -0,0 +1,5 @@
1#ifndef _PERF_PARSE_REGS_OPTIONS_H
2#define _PERF_PARSE_REGS_OPTIONS_H 1
3struct option;
4int parse_regs(const struct option *opt, const char *str, int unset);
5#endif /* _PERF_PARSE_REGS_OPTIONS_H */
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index 43168fb0d9a2..885e8ac83997 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -2,6 +2,10 @@
2#include "perf_regs.h" 2#include "perf_regs.h"
3#include "event.h" 3#include "event.h"
4 4
5const struct sample_reg __weak sample_reg_masks[] = {
6 SMPL_REG_END
7};
8
5int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) 9int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
6{ 10{
7 int i, idx = 0; 11 int i, idx = 0;
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 980dbf76bc98..2984dcc54d67 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -5,6 +5,15 @@
5 5
6struct regs_dump; 6struct regs_dump;
7 7
8struct sample_reg {
9 const char *name;
10 uint64_t mask;
11};
12#define SMPL_REG(n, b) { .name = #n, .mask = 1ULL << (b) }
13#define SMPL_REG_END { .name = NULL }
14
15extern const struct sample_reg sample_reg_masks[];
16
8#ifdef HAVE_PERF_REGS_SUPPORT 17#ifdef HAVE_PERF_REGS_SUPPORT
9#include <perf_regs.h> 18#include <perf_regs.h>
10 19