diff options
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/util/auxtrace.c | 107 | ||||
-rw-r--r-- | tools/perf/util/auxtrace.h | 17 | ||||
-rw-r--r-- | tools/perf/util/pmu.h | 1 | ||||
-rw-r--r-- | tools/perf/util/record.h | 2 |
4 files changed, 127 insertions, 0 deletions
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 263d1d9d8987..51fbe01f8a11 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -69,6 +69,13 @@ static struct perf_pmu *perf_evsel__find_pmu(struct evsel *evsel) return pmu; } +static bool perf_evsel__is_aux_event(struct evsel *evsel) +{ + struct perf_pmu *pmu = perf_evsel__find_pmu(evsel); + + return pmu && pmu->auxtrace; +} + static bool auxtrace__dont_decode(struct perf_session *session) { return !session->itrace_synth_opts || @@ -609,6 +616,106 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr, return -EINVAL; } +/* + * Event record size is 16-bit which results in a maximum size of about 64KiB. + * Allow about 4KiB for the rest of the sample record, to give a maximum + * AUX area sample size of 60KiB. + */ +#define MAX_AUX_SAMPLE_SIZE (60 * 1024) + +/* Arbitrary default size if no other default provided */ +#define DEFAULT_AUX_SAMPLE_SIZE (4 * 1024) + +static int auxtrace_validate_aux_sample_size(struct evlist *evlist, + struct record_opts *opts) +{ + struct evsel *evsel; + bool has_aux_leader = false; + u32 sz; + + evlist__for_each_entry(evlist, evsel) { + sz = evsel->core.attr.aux_sample_size; + if (perf_evsel__is_group_leader(evsel)) { + has_aux_leader = perf_evsel__is_aux_event(evsel); + if (sz) { + if (has_aux_leader) + pr_err("Cannot add AUX area sampling to an AUX area event\n"); + else + pr_err("Cannot add AUX area sampling to a group leader\n"); + return -EINVAL; + } + } + if (sz > MAX_AUX_SAMPLE_SIZE) { + pr_err("AUX area sample size %u too big, max. %d\n", + sz, MAX_AUX_SAMPLE_SIZE); + return -EINVAL; + } + if (sz) { + if (!has_aux_leader) { + pr_err("Cannot add AUX area sampling because group leader is not an AUX area event\n"); + return -EINVAL; + } + perf_evsel__set_sample_bit(evsel, AUX); + opts->auxtrace_sample_mode = true; + } else { + perf_evsel__reset_sample_bit(evsel, AUX); + } + } + + if (!opts->auxtrace_sample_mode) { + pr_err("AUX area sampling requires an AUX area event group leader plus other events to which to add samples\n"); + return -EINVAL; + } + + if (!perf_can_aux_sample()) { + pr_err("AUX area sampling is not supported by kernel\n"); + return -EINVAL; + } + + return 0; +} + +int auxtrace_parse_sample_options(struct auxtrace_record *itr, + struct evlist *evlist, + struct record_opts *opts, const char *str) +{ + bool has_aux_leader = false; + struct evsel *evsel; + char *endptr; + unsigned long sz; + + if (!str) + return 0; + + if (!itr) { + pr_err("No AUX area event to sample\n"); + return -EINVAL; + } + + sz = strtoul(str, &endptr, 0); + if (*endptr || sz > UINT_MAX) { + pr_err("Bad AUX area sampling option: '%s'\n", str); + return -EINVAL; + } + + if (!sz) + sz = itr->default_aux_sample_size; + + if (!sz) + sz = DEFAULT_AUX_SAMPLE_SIZE; + + /* Set aux_sample_size based on --aux-sample option */ + evlist__for_each_entry(evlist, evsel) { + if (perf_evsel__is_group_leader(evsel)) { + has_aux_leader = perf_evsel__is_aux_event(evsel); + } else if (has_aux_leader) { + evsel->core.attr.aux_sample_size = sz; + } + } + + return auxtrace_validate_aux_sample_size(evlist, opts); +} + struct auxtrace_record *__weak auxtrace_record__init(struct evlist *evlist __maybe_unused, int *err) { diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index 3f4aa5427d76..ab48de13c353 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -313,6 +313,7 @@ struct auxtrace_mmap_params { * @reference: provide a 64-bit reference number for auxtrace_event * @read_finish: called after reading from an auxtrace mmap * @alignment: alignment (if any) for AUX area data + * @default_aux_sample_size: default sample size for --aux sample option */ struct auxtrace_record { int (*recording_options)(struct auxtrace_record *itr, @@ -336,6 +337,7 @@ struct auxtrace_record { u64 (*reference)(struct auxtrace_record *itr); int (*read_finish)(struct auxtrace_record *itr, int idx); unsigned int alignment; + unsigned int default_aux_sample_size; }; /** @@ -498,6 +500,9 @@ struct auxtrace_record *auxtrace_record__init(struct evlist *evlist, int auxtrace_parse_snapshot_options(struct auxtrace_record *itr, struct record_opts *opts, const char *str); +int auxtrace_parse_sample_options(struct auxtrace_record *itr, + struct evlist *evlist, + struct record_opts *opts, const char *str); int auxtrace_record__options(struct auxtrace_record *itr, struct evlist *evlist, struct record_opts *opts); @@ -649,6 +654,18 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr __maybe_unused, } static inline +int auxtrace_parse_sample_options(struct auxtrace_record *itr __maybe_unused, + struct evlist *evlist __maybe_unused, + struct record_opts *opts __maybe_unused, + const char *str) +{ + if (!str) + return 0; + pr_err("AUX area tracing not supported\n"); + return -EINVAL; +} + +static inline int auxtrace__process_event(struct perf_session *session __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample __maybe_unused, diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 3e8cd31a89cc..2eb7a7001307 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -26,6 +26,7 @@ struct perf_pmu { __u32 type; bool selectable; bool is_uncore; + bool auxtrace; int max_precise; struct perf_event_attr *default_config; struct perf_cpu_map *cpus; diff --git a/tools/perf/util/record.h b/tools/perf/util/record.h index 948bbcf9aef3..5421fd2ad383 100644 --- a/tools/perf/util/record.h +++ b/tools/perf/util/record.h @@ -32,6 +32,7 @@ struct record_opts { bool full_auxtrace; bool auxtrace_snapshot_mode; bool auxtrace_snapshot_on_exit; + bool auxtrace_sample_mode; bool record_namespaces; bool record_switch_events; bool all_kernel; @@ -56,6 +57,7 @@ struct record_opts { u64 user_interval; size_t auxtrace_snapshot_size; const char *auxtrace_snapshot_opts; + const char *auxtrace_sample_opts; bool sample_transaction; unsigned initial_delay; bool use_clockid; |