]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - tools/perf/builtin-script.c
perf script: Allow specifying the files to process guest samples
[linux.git] / tools / perf / builtin-script.c
index 3a48a2627670fc085b6bc6a86b1d8545f392eb67..2f6232f1bfdc4649a242a8ad597ca736641abcd4 100644 (file)
@@ -49,7 +49,7 @@
 #include <unistd.h>
 #include <subcmd/pager.h>
 
-#include "sane_ctype.h"
+#include <linux/ctype.h>
 
 static char const              *script_name;
 static char const              *generate_script_lang;
@@ -102,6 +102,7 @@ enum perf_output_field {
        PERF_OUTPUT_METRIC          = 1U << 28,
        PERF_OUTPUT_MISC            = 1U << 29,
        PERF_OUTPUT_SRCCODE         = 1U << 30,
+       PERF_OUTPUT_IPC             = 1U << 31,
 };
 
 struct output_option {
@@ -139,6 +140,7 @@ struct output_option {
        {.str = "metric", .field = PERF_OUTPUT_METRIC},
        {.str = "misc", .field = PERF_OUTPUT_MISC},
        {.str = "srccode", .field = PERF_OUTPUT_SRCCODE},
+       {.str = "ipc", .field = PERF_OUTPUT_IPC},
 };
 
 enum {
@@ -1268,6 +1270,20 @@ static int perf_sample__fprintf_insn(struct perf_sample *sample,
        return printed;
 }
 
+static int perf_sample__fprintf_ipc(struct perf_sample *sample,
+                                   struct perf_event_attr *attr, FILE *fp)
+{
+       unsigned int ipc;
+
+       if (!PRINT_FIELD(IPC) || !sample->cyc_cnt || !sample->insn_cnt)
+               return 0;
+
+       ipc = (sample->insn_cnt * 100) / sample->cyc_cnt;
+
+       return fprintf(fp, " \t IPC: %u.%02u (%" PRIu64 "/%" PRIu64 ") ",
+                      ipc / 100, ipc % 100, sample->insn_cnt, sample->cyc_cnt);
+}
+
 static int perf_sample__fprintf_bts(struct perf_sample *sample,
                                    struct perf_evsel *evsel,
                                    struct thread *thread,
@@ -1312,6 +1328,8 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample,
                printed += perf_sample__fprintf_addr(sample, thread, attr, fp);
        }
 
+       printed += perf_sample__fprintf_ipc(sample, attr, fp);
+
        if (print_srcline_last)
                printed += map__fprintf_srcline(al->map, al->addr, "\n  ", fp);
 
@@ -1859,6 +1877,9 @@ static void process_event(struct perf_script *script,
 
        if (PRINT_FIELD(PHYS_ADDR))
                fprintf(fp, "%16" PRIx64, sample->phys_addr);
+
+       perf_sample__fprintf_ipc(sample, attr, fp);
+
        fprintf(fp, "\n");
 
        if (PRINT_FIELD(SRCCODE)) {
@@ -2859,7 +2880,7 @@ static int read_script_info(struct script_desc *desc, const char *filename)
                return -1;
 
        while (fgets(line, sizeof(line), fp)) {
-               p = ltrim(line);
+               p = skip_spaces(line);
                if (strlen(p) == 0)
                        continue;
                if (*p != '#')
@@ -2868,19 +2889,19 @@ static int read_script_info(struct script_desc *desc, const char *filename)
                if (strlen(p) && *p == '!')
                        continue;
 
-               p = ltrim(p);
+               p = skip_spaces(p);
                if (strlen(p) && p[strlen(p) - 1] == '\n')
                        p[strlen(p) - 1] = '\0';
 
                if (!strncmp(p, "description:", strlen("description:"))) {
                        p += strlen("description:");
-                       desc->half_liner = strdup(ltrim(p));
+                       desc->half_liner = strdup(skip_spaces(p));
                        continue;
                }
 
                if (!strncmp(p, "args:", strlen("args:"))) {
                        p += strlen("args:");
-                       desc->args = strdup(ltrim(p));
+                       desc->args = strdup(skip_spaces(p));
                        continue;
                }
        }
@@ -2987,7 +3008,7 @@ static int check_ev_match(char *dir_name, char *scriptname,
                return -1;
 
        while (fgets(line, sizeof(line), fp)) {
-               p = ltrim(line);
+               p = skip_spaces(line);
                if (*p == '#')
                        continue;
 
@@ -2997,7 +3018,7 @@ static int check_ev_match(char *dir_name, char *scriptname,
                                break;
 
                        p += 2;
-                       p = ltrim(p);
+                       p = skip_spaces(p);
                        len = strcspn(p, " \t");
                        if (!len)
                                break;
@@ -3433,7 +3454,7 @@ int cmd_script(int argc, const char **argv)
                     "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
                     "addr,symoff,srcline,period,iregs,uregs,brstack,"
                     "brstacksym,flags,bpf-output,brstackinsn,brstackoff,"
-                    "callindent,insn,insnlen,synth,phys_addr,metric,misc",
+                    "callindent,insn,insnlen,synth,phys_addr,metric,misc,ipc",
                     parse_output_fields),
        OPT_BOOLEAN('a', "all-cpus", &system_wide,
                    "system-wide collection from all CPUs"),
@@ -3501,6 +3522,15 @@ int cmd_script(int argc, const char **argv)
                   "Time span of interest (start,stop)"),
        OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
                    "Show inline function"),
+       OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
+                  "guest mount directory under which every guest os"
+                  " instance has a subdir"),
+       OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name,
+                  "file", "file saving guest os vmlinux"),
+       OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms,
+                  "file", "file saving guest os /proc/kallsyms"),
+       OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
+                  "file", "file saving guest os /proc/modules"),
        OPT_END()
        };
        const char * const script_subcommands[] = { "record", "report", NULL };
@@ -3520,6 +3550,16 @@ int cmd_script(int argc, const char **argv)
        argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
                             PARSE_OPT_STOP_AT_NON_OPTION);
 
+       if (symbol_conf.guestmount ||
+           symbol_conf.default_guest_vmlinux_name ||
+           symbol_conf.default_guest_kallsyms ||
+           symbol_conf.default_guest_modules) {
+               /*
+                * Enable guest sample processing.
+                */
+               perf_guest = true;
+       }
+
        data.path  = input_name;
        data.force = symbol_conf.force;
 
@@ -3808,6 +3848,10 @@ int cmd_script(int argc, const char **argv)
                                                  &script.range_num);
                if (err < 0)
                        goto out_delete;
+
+               itrace_synth_opts__set_time_range(&itrace_synth_opts,
+                                                 script.ptime_range,
+                                                 script.range_num);
        }
 
        err = __cmd_script(&script);
@@ -3815,8 +3859,10 @@ int cmd_script(int argc, const char **argv)
        flush_scripting();
 
 out_delete:
-       if (script.ptime_range)
+       if (script.ptime_range) {
+               itrace_synth_opts__clear_time_range(&itrace_synth_opts);
                zfree(&script.ptime_range);
+       }
 
        perf_evlist__free_stats(session->evlist);
        perf_session__delete(session);