From: Jiri Olsa <jo...@kernel.org> 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 b3f8a89ede40..f1fa7b8d1f69 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 b1507c04b257..e21853fe1312 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 2995bae6ac33..75c1660bda62 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 */ -- 2.5.0