Commit 3da297a6 authored by Ingo Molnar's avatar Ingo Molnar

perf record: Fall back to cpu-clock-ticks if no PMU

On architectures/CPUs without PMU support but with perfcounters
enabled 'perf record' currently fails because it cannot create a
cycle based hw-perfcounter.

Fall back to the cpu-clock-tick sw-perfcounter in this case, which
is hrtimer based and will always work (as long as perfcounters
are enabled).

Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 716c69fe
...@@ -37,6 +37,7 @@ static pid_t target_pid = -1; ...@@ -37,6 +37,7 @@ static pid_t target_pid = -1;
static int inherit = 1; static int inherit = 1;
static int force = 0; static int force = 0;
static int append_file = 0; static int append_file = 0;
static int verbose = 0;
static long samples; static long samples;
static struct timeval last_read; static struct timeval last_read;
...@@ -349,17 +350,35 @@ static void create_counter(int counter, int cpu, pid_t pid) ...@@ -349,17 +350,35 @@ static void create_counter(int counter, int cpu, pid_t pid)
track = 0; /* only the first counter needs these */ track = 0; /* only the first counter needs these */
try_again:
fd[nr_cpu][counter] = sys_perf_counter_open(attr, pid, cpu, group_fd, 0); fd[nr_cpu][counter] = sys_perf_counter_open(attr, pid, cpu, group_fd, 0);
if (fd[nr_cpu][counter] < 0) { if (fd[nr_cpu][counter] < 0) {
int err = errno; int err = errno;
error("syscall returned with %d (%s)\n", if (verbose)
error("sys_perf_counter_open() syscall returned with %d (%s)\n",
fd[nr_cpu][counter], strerror(err)); fd[nr_cpu][counter], strerror(err));
if (err == EPERM) if (err == EPERM)
printf("Are you root?\n"); die("Permission error - are you root?\n");
/*
* If it's cycles then fall back to hrtimer
* based cpu-clock-tick sw counter, which
* is always available even if no PMU support:
*/
if (attr->type == PERF_TYPE_HARDWARE
&& attr->config == PERF_COUNT_CPU_CYCLES) {
if (verbose)
warning(" ... trying to fall back to cpu-clock-ticks\n");
attr->type = PERF_TYPE_SOFTWARE;
attr->config = PERF_COUNT_CPU_CLOCK;
goto try_again;
}
exit(-1); exit(-1);
} }
assert(fd[nr_cpu][counter] >= 0); assert(fd[nr_cpu][counter] >= 0);
fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK); fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK);
...@@ -519,6 +538,8 @@ static const struct option options[] = { ...@@ -519,6 +538,8 @@ static const struct option options[] = {
"profile at this frequency"), "profile at this frequency"),
OPT_INTEGER('m', "mmap-pages", &mmap_pages, OPT_INTEGER('m', "mmap-pages", &mmap_pages,
"number of mmap data pages"), "number of mmap data pages"),
OPT_BOOLEAN('v', "verbose", &verbose,
"be more verbose (show counter open errors, etc)"),
OPT_END() OPT_END()
}; };
......
...@@ -65,6 +65,7 @@ static int group = 0; ...@@ -65,6 +65,7 @@ static int group = 0;
static unsigned int page_size; static unsigned int page_size;
static unsigned int mmap_pages = 16; static unsigned int mmap_pages = 16;
static int freq = 0; static int freq = 0;
static int verbose = 0;
static char *sym_filter; static char *sym_filter;
static unsigned long filter_start; static unsigned long filter_start;
...@@ -550,11 +551,12 @@ static void start_counter(int i, int counter) ...@@ -550,11 +551,12 @@ static void start_counter(int i, int counter)
if (fd[i][counter] < 0) { if (fd[i][counter] < 0) {
int err = errno; int err = errno;
error("sys_perf_counter_open() syscall returned with %d (%s)\n", if (verbose)
fd[i][counter], strerror(err)); error("sys_perf_counter_open() syscall returned with %d (%s)\n",
fd[i][counter], strerror(err));
if (err == EPERM) if (err == EPERM)
die(" No permission - are you root?\n"); die("No permission - are you root?\n");
/* /*
* If it's cycles then fall back to hrtimer * If it's cycles then fall back to hrtimer
* based cpu-clock-tick sw counter, which * based cpu-clock-tick sw counter, which
...@@ -563,7 +565,9 @@ static void start_counter(int i, int counter) ...@@ -563,7 +565,9 @@ static void start_counter(int i, int counter)
if (attr->type == PERF_TYPE_HARDWARE if (attr->type == PERF_TYPE_HARDWARE
&& attr->config == PERF_COUNT_CPU_CYCLES) { && attr->config == PERF_COUNT_CPU_CYCLES) {
warning(" ... trying to fall back to cpu-clock-ticks\n"); if (verbose)
warning(" ... trying to fall back to cpu-clock-ticks\n");
attr->type = PERF_TYPE_SOFTWARE; attr->type = PERF_TYPE_SOFTWARE;
attr->config = PERF_COUNT_CPU_CLOCK; attr->config = PERF_COUNT_CPU_CLOCK;
goto try_again; goto try_again;
...@@ -673,6 +677,8 @@ static const struct option options[] = { ...@@ -673,6 +677,8 @@ static const struct option options[] = {
"profile at this frequency"), "profile at this frequency"),
OPT_INTEGER('E', "entries", &print_entries, OPT_INTEGER('E', "entries", &print_entries,
"display this many functions"), "display this many functions"),
OPT_BOOLEAN('v', "verbose", &verbose,
"be more verbose (show counter open errors, etc)"),
OPT_END() OPT_END()
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment