Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf bpf_counter: Fix opening of "any"(-1) CPU events

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>

authored by

Ian Rogers and committed by
Namhyung Kim
2a67955d 6090e612

+19 -1
+13
tools/perf/builtin-stat.c
··· 2542 2542 unsigned int interval, timeout; 2543 2543 const char * const stat_subcommands[] = { "record", "report" }; 2544 2544 char errbuf[BUFSIZ]; 2545 + struct evsel *counter; 2545 2546 2546 2547 setlocale(LC_ALL, ""); 2547 2548 ··· 2799 2798 } 2800 2799 2801 2800 evlist__warn_user_requested_cpus(evsel_list, target.cpu_list); 2801 + 2802 + evlist__for_each_entry(evsel_list, counter) { 2803 + /* 2804 + * Setup BPF counters to require CPUs as any(-1) isn't 2805 + * supported. evlist__create_maps below will propagate this 2806 + * information to the evsels. Note, evsel__is_bperf isn't yet 2807 + * set up, and this change must happen early, so directly use 2808 + * the bpf_counter variable and target information. 2809 + */ 2810 + if ((counter->bpf_counter || target.use_bpf) && !target__has_cpu(&target)) 2811 + counter->core.requires_cpu = true; 2812 + } 2802 2813 2803 2814 if (evlist__create_maps(evsel_list, &target) < 0) { 2804 2815 if (target__has_task(&target)) {
+6 -1
tools/perf/util/bpf_counter.c
··· 460 460 struct bperf_leader_bpf *skel = bperf_leader_bpf__open(); 461 461 int link_fd, diff_map_fd, err; 462 462 struct bpf_link *link = NULL; 463 + struct perf_thread_map *threads; 463 464 464 465 if (!skel) { 465 466 pr_err("Failed to open leader skeleton\n"); ··· 496 495 * following evsel__open_per_cpu call 497 496 */ 498 497 evsel->leader_skel = skel; 499 - evsel__open(evsel, evsel->core.cpus, evsel->core.threads); 498 + assert(!perf_cpu_map__has_any_cpu_or_is_empty(evsel->core.cpus)); 499 + /* Always open system wide. */ 500 + threads = thread_map__new_by_tid(-1); 501 + evsel__open(evsel, evsel->core.cpus, threads); 502 + perf_thread_map__put(threads); 500 503 501 504 out: 502 505 bperf_leader_bpf__destroy(skel);