+++ /dev/null
-From 001ba9206e4fa7b3d737ddded8cf58be98620f97 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 14 Nov 2024 16:04:48 +0000
-Subject: libperf: evlist: Fix --cpu argument on hybrid platform
-
-From: James Clark <james.clark@linaro.org>
-
-[ Upstream commit f7e36d02d771ee14acae1482091718460cffb321 ]
-
-Since the linked fixes: commit, specifying a CPU on hybrid platforms
-results in an error because Perf tries to open an extended type event
-on "any" CPU which isn't valid. Extended type events can only be opened
-on CPUs that match the type.
-
-Before (working):
-
- $ perf record --cpu 1 -- true
- [ perf record: Woken up 1 times to write data ]
- [ perf record: Captured and wrote 2.385 MB perf.data (7 samples) ]
-
-After (not working):
-
- $ perf record -C 1 -- true
- WARNING: A requested CPU in '1' is not supported by PMU 'cpu_atom' (CPUs 16-27) for event 'cycles:P'
- Error:
- The sys_perf_event_open() syscall returned with 22 (Invalid argument) for event (cpu_atom/cycles:P/).
- /bin/dmesg | grep -i perf may provide additional information.
-
-(Ignore the warning message, that's expected and not particularly
-relevant to this issue).
-
-This is because perf_cpu_map__intersect() of the user specified CPU (1)
-and one of the PMU's CPUs (16-27) correctly results in an empty (NULL)
-CPU map. However for the purposes of opening an event, libperf converts
-empty CPU maps into an any CPU (-1) which the kernel rejects.
-
-Fix it by deleting evsels with empty CPU maps in the specific case where
-user requested CPU maps are evaluated.
-
-Fixes: 251aa040244a ("perf parse-events: Wildcard most "numeric" events")
-Reviewed-by: Ian Rogers <irogers@google.com>
-Tested-by: Thomas Falcon <thomas.falcon@intel.com>
-Signed-off-by: James Clark <james.clark@linaro.org>
-Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Link: https://lore.kernel.org/r/20241114160450.295844-2-james.clark@linaro.org
-Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/lib/perf/evlist.c | 18 ++++++++++++++++--
- 1 file changed, 16 insertions(+), 2 deletions(-)
-
-diff --git a/tools/lib/perf/evlist.c b/tools/lib/perf/evlist.c
-index fad607789d1e..00ada8acee61 100644
---- a/tools/lib/perf/evlist.c
-+++ b/tools/lib/perf/evlist.c
-@@ -47,6 +47,20 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
- */
- perf_cpu_map__put(evsel->cpus);
- evsel->cpus = perf_cpu_map__intersect(evlist->user_requested_cpus, evsel->own_cpus);
-+
-+ /*
-+ * Empty cpu lists would eventually get opened as "any" so remove
-+ * genuinely empty ones before they're opened in the wrong place.
-+ */
-+ if (perf_cpu_map__is_empty(evsel->cpus)) {
-+ struct perf_evsel *next = perf_evlist__next(evlist, evsel);
-+
-+ perf_evlist__remove(evlist, evsel);
-+ /* Keep idx contiguous */
-+ if (next)
-+ list_for_each_entry_from(next, &evlist->entries, node)
-+ next->idx--;
-+ }
- } else if (!evsel->own_cpus || evlist->has_user_cpus ||
- (!evsel->requires_cpu && perf_cpu_map__has_any_cpu(evlist->user_requested_cpus))) {
- /*
-@@ -80,11 +94,11 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
-
- static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
- {
-- struct perf_evsel *evsel;
-+ struct perf_evsel *evsel, *n;
-
- evlist->needs_map_propagation = true;
-
-- perf_evlist__for_each_evsel(evlist, evsel)
-+ list_for_each_entry_safe(evsel, n, &evlist->entries, node)
- __perf_evlist__propagate_maps(evlist, evsel);
- }
-
---
-2.39.5
-