diff options
Diffstat (limited to 'tools/perf/arch/x86/util')
-rw-r--r-- | tools/perf/arch/x86/util/evlist.c | 7 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/evsel.c | 31 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/intel-bts.c | 1 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/intel-pt.c | 32 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/topdown.c | 25 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/topdown.h | 7 |
6 files changed, 82 insertions, 21 deletions
diff --git a/tools/perf/arch/x86/util/evlist.c b/tools/perf/arch/x86/util/evlist.c index cfc208d71f00..68f681ad54c1 100644 --- a/tools/perf/arch/x86/util/evlist.c +++ b/tools/perf/arch/x86/util/evlist.c @@ -3,6 +3,7 @@ #include "util/pmu.h" #include "util/evlist.h" #include "util/parse-events.h" +#include "topdown.h" #define TOPDOWN_L1_EVENTS "{slots,topdown-retiring,topdown-bad-spec,topdown-fe-bound,topdown-be-bound}" #define TOPDOWN_L2_EVENTS "{slots,topdown-retiring,topdown-bad-spec,topdown-fe-bound,topdown-be-bound,topdown-heavy-ops,topdown-br-mispredict,topdown-fetch-lat,topdown-mem-bound}" @@ -25,18 +26,18 @@ struct evsel *arch_evlist__leader(struct list_head *list) first = list_first_entry(list, struct evsel, core.node); - if (!pmu_have_event("cpu", "slots")) + if (!topdown_sys_has_perf_metrics()) return first; /* If there is a slots event and a topdown event then the slots event comes first. */ __evlist__for_each_entry(list, evsel) { - if (evsel->pmu_name && !strcmp(evsel->pmu_name, "cpu") && evsel->name) { + if (evsel->pmu_name && !strncmp(evsel->pmu_name, "cpu", 3) && evsel->name) { if (strcasestr(evsel->name, "slots")) { slots = evsel; if (slots == first) return first; } - if (!strncasecmp(evsel->name, "topdown", 7)) + if (strcasestr(evsel->name, "topdown")) has_topdown = true; if (slots && has_topdown) return slots; diff --git a/tools/perf/arch/x86/util/evsel.c b/tools/perf/arch/x86/util/evsel.c index ac2899a25b7a..88306183d629 100644 --- a/tools/perf/arch/x86/util/evsel.c +++ b/tools/perf/arch/x86/util/evsel.c @@ -3,6 +3,7 @@ #include <stdlib.h> #include "util/evsel.h" #include "util/env.h" +#include "util/pmu.h" #include "linux/string.h" void arch_evsel__set_sample_weight(struct evsel *evsel) @@ -29,3 +30,33 @@ void arch_evsel__fixup_new_cycles(struct perf_event_attr *attr) free(env.cpuid); } + +/* Check whether the evsel's PMU supports the perf metrics */ +static bool evsel__sys_has_perf_metrics(const struct evsel *evsel) +{ + const char *pmu_name = evsel->pmu_name ? evsel->pmu_name : "cpu"; + + /* + * The PERF_TYPE_RAW type is the core PMU type, e.g., "cpu" PMU + * on a non-hybrid machine, "cpu_core" PMU on a hybrid machine. + * The slots event is only available for the core PMU, which + * supports the perf metrics feature. + * Checking both the PERF_TYPE_RAW type and the slots event + * should be good enough to detect the perf metrics feature. + */ + if ((evsel->core.attr.type == PERF_TYPE_RAW) && + pmu_have_event(pmu_name, "slots")) + return true; + + return false; +} + +bool arch_evsel__must_be_in_group(const struct evsel *evsel) +{ + if (!evsel__sys_has_perf_metrics(evsel)) + return false; + + return evsel->name && + (!strcasecmp(evsel->name, "slots") || + strcasestr(evsel->name, "topdown")); +} diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c index d68a0f48e41e..bcccfbade5c6 100644 --- a/tools/perf/arch/x86/util/intel-bts.c +++ b/tools/perf/arch/x86/util/intel-bts.c @@ -129,6 +129,7 @@ static int intel_bts_recording_options(struct auxtrace_record *itr, } evsel->core.attr.freq = 0; evsel->core.attr.sample_period = 1; + evsel->needs_auxtrace_mmap = true; intel_bts_evsel = evsel; opts->full_auxtrace = true; } diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index 38ec2666ec12..06c2cdfd8f2f 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -649,6 +649,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, evsel->core.attr.freq = 0; evsel->core.attr.sample_period = 1; evsel->no_aux_samples = true; + evsel->needs_auxtrace_mmap = true; intel_pt_evsel = evsel; opts->full_auxtrace = true; } @@ -810,18 +811,11 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, if (!cpu_wide && perf_can_record_cpu_wide()) { struct evsel *switch_evsel; - err = parse_events(evlist, "dummy:u", NULL); - if (err) - return err; + switch_evsel = evlist__add_dummy_on_all_cpus(evlist); + if (!switch_evsel) + return -ENOMEM; - switch_evsel = evlist__last(evlist); - - switch_evsel->core.attr.freq = 0; - switch_evsel->core.attr.sample_period = 1; switch_evsel->core.attr.context_switch = 1; - - switch_evsel->core.system_wide = true; - switch_evsel->no_aux_samples = true; switch_evsel->immediate = true; evsel__set_sample_bit(switch_evsel, TID); @@ -870,20 +864,22 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, /* Add dummy event to keep tracking */ if (opts->full_auxtrace) { + bool need_system_wide_tracking; struct evsel *tracking_evsel; - err = parse_events(evlist, "dummy:u", NULL); - if (err) - return err; + /* + * User space tasks can migrate between CPUs, so when tracing + * selected CPUs, sideband for all CPUs is still needed. + */ + need_system_wide_tracking = evlist->core.has_user_cpus && + !intel_pt_evsel->core.attr.exclude_user; - tracking_evsel = evlist__last(evlist); + tracking_evsel = evlist__add_aux_dummy(evlist, need_system_wide_tracking); + if (!tracking_evsel) + return -ENOMEM; evlist__set_tracking_event(evlist, tracking_evsel); - tracking_evsel->core.attr.freq = 0; - tracking_evsel->core.attr.sample_period = 1; - - tracking_evsel->no_aux_samples = true; if (need_immediate) tracking_evsel->immediate = true; diff --git a/tools/perf/arch/x86/util/topdown.c b/tools/perf/arch/x86/util/topdown.c index 2f3d96aa92a5..f4d5422e9960 100644 --- a/tools/perf/arch/x86/util/topdown.c +++ b/tools/perf/arch/x86/util/topdown.c @@ -3,6 +3,31 @@ #include "api/fs/fs.h" #include "util/pmu.h" #include "util/topdown.h" +#include "topdown.h" + +/* Check whether there is a PMU which supports the perf metrics. */ +bool topdown_sys_has_perf_metrics(void) +{ + static bool has_perf_metrics; + static bool cached; + struct perf_pmu *pmu; + + if (cached) + return has_perf_metrics; + + /* + * The perf metrics feature is a core PMU feature. + * The PERF_TYPE_RAW type is the type of a core PMU. + * The slots event is only available when the core PMU + * supports the perf metrics feature. + */ + pmu = perf_pmu__find_by_type(PERF_TYPE_RAW); + if (pmu && pmu_have_event(pmu->name, "slots")) + has_perf_metrics = true; + + cached = true; + return has_perf_metrics; +} /* * Check whether we can use a group for top down. diff --git a/tools/perf/arch/x86/util/topdown.h b/tools/perf/arch/x86/util/topdown.h new file mode 100644 index 000000000000..46bf9273e572 --- /dev/null +++ b/tools/perf/arch/x86/util/topdown.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _TOPDOWN_H +#define _TOPDOWN_H 1 + +bool topdown_sys_has_perf_metrics(void); + +#endif |