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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'perf-tools-fixes-for-v5.18-2022-05-21' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

Pull perf tools fixes from Arnaldo Carvalho de Melo:

- Fix and validate CPU map inputs in synthetic PERF_RECORD_STAT events
in 'perf stat'.

- Fix x86's arch__intr_reg_mask() for the hybrid platform.

- Address 'perf bench numa' compiler error on s390.

- Fix check for btf__load_from_kernel_by_id() in libbpf.

- Fix "all PMU test" 'perf test' to skip hv_24x7/hv_gpci tests on
powerpc.

- Fix session topology test to skip the test in guest environment.

- Skip BPF 'perf test' if clang is not present.

- Avoid shell test description infinite loop in 'perf test'.

- Fix Intel LBR callstack entries and nr print message.

* tag 'perf-tools-fixes-for-v5.18-2022-05-21' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux:
perf session: Fix Intel LBR callstack entries and nr print message
perf test bpf: Skip test if clang is not present
perf test session topology: Fix test to skip the test in guest environment
perf bench numa: Address compiler error on s390
perf test: Avoid shell test description infinite loop
perf regs x86: Fix arch__intr_reg_mask() for the hybrid platform
perf test: Fix "all PMU test" to skip hv_24x7/hv_gpci tests on powerpc
perf stat: Fix and validate CPU map inputs in synthetic PERF_RECORD_STAT events
perf build: Fix check for btf__load_from_kernel_by_id() in libbpf

+103 -16
+1
tools/build/Makefile.feature
··· 98 98 llvm-version \ 99 99 clang \ 100 100 libbpf \ 101 + libbpf-btf__load_from_kernel_by_id \ 101 102 libpfm4 \ 102 103 libdebuginfod \ 103 104 clang-bpf-co-re
+4
tools/build/feature/Makefile
··· 57 57 test-lzma.bin \ 58 58 test-bpf.bin \ 59 59 test-libbpf.bin \ 60 + test-libbpf-btf__load_from_kernel_by_id.bin \ 60 61 test-get_cpuid.bin \ 61 62 test-sdt.bin \ 62 63 test-cxx.bin \ ··· 286 285 $(BUILD) 287 286 288 287 $(OUTPUT)test-libbpf.bin: 288 + $(BUILD) -lbpf 289 + 290 + $(OUTPUT)test-libbpf-btf__load_from_kernel_by_id.bin: 289 291 $(BUILD) -lbpf 290 292 291 293 $(OUTPUT)test-sdt.bin:
+7
tools/build/feature/test-libbpf-btf__load_from_kernel_by_id.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <bpf/libbpf.h> 3 + 4 + int main(void) 5 + { 6 + return btf__load_from_kernel_by_id(20151128, NULL); 7 + }
+7
tools/perf/Makefile.config
··· 553 553 ifeq ($(feature-libbpf), 1) 554 554 EXTLIBS += -lbpf 555 555 $(call detected,CONFIG_LIBBPF_DYNAMIC) 556 + 557 + $(call feature_check,libbpf-btf__load_from_kernel_by_id) 558 + ifeq ($(feature-libbpf-btf__load_from_kernel_by_id), 1) 559 + CFLAGS += -DHAVE_LIBBPF_BTF__LOAD_FROM_KERNEL_BY_ID 560 + endif 556 561 else 557 562 dummy := $(error Error: No libbpf devel library found, please install libbpf-devel); 558 563 endif 564 + else 565 + CFLAGS += -DHAVE_LIBBPF_BTF__LOAD_FROM_KERNEL_BY_ID 559 566 endif 560 567 endif 561 568
+12
tools/perf/arch/x86/util/perf_regs.c
··· 9 9 #include "../../../util/perf_regs.h" 10 10 #include "../../../util/debug.h" 11 11 #include "../../../util/event.h" 12 + #include "../../../util/pmu.h" 13 + #include "../../../util/pmu-hybrid.h" 12 14 13 15 const struct sample_reg sample_reg_masks[] = { 14 16 SMPL_REG(AX, PERF_REG_X86_AX), ··· 286 284 .disabled = 1, 287 285 .exclude_kernel = 1, 288 286 }; 287 + struct perf_pmu *pmu; 289 288 int fd; 290 289 /* 291 290 * In an unnamed union, init it here to build on older gcc versions 292 291 */ 293 292 attr.sample_period = 1; 293 + 294 + if (perf_pmu__has_hybrid()) { 295 + /* 296 + * The same register set is supported among different hybrid PMUs. 297 + * Only check the first available one. 298 + */ 299 + pmu = list_first_entry(&perf_pmu__hybrid_pmus, typeof(*pmu), hybrid_list); 300 + attr.config |= (__u64)pmu->type << PERF_PMU_TYPE_SHIFT; 301 + } 294 302 295 303 event_attr_init(&attr); 296 304
+1 -1
tools/perf/bench/numa.c
··· 1740 1740 "GB/sec,", "total-speed", "GB/sec total speed"); 1741 1741 1742 1742 if (g->p.show_details >= 2) { 1743 - char tname[14 + 2 * 10 + 1]; 1743 + char tname[14 + 2 * 11 + 1]; 1744 1744 struct thread_data *td; 1745 1745 for (p = 0; p < g->p.nr_proc; p++) { 1746 1746 for (t = 0; t < g->p.nr_threads; t++) {
+6 -4
tools/perf/tests/bpf.c
··· 222 222 223 223 ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz, 224 224 bpf_testcase_table[idx].prog_id, 225 - true, NULL); 225 + false, NULL); 226 226 if (ret != TEST_OK || !obj_buf || !obj_buf_sz) { 227 227 pr_debug("Unable to get BPF object, %s\n", 228 228 bpf_testcase_table[idx].msg_compile_fail); 229 - if (idx == 0) 229 + if ((idx == 0) || (ret == TEST_SKIP)) 230 230 return TEST_SKIP; 231 231 else 232 232 return TEST_FAIL; ··· 364 364 static struct test_case bpf_tests[] = { 365 365 #ifdef HAVE_LIBBPF_SUPPORT 366 366 TEST_CASE("Basic BPF filtering", basic_bpf_test), 367 - TEST_CASE("BPF pinning", bpf_pinning), 367 + TEST_CASE_REASON("BPF pinning", bpf_pinning, 368 + "clang isn't installed or environment missing BPF support"), 368 369 #ifdef HAVE_BPF_PROLOGUE 369 - TEST_CASE("BPF prologue generation", bpf_prologue_test), 370 + TEST_CASE_REASON("BPF prologue generation", bpf_prologue_test, 371 + "clang isn't installed or environment missing BPF support"), 370 372 #else 371 373 TEST_CASE_REASON("BPF prologue generation", bpf_prologue_test, "not compiled in"), 372 374 #endif
+6 -2
tools/perf/tests/builtin-test.c
··· 279 279 { 280 280 FILE *fp; 281 281 char filename[PATH_MAX]; 282 + int ch; 282 283 283 284 path__join(filename, sizeof(filename), path, name); 284 285 fp = fopen(filename, "r"); ··· 287 286 return NULL; 288 287 289 288 /* Skip shebang */ 290 - while (fgetc(fp) != '\n'); 289 + do { 290 + ch = fgetc(fp); 291 + } while (ch != EOF && ch != '\n'); 291 292 292 293 description = fgets(description, size, fp); 293 294 fclose(fp); ··· 420 417 .priv = &st, 421 418 }; 422 419 423 - if (!perf_test__matches(test_suite.desc, curr, argc, argv)) 420 + if (test_suite.desc == NULL || 421 + !perf_test__matches(test_suite.desc, curr, argc, argv)) 424 422 continue; 425 423 426 424 st.file = ent->d_name;
+10
tools/perf/tests/shell/stat_all_pmu.sh
··· 5 5 set -e 6 6 7 7 for p in $(perf list --raw-dump pmu); do 8 + # In powerpc, skip the events for hv_24x7 and hv_gpci. 9 + # These events needs input values to be filled in for 10 + # core, chip, partition id based on system. 11 + # Example: hv_24x7/CPM_ADJUNCT_INST,domain=?,core=?/ 12 + # hv_gpci/event,partition_id=?/ 13 + # Hence skip these events for ppc. 14 + if echo "$p" |grep -Eq 'hv_24x7|hv_gpci' ; then 15 + echo "Skipping: Event '$p' in powerpc" 16 + continue 17 + fi 8 18 echo "Testing $p" 9 19 result=$(perf stat -e "$p" true 2>&1) 10 20 if ! echo "$result" | grep -q "$p" && ! echo "$result" | grep -q "<not supported>" ; then
+11
tools/perf/tests/topology.c
··· 109 109 && strncmp(session->header.env.arch, "aarch64", 7)) 110 110 return TEST_SKIP; 111 111 112 + /* 113 + * In powerpc pSeries platform, not all the topology information 114 + * are exposed via sysfs. Due to restriction, detail like 115 + * physical_package_id will be set to -1. Hence skip this 116 + * test if physical_package_id returns -1 for cpu from perf_cpu_map. 117 + */ 118 + if (strncmp(session->header.env.arch, "powerpc", 7)) { 119 + if (cpu__get_socket_id(perf_cpu_map__cpu(map, 0)) == -1) 120 + return TEST_SKIP; 121 + } 122 + 112 123 TEST_ASSERT_VAL("Session header CPU map not set", session->header.env.cpu); 113 124 114 125 for (i = 0; i < session->header.env.nr_cpus_avail; i++) {
+3 -1
tools/perf/util/bpf-event.c
··· 22 22 #include "record.h" 23 23 #include "util/synthetic-events.h" 24 24 25 - struct btf * __weak btf__load_from_kernel_by_id(__u32 id) 25 + #ifndef HAVE_LIBBPF_BTF__LOAD_FROM_KERNEL_BY_ID 26 + struct btf *btf__load_from_kernel_by_id(__u32 id) 26 27 { 27 28 struct btf *btf; 28 29 #pragma GCC diagnostic push ··· 33 32 34 33 return err ? ERR_PTR(err) : btf; 35 34 } 35 + #endif 36 36 37 37 int __weak bpf_prog_load(enum bpf_prog_type prog_type, 38 38 const char *prog_name __maybe_unused,
+21 -5
tools/perf/util/session.c
··· 1151 1151 struct branch_entry *entries = perf_sample__branch_entries(sample); 1152 1152 uint64_t i; 1153 1153 1154 - printf("%s: nr:%" PRIu64 "\n", 1155 - !callstack ? "... branch stack" : "... branch callstack", 1156 - sample->branch_stack->nr); 1154 + if (!callstack) { 1155 + printf("%s: nr:%" PRIu64 "\n", "... branch stack", sample->branch_stack->nr); 1156 + } else { 1157 + /* the reason of adding 1 to nr is because after expanding 1158 + * branch stack it generates nr + 1 callstack records. e.g., 1159 + * B()->C() 1160 + * A()->B() 1161 + * the final callstack should be: 1162 + * C() 1163 + * B() 1164 + * A() 1165 + */ 1166 + printf("%s: nr:%" PRIu64 "\n", "... branch callstack", sample->branch_stack->nr+1); 1167 + } 1157 1168 1158 1169 for (i = 0; i < sample->branch_stack->nr; i++) { 1159 1170 struct branch_entry *e = &entries[i]; ··· 1180 1169 (unsigned)e->flags.reserved, 1181 1170 e->flags.type ? branch_type_name(e->flags.type) : ""); 1182 1171 } else { 1183 - printf("..... %2"PRIu64": %016" PRIx64 "\n", 1184 - i, i > 0 ? e->from : e->to); 1172 + if (i == 0) { 1173 + printf("..... %2"PRIu64": %016" PRIx64 "\n" 1174 + "..... %2"PRIu64": %016" PRIx64 "\n", 1175 + i, e->to, i+1, e->from); 1176 + } else { 1177 + printf("..... %2"PRIu64": %016" PRIx64 "\n", i+1, e->from); 1178 + } 1185 1179 } 1186 1180 } 1187 1181 }
+14 -3
tools/perf/util/stat.c
··· 472 472 int perf_event__process_stat_event(struct perf_session *session, 473 473 union perf_event *event) 474 474 { 475 - struct perf_counts_values count; 475 + struct perf_counts_values count, *ptr; 476 476 struct perf_record_stat *st = &event->stat; 477 477 struct evsel *counter; 478 + int cpu_map_idx; 478 479 479 480 count.val = st->val; 480 481 count.ena = st->ena; ··· 486 485 pr_err("Failed to resolve counter for stat event.\n"); 487 486 return -EINVAL; 488 487 } 489 - 490 - *perf_counts(counter->counts, st->cpu, st->thread) = count; 488 + cpu_map_idx = perf_cpu_map__idx(evsel__cpus(counter), (struct perf_cpu){.cpu = st->cpu}); 489 + if (cpu_map_idx == -1) { 490 + pr_err("Invalid CPU %d for event %s.\n", st->cpu, evsel__name(counter)); 491 + return -EINVAL; 492 + } 493 + ptr = perf_counts(counter->counts, cpu_map_idx, st->thread); 494 + if (ptr == NULL) { 495 + pr_err("Failed to find perf count for CPU %d thread %d on event %s.\n", 496 + st->cpu, st->thread, evsel__name(counter)); 497 + return -EINVAL; 498 + } 499 + *ptr = count; 491 500 counter->supported = true; 492 501 return 0; 493 502 }