Skip to content

Commit f4f346c

Browse files
committed
Merge tag 'perf-tools-for-v6.17-2025-08-01' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools
Pull perf tools updates from Namhyung Kim: "Build-ID processing goodies: Build-IDs are content based hashes to link regions of memory to ELF files in post processing. They have been available in distros for quite a while: $ file /bin/bash /bin/bash: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=707a1c670cd72f8e55ffedfbe94ea98901b7ce3a, for GNU/Linux 3.2.0, stripped It is possible to ask the kernel to get it from mmap executable backing storage at time they are being put in place and send it as metadata at that moment to have in perf.data. Prefer that across the board to speed up 'record' time - it post processes the samples to find binaries touched by any samples and to save them with build-ID. It can skip reading build-ID in userspace if it comes from the kernel. perf record: * Make --buildid-mmap default. The kernel can generate MMAP2 events with a build-ID from ELF header. Use that by default instead of using inode and device ID to identify binaries. It also can be disabled with --no-buildid-mmap. * Use BPF for -u/--uid option to sample processes belong to a user. BPF can track user processes more accurately and the existing logic often fails to get the list of processes due to race with reading the /proc filesystem. * Generate PERF_RECORD_BPF_METADATA when it profiles BPF programs and they have variables starting with "bpf_metadata_". This will help to identify BPF objects used in the profile. This has been supported in bpftool for some time and allows the recording of metadata such as commit hashes, versions, etc, that now gets recorded in perf.data as well. * Collect list of DSOs touched in the sample callchains as well as in the sample itself. This would increase the processing time at the end of record, but can improve the data quality. perf stat: * Add a new 'drm' pseudo-PMU support like in 'hwmon'. It can collect DRM usage stats using fdinfo in /proc. On my Intel laptop, it shows like below: $ perf list drm ... drm: drm-active-stolen-system0 [Total memory active in one or more engines. Unit: drm_i915] drm-active-system0 [Total memory active in one or more engines. Unit: drm_i915] drm-engine-capacity-video [Engine capacity. Unit: drm_i915] drm-engine-copy [Utilization in ns. Unit: drm_i915] drm-engine-render [Utilization in ns. Unit: drm_i915] drm-engine-video [Utilization in ns. Unit: drm_i915] ... $ sudo perf stat -a -e drm-engine-render,drm-engine-video,drm-engine-capacity-video sleep 1 Performance counter stats for 'system wide': 48,137,316,988,873 ns drm-engine-render 34,452,696,746 ns drm-engine-video 20 capacity drm-engine-capacity-video 1.002086194 seconds time elapsed perf list * Add description for software events. The description is in JSON format and the event parser now can handle the software events like others (for example, it's case-insensitive and subject to wildcard matching). $ perf list software List of pre-defined events (to be used in -e or -M): software: alignment-faults [Number of kernel handled memory alignment faults. Unit: software] bpf-output [An event used by BPF programs to write to the perf ring buffer. Unit: software] cgroup-switches [Number of context switches to a task in a different cgroup. Unit: software] context-switches [Number of context switches [This event is an alias of cs]. Unit: software] cpu-clock [Per-CPU high-resolution timer based event. Unit: software] cpu-migrations [Number of times a process has migrated to a new CPU [This event is an alias of migrations]. Unit: software] cs [Number of context switches [This event is an alias of context-switches]. Unit: software] dummy [A placeholder event that doesn't count anything. Unit: software] emulation-faults [Number of kernel handled unimplemented instruction faults handled through emulation. Unit: software] faults [Number of page faults [This event is an alias of page-faults]. Unit: software] major-faults [Number of major page faults. Major faults require I/O to handle. Unit: software] migrations [Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]. Unit: software] minor-faults [Number of minor page faults. Minor faults don't require I/O to handle. Unit: software] page-faults [Number of page faults [This event is an alias of faults]. Unit: software] task-clock [Per-task high-resolution timer based event. Unit: software] perf ftrace: * Add -e/--events option to perf ftrace latency to measure latency between the two events instead of a function. $ sudo perf ftrace latency -ab -e i915_request_wait_begin,i915_request_wait_end --hide-empty -- sleep 1 # DURATION | COUNT | GRAPH | 256 - 512 us | 4 | ###### | 2 - 4 ms | 2 | ### | 4 - 8 ms | 12 | ################### | 8 - 16 ms | 10 | ################ | # statistics (in usec) total time: 194915 avg time: 6961 max time: 12855 min time: 373 count: 28 * Add new function graph tracer options (--graph-opts) to display more info like arguments and return value. They will be passed to the kernel ftrace directly. $ sudo perf ftrace -G vfs_write --graph-opts retval,retaddr # tracer: function_graph # # CPU DURATION FUNCTION CALLS # | | | | | | | ... 5) | mutex_unlock() { /* <-rb_simple_write+0xda/0x150 */ 5) 0.188 us | local_clock(); /* <-lock_release+0x2ad/0x440 ret=0x3bf2a3cf90e */ 5) | rt_mutex_slowunlock() { /* <-rb_simple_write+0xda/0x150 */ 5) | _raw_spin_lock_irqsave() { /* <-rt_mutex_slowunlock+0x4f/0x200 */ 5) 0.123 us | preempt_count_add(); /* <-_raw_spin_lock_irqsave+0x23/0x90 ret=0x0 */ 5) 0.128 us | local_clock(); /* <-__lock_acquire.isra.0+0x17a/0x740 ret=0x3bf2a3cfc8b */ 5) 0.086 us | do_raw_spin_trylock(); /* <-_raw_spin_lock_irqsave+0x4a/0x90 ret=0x1 */ 5) 0.845 us | } /* _raw_spin_lock_irqsave ret=0x292 */ ... Misc: * Add perf archive --exclude-buildids <FILE> option to skip some binaries. The format of the FILE should be same as an output of perf buildid-list. * Get rid of dependency of libcrypto. It was just to get SHA-1 hash so implement it directly like in the kernel. A side effect is that it needs -fno-strict-aliasing compiler option (again, like in the kernel). * Convert all shell script tests to use bash" * tag 'perf-tools-for-v6.17-2025-08-01' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools: (179 commits) perf record: Cache build-ID of hit DSOs only perf test: Ensure lock contention using pipe mode perf python: Stop using deprecated PyUnicode_AsString() perf list: Skip ABI PMUs when printing pmu values perf list: Remove tracepoint printing code perf tp_pmu: Add event APIs perf tp_pmu: Factor existing tracepoint logic to new file perf parse-events: Remove non-json software events perf jevents: Add common software event json perf tools: Remove libtraceevent in .gitignore perf test: Fix comment ordering perf sort: Use perf_env to set arch sort keys and header perf test: Move PERF_SAMPLE_WEIGHT_STRUCT parsing to common test perf sample: Remove arch notion of sample parsing perf env: Remove global perf_env perf trace: Avoid global perf_env with evsel__env perf auxtrace: Pass perf_env from session through to mmap read perf machine: Explicitly pass in host perf_env perf bench synthesize: Avoid use of global perf_env perf top: Make perf_env locally scoped ...
2 parents 0905809 + 6235ce7 commit f4f346c

File tree

359 files changed

+10612
-3324
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

359 files changed

+10612
-3324
lines changed

tools/build/Makefile.feature

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ FEATURE_TESTS_BASIC := \
8686
libtraceevent \
8787
libtracefs \
8888
libcpupower \
89-
libcrypto \
9089
pthread-attr-setaffinity-np \
9190
pthread-barrier \
9291
reallocarray \
@@ -126,12 +125,7 @@ FEATURE_TESTS_EXTRA := \
126125
llvm \
127126
clang \
128127
libbpf \
129-
libbpf-btf__load_from_kernel_by_id \
130-
libbpf-bpf_prog_load \
131-
libbpf-bpf_object__next_program \
132-
libbpf-bpf_object__next_map \
133-
libbpf-bpf_program__set_insns \
134-
libbpf-bpf_create_map \
128+
libbpf-strings \
135129
libpfm4 \
136130
libdebuginfod \
137131
clang-bpf-co-re \
@@ -152,7 +146,6 @@ FEATURE_DISPLAY ?= \
152146
numa_num_possible_cpus \
153147
libperl \
154148
libpython \
155-
libcrypto \
156149
libcapstone \
157150
llvm-perf \
158151
zlib \

tools/build/feature/Makefile

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ FILES= \
3838
test-libtraceevent.bin \
3939
test-libcpupower.bin \
4040
test-libtracefs.bin \
41-
test-libcrypto.bin \
4241
test-libunwind.bin \
4342
test-libunwind-debug-frame.bin \
4443
test-libunwind-x86.bin \
@@ -59,6 +58,7 @@ FILES= \
5958
test-lzma.bin \
6059
test-bpf.bin \
6160
test-libbpf.bin \
61+
test-libbpf-strings.bin \
6262
test-get_cpuid.bin \
6363
test-sdt.bin \
6464
test-cxx.bin \
@@ -246,9 +246,6 @@ $(OUTPUT)test-libcpupower.bin:
246246
$(OUTPUT)test-libtracefs.bin:
247247
$(BUILD) $(shell $(PKG_CONFIG) --cflags libtracefs 2>/dev/null) -ltracefs
248248

249-
$(OUTPUT)test-libcrypto.bin:
250-
$(BUILD) -lcrypto
251-
252249
$(OUTPUT)test-gtk2.bin:
253250
$(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) -Wno-deprecated-declarations
254251

@@ -339,26 +336,8 @@ $(OUTPUT)test-bpf.bin:
339336
$(OUTPUT)test-libbpf.bin:
340337
$(BUILD) -lbpf
341338

342-
$(OUTPUT)test-libbpf-btf__load_from_kernel_by_id.bin:
343-
$(BUILD) -lbpf
344-
345-
$(OUTPUT)test-libbpf-bpf_prog_load.bin:
346-
$(BUILD) -lbpf
347-
348-
$(OUTPUT)test-libbpf-bpf_map_create.bin:
349-
$(BUILD) -lbpf
350-
351-
$(OUTPUT)test-libbpf-bpf_object__next_program.bin:
352-
$(BUILD) -lbpf
353-
354-
$(OUTPUT)test-libbpf-bpf_object__next_map.bin:
355-
$(BUILD) -lbpf
356-
357-
$(OUTPUT)test-libbpf-bpf_program__set_insns.bin:
358-
$(BUILD) -lbpf
359-
360-
$(OUTPUT)test-libbpf-btf__raw_data.bin:
361-
$(BUILD) -lbpf
339+
$(OUTPUT)test-libbpf-strings.bin:
340+
$(BUILD)
362341

363342
$(OUTPUT)test-sdt.bin:
364343
$(BUILD)

tools/build/feature/test-all.c

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,6 @@
6666
# include "test-libslang.c"
6767
#undef main
6868

69-
#define main main_test_libbfd
70-
# include "test-libbfd.c"
71-
#undef main
72-
73-
#define main main_test_libbfd_buildid
74-
# include "test-libbfd-buildid.c"
75-
#undef main
76-
7769
#define main main_test_backtrace
7870
# include "test-backtrace.c"
7971
#undef main
@@ -138,10 +130,6 @@
138130
# include "test-bpf.c"
139131
#undef main
140132

141-
#define main main_test_libcrypto
142-
# include "test-libcrypto.c"
143-
#undef main
144-
145133
#define main main_test_sdt
146134
# include "test-sdt.c"
147135
#undef main
@@ -158,14 +146,6 @@
158146
# include "test-reallocarray.c"
159147
#undef main
160148

161-
#define main main_test_disassembler_four_args
162-
# include "test-disassembler-four-args.c"
163-
#undef main
164-
165-
#define main main_test_disassembler_init_styled
166-
# include "test-disassembler-init-styled.c"
167-
#undef main
168-
169149
#define main main_test_libzstd
170150
# include "test-libzstd.c"
171151
#undef main
@@ -193,8 +173,6 @@ int main(int argc, char *argv[])
193173
main_test_libelf_gelf_getnote();
194174
main_test_libelf_getshdrstrndx();
195175
main_test_libslang();
196-
main_test_libbfd();
197-
main_test_libbfd_buildid();
198176
main_test_backtrace();
199177
main_test_libnuma();
200178
main_test_numa_num_possible_cpus();
@@ -206,14 +184,12 @@ int main(int argc, char *argv[])
206184
main_test_lzma();
207185
main_test_get_cpuid();
208186
main_test_bpf();
209-
main_test_libcrypto();
210187
main_test_scandirat();
211188
main_test_sched_getcpu();
212189
main_test_sdt();
213190
main_test_setns();
214191
main_test_libaio();
215192
main_test_reallocarray();
216-
main_test_disassembler_four_args();
217193
main_test_libzstd();
218194
main_test_libtraceevent();
219195
main_test_libtracefs();
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <bpf/btf.h>
3+
4+
int main(void)
5+
{
6+
struct btf_dump_type_data_opts opts;
7+
8+
opts.emit_strings = 0;
9+
return opts.emit_strings;
10+
}

tools/build/feature/test-libcrypto.c

Lines changed: 0 additions & 25 deletions
This file was deleted.

tools/lib/perf/evlist.c

Lines changed: 81 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -36,49 +36,88 @@ void perf_evlist__init(struct perf_evlist *evlist)
3636
static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
3737
struct perf_evsel *evsel)
3838
{
39-
if (evsel->system_wide) {
40-
/* System wide: set the cpu map of the evsel to all online CPUs. */
41-
perf_cpu_map__put(evsel->cpus);
42-
evsel->cpus = perf_cpu_map__new_online_cpus();
43-
} else if (evlist->has_user_cpus && evsel->is_pmu_core) {
44-
/*
45-
* User requested CPUs on a core PMU, ensure the requested CPUs
46-
* are valid by intersecting with those of the PMU.
47-
*/
39+
if (perf_cpu_map__is_empty(evsel->cpus)) {
40+
if (perf_cpu_map__is_empty(evsel->pmu_cpus)) {
41+
/*
42+
* Assume the unset PMU cpus were for a system-wide
43+
* event, like a software or tracepoint.
44+
*/
45+
evsel->pmu_cpus = perf_cpu_map__new_online_cpus();
46+
}
47+
if (evlist->has_user_cpus && !evsel->system_wide) {
48+
/*
49+
* Use the user CPUs unless the evsel is set to be
50+
* system wide, such as the dummy event.
51+
*/
52+
evsel->cpus = perf_cpu_map__get(evlist->user_requested_cpus);
53+
} else {
54+
/*
55+
* System wide and other modes, assume the cpu map
56+
* should be set to all PMU CPUs.
57+
*/
58+
evsel->cpus = perf_cpu_map__get(evsel->pmu_cpus);
59+
}
60+
}
61+
/*
62+
* Avoid "any CPU"(-1) for uncore and PMUs that require a CPU, even if
63+
* requested.
64+
*/
65+
if (evsel->requires_cpu && perf_cpu_map__has_any_cpu(evsel->cpus)) {
4866
perf_cpu_map__put(evsel->cpus);
49-
evsel->cpus = perf_cpu_map__intersect(evlist->user_requested_cpus, evsel->own_cpus);
67+
evsel->cpus = perf_cpu_map__get(evsel->pmu_cpus);
68+
}
5069

51-
/*
52-
* Empty cpu lists would eventually get opened as "any" so remove
53-
* genuinely empty ones before they're opened in the wrong place.
54-
*/
55-
if (perf_cpu_map__is_empty(evsel->cpus)) {
56-
struct perf_evsel *next = perf_evlist__next(evlist, evsel);
57-
58-
perf_evlist__remove(evlist, evsel);
59-
/* Keep idx contiguous */
60-
if (next)
61-
list_for_each_entry_from(next, &evlist->entries, node)
62-
next->idx--;
70+
/*
71+
* Globally requested CPUs replace user requested unless the evsel is
72+
* set to be system wide.
73+
*/
74+
if (evlist->has_user_cpus && !evsel->system_wide) {
75+
assert(!perf_cpu_map__has_any_cpu(evlist->user_requested_cpus));
76+
if (!perf_cpu_map__equal(evsel->cpus, evlist->user_requested_cpus)) {
77+
perf_cpu_map__put(evsel->cpus);
78+
evsel->cpus = perf_cpu_map__get(evlist->user_requested_cpus);
6379
}
64-
} else if (!evsel->own_cpus || evlist->has_user_cpus ||
65-
(!evsel->requires_cpu && perf_cpu_map__has_any_cpu(evlist->user_requested_cpus))) {
66-
/*
67-
* The PMU didn't specify a default cpu map, this isn't a core
68-
* event and the user requested CPUs or the evlist user
69-
* requested CPUs have the "any CPU" (aka dummy) CPU value. In
70-
* which case use the user requested CPUs rather than the PMU
71-
* ones.
72-
*/
80+
}
81+
82+
/* Ensure cpus only references valid PMU CPUs. */
83+
if (!perf_cpu_map__has_any_cpu(evsel->cpus) &&
84+
!perf_cpu_map__is_subset(evsel->pmu_cpus, evsel->cpus)) {
85+
struct perf_cpu_map *tmp = perf_cpu_map__intersect(evsel->pmu_cpus, evsel->cpus);
86+
7387
perf_cpu_map__put(evsel->cpus);
74-
evsel->cpus = perf_cpu_map__get(evlist->user_requested_cpus);
75-
} else if (evsel->cpus != evsel->own_cpus) {
76-
/*
77-
* No user requested cpu map but the PMU cpu map doesn't match
78-
* the evsel's. Reset it back to the PMU cpu map.
79-
*/
88+
evsel->cpus = tmp;
89+
}
90+
91+
/*
92+
* Was event requested on all the PMU's CPUs but the user requested is
93+
* any CPU (-1)? If so switch to using any CPU (-1) to reduce the number
94+
* of events.
95+
*/
96+
if (!evsel->system_wide &&
97+
!evsel->requires_cpu &&
98+
perf_cpu_map__equal(evsel->cpus, evsel->pmu_cpus) &&
99+
perf_cpu_map__has_any_cpu(evlist->user_requested_cpus)) {
80100
perf_cpu_map__put(evsel->cpus);
81-
evsel->cpus = perf_cpu_map__get(evsel->own_cpus);
101+
evsel->cpus = perf_cpu_map__get(evlist->user_requested_cpus);
102+
}
103+
104+
/* Sanity check assert before the evsel is potentially removed. */
105+
assert(!evsel->requires_cpu || !perf_cpu_map__has_any_cpu(evsel->cpus));
106+
107+
/*
108+
* Empty cpu lists would eventually get opened as "any" so remove
109+
* genuinely empty ones before they're opened in the wrong place.
110+
*/
111+
if (perf_cpu_map__is_empty(evsel->cpus)) {
112+
struct perf_evsel *next = perf_evlist__next(evlist, evsel);
113+
114+
perf_evlist__remove(evlist, evsel);
115+
/* Keep idx contiguous */
116+
if (next)
117+
list_for_each_entry_from(next, &evlist->entries, node)
118+
next->idx--;
119+
120+
return;
82121
}
83122

84123
if (evsel->system_wide) {
@@ -98,6 +137,10 @@ static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
98137

99138
evlist->needs_map_propagation = true;
100139

140+
/* Clear the all_cpus set which will be merged into during propagation. */
141+
perf_cpu_map__put(evlist->all_cpus);
142+
evlist->all_cpus = NULL;
143+
101144
list_for_each_entry_safe(evsel, n, &evlist->entries, node)
102145
__perf_evlist__propagate_maps(evlist, evsel);
103146
}

tools/lib/perf/evsel.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,19 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr)
4040
return evsel;
4141
}
4242

43+
void perf_evsel__exit(struct perf_evsel *evsel)
44+
{
45+
assert(evsel->fd == NULL); /* If not fds were not closed. */
46+
assert(evsel->mmap == NULL); /* If not munmap wasn't called. */
47+
assert(evsel->sample_id == NULL); /* If not free_id wasn't called. */
48+
perf_cpu_map__put(evsel->cpus);
49+
perf_cpu_map__put(evsel->pmu_cpus);
50+
perf_thread_map__put(evsel->threads);
51+
}
52+
4353
void perf_evsel__delete(struct perf_evsel *evsel)
4454
{
55+
perf_evsel__exit(evsel);
4556
free(evsel);
4657
}
4758

tools/lib/perf/include/internal/evsel.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ struct perf_evsel {
9999
* cpu map for opening the event on, for example, the first CPU on a
100100
* socket for an uncore event.
101101
*/
102-
struct perf_cpu_map *own_cpus;
102+
struct perf_cpu_map *pmu_cpus;
103103
struct perf_thread_map *threads;
104104
struct xyarray *fd;
105105
struct xyarray *mmap;
@@ -133,6 +133,7 @@ struct perf_evsel {
133133

134134
void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr,
135135
int idx);
136+
void perf_evsel__exit(struct perf_evsel *evsel);
136137
int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
137138
void perf_evsel__close_fd(struct perf_evsel *evsel);
138139
void perf_evsel__free_fd(struct perf_evsel *evsel);

0 commit comments

Comments
 (0)