diff options
author | Stephane Eranian <eranian@google.com> | 2015-08-31 12:41:12 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-08-31 17:01:33 -0400 |
commit | bcc84ec65ad1bd9f777a1fade6f8e5e0c5808fa5 (patch) | |
tree | f824e46632026abbbe0f76f109e86b2c09bec18f /tools/perf | |
parent | c5e991ee9dff0f8136168ed2d0d1a8cc3620dac4 (diff) |
perf record: Add ability to name registers to record
This patch modifies the -I/--int-regs option to enablepassing the name
of the registers to sample on interrupt. Registers can be specified by
their symbolic names. For instance on x86, --intr-regs=ax,si.
The motivation is to reduce the size of the perf.data file and the
overhead of sampling by only collecting the registers useful to a
specific analysis. For instance, for value profiling, sampling only the
registers used to passed arguements to functions.
With no parameter, the --intr-regs still records all possible registers
based on the architecture.
To name registers, it is necessary to use the long form of the option,
i.e., --intr-regs:
$ perf record --intr-regs=si,di,r8,r9 .....
To record any possible registers:
$ perf record -I .....
$ perf report --intr-regs ...
To display the register, one can use perf report -D
To list the available registers:
$ perf record --intr-regs=\?
available registers: AX BX CX DX SI DI BP SP IP FLAGS CS SS R8 R9 R10 R11 R12 R13 R14 R15
Signed-off-by: Stephane Eranian <eranian@google.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1441039273-16260-4-git-send-email-eranian@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/Documentation/perf-record.txt | 6 | ||||
-rw-r--r-- | tools/perf/builtin-record.c | 7 | ||||
-rw-r--r-- | tools/perf/perf.h | 2 | ||||
-rw-r--r-- | tools/perf/util/Build | 1 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 2 | ||||
-rw-r--r-- | tools/perf/util/parse-regs-options.c | 71 | ||||
-rw-r--r-- | tools/perf/util/parse-regs-options.h | 5 |
7 files changed, 89 insertions, 5 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/builtin-record.c b/tools/perf/builtin-record.c index 1d14f382f614..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> |
@@ -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/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/util/Build b/tools/perf/util/Build index e79e4522368a..349bc96ca1fe 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build | |||
@@ -83,6 +83,7 @@ libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/ | |||
83 | libperf-$(CONFIG_AUXTRACE) += intel-pt.o | 83 | libperf-$(CONFIG_AUXTRACE) += intel-pt.o |
84 | libperf-$(CONFIG_AUXTRACE) += intel-bts.o | 84 | libperf-$(CONFIG_AUXTRACE) += intel-bts.o |
85 | libperf-y += parse-branch-options.o | 85 | libperf-y += parse-branch-options.o |
86 | libperf-y += parse-regs-options.o | ||
86 | 87 | ||
87 | libperf-$(CONFIG_LIBELF) += symbol-elf.o | 88 | libperf-$(CONFIG_LIBELF) += symbol-elf.o |
88 | libperf-$(CONFIG_LIBELF) += probe-file.o | 89 | libperf-$(CONFIG_LIBELF) += probe-file.o |
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/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 */ | ||