diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index b8d0a39b484e889b004f3bf21b488ec510fb0591..de60dd4ee5d3a0d4abf0d06d5bf3c19a3c8f0ed7 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -224,7 +224,7 @@ static bool perf_evlist__equal(struct perf_evlist *evlist, static int perf_record__open(struct perf_record *rec) { - char msg[128]; + char msg[512]; struct perf_evsel *pos; struct perf_evlist *evlist = rec->evlist; struct perf_session *session = rec->session; @@ -234,60 +234,18 @@ static int perf_record__open(struct perf_record *rec) perf_evlist__config(evlist, opts); list_for_each_entry(pos, &evlist->entries, node) { - struct perf_event_attr *attr = &pos->attr; try_again: if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { - int err = errno; - - if (err == EPERM || err == EACCES) { - ui__error_paranoid(); - rc = -err; - goto out; - } else if (err == ENODEV && opts->target.cpu_list) { - pr_err("No such device - did you specify" - " an out-of-range profile CPU?\n"); - rc = -err; - goto out; - } - - if (perf_evsel__fallback(pos, err, msg, sizeof(msg))) { + if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { if (verbose) ui__warning("%s\n", msg); goto try_again; } - if (err == ENOENT) { - ui__error("The %s event is not supported.\n", - perf_evsel__name(pos)); - rc = -err; - goto out; - } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) { - ui__error("\'precise\' request may not be supported. " - "Try removing 'p' modifier\n"); - rc = -err; - goto out; - } - - printf("\n"); - error("sys_perf_event_open() syscall returned with %d " - "(%s) for event %s. /bin/dmesg may provide " - "additional information.\n", - err, strerror(err), perf_evsel__name(pos)); - -#if defined(__i386__) || defined(__x86_64__) - if (attr->type == PERF_TYPE_HARDWARE && - err == EOPNOTSUPP) { - pr_err("No hardware sampling interrupt available." - " No APIC? If so then you can boot the kernel" - " with the \"lapic\" boot parameter to" - " force-enable it.\n"); - rc = -err; - goto out; - } -#endif - - pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); - rc = -err; + rc = -errno; + perf_evsel__open_strerror(pos, &opts->target, + errno, msg, sizeof(msg)); + ui__error("%s\n", msg); goto out; } } diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index ef067c193f9397dafe345819ab890000a105e1a7..1c2ac148a7d523e3de32daa06ce984375945b19f 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -247,6 +247,7 @@ static int read_counter(struct perf_evsel *counter) static int __run_perf_stat(int argc __maybe_unused, const char **argv) { + char msg[512]; unsigned long long t0, t1; struct perf_evsel *counter; int status = 0; @@ -324,20 +325,13 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv) continue; } - if (errno == EPERM || errno == EACCES) { - error("You may not have permission to collect %sstats.\n" - "\t Consider tweaking" - " /proc/sys/kernel/perf_event_paranoid or running as root.", - target.system_wide ? "system-wide " : ""); - } else { - error("open_counter returned with %d (%s). " - "/bin/dmesg may provide additional information.\n", - errno, strerror(errno)); - } + perf_evsel__open_strerror(counter, &target, + errno, msg, sizeof(msg)); + ui__error("%s\n", msg); + if (child_pid != -1) kill(child_pid, SIGTERM); - pr_err("Not all events could be opened.\n"); return -1; } counter->supported = true; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 8d41d0b589568458c057fa41f0eb9bfcd61de074..f5fd260f7b208a541d4475d85558fb112f50054a 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -892,7 +892,7 @@ static void perf_top__mmap_read(struct perf_top *top) static void perf_top__start_counters(struct perf_top *top) { - char msg[128]; + char msg[512]; struct perf_evsel *counter; struct perf_evlist *evlist = top->evlist; struct perf_record_opts *opts = &top->record_opts; @@ -900,42 +900,18 @@ static void perf_top__start_counters(struct perf_top *top) perf_evlist__config(evlist, opts); list_for_each_entry(counter, &evlist->entries, node) { - struct perf_event_attr *attr = &counter->attr; try_again: if (perf_evsel__open(counter, top->evlist->cpus, top->evlist->threads) < 0) { - int err = errno; - - if (err == EPERM || err == EACCES) { - ui__error_paranoid(); - goto out_err; - } - - if (perf_evsel__fallback(counter, err, msg, sizeof(msg))) { + if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) { if (verbose) ui__warning("%s\n", msg); goto try_again; } - if (err == ENOENT) { - ui__error("The %s event is not supported.\n", - perf_evsel__name(counter)); - goto out_err; - } else if (err == EMFILE) { - ui__error("Too many events are opened.\n" - "Try again after reducing the number of events\n"); - goto out_err; - } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) { - ui__error("\'precise\' request may not be supported. " - "Try removing 'p' modifier\n"); - goto out_err; - } - - ui__error("The sys_perf_event_open() syscall " - "returned with %d (%s). /bin/dmesg " - "may provide additional information.\n" - "No CONFIG_PERF_EVENTS=y kernel support " - "configured?\n", err, strerror(err)); + perf_evsel__open_strerror(counter, &opts->target, + errno, msg, sizeof(msg)); + ui__error("%s\n", msg); goto out_err; } } diff --git a/tools/perf/ui/util.c b/tools/perf/ui/util.c index 3014a7cd527186b1ee96cc5a84857bb9306c2228..e3e0a963d03aa3559924af97a33bb67c3f48b275 100644 --- a/tools/perf/ui/util.c +++ b/tools/perf/ui/util.c @@ -52,17 +52,6 @@ int ui__warning(const char *format, ...) return ret; } -int ui__error_paranoid(void) -{ - return ui__error("Permission error - are you root?\n" - "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n" - " -1 - Not paranoid at all\n" - " 0 - Disallow raw tracepoint access for unpriv\n" - " 1 - Disallow cpu events for unpriv\n" - " 2 - Disallow kernel profiling for unpriv\n"); -} - - /** * perf_error__register - Register error logging functions * @eops: The pointer to error logging function struct diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index 6e2667fb821195dfc10f43f26b5b6ce1151d50c0..efbd98805ad0b0086996298b698122a2b0ceb018 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h @@ -16,6 +16,5 @@ void trace_event(union perf_event *event); int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); -int ui__error_paranoid(void); #endif /* __PERF_DEBUG_H */ diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 0c88e5c12dabc9fecb8f3c33344395a63ac46124..e45332d08a58ebc20c80b60afc3f99a0b26fd4c5 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1406,3 +1406,52 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err, return false; } + +int perf_evsel__open_strerror(struct perf_evsel *evsel, + struct perf_target *target, + int err, char *msg, size_t size) +{ + switch (err) { + case EPERM: + case EACCES: + return scnprintf(msg, size, "%s", + "You may not have permission to collect %sstats.\n" + "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n" + " -1 - Not paranoid at all\n" + " 0 - Disallow raw tracepoint access for unpriv\n" + " 1 - Disallow cpu events for unpriv\n" + " 2 - Disallow kernel profiling for unpriv", + target->system_wide ? "system-wide " : ""); + case ENOENT: + return scnprintf(msg, size, "The %s event is not supported.", + perf_evsel__name(evsel)); + case EMFILE: + return scnprintf(msg, size, "%s", + "Too many events are opened.\n" + "Try again after reducing the number of events."); + case ENODEV: + if (target->cpu_list) + return scnprintf(msg, size, "%s", + "No such device - did you specify an out-of-range profile CPU?\n"); + break; + case EOPNOTSUPP: + if (evsel->attr.precise_ip) + return scnprintf(msg, size, "%s", + "\'precise\' request may not be supported. Try removing 'p' modifier."); +#if defined(__i386__) || defined(__x86_64__) + if (evsel->attr.type == PERF_TYPE_HARDWARE) + return scnprintf(msg, size, "%s", + "No hardware sampling interrupt available.\n" + "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it."); +#endif + break; + default: + break; + } + + return scnprintf(msg, size, + "The sys_perf_event_open() syscall returned with %d (%s) for event (%s). \n" + "/bin/dmesg may provide additional information.\n" + "No CONFIG_PERF_EVENTS=y kernel support configured?\n", + err, strerror(err), perf_evsel__name(evsel)); +} diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 26d8cfd86e0ad14a04af7b102cb78690247062b3..c68d1b82e843a88cc33e82a508b05bd021996eeb 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -254,4 +254,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, bool perf_evsel__fallback(struct perf_evsel *evsel, int err, char *msg, size_t msgsize); +int perf_evsel__open_strerror(struct perf_evsel *evsel, + struct perf_target *target, + int err, char *msg, size_t size); #endif /* __PERF_EVSEL_H */