Skip to content

Commit 5ac7263

Browse files
captain5050acmel
authored andcommitted
perf tools: Warn if no user requested CPUs match PMU's CPUs
In commit 1d3351e ("perf tools: Enable on a list of CPUs for hybrid") perf on hybrid will warn if a user requested CPU doesn't match the PMU of the given event but only for hybrid PMUs. Make the logic generic for all PMUs and remove the hybrid logic. Warn if a CPU is requested that isn't present/offline for events not on the core. Warn if a CPU is requested for a core PMU, but the CPU isn't within the cpu map of that PMU. For example on a 16 (0-15) CPU system: ``` $ perf stat -e imc_free_running/data_read/,cycles -C 16 true WARNING: A requested CPU in '16' is not supported by PMU 'uncore_imc_free_running_1' (CPUs 0-15) for event 'imc_free_running/data_read/' WARNING: A requested CPU in '16' is not supported by PMU 'uncore_imc_free_running_0' (CPUs 0-15) for event 'imc_free_running/data_read/' WARNING: A requested CPU in '16' is not supported by PMU 'cpu' (CPUs 0-15) for event 'cycles' Performance counter stats for 'CPU(s) 16': <not supported> MiB imc_free_running/data_read/ <not supported> cycles 0.000575312 seconds time elapsed ``` Remove evlist__fix_hybrid_cpus that previously produced the warnings and also perf_pmu__cpus_match that worked with evlist__fix_hybrid_cpus to change CPU maps for hybrid CPUs, something that is no longer necessary as CPU map propagation properly intersects user requested CPUs with the core PMU's CPU map. Reviewed-by: Kan Liang <[email protected]> Signed-off-by: Ian Rogers <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Ali Saidi <[email protected]> Cc: Athira Rajeev <[email protected]> Cc: Dmitrii Dolgov <[email protected]> Cc: Huacai Chen <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: James Clark <[email protected]> Cc: Jing Zhang <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: John Garry <[email protected]> Cc: Kajol Jain <[email protected]> Cc: Kang Minchul <[email protected]> Cc: Leo Yan <[email protected]> Cc: Madhavan Srinivasan <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Mike Leach <[email protected]> Cc: Ming Wang <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Ravi Bangoria <[email protected]> Cc: Rob Herring <[email protected]> Cc: Sandipan Das <[email protected]> Cc: Sean Christopherson <[email protected]> Cc: Suzuki Poulouse <[email protected]> Cc: Thomas Richter <[email protected]> Cc: Will Deacon <[email protected]> Cc: Xing Zhengjun <[email protected]> Cc: [email protected] Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 8ec984d commit 5ac7263

File tree

8 files changed

+43
-121
lines changed

8 files changed

+43
-121
lines changed

tools/perf/builtin-record.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4198,11 +4198,7 @@ int cmd_record(int argc, const char **argv)
41984198
/* Enable ignoring missing threads when -u/-p option is defined. */
41994199
rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid;
42004200

4201-
if (evlist__fix_hybrid_cpus(rec->evlist, rec->opts.target.cpu_list)) {
4202-
pr_err("failed to use cpu list %s\n",
4203-
rec->opts.target.cpu_list);
4204-
goto out;
4205-
}
4201+
evlist__warn_user_requested_cpus(rec->evlist, rec->opts.target.cpu_list);
42064202

42074203
if (callchain_param.enabled && callchain_param.record_mode == CALLCHAIN_FP)
42084204
arch__add_leaf_frame_record_opts(&rec->opts);

tools/perf/builtin-stat.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2725,10 +2725,7 @@ int cmd_stat(int argc, const char **argv)
27252725
}
27262726
}
27272727

2728-
if (evlist__fix_hybrid_cpus(evsel_list, target.cpu_list)) {
2729-
pr_err("failed to use cpu list %s\n", target.cpu_list);
2730-
goto out;
2731-
}
2728+
evlist__warn_user_requested_cpus(evsel_list, target.cpu_list);
27322729

27332730
if (evlist__create_maps(evsel_list, &target) < 0) {
27342731
if (target__has_task(&target)) {

tools/perf/util/evlist-hybrid.c

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -86,77 +86,3 @@ bool evlist__has_hybrid(struct evlist *evlist)
8686

8787
return false;
8888
}
89-
90-
int evlist__fix_hybrid_cpus(struct evlist *evlist, const char *cpu_list)
91-
{
92-
struct perf_cpu_map *cpus;
93-
struct evsel *evsel, *tmp;
94-
struct perf_pmu *pmu;
95-
int ret, unmatched_count = 0, events_nr = 0;
96-
97-
if (!perf_pmu__has_hybrid() || !cpu_list)
98-
return 0;
99-
100-
cpus = perf_cpu_map__new(cpu_list);
101-
if (!cpus)
102-
return -1;
103-
104-
/*
105-
* The evsels are created with hybrid pmu's cpus. But now we
106-
* need to check and adjust the cpus of evsel by cpu_list because
107-
* cpu_list may cause conflicts with cpus of evsel. For example,
108-
* cpus of evsel is cpu0-7, but the cpu_list is cpu6-8, we need
109-
* to adjust the cpus of evsel to cpu6-7. And then propatate maps
110-
* in evlist__create_maps().
111-
*/
112-
evlist__for_each_entry_safe(evlist, tmp, evsel) {
113-
struct perf_cpu_map *matched_cpus, *unmatched_cpus;
114-
char buf1[128], buf2[128];
115-
116-
pmu = perf_pmu__find_hybrid_pmu(evsel->pmu_name);
117-
if (!pmu)
118-
continue;
119-
120-
ret = perf_pmu__cpus_match(pmu, cpus, &matched_cpus,
121-
&unmatched_cpus);
122-
if (ret)
123-
goto out;
124-
125-
events_nr++;
126-
127-
if (perf_cpu_map__nr(matched_cpus) > 0 &&
128-
(perf_cpu_map__nr(unmatched_cpus) > 0 ||
129-
perf_cpu_map__nr(matched_cpus) < perf_cpu_map__nr(cpus) ||
130-
perf_cpu_map__nr(matched_cpus) < perf_cpu_map__nr(pmu->cpus))) {
131-
perf_cpu_map__put(evsel->core.cpus);
132-
perf_cpu_map__put(evsel->core.own_cpus);
133-
evsel->core.cpus = perf_cpu_map__get(matched_cpus);
134-
evsel->core.own_cpus = perf_cpu_map__get(matched_cpus);
135-
136-
if (perf_cpu_map__nr(unmatched_cpus) > 0) {
137-
cpu_map__snprint(matched_cpus, buf1, sizeof(buf1));
138-
pr_warning("WARNING: use %s in '%s' for '%s', skip other cpus in list.\n",
139-
buf1, pmu->name, evsel->name);
140-
}
141-
}
142-
143-
if (perf_cpu_map__nr(matched_cpus) == 0) {
144-
evlist__remove(evlist, evsel);
145-
evsel__delete(evsel);
146-
147-
cpu_map__snprint(cpus, buf1, sizeof(buf1));
148-
cpu_map__snprint(pmu->cpus, buf2, sizeof(buf2));
149-
pr_warning("WARNING: %s isn't a '%s', please use a CPU list in the '%s' range (%s)\n",
150-
buf1, pmu->name, pmu->name, buf2);
151-
unmatched_count++;
152-
}
153-
154-
perf_cpu_map__put(matched_cpus);
155-
perf_cpu_map__put(unmatched_cpus);
156-
}
157-
if (events_nr)
158-
ret = (unmatched_count == events_nr) ? -1 : 0;
159-
out:
160-
perf_cpu_map__put(cpus);
161-
return ret;
162-
}

tools/perf/util/evlist-hybrid.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,5 @@
1010
int evlist__add_default_hybrid(struct evlist *evlist, bool precise);
1111
void evlist__warn_hybrid_group(struct evlist *evlist);
1212
bool evlist__has_hybrid(struct evlist *evlist);
13-
int evlist__fix_hybrid_cpus(struct evlist *evlist, const char *cpu_list);
1413

1514
#endif /* __PERF_EVLIST_HYBRID_H */

tools/perf/util/evlist.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2465,3 +2465,42 @@ void evlist__check_mem_load_aux(struct evlist *evlist)
24652465
}
24662466
}
24672467
}
2468+
2469+
/**
2470+
* evlist__warn_user_requested_cpus() - Check each evsel against requested CPUs
2471+
* and warn if the user CPU list is inapplicable for the event's PMU's
2472+
* CPUs. Not core PMUs list a CPU in sysfs, but this may be overwritten by a
2473+
* user requested CPU and so any online CPU is applicable. Core PMUs handle
2474+
* events on the CPUs in their list and otherwise the event isn't supported.
2475+
* @evlist: The list of events being checked.
2476+
* @cpu_list: The user provided list of CPUs.
2477+
*/
2478+
void evlist__warn_user_requested_cpus(struct evlist *evlist, const char *cpu_list)
2479+
{
2480+
struct perf_cpu_map *user_requested_cpus;
2481+
struct evsel *pos;
2482+
2483+
if (!cpu_list)
2484+
return;
2485+
2486+
user_requested_cpus = perf_cpu_map__new(cpu_list);
2487+
if (!user_requested_cpus)
2488+
return;
2489+
2490+
evlist__for_each_entry(evlist, pos) {
2491+
struct perf_cpu_map *intersect, *to_test;
2492+
const struct perf_pmu *pmu = evsel__find_pmu(pos);
2493+
2494+
to_test = pmu && pmu->is_core ? pmu->cpus : cpu_map__online();
2495+
intersect = perf_cpu_map__intersect(to_test, user_requested_cpus);
2496+
if (!perf_cpu_map__equal(intersect, user_requested_cpus)) {
2497+
char buf[128];
2498+
2499+
cpu_map__snprint(to_test, buf, sizeof(buf));
2500+
pr_warning("WARNING: A requested CPU in '%s' is not supported by PMU '%s' (CPUs %s) for event '%s'\n",
2501+
cpu_list, pmu ? pmu->name : "cpu", buf, evsel__name(pos));
2502+
}
2503+
perf_cpu_map__put(intersect);
2504+
}
2505+
perf_cpu_map__put(user_requested_cpus);
2506+
}

tools/perf/util/evlist.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,4 +447,6 @@ struct evsel *evlist__find_evsel(struct evlist *evlist, int idx);
447447

448448
int evlist__scnprintf_evsels(struct evlist *evlist, size_t size, char *bf);
449449
void evlist__check_mem_load_aux(struct evlist *evlist);
450+
void evlist__warn_user_requested_cpus(struct evlist *evlist, const char *cpu_list);
451+
450452
#endif /* __PERF_EVLIST_H */

tools/perf/util/pmu.c

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,39 +2046,6 @@ int perf_pmu__match(char *pattern, char *name, char *tok)
20462046
return 0;
20472047
}
20482048

2049-
int perf_pmu__cpus_match(struct perf_pmu *pmu, struct perf_cpu_map *cpus,
2050-
struct perf_cpu_map **mcpus_ptr,
2051-
struct perf_cpu_map **ucpus_ptr)
2052-
{
2053-
struct perf_cpu_map *pmu_cpus = pmu->cpus;
2054-
struct perf_cpu_map *matched_cpus, *unmatched_cpus;
2055-
struct perf_cpu cpu;
2056-
int i, matched_nr = 0, unmatched_nr = 0;
2057-
2058-
matched_cpus = perf_cpu_map__default_new();
2059-
if (!matched_cpus)
2060-
return -1;
2061-
2062-
unmatched_cpus = perf_cpu_map__default_new();
2063-
if (!unmatched_cpus) {
2064-
perf_cpu_map__put(matched_cpus);
2065-
return -1;
2066-
}
2067-
2068-
perf_cpu_map__for_each_cpu(cpu, i, cpus) {
2069-
if (!perf_cpu_map__has(pmu_cpus, cpu))
2070-
RC_CHK_ACCESS(unmatched_cpus)->map[unmatched_nr++] = cpu;
2071-
else
2072-
RC_CHK_ACCESS(matched_cpus)->map[matched_nr++] = cpu;
2073-
}
2074-
2075-
perf_cpu_map__set_nr(unmatched_cpus, unmatched_nr);
2076-
perf_cpu_map__set_nr(matched_cpus, matched_nr);
2077-
*mcpus_ptr = matched_cpus;
2078-
*ucpus_ptr = unmatched_cpus;
2079-
return 0;
2080-
}
2081-
20822049
double __weak perf_pmu__cpu_slots_per_cycle(void)
20832050
{
20842051
return NAN;

tools/perf/util/pmu.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,6 @@ void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu);
265265
bool perf_pmu__has_hybrid(void);
266266
int perf_pmu__match(char *pattern, char *name, char *tok);
267267

268-
int perf_pmu__cpus_match(struct perf_pmu *pmu, struct perf_cpu_map *cpus,
269-
struct perf_cpu_map **mcpus_ptr,
270-
struct perf_cpu_map **ucpus_ptr);
271-
272268
char *pmu_find_real_name(const char *name);
273269
char *pmu_find_alias_name(const char *name);
274270
double perf_pmu__cpu_slots_per_cycle(void);

0 commit comments

Comments
 (0)