]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - tools/perf/util/evlist.c
Merge remote-tracking branches 'regulator/topic/max8649', 'regulator/topic/mode'...
[karo-tx-linux.git] / tools / perf / util / evlist.c
index cfbe2b99b9aa5826b60fc574a211a115fc6f6a2d..2e507b5025a3ed6e3f3df1e385aa3c8f13637389 100644 (file)
@@ -8,6 +8,7 @@
  */
 #include "util.h"
 #include <api/fs/debugfs.h>
+#include <api/fs/fs.h>
 #include <poll.h>
 #include "cpumap.h"
 #include "thread_map.h"
@@ -24,6 +25,7 @@
 
 #include <linux/bitops.h>
 #include <linux/hash.h>
+#include <linux/log2.h>
 
 static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
 static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
@@ -892,10 +894,24 @@ out_unmap:
 
 static size_t perf_evlist__mmap_size(unsigned long pages)
 {
-       /* 512 kiB: default amount of unprivileged mlocked memory */
-       if (pages == UINT_MAX)
-               pages = (512 * 1024) / page_size;
-       else if (!is_power_of_2(pages))
+       if (pages == UINT_MAX) {
+               int max;
+
+               if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) {
+                       /*
+                        * Pick a once upon a time good value, i.e. things look
+                        * strange since we can't read a sysctl value, but lets not
+                        * die yet...
+                        */
+                       max = 512;
+               } else {
+                       max -= (page_size / 1024);
+               }
+
+               pages = (max * 1024) / page_size;
+               if (!is_power_of_2(pages))
+                       pages = rounddown_pow_of_two(pages);
+       } else if (!is_power_of_2(pages))
                return 0;
 
        return (pages + 1) * page_size;
@@ -932,7 +948,7 @@ static long parse_pages_arg(const char *str, unsigned long min,
                /* leave number of pages at 0 */
        } else if (!is_power_of_2(pages)) {
                /* round pages up to next power of 2 */
-               pages = next_pow2_l(pages);
+               pages = roundup_pow_of_two(pages);
                if (!pages)
                        return -EINVAL;
                pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n",
@@ -1429,7 +1445,7 @@ int perf_evlist__strerror_tp(struct perf_evlist *evlist __maybe_unused,
        case ENOENT:
                scnprintf(buf, size, "%s",
                          "Error:\tUnable to find debugfs\n"
-                         "Hint:\tWas your kernel was compiled with debugfs support?\n"
+                         "Hint:\tWas your kernel compiled with debugfs support?\n"
                          "Hint:\tIs the debugfs filesystem mounted?\n"
                          "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'");
                break;
@@ -1483,6 +1499,37 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
        return 0;
 }
 
+int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size)
+{
+       char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
+       int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0;
+
+       switch (err) {
+       case EPERM:
+               sysctl__read_int("kernel/perf_event_mlock_kb", &pages_max_per_user);
+               printed += scnprintf(buf + printed, size - printed,
+                                    "Error:\t%s.\n"
+                                    "Hint:\tCheck /proc/sys/kernel/perf_event_mlock_kb (%d kB) setting.\n"
+                                    "Hint:\tTried using %zd kB.\n",
+                                    emsg, pages_max_per_user, pages_attempted);
+
+               if (pages_attempted >= pages_max_per_user) {
+                       printed += scnprintf(buf + printed, size - printed,
+                                            "Hint:\tTry 'sudo sh -c \"echo %d > /proc/sys/kernel/perf_event_mlock_kb\"', or\n",
+                                            pages_max_per_user + pages_attempted);
+               }
+
+               printed += scnprintf(buf + printed, size - printed,
+                                    "Hint:\tTry using a smaller -m/--mmap-pages value.");
+               break;
+       default:
+               scnprintf(buf, size, "%s", emsg);
+               break;
+       }
+
+       return 0;
+}
+
 void perf_evlist__to_front(struct perf_evlist *evlist,
                           struct perf_evsel *move_evsel)
 {