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

perf bpf_counter: Fix handling of cpumap fixing hybrid

Don't open evsels on all CPUs, open them just on the CPUs they
support. This avoids opening say an e-core event on a p-core and
getting a failure - achieve this by getting rid of the "all_cpu_map".

In install_pe functions don't use the cpu_map_idx as a CPU number,
translate the cpu_map_idx, which is a dense index into the cpu_map
skipping holes at the beginning, to a proper CPU number.

Before:
```
$ perf stat --bpf-counters -a -e cycles,instructions -- sleep 1

Performance counter stats for 'system wide':

<not supported> cpu_atom/cycles/
566,270,672 cpu_core/cycles/
<not supported> cpu_atom/instructions/
572,792,836 cpu_core/instructions/ # 1.01 insn per cycle

1.001595384 seconds time elapsed
```

After:
```
$ perf stat --bpf-counters -a -e cycles,instructions -- sleep 1

Performance counter stats for 'system wide':

443,299,201 cpu_atom/cycles/
1,233,919,737 cpu_core/cycles/
213,634,112 cpu_atom/instructions/ # 0.48 insn per cycle
2,758,965,527 cpu_core/instructions/ # 2.24 insn per cycle

1.001699485 seconds time elapsed
```

Fixes: 7fac83aaf2eecc9e ("perf stat: Introduce 'bperf' to share hardware PMCs with BPF")
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: bpf@vger.kernel.org
Cc: Gabriele Monaco <gmonaco@redhat.com>
Cc: Howard Chu <howardchu95@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Song Liu <songliubraving@fb.com>
Cc: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
b91917c0 8c519a82

+12 -17
+10 -16
tools/perf/util/bpf_counter.c
··· 336 336 { 337 337 struct bpf_prog_profiler_bpf *skel; 338 338 struct bpf_counter *counter; 339 + int cpu = perf_cpu_map__cpu(evsel->core.cpus, cpu_map_idx).cpu; 339 340 int ret; 340 341 341 342 list_for_each_entry(counter, &evsel->bpf_counter_list, list) { ··· 344 343 assert(skel != NULL); 345 344 346 345 ret = bpf_map_update_elem(bpf_map__fd(skel->maps.events), 347 - &cpu_map_idx, &fd, BPF_ANY); 346 + &cpu, &fd, BPF_ANY); 348 347 if (ret) 349 348 return ret; 350 349 } ··· 452 451 return 0; 453 452 } 454 453 455 - static struct perf_cpu_map *all_cpu_map; 456 454 static __u32 filter_entry_cnt; 457 455 458 456 static int bperf_reload_leader_program(struct evsel *evsel, int attr_map_fd, ··· 495 495 * following evsel__open_per_cpu call 496 496 */ 497 497 evsel->leader_skel = skel; 498 - evsel__open_per_cpu(evsel, all_cpu_map, -1); 498 + evsel__open(evsel, evsel->core.cpus, evsel->core.threads); 499 499 500 500 out: 501 501 bperf_leader_bpf__destroy(skel); ··· 532 532 533 533 if (bperf_check_target(evsel, target, &filter_type, &filter_entry_cnt)) 534 534 return -1; 535 - 536 - if (!all_cpu_map) { 537 - all_cpu_map = perf_cpu_map__new_online_cpus(); 538 - if (!all_cpu_map) 539 - return -1; 540 - } 541 535 542 536 evsel->bperf_leader_prog_fd = -1; 543 537 evsel->bperf_leader_link_fd = -1; ··· 650 656 static int bperf__install_pe(struct evsel *evsel, int cpu_map_idx, int fd) 651 657 { 652 658 struct bperf_leader_bpf *skel = evsel->leader_skel; 659 + int cpu = perf_cpu_map__cpu(evsel->core.cpus, cpu_map_idx).cpu; 653 660 654 661 return bpf_map_update_elem(bpf_map__fd(skel->maps.events), 655 - &cpu_map_idx, &fd, BPF_ANY); 662 + &cpu, &fd, BPF_ANY); 656 663 } 657 664 658 665 /* ··· 662 667 */ 663 668 static int bperf_sync_counters(struct evsel *evsel) 664 669 { 665 - int num_cpu, i, cpu; 670 + struct perf_cpu cpu; 671 + int idx; 666 672 667 - num_cpu = perf_cpu_map__nr(all_cpu_map); 668 - for (i = 0; i < num_cpu; i++) { 669 - cpu = perf_cpu_map__cpu(all_cpu_map, i).cpu; 670 - bperf_trigger_reading(evsel->bperf_leader_prog_fd, cpu); 671 - } 673 + perf_cpu_map__for_each_cpu(cpu, idx, evsel->core.cpus) 674 + bperf_trigger_reading(evsel->bperf_leader_prog_fd, cpu.cpu); 675 + 672 676 return 0; 673 677 } 674 678
+2 -1
tools/perf/util/bpf_counter_cgroup.c
··· 186 186 } 187 187 188 188 static int bperf_cgrp__install_pe(struct evsel *evsel __maybe_unused, 189 - int cpu __maybe_unused, int fd __maybe_unused) 189 + int cpu_map_idx __maybe_unused, 190 + int fd __maybe_unused) 190 191 { 191 192 /* nothing to do */ 192 193 return 0;