mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
perf evsel: Fix missing exclude_{host,guest} setting
The current logic for the perf missing feature has a bug that it can wrongly clear some modifiers like G or H. Actually some PMUs don't support any filtering or exclusion while others do. But we check it as a global feature. For example, the cycles event can have 'G' modifier to enable it only in the guest mode on x86. When you don't run any VMs it'll return 0. # perf stat -a -e cycles:G sleep 1 Performance counter stats for 'system wide': 0 cycles:G 1.000721670 seconds time elapsed But when it's used with other pmu events that don't support G modifier, it'll be reset and return non-zero values. # perf stat -a -e cycles:G,msr/tsc/ sleep 1 Performance counter stats for 'system wide': 538,029,960 cycles:G 16,924,010,738 msr/tsc/ 1.001815327 seconds time elapsed This is because of the missing feature detection logic being global. Add a hashmap to set pmu-specific exclude_host/guest features. Committer notes: Fix 'perf test python' by adding a stub for evsel__find_pmu() in tools/perf/util/python.c, document that it is used so far only for the above reasons so that if anybody needs this in the python binding usecases, we can revisit this. Reported-by: Stephane Eranian <eranian@google.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org> Cc: Andi Kleen <ak@linux.intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@amd.com> Link: http://lore.kernel.org/lkml/20211105205847.120950-1-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
88c42f4d6c
commit
3500eeebed
@ -1824,7 +1824,7 @@ static void evsel__disable_missing_features(struct evsel *evsel)
|
||||
evsel->open_flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC;
|
||||
if (perf_missing_features.mmap2)
|
||||
evsel->core.attr.mmap2 = 0;
|
||||
if (perf_missing_features.exclude_guest)
|
||||
if (evsel->pmu && evsel->pmu->missing_features.exclude_guest)
|
||||
evsel->core.attr.exclude_guest = evsel->core.attr.exclude_host = 0;
|
||||
if (perf_missing_features.lbr_flags)
|
||||
evsel->core.attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS |
|
||||
@ -1917,10 +1917,27 @@ bool evsel__detect_missing_features(struct evsel *evsel)
|
||||
perf_missing_features.mmap2 = true;
|
||||
pr_debug2_peo("switching off mmap2\n");
|
||||
return true;
|
||||
} else if (!perf_missing_features.exclude_guest &&
|
||||
(evsel->core.attr.exclude_guest || evsel->core.attr.exclude_host)) {
|
||||
perf_missing_features.exclude_guest = true;
|
||||
pr_debug2_peo("switching off exclude_guest, exclude_host\n");
|
||||
} else if ((evsel->core.attr.exclude_guest || evsel->core.attr.exclude_host) &&
|
||||
(evsel->pmu == NULL || evsel->pmu->missing_features.exclude_guest)) {
|
||||
if (evsel->pmu == NULL) {
|
||||
evsel->pmu = evsel__find_pmu(evsel);
|
||||
if (evsel->pmu)
|
||||
evsel->pmu->missing_features.exclude_guest = true;
|
||||
else {
|
||||
/* we cannot find PMU, disable attrs now */
|
||||
evsel->core.attr.exclude_host = false;
|
||||
evsel->core.attr.exclude_guest = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (evsel->exclude_GH) {
|
||||
pr_debug2_peo("PMU has no exclude_host/guest support, bailing out\n");
|
||||
return false;
|
||||
}
|
||||
if (!perf_missing_features.exclude_guest) {
|
||||
perf_missing_features.exclude_guest = true;
|
||||
pr_debug2_peo("switching off exclude_guest, exclude_host\n");
|
||||
}
|
||||
return true;
|
||||
} else if (!perf_missing_features.sample_id_all) {
|
||||
perf_missing_features.sample_id_all = true;
|
||||
|
@ -22,6 +22,7 @@ struct target;
|
||||
struct hashmap;
|
||||
struct bperf_leader_bpf;
|
||||
struct bperf_follower_bpf;
|
||||
struct perf_pmu;
|
||||
|
||||
typedef int (evsel__sb_cb_t)(union perf_event *event, void *data);
|
||||
|
||||
@ -153,6 +154,9 @@ struct evsel {
|
||||
};
|
||||
unsigned long open_flags;
|
||||
int precise_ip_original;
|
||||
|
||||
/* for missing_features */
|
||||
struct perf_pmu *pmu;
|
||||
};
|
||||
|
||||
struct perf_missing_features {
|
||||
|
@ -49,6 +49,10 @@ struct perf_pmu {
|
||||
struct list_head caps; /* HEAD struct perf_pmu_caps -> list */
|
||||
struct list_head list; /* ELEM */
|
||||
struct list_head hybrid_list;
|
||||
|
||||
struct {
|
||||
bool exclude_guest;
|
||||
} missing_features;
|
||||
};
|
||||
|
||||
extern struct perf_pmu perf_pmu__fake;
|
||||
|
@ -69,6 +69,18 @@ void perf_stat__collect_metric_expr(struct evlist *evsel_list)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* This one is needed not to drag the PMU bandwagon, jevents generated
|
||||
* pmu_sys_event_tables, etc and evsel__find_pmu() is used so far just for
|
||||
* doing per PMU perf_event_attr.exclude_guest handling, not really needed, so
|
||||
* far, for the perf python binding known usecases, revisit if this become
|
||||
* necessary.
|
||||
*/
|
||||
struct perf_pmu *evsel__find_pmu(struct evsel *evsel __maybe_unused)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add this one here not to drag util/metricgroup.c
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user