diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-03 19:15:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-03 19:15:41 -0400 |
commit | 79b0691d0c1d3d4a976e3304a1512e6eca9671ec (patch) | |
tree | 23185e0f096a0924b3e2eafd823c83644c06d998 /tools/perf | |
parent | ca520cab25e0e8da717c596ccaa2c2b3650cfa09 (diff) | |
parent | 5b923564ccf43f92969c9e0fd199c8c5db657039 (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.txt | 6 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-script.txt | 2 | ||||
-rw-r--r-- | tools/perf/arch/sh/util/dwarf-regs.c | 2 | ||||
-rw-r--r-- | tools/perf/arch/sparc/util/dwarf-regs.c | 2 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/Build | 1 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/dwarf-regs.c | 2 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/perf_regs.c | 28 | ||||
-rw-r--r-- | tools/perf/builtin-record.c | 9 | ||||
-rw-r--r-- | tools/perf/builtin-script.c | 31 | ||||
-rw-r--r-- | tools/perf/perf.h | 2 | ||||
-rw-r--r-- | tools/perf/tests/llvm.c | 2 | ||||
-rw-r--r-- | tools/perf/util/Build | 2 | ||||
-rw-r--r-- | tools/perf/util/evlist.c | 4 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 2 | ||||
-rw-r--r-- | tools/perf/util/intel-pt-decoder/Build | 1 | ||||
-rw-r--r-- | tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c | 3 | ||||
-rw-r--r-- | tools/perf/util/parse-regs-options.c | 71 | ||||
-rw-r--r-- | tools/perf/util/parse-regs-options.h | 5 | ||||
-rw-r--r-- | tools/perf/util/perf_regs.c | 4 | ||||
-rw-r--r-- | tools/perf/util/perf_regs.h | 9 |
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:: |
277 | Capture machine state (registers) at interrupt, i.e., on counter overflows for | 277 | Capture machine state (registers) at interrupt, i.e., on counter overflows for |
278 | each sample. List of captured registers depends on the architecture. This option | 278 | each sample. List of captured registers depends on the architecture. This option |
279 | is off by default. | 279 | is off by default. It is possible to select the registers to sample using their |
280 | symbolic 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:: |
282 | Record running and enabled time for read events (:S) | 286 | Record 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) */ |
52 | const char *get_arch_regstr(unsigned int n) | 52 | const 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 | */ |
40 | const char *get_arch_regstr(unsigned int n) | 40 | const 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 | |||
2 | libperf-y += tsc.o | 2 | libperf-y += tsc.o |
3 | libperf-y += pmu.o | 3 | libperf-y += pmu.o |
4 | libperf-y += kvm-stat.o | 4 | libperf-y += kvm-stat.o |
5 | libperf-y += perf_regs.o | ||
5 | 6 | ||
6 | libperf-$(CONFIG_DWARF) += dwarf-regs.o | 7 | libperf-$(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) */ |
72 | const char *get_arch_regstr(unsigned int n) | 72 | const 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 | |||
4 | const 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) { |
281 | try_again: | 283 | try_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 | ||
51 | struct output_option { | 53 | struct 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 | ||
363 | static 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 | |||
355 | static void print_sample_start(struct perf_sample *sample, | 381 | static 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 | |||
75 | libperf-y += srcline.o | 75 | libperf-y += srcline.o |
76 | libperf-y += data.o | 76 | libperf-y += data.o |
77 | libperf-$(CONFIG_X86) += tsc.o | 77 | libperf-$(CONFIG_X86) += tsc.o |
78 | libperf-$(CONFIG_AUXTRACE) += tsc.o | ||
78 | libperf-y += cloexec.o | 79 | libperf-y += cloexec.o |
79 | libperf-y += thread-stack.o | 80 | libperf-y += thread-stack.o |
80 | libperf-$(CONFIG_AUXTRACE) += auxtrace.o | 81 | libperf-$(CONFIG_AUXTRACE) += auxtrace.o |
@@ -82,6 +83,7 @@ libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/ | |||
82 | libperf-$(CONFIG_AUXTRACE) += intel-pt.o | 83 | libperf-$(CONFIG_AUXTRACE) += intel-pt.o |
83 | libperf-$(CONFIG_AUXTRACE) += intel-bts.o | 84 | libperf-$(CONFIG_AUXTRACE) += intel-bts.o |
84 | libperf-y += parse-branch-options.o | 85 | libperf-y += parse-branch-options.o |
86 | libperf-y += parse-regs-options.o | ||
85 | 87 | ||
86 | libperf-$(CONFIG_LIBELF) += symbol-elf.o | 88 | libperf-$(CONFIG_LIBELF) += symbol-elf.o |
87 | libperf-$(CONFIG_LIBELF) += probe-file.o | 89 | libperf-$(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 | |||
4 | inat_tables_maps = util/intel-pt-decoder/x86-opcode-map.txt | 4 | inat_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 | |||
7 | int | ||
8 | parse_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; | ||
68 | error: | ||
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 | ||
3 | struct option; | ||
4 | int 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 | ||
5 | const struct sample_reg __weak sample_reg_masks[] = { | ||
6 | SMPL_REG_END | ||
7 | }; | ||
8 | |||
5 | int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) | 9 | int 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 | ||
6 | struct regs_dump; | 6 | struct regs_dump; |
7 | 7 | ||
8 | struct 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 | |||
15 | extern 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 | ||