perf inject: Add --vm-time-correlation option
authorAdrian Hunter <adrian.hunter@intel.com>
Fri, 30 Apr 2021 07:03:02 +0000 (10:03 +0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 12 May 2021 15:43:10 +0000 (12:43 -0300)
Intel PT timestamps are affected by virtualization. Add a new option
that will allow the Intel PT decoder to correlate the timestamps and
translate the virtual machine timestamps to host timestamps.

The advantages of making this a separate step, rather than a part of
normal decoding are that it is simpler to implement, and it needs to
be done only once.

This patch adds only the option. Later patches add Intel PT support.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: https://lore.kernel.org/r/20210430070309.17624-6-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/Documentation/perf-inject.txt
tools/perf/builtin-inject.c
tools/perf/util/auxtrace.h

index a8eccff212813e51b27f2a19ecbb9d74addd087f..91108fe3ad5fa5542160a6ef98d3209aa6aa4d37 100644 (file)
@@ -68,6 +68,16 @@ include::itrace.txt[]
 --force::
        Don't complain, do it.
 
+--vm-time-correlation[=OPTIONS]::
+       Some architectures may capture AUX area data which contains timestamps
+       affected by virtualization. This option will update those timestamps
+       in place, to correlate with host timestamps. The in-place update means
+       that an output file is not specified, and instead the input file is
+       modified.  The options are architecture specific, except that they may
+       start with "dry-run" which will cause the file to be processed but
+       without updating it. Currently this option is supported only by
+       Intel PT, refer linkperf:perf-intel-pt[1]
+
 SEE ALSO
 --------
 linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1],
index 6007f1844b012cb4b81e8211df1c770c50117f06..102cafb0c0b3fe1f7bc9099b9cfdd6c70ff2da44 100644 (file)
@@ -31,6 +31,7 @@
 #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
 
 #include <linux/list.h>
+#include <linux/string.h>
 #include <errno.h>
 #include <signal.h>
 
@@ -698,6 +699,36 @@ static void strip_init(struct perf_inject *inject)
                evsel->handler = drop_sample;
 }
 
+static int parse_vm_time_correlation(const struct option *opt, const char *str, int unset)
+{
+       struct perf_inject *inject = opt->value;
+       const char *args;
+       char *dry_run;
+
+       if (unset)
+               return 0;
+
+       inject->itrace_synth_opts.set = true;
+       inject->itrace_synth_opts.vm_time_correlation = true;
+       inject->in_place_update = true;
+
+       if (!str)
+               return 0;
+
+       dry_run = skip_spaces(str);
+       if (!strncmp(dry_run, "dry-run", strlen("dry-run"))) {
+               inject->itrace_synth_opts.vm_tm_corr_dry_run = true;
+               inject->in_place_update_dry_run = true;
+               args = dry_run + strlen("dry-run");
+       } else {
+               args = str;
+       }
+
+       inject->itrace_synth_opts.vm_tm_corr_args = strdup(args);
+
+       return inject->itrace_synth_opts.vm_tm_corr_args ? 0 : -ENOMEM;
+}
+
 static int __cmd_inject(struct perf_inject *inject)
 {
        int ret = -EINVAL;
@@ -739,6 +770,15 @@ static int __cmd_inject(struct perf_inject *inject)
                        else if (!strncmp(name, "sched:sched_stat_", 17))
                                evsel->handler = perf_inject__sched_stat;
                }
+       } else if (inject->itrace_synth_opts.vm_time_correlation) {
+               session->itrace_synth_opts = &inject->itrace_synth_opts;
+               memset(&inject->tool, 0, sizeof(inject->tool));
+               inject->tool.id_index       = perf_event__process_id_index;
+               inject->tool.auxtrace_info  = perf_event__process_auxtrace_info;
+               inject->tool.auxtrace       = perf_event__process_auxtrace;
+               inject->tool.auxtrace_error = perf_event__process_auxtrace_error;
+               inject->tool.ordered_events = true;
+               inject->tool.ordering_requires_timestamps = true;
        } else if (inject->itrace_synth_opts.set) {
                session->itrace_synth_opts = &inject->itrace_synth_opts;
                inject->itrace_synth_opts.inject = true;
@@ -880,6 +920,9 @@ int cmd_inject(int argc, const char **argv)
                                    itrace_parse_synth_opts),
                OPT_BOOLEAN(0, "strip", &inject.strip,
                            "strip non-synthesized events (use with --itrace)"),
+               OPT_CALLBACK_OPTARG(0, "vm-time-correlation", &inject, NULL, "opts",
+                                   "correlate time between VM guests and the host",
+                                   parse_vm_time_correlation),
                OPT_END()
        };
        const char * const inject_usage[] = {
@@ -968,5 +1011,6 @@ int cmd_inject(int argc, const char **argv)
 out_delete:
        zstd_fini(&(inject.session->zstd_data));
        perf_session__delete(inject.session);
+       free(inject.itrace_synth_opts.vm_tm_corr_args);
        return ret;
 }
index 59c3c05384a4d925deb2fd5382596ce91e1fb72d..9ac2ac1bd79345d3fa7ab9f9c4fa3cae377f827e 100644 (file)
@@ -90,6 +90,9 @@ enum itrace_period_type {
  * @remote_access: whether to synthesize remote access events
  * @mem: whether to synthesize memory events
  * @timeless_decoding: prefer "timeless" decoding i.e. ignore timestamps
+ * @vm_time_correlation: perform VM Time Correlation
+ * @vm_tm_corr_dry_run: VM Time Correlation dry-run
+ * @vm_tm_corr_args:  VM Time Correlation implementation-specific arguments
  * @callchain_sz: maximum callchain size
  * @last_branch_sz: branch context size
  * @period: 'instructions' events period
@@ -130,6 +133,9 @@ struct itrace_synth_opts {
        bool                    remote_access;
        bool                    mem;
        bool                    timeless_decoding;
+       bool                    vm_time_correlation;
+       bool                    vm_tm_corr_dry_run;
+       char                    *vm_tm_corr_args;
        unsigned int            callchain_sz;
        unsigned int            last_branch_sz;
        unsigned long long      period;