#include "util/cache.h"
 #include "util/quote.h"
 #include "util/run-command.h"
+#include "util/parse-events.h"
+#include "util/string.h"
 
 const char perf_usage_string[] =
        "perf [--version] [--help] COMMAND [ARGS]";
        int val;
 };
 
+static char debugfs_mntpt[MAXPATHLEN];
+
 static int pager_command_config(const char *var, const char *value, void *data)
 {
        struct pager_config *c = data;
        }
 }
 
+static void set_debugfs_path(void)
+{
+       char *path;
+
+       path = getenv(PERF_DEBUGFS_ENVIRONMENT);
+       snprintf(debugfs_path, MAXPATHLEN, "%s/%s", path ?: debugfs_mntpt,
+                "tracing/events");
+}
+
 static int handle_options(const char*** argv, int* argc, int* envchanged)
 {
        int handled = 0;
                        setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
                        if (envchanged)
                                *envchanged = 1;
+               } else if (!strcmp(cmd, "--debugfs-dir")) {
+                       if (*argc < 2) {
+                               fprintf(stderr, "No directory given for --debugfs-dir.\n");
+                               usage(perf_usage_string);
+                       }
+                       strncpy(debugfs_mntpt, (*argv)[1], MAXPATHLEN);
+                       debugfs_mntpt[MAXPATHLEN - 1] = '\0';
+                       if (envchanged)
+                               *envchanged = 1;
+                       (*argv)++;
+                       (*argc)--;
+               } else if (!prefixcmp(cmd, "--debugfs-dir=")) {
+                       strncpy(debugfs_mntpt, cmd + 14, MAXPATHLEN);
+                       debugfs_mntpt[MAXPATHLEN - 1] = '\0';
+                       if (envchanged)
+                               *envchanged = 1;
                } else {
                        fprintf(stderr, "Unknown option: %s\n", cmd);
                        usage(perf_usage_string);
        if (use_pager == -1 && p->option & USE_PAGER)
                use_pager = 1;
        commit_pager_choice();
+       set_debugfs_path();
 
        status = p->fn(argc, argv, prefix);
        if (status)
        return done_alias;
 }
 
+/* mini /proc/mounts parser: searching for "^blah /mount/point debugfs" */
+static void get_debugfs_mntpt(void)
+{
+       FILE *file;
+       char fs_type[100];
+       char debugfs[MAXPATHLEN];
+
+       /*
+        * try the standard location
+        */
+       if (valid_debugfs_mount("/sys/kernel/debug/") == 0) {
+               strcpy(debugfs_mntpt, "/sys/kernel/debug/");
+               return;
+       }
+
+       /*
+        * try the sane location
+        */
+       if (valid_debugfs_mount("/debug/") == 0) {
+               strcpy(debugfs_mntpt, "/debug/");
+               return;
+       }
+
+       /*
+        * give up and parse /proc/mounts
+        */
+       file = fopen("/proc/mounts", "r");
+       if (file == NULL)
+               return;
+
+       while (fscanf(file, "%*s %"
+                     STR(MAXPATHLEN)
+                     "s %99s %*s %*d %*d\n",
+                     debugfs, fs_type) == 2) {
+               if (strcmp(fs_type, "debugfs") == 0)
+                       break;
+       }
+       fclose(file);
+       if (strcmp(fs_type, "debugfs") == 0) {
+               strncpy(debugfs_mntpt, debugfs, MAXPATHLEN);
+               debugfs_mntpt[MAXPATHLEN - 1] = '\0';
+       }
+}
 
 int main(int argc, const char **argv)
 {
        cmd = perf_extract_argv0_path(argv[0]);
        if (!cmd)
                cmd = "perf-help";
-
+       /* get debugfs mount point from /proc/mounts */
+       get_debugfs_mntpt();
        /*
         * "perf-xxxx" is the same as "perf xxxx", but we obviously:
         *
        argc--;
        handle_options(&argv, &argc, NULL);
        commit_pager_choice();
+       set_debugfs_path();
        if (argc > 0) {
                if (!prefixcmp(argv[0], "--"))
                        argv[0] += 2;
 
 #include "parse-events.h"
 #include "exec_cmd.h"
 #include "string.h"
+#include "cache.h"
 
 extern char *strcasestr(const char *haystack, const char *needle);
 
 
 struct perf_counter_attr               attrs[MAX_COUNTERS];
 
-static char default_debugfs_path[] = "/sys/kernel/debug/tracing/events";
-
 struct event_symbol {
        u8      type;
        u64     config;
        char    *alias;
 };
 
+char debugfs_path[MAXPATHLEN];
+
 #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
 #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
 
 
 #define for_each_subsystem(sys_dir, sys_dirent, sys_next, file, st)           \
        while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)        \
-       if (snprintf(file, MAXPATHLEN, "%s/%s", default_debugfs_path,          \
-                       sys_dirent.d_name) &&                                  \
+       if (snprintf(file, MAXPATHLEN, "%s/%s", debugfs_path,                  \
+                       sys_dirent.d_name) &&                                  \
           (!stat(file, &st)) && (S_ISDIR(st.st_mode)) &&                      \
           (strcmp(sys_dirent.d_name, ".")) &&                                 \
           (strcmp(sys_dirent.d_name, "..")))
 
 #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, file, st)    \
        while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next)        \
-       if (snprintf(file, MAXPATHLEN, "%s/%s/%s", default_debugfs_path,       \
-                       sys_dirent.d_name, evt_dirent.d_name) &&               \
+       if (snprintf(file, MAXPATHLEN, "%s/%s/%s", debugfs_path,               \
+                    sys_dirent.d_name, evt_dirent.d_name) &&                  \
           (!stat(file, &st)) && (S_ISDIR(st.st_mode)) &&                      \
           (strcmp(evt_dirent.d_name, ".")) &&                                 \
           (strcmp(evt_dirent.d_name, "..")))
 
 #define MAX_EVENT_LENGTH 30
 
-static int valid_debugfs_mount(void)
+int valid_debugfs_mount(const char *debugfs)
 {
        struct statfs st_fs;
 
-       if (statfs(default_debugfs_path, &st_fs) < 0)
+       if (statfs(debugfs, &st_fs) < 0)
                return -ENOENT;
        else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
                return -ENOENT;
        u64 id;
        char evt_path[MAXPATHLEN];
 
-       if (valid_debugfs_mount())
+       if (valid_debugfs_mount(debugfs_path))
                return "unkown";
 
-       sys_dir = opendir(default_debugfs_path);
+       sys_dir = opendir(debugfs_path);
        if (!sys_dir)
                goto cleanup;
 
                for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next,
                                                                evt_path, st) {
                        snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id",
-                                default_debugfs_path, sys_dirent.d_name,
+                                debugfs_path, sys_dirent.d_name,
                                 evt_dirent.d_name);
                        fd = open(evt_path, O_RDONLY);
                        if (fd < 0)
        u64 id;
        char evt_path[MAXPATHLEN];
 
-       if (valid_debugfs_mount())
+       if (valid_debugfs_mount(debugfs_path))
                return 0;
 
        evt_name = strchr(*strp, ':');
        if (evt_length >= MAX_EVENT_LENGTH)
                return 0;
 
-       snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", default_debugfs_path,
-                               sys_name, evt_name);
+       snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
+                sys_name, evt_name);
        fd = open(evt_path, O_RDONLY);
        if (fd < 0)
                return 0;
        struct stat st;
        char evt_path[MAXPATHLEN];
 
-       if (valid_debugfs_mount())
+       if (valid_debugfs_mount(debugfs_path))
                return;
 
-       sys_dir = opendir(default_debugfs_path);
+       sys_dir = opendir(debugfs_path);
        if (!sys_dir)
                goto cleanup;