]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
perf bpf_counter: Fix opening of "any"(-1) CPU events
authorIan Rogers <irogers@google.com>
Thu, 9 Oct 2025 13:29:11 +0000 (06:29 -0700)
committerNamhyung Kim <namhyung@kernel.org>
Mon, 13 Oct 2025 08:58:51 +0000 (01:58 -0700)
The bperf BPF counter code doesn't handle "any"(-1) CPU events, always
wanting to aggregate a count against a CPU, which avoids the need for
atomics so let's not change that. Force evsels used for BPF counters
to require a CPU when not in system-wide mode so that the "any"(-1)
value isn't used during map propagation and evsel's CPU map matches
that of the PMU.

Fixes: b91917c0c6fa ("perf bpf_counter: Fix handling of cpumap fixing hybrid")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/builtin-stat.c
tools/perf/util/bpf_counter.c

index 84e06ec09cc270dee93336f1806d900e58b27bf9..4314012846ba346799f2df010d01747f5978ea0c 100644 (file)
@@ -2542,6 +2542,7 @@ int cmd_stat(int argc, const char **argv)
        unsigned int interval, timeout;
        const char * const stat_subcommands[] = { "record", "report" };
        char errbuf[BUFSIZ];
+       struct evsel *counter;
 
        setlocale(LC_ALL, "");
 
@@ -2799,6 +2800,18 @@ int cmd_stat(int argc, const char **argv)
 
        evlist__warn_user_requested_cpus(evsel_list, target.cpu_list);
 
+       evlist__for_each_entry(evsel_list, counter) {
+               /*
+                * Setup BPF counters to require CPUs as any(-1) isn't
+                * supported. evlist__create_maps below will propagate this
+                * information to the evsels. Note, evsel__is_bperf isn't yet
+                * set up, and this change must happen early, so directly use
+                * the bpf_counter variable and target information.
+                */
+               if ((counter->bpf_counter || target.use_bpf) && !target__has_cpu(&target))
+                       counter->core.requires_cpu = true;
+       }
+
        if (evlist__create_maps(evsel_list, &target) < 0) {
                if (target__has_task(&target)) {
                        pr_err("Problems finding threads of monitor\n");
index ca5d01b9017dbac9b3b71c91ca18015b88ef7d11..a5882b5822057b528807c3666e3a8da7b43bd653 100644 (file)
@@ -460,6 +460,7 @@ static int bperf_reload_leader_program(struct evsel *evsel, int attr_map_fd,
        struct bperf_leader_bpf *skel = bperf_leader_bpf__open();
        int link_fd, diff_map_fd, err;
        struct bpf_link *link = NULL;
+       struct perf_thread_map *threads;
 
        if (!skel) {
                pr_err("Failed to open leader skeleton\n");
@@ -495,7 +496,11 @@ static int bperf_reload_leader_program(struct evsel *evsel, int attr_map_fd,
         * following evsel__open_per_cpu call
         */
        evsel->leader_skel = skel;
-       evsel__open(evsel, evsel->core.cpus, evsel->core.threads);
+       assert(!perf_cpu_map__has_any_cpu_or_is_empty(evsel->core.cpus));
+       /* Always open system wide. */
+       threads = thread_map__new_by_tid(-1);
+       evsel__open(evsel, evsel->core.cpus, threads);
+       perf_thread_map__put(threads);
 
 out:
        bperf_leader_bpf__destroy(skel);