Commit-ID:  54fbad54ebcde9db9c7459e9e379f2350c25e1f1
Gitweb:     http://git.kernel.org/tip/54fbad54ebcde9db9c7459e9e379f2350c25e1f1
Author:     Jiri Olsa <jo...@kernel.org>
AuthorDate: Wed, 24 Feb 2016 09:46:42 +0100
Committer:  Arnaldo Carvalho de Melo <a...@redhat.com>
CommitDate: Wed, 24 Feb 2016 10:10:59 -0300

perf mem record: Check for memory events support

Check if current kernel support available memory events and display the
status within -e  list option:

  $ perf mem record -e list
  ldlat-loads  : available
  ldlat-stores : available

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <a...@redhat.com>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: David Ahern <dsah...@gmail.com>
Cc: Namhyung Kim <namhy...@kernel.org>
Cc: Peter Zijlstra <a.p.zijls...@chello.nl>
Cc: Stephane Eranian <eran...@google.com>
Link: 
http://lkml.kernel.org/r/1456303616-26926-2-git-send-email-jo...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <a...@redhat.com>
---
 tools/perf/builtin-mem.c     | 20 ++++++++++++++++----
 tools/perf/util/mem-events.c | 35 ++++++++++++++++++++++++++++++++---
 tools/perf/util/mem-events.h |  3 +++
 3 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index b3f8a89..f1fa7b8 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -40,10 +40,11 @@ static int parse_record_events(const struct option *opt,
        for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
                struct perf_mem_event *e = &perf_mem_events[j];
 
-               fprintf(stderr, "%-20s%s",
-                       e->tag, verbose ? "" : "\n");
-               if (verbose)
-                       fprintf(stderr, " [%s]\n", e->name);
+               fprintf(stderr, "%-13s%-*s%s\n",
+                       e->tag,
+                       verbose ? 25 : 0,
+                       verbose ? e->name : "",
+                       e->supported ? ": available" : "");
        }
        exit(0);
 }
@@ -92,6 +93,12 @@ static int __cmd_record(int argc, const char **argv, struct 
perf_mem *mem)
                if (!perf_mem_events[j].record)
                        continue;
 
+               if (!perf_mem_events[j].supported) {
+                       pr_err("failed: event '%s' not supported\n",
+                              perf_mem_events[j].name);
+                       return -1;
+               }
+
                rec_argv[i++] = "-e";
                rec_argv[i++] = perf_mem_events[j].name;
        };
@@ -355,6 +362,11 @@ int cmd_mem(int argc, const char **argv, const char 
*prefix __maybe_unused)
                NULL
        };
 
+       if (perf_mem_events__init()) {
+               pr_err("failed: memory events not supported\n");
+               return -1;
+       }
+
        argc = parse_options_subcommand(argc, argv, mem_options, 
mem_subcommands,
                                        mem_usage, 
PARSE_OPT_STOP_AT_NON_OPTION);
 
diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c
index b1507c0..e21853f 100644
--- a/tools/perf/util/mem-events.c
+++ b/tools/perf/util/mem-events.c
@@ -2,15 +2,20 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <api/fs/fs.h>
 #include "mem-events.h"
 #include "debug.h"
 
-#define E(t, n) { .tag = t, .name = n }
+#define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s }
 
 struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
-       E("ldlat-loads",        "cpu/mem-loads,ldlat=30/P"),
-       E("ldlat-stores",       "cpu/mem-stores/P"),
+       E("ldlat-loads",        "cpu/mem-loads,ldlat=30/P",     "mem-loads"),
+       E("ldlat-stores",       "cpu/mem-stores/P",             "mem-stores"),
 };
+#undef E
 
 #undef E
 
@@ -49,3 +54,27 @@ int perf_mem_events__parse(const char *str)
        pr_err("failed: event '%s' not found, use '-e list' to get list of 
available events\n", str);
        return -1;
 }
+
+int perf_mem_events__init(void)
+{
+       const char *mnt = sysfs__mount();
+       bool found = false;
+       int j;
+
+       if (!mnt)
+               return -ENOENT;
+
+       for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
+               char path[PATH_MAX];
+               struct perf_mem_event *e = &perf_mem_events[j];
+               struct stat st;
+
+               scnprintf(path, PATH_MAX, "%s/devices/cpu/events/%s",
+                         mnt, e->sysfs_name);
+
+               if (!stat(path, &st))
+                       e->supported = found = true;
+       }
+
+       return found ? 0 : -ENOENT;
+}
diff --git a/tools/perf/util/mem-events.h b/tools/perf/util/mem-events.h
index 2995bae..75c1660 100644
--- a/tools/perf/util/mem-events.h
+++ b/tools/perf/util/mem-events.h
@@ -5,8 +5,10 @@
 
 struct perf_mem_event {
        bool            record;
+       bool            supported;
        const char      *tag;
        const char      *name;
+       const char      *sysfs_name;
 };
 
 enum {
@@ -18,5 +20,6 @@ enum {
 extern struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX];
 
 int perf_mem_events__parse(const char *str);
+int perf_mem_events__init(void);
 
 #endif /* __PERF_MEM_EVENTS_H */

Reply via email to