Re: [PATCH] perf evlist: don't restrict uncore events to PMU CPUs
From: Ian Rogers
Date: Fri Sep 04 2026 - 12:06:11 EST
On Fri, Sep 4, 2026 at 6:45 AM Nia Su <nia.su@xxxxxxxxxx> wrote:
>
> The PMU CPU map has different semantics for core and uncore PMUs.
>
> For core PMUs, pmu_cpus contains the CPUs on which the event can be
> opened. Intersect the user-requested CPU map with the PMU CPU map to
> reject CPUs unsupported by the PMU.
>
> For uncore PMUs, pmu_cpus is just the default CPU to open the event on,
> not the set of CPUs it can only be opened on.
This isn't quite true. On a dual socket Intel machine, `pmu_cpus` will
contain a CPU to open the event on per-socket.
> The user-requested CPU may
> override the default and be used directly, and the driver can redirect
> the event to the appropriate control CPU.
Agreed.
> Currently, __perf_evlist__propagate_maps() intersects the user-requested
> CPU map with pmu_cpus for all PMUs. If the user-requested CPU is not in
> pmu_cpus, the intersection becomes empty and the evsel is removed before
> perf_event_open() is called.
Could you give a command line example of the perf tool doing this? I
ask because I'm surprised the uncore specifying a CPU behavior has
been broken. As well as `perf record -C` there is also a somewhat
newer cpu event qualifier.
> Skip the intersection when evsel->requires_cpu is true, which is set for
> uncore PMUs. is_pmu_core is also false for other non-core PMUs, so
> gating on it would have loosened this check for them too. Core PMUs
> continue to be restricted to their PMU CPU map.
>
> requires_cpu can also be set for BPF counters regardless of PMU type,
> but only when has_user_cpus is false, so this guard has no effect there
> today.
So the separation between libperf and perf is frustrating, and libperf
lacks the necessary PMU abstraction. Using requires_cpu as a proxy for
an uncore PMU test is okay, but it would be better if we had a boolean
flag especially for this. Given this, a comment should be added saying
that requires_cpu is used as a proxy for an uncore PMU. The real
meaning of requires_cpu is that the event doesn't support
perf_event_open with a thread.
Thanks,
Ian
> Fixes: 811082e4b668 ("perf parse-events: Support user CPUs mixed with threads/processes")
>
> Assisted-by: Claude Sonnet 5
> Signed-off-by: Nia Su <nia.su@xxxxxxxxxx>
> ---
> tools/lib/perf/evlist.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/tools/lib/perf/evlist.c b/tools/lib/perf/evlist.c
> index 1f210dadd666ff818a23712ab95acaa659ccf8dc..a1064175f12ba655a9f7fe42e7c7e4c49ae60423 100644
> --- a/tools/lib/perf/evlist.c
> +++ b/tools/lib/perf/evlist.c
> @@ -80,7 +80,8 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
> }
>
> /* Ensure cpus only references valid PMU CPUs. */
> - if (!perf_cpu_map__has_any_cpu(evsel->cpus) &&
> + if (!evsel->requires_cpu &&
> + !perf_cpu_map__has_any_cpu(evsel->cpus) &&
> !perf_cpu_map__is_subset(evsel->pmu_cpus, evsel->cpus)) {
> struct perf_cpu_map *tmp = perf_cpu_map__intersect(evsel->pmu_cpus, evsel->cpus);
>
>
> ---
> base-commit: 73e3f0710014fe6d4ed98cfc02292f6121db7558
> change-id: 20260904-perf-evlist-uncore-cpu-b4-418af0f17c80
>
> --
>