Skip to content
Snippets Groups Projects
Commit 5622c07b authored by Stephane Eranian's avatar Stephane Eranian Committed by Arnaldo Carvalho de Melo
Browse files

perf stat: Fix case where guest/host monitoring is not supported by kernel


By default, perf stat sets exclude_guest = 1. But when you run perf on a
kernel which does not support  host/guest filtering, then you get an
error saying the event in unsupported. This comes from the fact that
when the perf_event_attr struct passed by the user is larger than the
one known to the kernel there is safety check which ensures that all
unknown bits are zero. But here, exclude_guest is 1 (part of the unknown
bits) and thus the perf_event_open() syscall return EINVAL.

To my surprise, running perf record on the same kernel did not exhibit
the problem. The reason is that perf record handles the problem by
catching the error and retrying with guest/host excludes set to zero.
For some reason, this was not done with perf stat. This patch fixes this
problem.

Signed-off-by: default avatarStephane Eranian <eranian@google.com>
Cc: Gleb Natapov <gleb@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Robert Richter <robert.richter@amd.com>
Link: http://lkml.kernel.org/r/20120427124538.GA7230@quad


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent afda0f94
No related merge requests found
......@@ -283,6 +283,8 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
{
struct perf_event_attr *attr = &evsel->attr;
struct xyarray *group_fd = NULL;
bool exclude_guest_missing = false;
int ret;
if (group && evsel != first)
group_fd = first->fd;
......@@ -293,16 +295,39 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
attr->inherit = !no_inherit;
if (system_wide)
return perf_evsel__open_per_cpu(evsel, evsel_list->cpus,
retry:
if (exclude_guest_missing)
evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
if (system_wide) {
ret = perf_evsel__open_per_cpu(evsel, evsel_list->cpus,
group, group_fd);
if (ret)
goto check_ret;
return 0;
}
if (!target_pid && !target_tid && (!group || evsel == first)) {
attr->disabled = 1;
attr->enable_on_exec = 1;
}
return perf_evsel__open_per_thread(evsel, evsel_list->threads,
group, group_fd);
ret = perf_evsel__open_per_thread(evsel, evsel_list->threads,
group, group_fd);
if (!ret)
return 0;
/* fall through */
check_ret:
if (ret && errno == EINVAL) {
if (!exclude_guest_missing &&
(evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
pr_debug("Old kernel, cannot exclude "
"guest or host samples.\n");
exclude_guest_missing = true;
goto retry;
}
}
return ret;
}
/*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment