Em Mon, Aug 31, 2015 at 06:41:12PM +0200, Stephane Eranian escreveu:
> 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.

Applied and tested up to this one, waiting for the discussion with Andi
to proceed to the last one.

- Arnaldo
 
> 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 <[email protected]>
> ---
>  tools/perf/Documentation/perf-record.txt |  6 ++-
>  tools/perf/builtin-record.c              |  7 +++-
>  tools/perf/perf.h                        |  2 +-
>  tools/perf/util/Build                    |  1 +
>  tools/perf/util/evsel.c                  |  2 +-
>  tools/perf/util/parse-regs-options.c     | 71 
> ++++++++++++++++++++++++++++++++
>  tools/perf/util/parse-regs-options.h     |  5 +++
>  7 files changed, 89 insertions(+), 5 deletions(-)
>  create mode 100644 tools/perf/util/parse-regs-options.c
>  create mode 100644 tools/perf/util/parse-regs-options.h
> 
> diff --git a/tools/perf/Documentation/perf-record.txt 
> b/tools/perf/Documentation/perf-record.txt
> index 347a273..2e9ce77 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.
>  --intr-regs::
>  Capture machine state (registers) at interrupt, i.e., on counter overflows 
> for
>  each sample. List of captured registers depends on the architecture. This 
> option
> -is off by default.
> +is off by default. It is possible to select the registers to sample using 
> their
> +symbolic names, e.g. on x86, ax, si. To list the available registers use
> +--intr-regs=\?. To name registers, pass a comma separated list such as
> +--intr-regs=ax,bx. The list of register is architecture dependent.
> +
>  
>  --running-time::
>  Record running and enabled time for read events (:S)
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index a660022..d3a5d91 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -27,8 +27,10 @@
>  #include "util/cpumap.h"
>  #include "util/thread_map.h"
>  #include "util/data.h"
> +#include "util/perf_regs.h"
>  #include "util/auxtrace.h"
>  #include "util/parse-branch-options.h"
> +#include "util/parse-regs-options.h"
>  
>  #include <unistd.h>
>  #include <sched.h>
> @@ -1080,8 +1082,9 @@ struct option __record_options[] = {
>                   "sample transaction flags (special events only)"),
>       OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
>                   "use per-thread mmaps"),
> -     OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs,
> -                 "Sample machine registers on interrupt"),
> +     OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, 
> NULL, "any register",
> +                 "sample selected machine registers on interrupt,"
> +                 " use -I ? to list register names", parse_regs),
>       OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
>                   "Record running/enabled time of read (:S) events"),
>       OPT_CALLBACK('k', "clockid", &record.opts,
> diff --git a/tools/perf/perf.h b/tools/perf/perf.h
> index cccb4cf..90129ac 100644
> --- a/tools/perf/perf.h
> +++ b/tools/perf/perf.h
> @@ -54,7 +54,6 @@ struct record_opts {
>       bool         sample_time_set;
>       bool         callgraph_set;
>       bool         period;
> -     bool         sample_intr_regs;
>       bool         running_time;
>       bool         full_auxtrace;
>       bool         auxtrace_snapshot_mode;
> @@ -64,6 +63,7 @@ struct record_opts {
>       unsigned int auxtrace_mmap_pages;
>       unsigned int user_freq;
>       u64          branch_stack;
> +     u64          sample_intr_regs;
>       u64          default_interval;
>       u64          user_interval;
>       size_t       auxtrace_snapshot_size;
> diff --git a/tools/perf/util/Build b/tools/perf/util/Build
> index e912856..7df4937 100644
> --- a/tools/perf/util/Build
> +++ b/tools/perf/util/Build
> @@ -82,6 +82,7 @@ libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/
>  libperf-$(CONFIG_AUXTRACE) += intel-pt.o
>  libperf-$(CONFIG_AUXTRACE) += intel-bts.o
>  libperf-y += parse-branch-options.o
> +libperf-y += parse-regs-options.o
>  
>  libperf-$(CONFIG_LIBELF) += symbol-elf.o
>  libperf-$(CONFIG_LIBELF) += probe-file.o
> diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
> index fd53cc2..b049633 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)
>               perf_evsel__config_callgraph(evsel, opts, &callchain_param);
>  
>       if (opts->sample_intr_regs) {
> -             attr->sample_regs_intr = PERF_REGS_MASK;
> +             attr->sample_regs_intr = opts->sample_intr_regs;
>               perf_evsel__set_sample_bit(evsel, REGS_INTR);
>       }
>  
> diff --git a/tools/perf/util/parse-regs-options.c 
> b/tools/perf/util/parse-regs-options.c
> new file mode 100644
> index 0000000..4f2c1c2
> --- /dev/null
> +++ b/tools/perf/util/parse-regs-options.c
> @@ -0,0 +1,71 @@
> +#include "perf.h"
> +#include "util/util.h"
> +#include "util/debug.h"
> +#include "util/parse-options.h"
> +#include "util/parse-regs-options.h"
> +
> +int
> +parse_regs(const struct option *opt, const char *str, int unset)
> +{
> +     uint64_t *mode = (uint64_t *)opt->value;
> +     const struct sample_reg *r;
> +     char *s, *os = NULL, *p;
> +     int ret = -1;
> +
> +     if (unset)
> +             return 0;
> +
> +     /*
> +      * cannot set it twice
> +      */
> +     if (*mode)
> +             return -1;
> +
> +     /* str may be NULL in case no arg is passed to -I */
> +     if (str) {
> +             /* because str is read-only */
> +             s = os = strdup(str);
> +             if (!s)
> +                     return -1;
> +
> +             for (;;) {
> +                     p = strchr(s, ',');
> +                     if (p)
> +                             *p = '\0';
> +
> +                     if (!strcmp(s, "?")) {
> +                             fprintf(stderr, "available registers: ");
> +                             for (r = sample_reg_masks; r->name; r++) {
> +                                     fprintf(stderr, "%s ", r->name);
> +                             }
> +                             fputc('\n', stderr);
> +                             /* just printing available regs */
> +                             return -1;
> +                     }
> +                     for (r = sample_reg_masks; r->name; r++) {
> +                             if (!strcasecmp(s, r->name))
> +                                     break;
> +                     }
> +                     if (!r->name) {
> +                             ui__warning("unknown register %s,"
> +                                         " check man page\n", s);
> +                             goto error;
> +                     }
> +
> +                     *mode |= r->mask;
> +
> +                     if (!p)
> +                             break;
> +
> +                     s = p + 1;
> +             }
> +     }
> +     ret = 0;
> +
> +     /* default to all possible regs */
> +     if (*mode == 0)
> +             *mode = PERF_REGS_MASK;
> +error:
> +     free(os);
> +     return ret;
> +}
> diff --git a/tools/perf/util/parse-regs-options.h 
> b/tools/perf/util/parse-regs-options.h
> new file mode 100644
> index 0000000..7d762b1
> --- /dev/null
> +++ b/tools/perf/util/parse-regs-options.h
> @@ -0,0 +1,5 @@
> +#ifndef _PERF_PARSE_REGS_OPTIONS_H
> +#define _PERF_PARSE_REGS_OPTIONS_H 1
> +struct option;
> +int parse_regs(const struct option *opt, const char *str, int unset);
> +#endif /* _PERF_PARSE_REGS_OPTIONS_H */
> -- 
> 1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to