From: Tony Luck <tony.l...@intel.com>

-f shows absolute value from the file each time. -F shows the delta
---

This is a proof-of-concept patch to show how "perf" might be extended to
use the new RDT file system monitoring files. "-f" is useful for the 
llc_occupancy
"-F" for the MBM files.

 tools/perf/builtin-c2c.c       |  2 ++
 tools/perf/builtin-mem.c       |  2 ++
 tools/perf/builtin-record.c    |  4 ++++
 tools/perf/builtin-stat.c      |  4 ++++
 tools/perf/builtin-top.c       |  4 ++++
 tools/perf/builtin-trace.c     |  4 ++++
 tools/perf/util/evsel.c        | 22 ++++++++++++++++++++++
 tools/perf/util/evsel.h        |  1 +
 tools/perf/util/parse-events.c | 17 +++++++++++++++++
 tools/perf/util/parse-events.h |  1 +
 10 files changed, 61 insertions(+)

diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index 475999e48f66..094b84d34f7b 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -2692,6 +2692,8 @@ static int perf_c2c__record(int argc, const char **argv)
        OPT_CALLBACK('e', "event", &event_set, "event",
                     "event selector. Use 'perf mem record -e list' to list 
available events",
                     parse_record_events),
+       OPT_CALLBACK('f', "file", &event_set, "file", "file selector", 
parse_files_option),
+       OPT_CALLBACK('F', "file", &event_set, "file", "delta file selector", 
parse_files_option),
        OPT_BOOLEAN('u', "all-user", &all_user, "collect only user level data"),
        OPT_BOOLEAN('k', "all-kernel", &all_kernel, "collect only kernel level 
data"),
        OPT_UINTEGER('l', "ldlat", &perf_mem_events__loads_ldlat, "setup 
mem-loads latency"),
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index e001c0290793..86a332dd30cc 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -72,6 +72,8 @@ static int __cmd_record(int argc, const char **argv, struct 
perf_mem *mem)
        OPT_CALLBACK('e', "event", &mem, "event",
                     "event selector. use 'perf mem record -e list' to list 
available events",
                     parse_record_events),
+       OPT_CALLBACK('f', "file", &mem, "file", "file selector", 
parse_files_option),
+       OPT_CALLBACK('F', "file", &mem, "file", "delta file selector", 
parse_files_option),
        OPT_UINTEGER(0, "ldlat", &perf_mem_events__loads_ldlat, "mem-loads 
latency"),
        OPT_INCR('v', "verbose", &verbose,
                 "be more verbose (show counter open errors, etc)"),
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 17a14bcce34a..096a7b22f897 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1551,6 +1551,10 @@ static struct option __record_options[] = {
        OPT_CALLBACK('e', "event", &record.evlist, "event",
                     "event selector. use 'perf list' to list available events",
                     parse_events_option),
+       OPT_CALLBACK('f', "file", &record.evlist, "file",
+                    "file selector", parse_files_option),
+       OPT_CALLBACK('F', "file", &record.evlist, "file",
+                    "delta file selector", parse_files_option),
        OPT_CALLBACK(0, "filter", &record.evlist, "filter",
                     "event filter", parse_filter),
        OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 48ac53b199fc..c5da65d0acce 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1736,6 +1736,10 @@ static const struct option stat_options[] = {
        OPT_CALLBACK('e', "event", &evsel_list, "event",
                     "event selector. use 'perf list' to list available events",
                     parse_events_option),
+       OPT_CALLBACK('f', "file", &evsel_list, "file",
+                    "file selector", parse_files_option),
+       OPT_CALLBACK('F', "file", &evsel_list, "file",
+                    "delta file selector", parse_files_option),
        OPT_CALLBACK(0, "filter", &evsel_list, "filter",
                     "event filter", parse_filter),
        OPT_BOOLEAN('i', "no-inherit", &no_inherit,
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 6052376634c0..ded5a9e35c6b 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1104,6 +1104,10 @@ int cmd_top(int argc, const char **argv)
        OPT_CALLBACK('e', "event", &top.evlist, "event",
                     "event selector. use 'perf list' to list available events",
                     parse_events_option),
+       OPT_CALLBACK('f', "file", &top.evlist, "file",
+                    "file selector", parse_files_option),
+       OPT_CALLBACK('F', "file", &top.evlist, "file",
+                    "delta file selector", parse_files_option),
        OPT_U64('c', "count", &opts->user_interval, "event period to sample"),
        OPT_STRING('p', "pid", &target->pid, "pid",
                    "profile events on existing process id"),
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 4b2a5d298197..b404ebc829bc 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2862,6 +2862,10 @@ int cmd_trace(int argc, const char **argv)
        OPT_CALLBACK('e', "event", &trace, "event",
                     "event/syscall selector. use 'perf list' to list available 
events",
                     trace__parse_events_option),
+       OPT_CALLBACK('f', "file", &evsel_list, "file",
+                    "file selector", parse_files_option),
+       OPT_CALLBACK('F', "file", &evsel_list, "file",
+                    "delta file selector", parse_files_option),
        OPT_BOOLEAN(0, "comm", &trace.show_comm,
                    "show the thread COMM next to its id"),
        OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 413f74df08de..3353571a5c7e 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1256,6 +1256,21 @@ void perf_counts_values__scale(struct perf_counts_values 
*count,
                *pscaled = scaled;
 }
 
+static int read_sys_file(int fd, struct perf_counts_values *count)
+{
+       char buf[100];
+       int n;
+       static u64 fake;
+
+       n = pread(fd, buf, sizeof buf, 0);
+       if (n >= 0) {
+               count->val = n ? strtol(buf, NULL, 0) : 0;
+               count->ena = count->run = ++fake;
+               return 0;
+       } else
+               return -errno;
+}
+
 int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
                     struct perf_counts_values *count)
 {
@@ -1264,6 +1279,8 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu, 
int thread,
        if (FD(evsel, cpu, thread) < 0)
                return -EINVAL;
 
+       if (evsel->sysfile)
+               return read_sys_file(FD(evsel, cpu, thread), count);
        if (readn(FD(evsel, cpu, thread), count, sizeof(*count)) <= 0)
                return -errno;
 
@@ -1556,6 +1573,11 @@ int perf_evsel__open(struct perf_evsel *evsel, struct 
cpu_map *cpus,
                fprintf(stderr, "%.60s\n", graph_dotted_line);
        }
 
+       if (evsel->sysfile) {
+               FD(evsel, 0, 0) = open(evsel->name, O_RDONLY, 0);
+               return 0;
+       }
+
        for (cpu = 0; cpu < cpus->nr; cpu++) {
 
                for (thread = 0; thread < nthreads; thread++) {
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index d101695c482c..ede30e111947 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -121,6 +121,7 @@ struct perf_evsel {
        bool                    per_pkg;
        bool                    precise_max;
        bool                    ignore_missing_thread;
+       bool                    sysfile;
        /* parse modifier helper */
        int                     exclude_GH;
        int                     nr_members;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 01e779b91c8e..0d725eda476d 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1793,6 +1793,23 @@ int parse_events_option(const struct option *opt, const 
char *str,
        return ret;
 }
 
+int parse_files_option(const struct option *opt, const char *str,
+                      int unset __maybe_unused)
+{
+       struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
+       struct perf_evsel *evsel = calloc(1, sizeof (*evsel));
+
+       evsel->name = strdup(str);
+       evsel->unit = "";
+       evsel->sysfile = true;
+       evsel->snapshot = (opt->short_name == 'f');
+       evsel->scale = 1.0;
+       INIT_LIST_HEAD(&evsel->config_terms);
+       evsel->bpf_fd = -1;
+       perf_evlist__add(evlist, evsel);
+       return 0;
+}
+
 static int
 foreach_evsel_in_last_glob(struct perf_evlist *evlist,
                           int (*func)(struct perf_evsel *evsel,
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index a235f4d6d5e5..7e14a4c66fad 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -30,6 +30,7 @@ bool have_tracepoints(struct list_head *evlist);
 const char *event_type(int type);
 
 int parse_events_option(const struct option *opt, const char *str, int unset);
+int parse_files_option(const struct option *opt, const char *str, int unset);
 int parse_events(struct perf_evlist *evlist, const char *str,
                 struct parse_events_error *error);
 int parse_events_terms(struct list_head *terms, const char *str);
-- 
2.11.0

Reply via email to