mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
perf session: Add instruction tracing options
It is assumed that AUX area decoding will synthesize events for consumption by other tools. At this time, the main use of AUX area tracing will be to capture instruction trace (aka processor trace) data. The nature of instruction tracing suggests the initial inclusion of options for "instructions" and "branches" events, but more could be added as needed. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/r/1428594864-29309-10-git-send-email-adrian.hunter@intel.com [ Added ref to tools/perf/Documentation/perf-script.txt describing what is parsed ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
c446870d80
commit
f6986c95af
3 changed files with 181 additions and 0 deletions
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include "event.h"
|
||||
#include "debug.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
|
||||
struct auxtrace_mmap_params *mp,
|
||||
|
@ -200,6 +201,141 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
|
|||
return err;
|
||||
}
|
||||
|
||||
#define PERF_ITRACE_DEFAULT_PERIOD_TYPE PERF_ITRACE_PERIOD_NANOSECS
|
||||
#define PERF_ITRACE_DEFAULT_PERIOD 100000
|
||||
#define PERF_ITRACE_DEFAULT_CALLCHAIN_SZ 16
|
||||
#define PERF_ITRACE_MAX_CALLCHAIN_SZ 1024
|
||||
|
||||
void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts)
|
||||
{
|
||||
synth_opts->instructions = true;
|
||||
synth_opts->branches = true;
|
||||
synth_opts->errors = true;
|
||||
synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE;
|
||||
synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
|
||||
synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Please check tools/perf/Documentation/perf-script.txt for information
|
||||
* about the options parsed here, which is introduced after this cset,
|
||||
* when support in 'perf script' for these options is introduced.
|
||||
*/
|
||||
int itrace_parse_synth_opts(const struct option *opt, const char *str,
|
||||
int unset)
|
||||
{
|
||||
struct itrace_synth_opts *synth_opts = opt->value;
|
||||
const char *p;
|
||||
char *endptr;
|
||||
|
||||
synth_opts->set = true;
|
||||
|
||||
if (unset) {
|
||||
synth_opts->dont_decode = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!str) {
|
||||
itrace_synth_opts__set_default(synth_opts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (p = str; *p;) {
|
||||
switch (*p++) {
|
||||
case 'i':
|
||||
synth_opts->instructions = true;
|
||||
while (*p == ' ' || *p == ',')
|
||||
p += 1;
|
||||
if (isdigit(*p)) {
|
||||
synth_opts->period = strtoull(p, &endptr, 10);
|
||||
p = endptr;
|
||||
while (*p == ' ' || *p == ',')
|
||||
p += 1;
|
||||
switch (*p++) {
|
||||
case 'i':
|
||||
synth_opts->period_type =
|
||||
PERF_ITRACE_PERIOD_INSTRUCTIONS;
|
||||
break;
|
||||
case 't':
|
||||
synth_opts->period_type =
|
||||
PERF_ITRACE_PERIOD_TICKS;
|
||||
break;
|
||||
case 'm':
|
||||
synth_opts->period *= 1000;
|
||||
/* Fall through */
|
||||
case 'u':
|
||||
synth_opts->period *= 1000;
|
||||
/* Fall through */
|
||||
case 'n':
|
||||
if (*p++ != 's')
|
||||
goto out_err;
|
||||
synth_opts->period_type =
|
||||
PERF_ITRACE_PERIOD_NANOSECS;
|
||||
break;
|
||||
case '\0':
|
||||
goto out;
|
||||
default:
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
synth_opts->branches = true;
|
||||
break;
|
||||
case 'e':
|
||||
synth_opts->errors = true;
|
||||
break;
|
||||
case 'd':
|
||||
synth_opts->log = true;
|
||||
break;
|
||||
case 'c':
|
||||
synth_opts->branches = true;
|
||||
synth_opts->calls = true;
|
||||
break;
|
||||
case 'r':
|
||||
synth_opts->branches = true;
|
||||
synth_opts->returns = true;
|
||||
break;
|
||||
case 'g':
|
||||
synth_opts->instructions = true;
|
||||
synth_opts->callchain = true;
|
||||
synth_opts->callchain_sz =
|
||||
PERF_ITRACE_DEFAULT_CALLCHAIN_SZ;
|
||||
while (*p == ' ' || *p == ',')
|
||||
p += 1;
|
||||
if (isdigit(*p)) {
|
||||
unsigned int val;
|
||||
|
||||
val = strtoul(p, &endptr, 10);
|
||||
p = endptr;
|
||||
if (!val || val > PERF_ITRACE_MAX_CALLCHAIN_SZ)
|
||||
goto out_err;
|
||||
synth_opts->callchain_sz = val;
|
||||
}
|
||||
break;
|
||||
case ' ':
|
||||
case ',':
|
||||
break;
|
||||
default:
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (synth_opts->instructions) {
|
||||
if (!synth_opts->period_type)
|
||||
synth_opts->period_type =
|
||||
PERF_ITRACE_DEFAULT_PERIOD_TYPE;
|
||||
if (!synth_opts->period)
|
||||
synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_err:
|
||||
pr_err("Bad Instruction Tracing options '%s'\n", str);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
|
||||
struct perf_tool *tool, process_auxtrace_t fn)
|
||||
{
|
||||
|
|
|
@ -29,9 +29,49 @@ union perf_event;
|
|||
struct perf_session;
|
||||
struct perf_evlist;
|
||||
struct perf_tool;
|
||||
struct option;
|
||||
struct record_opts;
|
||||
struct auxtrace_info_event;
|
||||
|
||||
enum itrace_period_type {
|
||||
PERF_ITRACE_PERIOD_INSTRUCTIONS,
|
||||
PERF_ITRACE_PERIOD_TICKS,
|
||||
PERF_ITRACE_PERIOD_NANOSECS,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct itrace_synth_opts - AUX area tracing synthesis options.
|
||||
* @set: indicates whether or not options have been set
|
||||
* @inject: indicates the event (not just the sample) must be fully synthesized
|
||||
* because 'perf inject' will write it out
|
||||
* @instructions: whether to synthesize 'instructions' events
|
||||
* @branches: whether to synthesize 'branches' events
|
||||
* @errors: whether to synthesize decoder error events
|
||||
* @dont_decode: whether to skip decoding entirely
|
||||
* @log: write a decoding log
|
||||
* @calls: limit branch samples to calls (can be combined with @returns)
|
||||
* @returns: limit branch samples to returns (can be combined with @calls)
|
||||
* @callchain: add callchain to 'instructions' events
|
||||
* @callchain_sz: maximum callchain size
|
||||
* @period: 'instructions' events period
|
||||
* @period_type: 'instructions' events period type
|
||||
*/
|
||||
struct itrace_synth_opts {
|
||||
bool set;
|
||||
bool inject;
|
||||
bool instructions;
|
||||
bool branches;
|
||||
bool errors;
|
||||
bool dont_decode;
|
||||
bool log;
|
||||
bool calls;
|
||||
bool returns;
|
||||
bool callchain;
|
||||
unsigned int callchain_sz;
|
||||
unsigned long long period;
|
||||
enum itrace_period_type period_type;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct auxtrace - session callbacks to allow AUX area data decoding.
|
||||
* @process_event: lets the decoder see all session events
|
||||
|
@ -186,6 +226,9 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
|
|||
struct perf_tool *tool,
|
||||
struct perf_session *session,
|
||||
perf_event__handler_t process);
|
||||
int itrace_parse_synth_opts(const struct option *opt, const char *str,
|
||||
int unset);
|
||||
void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts);
|
||||
|
||||
static inline int auxtrace__process_event(struct perf_session *session,
|
||||
union perf_event *event,
|
||||
|
|
|
@ -16,12 +16,14 @@ struct ip_callchain;
|
|||
struct thread;
|
||||
|
||||
struct auxtrace;
|
||||
struct itrace_synth_opts;
|
||||
|
||||
struct perf_session {
|
||||
struct perf_header header;
|
||||
struct machines machines;
|
||||
struct perf_evlist *evlist;
|
||||
struct auxtrace *auxtrace;
|
||||
struct itrace_synth_opts *itrace_synth_opts;
|
||||
struct trace_event tevent;
|
||||
bool repipe;
|
||||
bool one_mmap;
|
||||
|
|
Loading…
Reference in a new issue