aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorStephane Eranian <eranian@google.com>2015-08-31 12:41:12 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-08-31 17:01:33 -0400
commitbcc84ec65ad1bd9f777a1fade6f8e5e0c5808fa5 (patch)
treef824e46632026abbbe0f76f109e86b2c09bec18f /tools/perf
parentc5e991ee9dff0f8136168ed2d0d1a8cc3620dac4 (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.txt6
-rw-r--r--tools/perf/builtin-record.c7
-rw-r--r--tools/perf/perf.h2
-rw-r--r--tools/perf/util/Build1
-rw-r--r--tools/perf/util/evsel.c2
-rw-r--r--tools/perf/util/parse-regs-options.c71
-rw-r--r--tools/perf/util/parse-regs-options.h5
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::
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/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/
83libperf-$(CONFIG_AUXTRACE) += intel-pt.o 83libperf-$(CONFIG_AUXTRACE) += intel-pt.o
84libperf-$(CONFIG_AUXTRACE) += intel-bts.o 84libperf-$(CONFIG_AUXTRACE) += intel-bts.o
85libperf-y += parse-branch-options.o 85libperf-y += parse-branch-options.o
86libperf-y += parse-regs-options.o
86 87
87libperf-$(CONFIG_LIBELF) += symbol-elf.o 88libperf-$(CONFIG_LIBELF) += symbol-elf.o
88libperf-$(CONFIG_LIBELF) += probe-file.o 89libperf-$(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
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 */