Messages in this thread Patch in this message | | | From | Adrian Hunter <> | Subject | [PATCH V5 05/25] perf record: Add basic Instruction Tracing support | Date | Sat, 7 Mar 2015 23:06:14 +0200 |
| |
Amend the perf record tool to read the Instruction Tracing mmap and synthesize Instruction Tracing events.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> --- tools/perf/builtin-record.c | 80 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 4 deletions(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 4fdad06..91e642f 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -27,6 +27,7 @@ #include "util/cpumap.h" #include "util/thread_map.h" #include "util/data.h" +#include "util/itrace.h" #include <unistd.h> #include <sched.h> @@ -38,6 +39,7 @@ struct record { struct record_opts opts; u64 bytes_written; struct perf_data_file file; + struct itrace_record *itr; struct perf_evlist *evlist; struct perf_session *session; const char *progname; @@ -110,6 +112,43 @@ out: return rc; } +static int record__process_itrace(struct perf_tool *tool, + union perf_event *event, void *data1, + size_t len1, void *data2, size_t len2) +{ + struct record *rec = container_of(tool, struct record, tool); + size_t padding; + u8 pad[8] = {0}; + + /* event.itrace.size includes padding, see __itrace_mmap__read() */ + padding = (len1 + len2) & 7; + if (padding) + padding = 8 - padding; + + record__write(rec, event, event->header.size); + record__write(rec, data1, len1); + record__write(rec, data2, len2); + record__write(rec, &pad, padding); + + return 0; +} + +static int record__itrace_mmap_read(struct record *rec, + struct itrace_mmap *mm) +{ + int ret; + + ret = itrace_mmap__read(mm, rec->itr, &rec->tool, + record__process_itrace); + if (ret < 0) + return ret; + + if (ret) + rec->samples++; + + return 0; +} + static volatile int done = 0; static volatile int signr = -1; static volatile int child_finished = 0; @@ -168,13 +207,15 @@ try_again: goto out; } - if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { + if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, + opts->itrace_mmap_pages, false) < 0) { if (errno == EPERM) { pr_err("Permission error mapping pages.\n" "Consider increasing " "/proc/sys/kernel/perf_event_mlock_kb,\n" "or try again with a smaller value of -m/--mmap_pages.\n" - "(current value: %u)\n", opts->mmap_pages); + "(current value: %u,%u)\n", + opts->mmap_pages, opts->itrace_mmap_pages); rc = -errno; } else { pr_err("failed to mmap with %d (%s)\n", errno, @@ -269,12 +310,20 @@ static int record__mmap_read_all(struct record *rec) int rc = 0; for (i = 0; i < rec->evlist->nr_mmaps; i++) { + struct itrace_mmap *mm = &rec->evlist->mmap[i].itrace_mmap; + if (rec->evlist->mmap[i].base) { if (record__mmap_read(rec, i) != 0) { rc = -1; goto out; } } + + if (mm->base && + record__itrace_mmap_read(rec, mm) != 0) { + rc = -1; + goto out; + } } /* @@ -304,6 +353,9 @@ static void record__init_features(struct record *rec) if (!rec->opts.branch_stack) perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); + + if (!rec->opts.full_itrace) + perf_header__clear_feat(&session->header, HEADER_ITRACE); } static volatile int workload_exec_errno; @@ -420,6 +472,13 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) } } + if (rec->opts.full_itrace) { + err = perf_event__synthesize_itrace_info(rec->itr, tool, + session, process_synthesized_event); + if (err) + goto out_delete_session; + } + err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, machine); if (err < 0) @@ -552,7 +611,7 @@ out_child: if (!err && !quiet) { char samples[128]; - if (rec->samples) + if (rec->samples && !rec->opts.full_itrace) scnprintf(samples, sizeof(samples), " (%" PRIu64 " samples)", rec->samples); else @@ -848,7 +907,7 @@ struct option *record_options = __record_options; int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) { - int err = -ENOMEM; + int err; struct record *rec = &record; char errbuf[BUFSIZ]; @@ -869,6 +928,14 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) usage_with_options(record_usage, record_options); } + if (!rec->itr) { + rec->itr = itrace_record__init(rec->evlist, &err); + if (err) + return err; + } + + err = -ENOMEM; + symbol__init(NULL); if (symbol_conf.kptr_restrict) @@ -914,6 +981,10 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) usage_with_options(record_usage, record_options); + err = itrace_record__options(rec->itr, rec->evlist, &rec->opts); + if (err) + goto out_symbol_exit; + if (record_opts__config(&rec->opts)) { err = -EINVAL; goto out_symbol_exit; @@ -923,5 +994,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) out_symbol_exit: perf_evlist__delete(rec->evlist); symbol__exit(); + itrace_record__free(rec->itr); return err; } -- 1.9.1
| |