Skip to content

Commit 9597f08

Browse files
committed
Merge tag 'perf-tools-fixes-for-v6.0-2022-09-21' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux
Pull perf tools fixes from Arnaldo Carvalho de Melo: - Fix polling of system-wide events related to mixing per-cpu and per-thread events. - Do not check if /proc/modules is unchanged when copying /proc/kcore, that doesn't get in the way of post processing analysis. - Include program header in ELF files generated for JIT files, so that they can be opened by tools using elfutils libraries. - Enter namespaces when synthesizing build-ids. - Fix some bugs related to a recent cpu_map overhaul where we should be using an index and not the cpu number. - Fix BPF program ELF section name, using the naming expected by libbpf when using BPF counters in 'perf stat'. - Add a new test for perf stat cgroup BPF counter. - Adjust check on 'perf test wp' for older kernels, where the PERF_EVENT_IOC_MODIFY_ATTRIBUTES ioctl isn't supported. - Sync x86 cpufeatures with the kernel sources, no changes in tooling. * tag 'perf-tools-fixes-for-v6.0-2022-09-21' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux: perf tools: Honor namespace when synthesizing build-ids tools headers cpufeatures: Sync with the kernel sources perf kcore_copy: Do not check /proc/modules is unchanged libperf evlist: Fix polling of system-wide events perf record: Fix cpu mask bit setting for mixed mmaps perf test: Skip wp modify test on old kernels perf jit: Include program header in ELF files perf test: Add a new test for perf stat cgroup BPF counter perf stat: Use evsel->core.cpus to iterate cpus in BPF cgroup counters perf stat: Fix cpu map index in bperf cgroup code perf stat: Fix BPF program section name
2 parents dc164f4 + 999e4ea commit 9597f08

File tree

11 files changed

+139
-20
lines changed

11 files changed

+139
-20
lines changed

tools/arch/x86/include/asm/cpufeatures.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,8 @@
457457
#define X86_BUG_ITLB_MULTIHIT X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
458458
#define X86_BUG_SRBDS X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
459459
#define X86_BUG_MMIO_STALE_DATA X86_BUG(25) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */
460-
#define X86_BUG_RETBLEED X86_BUG(26) /* CPU is affected by RETBleed */
461-
#define X86_BUG_EIBRS_PBRSB X86_BUG(27) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
460+
#define X86_BUG_MMIO_UNKNOWN X86_BUG(26) /* CPU is too old and its MMIO Stale Data status is unknown */
461+
#define X86_BUG_RETBLEED X86_BUG(27) /* CPU is affected by RETBleed */
462+
#define X86_BUG_EIBRS_PBRSB X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
462463

463464
#endif /* _ASM_X86_CPUFEATURES_H */

tools/lib/perf/evlist.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@ mmap_per_evsel(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops,
441441

442442
perf_evlist__for_each_entry(evlist, evsel) {
443443
bool overwrite = evsel->attr.write_backward;
444+
enum fdarray_flags flgs;
444445
struct perf_mmap *map;
445446
int *output, fd, cpu;
446447

@@ -504,8 +505,8 @@ mmap_per_evsel(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops,
504505

505506
revent = !overwrite ? POLLIN : 0;
506507

507-
if (!evsel->system_wide &&
508-
perf_evlist__add_pollfd(evlist, fd, map, revent, fdarray_flag__default) < 0) {
508+
flgs = evsel->system_wide ? fdarray_flag__nonfilterable : fdarray_flag__default;
509+
if (perf_evlist__add_pollfd(evlist, fd, map, revent, flgs) < 0) {
509510
perf_mmap__put(map);
510511
return -1;
511512
}

tools/perf/builtin-record.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3371,6 +3371,8 @@ static int record__mmap_cpu_mask_init(struct mmap_cpu_mask *mask, struct perf_cp
33713371
return 0;
33723372

33733373
perf_cpu_map__for_each_cpu(cpu, idx, cpus) {
3374+
if (cpu.cpu == -1)
3375+
continue;
33743376
/* Return ENODEV is input cpu is greater than max cpu */
33753377
if ((unsigned long)cpu.cpu > mask->nbits)
33763378
return -ENODEV;
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#!/bin/sh
2+
# perf stat --bpf-counters --for-each-cgroup test
3+
# SPDX-License-Identifier: GPL-2.0
4+
5+
set -e
6+
7+
test_cgroups=
8+
if [ "$1" = "-v" ]; then
9+
verbose="1"
10+
fi
11+
12+
# skip if --bpf-counters --for-each-cgroup is not supported
13+
check_bpf_counter()
14+
{
15+
if ! perf stat -a --bpf-counters --for-each-cgroup / true > /dev/null 2>&1; then
16+
if [ "${verbose}" = "1" ]; then
17+
echo "Skipping: --bpf-counters --for-each-cgroup not supported"
18+
perf --no-pager stat -a --bpf-counters --for-each-cgroup / true || true
19+
fi
20+
exit 2
21+
fi
22+
}
23+
24+
# find two cgroups to measure
25+
find_cgroups()
26+
{
27+
# try usual systemd slices first
28+
if [ -d /sys/fs/cgroup/system.slice -a -d /sys/fs/cgroup/user.slice ]; then
29+
test_cgroups="system.slice,user.slice"
30+
return
31+
fi
32+
33+
# try root and self cgroups
34+
local self_cgrp=$(grep perf_event /proc/self/cgroup | cut -d: -f3)
35+
if [ -z ${self_cgrp} ]; then
36+
# cgroup v2 doesn't specify perf_event
37+
self_cgrp=$(grep ^0: /proc/self/cgroup | cut -d: -f3)
38+
fi
39+
40+
if [ -z ${self_cgrp} ]; then
41+
test_cgroups="/"
42+
else
43+
test_cgroups="/,${self_cgrp}"
44+
fi
45+
}
46+
47+
# As cgroup events are cpu-wide, we cannot simply compare the result.
48+
# Just check if it runs without failure and has non-zero results.
49+
check_system_wide_counted()
50+
{
51+
local output
52+
53+
output=$(perf stat -a --bpf-counters --for-each-cgroup ${test_cgroups} -e cpu-clock -x, sleep 1 2>&1)
54+
if echo ${output} | grep -q -F "<not "; then
55+
echo "Some system-wide events are not counted"
56+
if [ "${verbose}" = "1" ]; then
57+
echo ${output}
58+
fi
59+
exit 1
60+
fi
61+
}
62+
63+
check_cpu_list_counted()
64+
{
65+
local output
66+
67+
output=$(perf stat -C 1 --bpf-counters --for-each-cgroup ${test_cgroups} -e cpu-clock -x, taskset -c 1 sleep 1 2>&1)
68+
if echo ${output} | grep -q -F "<not "; then
69+
echo "Some CPU events are not counted"
70+
if [ "${verbose}" = "1" ]; then
71+
echo ${output}
72+
fi
73+
exit 1
74+
fi
75+
}
76+
77+
check_bpf_counter
78+
find_cgroups
79+
80+
check_system_wide_counted
81+
check_cpu_list_counted
82+
83+
exit 0

tools/perf/tests/wp.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
#include <stdlib.h>
33
#include <string.h>
44
#include <unistd.h>
5+
#include <errno.h>
56
#include <sys/ioctl.h>
7+
#include <linux/compiler.h>
68
#include <linux/hw_breakpoint.h>
79
#include <linux/kernel.h>
810
#include "tests.h"
@@ -137,8 +139,7 @@ static int test__wp_rw(struct test_suite *test __maybe_unused,
137139
#endif
138140
}
139141

140-
static int test__wp_modify(struct test_suite *test __maybe_unused,
141-
int subtest __maybe_unused)
142+
static int test__wp_modify(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
142143
{
143144
#if defined(__s390x__)
144145
return TEST_SKIP;
@@ -160,6 +161,11 @@ static int test__wp_modify(struct test_suite *test __maybe_unused,
160161
new_attr.disabled = 1;
161162
ret = ioctl(fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &new_attr);
162163
if (ret < 0) {
164+
if (errno == ENOTTY) {
165+
test->test_cases[subtest].skip_reason = "missing kernel support";
166+
ret = TEST_SKIP;
167+
}
168+
163169
pr_debug("ioctl(PERF_EVENT_IOC_MODIFY_ATTRIBUTES) failed\n");
164170
close(fd);
165171
return ret;

tools/perf/util/bpf_counter_cgroup.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ static int bperf_load_program(struct evlist *evlist)
9595

9696
perf_cpu_map__for_each_cpu(cpu, i, evlist->core.all_cpus) {
9797
link = bpf_program__attach_perf_event(skel->progs.on_cgrp_switch,
98-
FD(cgrp_switch, cpu.cpu));
98+
FD(cgrp_switch, i));
9999
if (IS_ERR(link)) {
100100
pr_err("Failed to attach cgroup program\n");
101101
err = PTR_ERR(link);
@@ -115,15 +115,15 @@ static int bperf_load_program(struct evlist *evlist)
115115
evsel->cgrp = NULL;
116116

117117
/* open single copy of the events w/o cgroup */
118-
err = evsel__open_per_cpu(evsel, evlist->core.all_cpus, -1);
118+
err = evsel__open_per_cpu(evsel, evsel->core.cpus, -1);
119119
if (err) {
120120
pr_err("Failed to open first cgroup events\n");
121121
goto out;
122122
}
123123

124124
map_fd = bpf_map__fd(skel->maps.events);
125-
perf_cpu_map__for_each_cpu(cpu, j, evlist->core.all_cpus) {
126-
int fd = FD(evsel, cpu.cpu);
125+
perf_cpu_map__for_each_cpu(cpu, j, evsel->core.cpus) {
126+
int fd = FD(evsel, j);
127127
__u32 idx = evsel->core.idx * total_cpus + cpu.cpu;
128128

129129
err = bpf_map_update_elem(map_fd, &idx, &fd,
@@ -269,7 +269,7 @@ static int bperf_cgrp__read(struct evsel *evsel)
269269
goto out;
270270
}
271271

272-
perf_cpu_map__for_each_cpu(cpu, i, evlist->core.all_cpus) {
272+
perf_cpu_map__for_each_cpu(cpu, i, evsel->core.cpus) {
273273
counts = perf_counts(evsel->counts, i, 0);
274274
counts->val = values[cpu.cpu].counter;
275275
counts->ena = values[cpu.cpu].enabled;

tools/perf/util/bpf_skel/bperf_cgroup.bpf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ static int bperf_cgroup_count(void)
176176
}
177177

178178
// This will be attached to cgroup-switches event for each cpu
179-
SEC("perf_events")
179+
SEC("perf_event")
180180
int BPF_PROG(on_cgrp_switch)
181181
{
182182
return bperf_cgroup_count();

tools/perf/util/genelf.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ jit_write_elf(int fd, uint64_t load_addr, const char *sym,
253253
Elf_Data *d;
254254
Elf_Scn *scn;
255255
Elf_Ehdr *ehdr;
256+
Elf_Phdr *phdr;
256257
Elf_Shdr *shdr;
257258
uint64_t eh_frame_base_offset;
258259
char *strsym = NULL;
@@ -287,6 +288,19 @@ jit_write_elf(int fd, uint64_t load_addr, const char *sym,
287288
ehdr->e_version = EV_CURRENT;
288289
ehdr->e_shstrndx= unwinding ? 4 : 2; /* shdr index for section name */
289290

291+
/*
292+
* setup program header
293+
*/
294+
phdr = elf_newphdr(e, 1);
295+
phdr[0].p_type = PT_LOAD;
296+
phdr[0].p_offset = 0;
297+
phdr[0].p_vaddr = 0;
298+
phdr[0].p_paddr = 0;
299+
phdr[0].p_filesz = csize;
300+
phdr[0].p_memsz = csize;
301+
phdr[0].p_flags = PF_X | PF_R;
302+
phdr[0].p_align = 8;
303+
290304
/*
291305
* setup text section
292306
*/

tools/perf/util/genelf.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,21 @@ int jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_ent
5353

5454
#if GEN_ELF_CLASS == ELFCLASS64
5555
#define elf_newehdr elf64_newehdr
56+
#define elf_newphdr elf64_newphdr
5657
#define elf_getshdr elf64_getshdr
5758
#define Elf_Ehdr Elf64_Ehdr
59+
#define Elf_Phdr Elf64_Phdr
5860
#define Elf_Shdr Elf64_Shdr
5961
#define Elf_Sym Elf64_Sym
6062
#define ELF_ST_TYPE(a) ELF64_ST_TYPE(a)
6163
#define ELF_ST_BIND(a) ELF64_ST_BIND(a)
6264
#define ELF_ST_VIS(a) ELF64_ST_VISIBILITY(a)
6365
#else
6466
#define elf_newehdr elf32_newehdr
67+
#define elf_newphdr elf32_newphdr
6568
#define elf_getshdr elf32_getshdr
6669
#define Elf_Ehdr Elf32_Ehdr
70+
#define Elf_Phdr Elf32_Phdr
6771
#define Elf_Shdr Elf32_Shdr
6872
#define Elf_Sym Elf32_Sym
6973
#define ELF_ST_TYPE(a) ELF32_ST_TYPE(a)

tools/perf/util/symbol-elf.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2102,8 +2102,8 @@ static int kcore_copy__compare_file(const char *from_dir, const char *to_dir,
21022102
* unusual. One significant peculiarity is that the mapping (start -> pgoff)
21032103
* is not the same for the kernel map and the modules map. That happens because
21042104
* the data is copied adjacently whereas the original kcore has gaps. Finally,
2105-
* kallsyms and modules files are compared with their copies to check that
2106-
* modules have not been loaded or unloaded while the copies were taking place.
2105+
* kallsyms file is compared with its copy to check that modules have not been
2106+
* loaded or unloaded while the copies were taking place.
21072107
*
21082108
* Return: %0 on success, %-1 on failure.
21092109
*/
@@ -2166,9 +2166,6 @@ int kcore_copy(const char *from_dir, const char *to_dir)
21662166
goto out_extract_close;
21672167
}
21682168

2169-
if (kcore_copy__compare_file(from_dir, to_dir, "modules"))
2170-
goto out_extract_close;
2171-
21722169
if (kcore_copy__compare_file(from_dir, to_dir, "kallsyms"))
21732170
goto out_extract_close;
21742171

0 commit comments

Comments
 (0)