summaryrefslogtreecommitdiff
path: root/tools/perf
AgeCommit message (Collapse)Author
2026-06-06perf mmap: Fix NULL deref in aio cleanup on alloc failureArnaldo Carvalho de Melo
perf_mmap__aio_mmap() sets map->aio.nr_cblocks before allocating the data array. If calloc() for aiocb or cblocks fails before the data array is allocated, the return -1 path leads to perf_mmap__aio_munmap() which loops nr_cblocks times calling perf_mmap__aio_free(). Both versions of perf_mmap__aio_free() (NUMA and non-NUMA) dereference map->aio.data[idx] without checking if data is NULL, causing a NULL pointer dereference. Add NULL checks for map->aio.data at the top of both perf_mmap__aio_free() variants so the cleanup path is safe when allocation fails partway through perf_mmap__aio_mmap(). Fixes: d3d1af6f011a553a ("perf record: Enable asynchronous trace writing") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Alexey Budankov <alexey.budankov@linux.intel.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-05perf sched: Replace BUG_ON and add NULL checks in replay event helpersArnaldo Carvalho de Melo
get_new_event() has three issues: 1. The zalloc() result is dereferenced without a NULL check, crashing on allocation failure. 2. BUG_ON(!task->atoms) kills the process when realloc() fails. Since perf.data is untrusted input, this should be a graceful error. 3. The realloc pattern assigns directly to task->atoms, losing the old pointer on failure. task->nr_events is also incremented before the realloc, leaving corrupted state on failure. Fix get_new_event() to: - Check the zalloc() result before dereferencing - Use a temporary for realloc() to avoid losing the old pointer - Increment nr_events only after successful realloc - Return NULL instead of calling BUG_ON on failure Also fix add_sched_event_wakeup() where zalloc() for wait_sem is passed to sem_init() without a NULL check. Update all callers (add_sched_event_run, add_sched_event_wakeup, add_sched_event_sleep) to handle NULL returns by returning early. The replay may produce incomplete output on OOM but will not crash. Fixes: ec156764d424 ("perf sched: Import schedbench.c") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Ingo Molnar <mingo@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-05perf sched: Use thread__put() in free_idle_threads()Arnaldo Carvalho de Melo
free_idle_threads() calls thread__delete() directly instead of thread__put(), bypassing the reference counting lifecycle. Under REFCNT_CHECKING builds, this leaks the pointer handle since thread__delete() frees the object without going through the refcount wrapper. The idle threads are created via thread__new() (refcount=1) in get_idle_thread(). Callers get additional references via thread__get() which they release with thread__put(). free_idle_threads() drops the base reference — thread__put() is the correct call, matching the thread__new() acquisition. Fixes: 49394a2a24c7 ("perf sched timehist: Introduce timehist command") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: David Ahern <dsahern@gmail.com> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-05perf sched: Fix thread reference leak in idle hist processingArnaldo Carvalho de Melo
timehist_sched_change_event() sets itr->last_thread to NULL at the end of idle hist processing without calling thread__put() first. The thread reference was acquired via thread__get() in timehist_get_thread() (line 2581), so every idle context switch leaks a thread reference when --idle-hist is active. Use thread__zput() to properly release the reference before clearing the pointer. Fixes: 5d8f17fb5822 ("perf sched timehist: Add -I/--idle-hist option") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: David Ahern <dsahern@gmail.com> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-05perf sched: Use is_idle_sample() for idle thread runtime cast guardArnaldo Carvalho de Melo
timehist_sched_change_event() uses thread__tid(thread) == 0 to decide whether to cast thread_runtime to idle_thread_runtime. However, a crafted perf.data can set common_pid=0 and common_tid=0 (the perf_sample fields) while prev_pid != 0 (the tracepoint field). is_idle_sample() returns false (it checks prev_pid for sched_switch), so timehist_get_thread() goes through machine__findnew_thread() and returns the machine's TID 0 thread — whose priv data is a regular thread_runtime, not the larger idle_thread_runtime allocated by init_idle_thread(). The subsequent cast to idle_thread_runtime reads past the thread_runtime allocation, accessing itr->last_thread, itr->cursor, and itr->callchain from adjacent heap memory. Writing to itr->last_thread corrupts the heap; calling thread__put() on the OOB value frees an arbitrary pointer. Replace the thread__tid() == 0 check with is_idle_sample(), which uses the tracepoint-specific prev_pid field and correctly identifies whether the sample originated from an idle thread with idle_thread_runtime priv. Fixes: 5d8f17fb5822 ("perf sched timehist: Add -I/--idle-hist option") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-05perf sched: Clean up idle_threads entry on init failureArnaldo Carvalho de Melo
get_idle_thread() allocates a thread via thread__new() and stores it in idle_threads[cpu], then calls init_idle_thread() to set up the private data. If init_idle_thread() fails (e.g. OOM for the idle_thread_runtime struct), the function returns NULL but leaves the partially initialized thread in idle_threads[cpu]. On subsequent calls for the same CPU, get_idle_thread() finds a non-NULL idle_threads[cpu], skips allocation, and returns thread__get() on a thread that has no priv data. Callers then get a thread whose thread__priv() returns NULL, leading to unexpected behavior. Release the thread and reset the slot to NULL on init failure so the entry doesn't persist in a corrupted state. Fixes: 49394a2a24c7 ("perf sched timehist: Introduce timehist command") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: David Ahern <dsahern@gmail.com> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-05perf c2c: Bounds-check CPU IDs in setup_nodes() topology loopArnaldo Carvalho de Melo
setup_nodes() iterates CPU maps from the perf.data topology header and uses cpu.cpu directly as an array index into cpu2node[] (allocated with c2c.cpus_cnt = env->nr_cpus_avail entries) and __set_bit(cpu.cpu, set) (bitmap also sized to c2c.cpus_cnt). A crafted perf.data with topology CPU IDs exceeding nr_cpus_avail causes out-of-bounds heap writes into both the cpu2node array and the per-node bitmap. Add a bounds check to skip CPU IDs that fall outside the valid range. Fixes: 1e181b92a2da ("perf c2c report: Add 'node' sort key") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-05perf c2c: Bounds-check CPU and node IDs before bitmap and array accessArnaldo Carvalho de Melo
c2c_he__set_cpu() passes sample->cpu directly to __set_bit(cpu, cpuset) after only checking for the (u32)-1 sentinel. The cpuset bitmap is allocated with c2c.cpus_cnt bits (from env->nr_cpus_avail), so a crafted perf.data with CPU IDs exceeding that count causes out-of-bounds heap writes. c2c_he__set_node() similarly passes the node ID from mem2node__node() to __set_bit(node, nodeset) after only checking for negative values. The nodeset bitmap is sized to c2c.nodes_cnt (from env->nr_numa_nodes), so a node ID exceeding that causes OOB writes. process_sample_event() indexes c2c.cpu2node[cpu] and c2c_he->node_stats[node] without bounds checking. Both arrays are sized to c2c.cpus_cnt and c2c.nodes_cnt respectively. Add bounds checks in all three paths: - c2c_he__set_cpu(): return if sample->cpu >= c2c.cpus_cnt - c2c_he__set_node(): return if node >= c2c.nodes_cnt - process_sample_event(): clamp cpu to 0 if >= cpus_cnt, guard node_stats access with bounds check Fixes: 1e181b92a2da ("perf c2c report: Add 'node' sort key") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-05perf stat: Bounds-check CPU index in topology aggregation callbacksArnaldo Carvalho de Melo
Six perf_env__get_*_aggr_by_cpu() functions access env->cpu[cpu.cpu] after only checking cpu.cpu != -1. env->cpu[] is allocated with env->nr_cpus_avail entries, so a CPU index from an untrusted perf.data file that exceeds that count causes an out-of-bounds heap read. Replace the != -1 guard with >= 0 && < env->nr_cpus_avail in all six functions. The >= 0 check also catches -1 and any other negative values that could bypass the old check. Affected functions: - perf_env__get_socket_aggr_by_cpu() - perf_env__get_die_aggr_by_cpu() - perf_env__get_cache_aggr_by_cpu() - perf_env__get_cluster_aggr_by_cpu() - perf_env__get_core_aggr_by_cpu() - perf_env__get_cpu_aggr_by_cpu() Fixes: 68d702f7a120 ("perf stat report: Add support to initialize aggr_map from file") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Ian Rogers <irogers@google.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-05perf mmap: Guard cpu__get_node() return in aio_bind()Arnaldo Carvalho de Melo
perf_mmap__aio_bind() passes the cpu__get_node() return value directly to an unsigned long variable (node_index). When cpu__get_node() returns -1 for an unknown CPU, the implicit int-to-unsigned-long conversion sign-extends it to ULONG_MAX. This causes bitmap_zalloc(ULONG_MAX + 1) which wraps to bitmap_zalloc(0), returning a zero-sized allocation. The subsequent __set_bit(ULONG_MAX, node_mask) then writes massively out of bounds. Check the return value in a signed temporary before assigning to node_index, and skip the NUMA binding when the node is unknown. Fixes: c44a8b44ca9f ("perf record: Bind the AIO user space buffers to nodes") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Alexey Budankov <alexey.budankov@linux.intel.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-05perf sched: Fix register_pid() overflow, strcpy, and BUG_ONArnaldo Carvalho de Melo
register_pid() has several issues when processing untrusted perf.data: 1. Integer overflow: (pid + 1) * sizeof(struct task_desc *) can wrap to a small value on 32-bit systems when pid is large (e.g. 0x40000000), causing realloc to return a tiny buffer followed by out-of-bounds writes in the initialization loop. 2. Heap buffer overflow: strcpy(task->comm, comm) copies the untrusted comm string into a fixed 20-byte COMM_LEN buffer with no length check. 3. BUG_ON on allocation failure: perf.data is untrusted input, so allocation failures should be handled gracefully rather than killing the process. 4. Realloc of sched->tasks assigned directly back, leaking the old pointer on failure; nr_tasks incremented before the realloc, leaving corrupted state on failure. Cap pid at PID_MAX_LIMIT (4194304, matching the kernel's maximum on 64-bit), replace strcpy with strlcpy, guard against NULL comm, replace BUG_ON with NULL returns using safe realloc patterns, and add NULL checks in callers that dereference the result. Fixes: ec156764d424 ("perf sched: Import schedbench.c") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Ingo Molnar <mingo@elte.hu> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-05perf sched: Cap max_cpu at MAX_CPUS in timehist sample processingArnaldo Carvalho de Melo
perf_timehist__process_sample() updates sched->max_cpu from the sample CPU without bounds checking. Later code uses max_cpu + 1 as an iteration count over arrays allocated with MAX_CPUS entries (curr_thread, cpu_last_switched). A recording with CPU IDs >= MAX_CPUS causes out-of-bounds array accesses. Also cap the env->nr_cpus_online initialization of max_cpu in perf_sched__timehist(), which could exceed MAX_CPUS on very large systems. Add bounds checks before both max_cpu updates, matching the pattern already used in map_switch_event(). Fixes: 49394a2a24c7 ("perf sched timehist: Introduce timehist command") Reviewed-by: David Ahern <dsahern@kernel.org> Reported-by: sashiko-bot <sashiko-bot@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf sched: Fix thread reference leaks in timehist_get_thread()Arnaldo Carvalho de Melo
timehist_get_thread() acquires a thread reference via machine__findnew_thread() and an idle thread reference via get_idle_thread() (which calls thread__get()). Two error paths in the idle_hist block return NULL without releasing these references: - When get_idle_thread() fails, the thread reference leaks. - When thread__priv(idle) returns NULL, both idle and thread leak. Additionally, the idle thread reference acquired on the success path is never released, leaking a reference on every sample when --idle-hist is active. Add thread__put() calls on both error paths and release the idle reference after use on the success path. Fixes: 5d8f17fb5822 ("perf sched timehist: Add -I/--idle-hist option") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf tools: Add bounds check to cpu__get_node()Arnaldo Carvalho de Melo
cpu__get_node() accesses cpunode_map[cpu.cpu] without checking against max_cpu_num, the allocation size of cpunode_map. Callers such as builtin-kmem.c:evsel__process_alloc_event() pass sample->cpu from perf.data events, which may exceed the host's CPU count when analyzing cross-machine recordings. Add a bounds check against max_cpu_num before indexing, returning -1 for out-of-range values. This is a central fix that protects all callers. Fixes: 86895b480a2f ("perf stat: Add --per-node agregation support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Jiri Olsa <jolsa@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf tools: Guard remaining test_bit calls from OOB sample CPUArnaldo Carvalho de Melo
auxtrace.c:filter_cpu() and builtin-script.c:filter_cpu() call test_bit(cpu, cpu_bitmap) where cpu_bitmap is declared with MAX_NR_CPUS bits. When the CPU value from a perf.data event is corrupt or absent (e.g. negative or >= MAX_NR_CPUS), test_bit reads out of bounds. Add bounds checks before test_bit(): >= 0 for the int16_t cpu.cpu in auxtrace (which also covers the -1 sentinel), and < MAX_NR_CPUS for both sites. Matches the pattern applied in the previous series for builtin-annotate.c, builtin-diff.c, builtin-report.c, and builtin-sched.c. Fixes: 644e0840ad46 ("perf auxtrace: Add CPU filter support") Fixes: 5d67be97f890 ("perf report/annotate/script: Add option to specify a CPU range") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Anton Blanchard <anton@samba.org> Cc: Jiri Olsa <jolsa@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf sched: Fix comp_cpus heap overflow with cross-machine recordingsArnaldo Carvalho de Melo
setup_map_cpus() allocates comp_cpus based on sysconf(_SC_NPROCESSORS_CONF), the host machine's CPU count. But map_switch_event() indexes comp_cpus using cpus_nr derived from bitmap_weight(comp_cpus_mask, MAX_CPUS), where comp_cpus_mask is declared as DECLARE_BITMAP(..., MAX_CPUS) with MAX_CPUS=4096. When analyzing a perf.data recording from a machine with more CPUs than the analysis host (e.g. 128-CPU server recording analyzed on an 8-CPU laptop), cpus_nr exceeds the allocation size, causing a heap buffer overflow. Also fix a type mismatch: comp_cpus is 'struct perf_cpu *' (2 bytes per element) but was allocated with sizeof(int) (4 bytes per element). Allocate comp_cpus with MAX_CPUS entries using the correct element size, matching the comp_cpus_mask bitmap bounds. Remove the sysconf(_SC_NPROCESSORS_CONF) initialization of max_cpu — its only consumer was the comp_cpus allocation, and max_cpu is dynamically updated from the recording's events during processing. Fix the non-compact path to use max_cpu.cpu + 1 as cpus_nr, converting from 0-based index to count — sysconf() returned a count which masked this off-by-one. Fixes: 99623c628f54 ("perf sched: Add compact display option") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Jiri Olsa <jolsa@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf sched: Fix NULL dereference in latency_runtime_eventArnaldo Carvalho de Melo
latency_runtime_event() passes the return value of machine__findnew_thread() directly to thread_atoms_search() at line 1216, before checking for NULL at line 1220. thread_atoms_search() calls pid_cmp() which dereferences the thread pointer via thread__tid(), causing a NULL pointer dereference if the allocation fails. All other callers of thread_atoms_search() in this file (latency_switch_event, latency_wakeup_event, latency_migrate_task_event) correctly check for NULL first. Move the atoms assignment after the NULL check to match the pattern used by the other callers. Fixes: b91fc39f4ad7 ("perf machine: Protect the machine->threads with a rwlock") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf sched: Fix thread reference leak in latency_switch_eventArnaldo Carvalho de Melo
In latency_switch_event(), after acquiring thread references for sched_out and sched_in via machine__findnew_thread(), the first add_sched_out_event() failure path does 'return -1', bypassing the out_put label that calls thread__put() on both references. The second and third add_sched_out_event() failures correctly use 'goto out_put'. Fix the first one to match. Fixes: b91fc39f4ad7 ("perf machine: Protect the machine->threads with a rwlock") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf tools: Guard test_bit from out-of-bounds sample CPUArnaldo Carvalho de Melo
When PERF_SAMPLE_CPU is absent from a perf.data file, sample->cpu is initialized to (u32)-1 by evsel__parse_sample(). Five call sites pass this value directly to test_bit(sample->cpu, cpu_bitmap), reading massively out of bounds past the DECLARE_BITMAP(..., MAX_NR_CPUS) allocation of 4096 bits. Add a sample->cpu >= MAX_NR_CPUS guard before each test_bit() call, matching the existing safe pattern in builtin-kwork.c. This catches both the (u32)-1 sentinel and any corrupted CPU value exceeding the bitmap size. Fixes: 5d67be97f890 ("perf report/annotate/script: Add option to specify a CPU range") Cc: Anton Blanchard <anton@samba.org> Reported-by: sashiko-bot <sashiko-bot@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf lock contention: Enable end-timestamp accounting for cgroup aggregationSuchit Karunakaran
update_lock_stat() handles lock contentions that start but never reach a contention_end event (e.g., locks still held when profiling stops), but previously treated LOCK_AGGR_CGROUP as a no-op due to missing cgroup context in userspace. Fix this by adding a cgroup_id field to struct tstamp_data, recording it at contention_begin using get_current_cgroup_id() when aggr_mode is LOCK_AGGR_CGROUP. Capturing it at contention_begin is semantically correct, the contention cost is incurred by the task that had to wait, not by whatever task happens to be running at contention_end. It is also preferable from a performance standpoint, as contention_end runs just before the task enters the critical section. Update contention_end to use pelem->cgroup_id instead of calling get_current_cgroup_id() dynamically, ensuring both complete and incomplete contention events attribute the wait time to the cgroup at wait-start time consistently. Reviewed-by: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Suchit Karunakaran <suchitkarunakaran@gmail.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@linaro.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Tycho Andersen (AMD) <tycho@kernel.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf pmu: Recognize 'default_core' as a core PMU and document matchingIan Rogers
The is_pmu_core function checks if a PMU name corresponds to a core CPU PMU. However, it currently fails to recognize "default_core" as a core PMU. When "default_core" is used, the PMU scanning fallback in pmus.c scans the "other_pmus" list. This scan is slow and always misses because "default_core" is a core PMU, leading to unnecessary overhead. Update is_pmu_core to recognize "default_core" directly. Additionally, document the different matching approaches (exact name for x86/s390, sysfs-based cpus file check for ARM/hybrid) to clarify how core PMUs are classified. Also, explicitly treat "default_core" as `all_pmus` in `setup_metric_events()` to preserve the original metric resolution behavior for this pseudo-PMU. Assisted-by: Gemini-CLI:Google Gemini 3.1 Pro Signed-off-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.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> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf data ctf: replace libbabeltrace with babeltrace2-ctf-writerMichael Jeanson
The 1.x branch of Babeltrace has been superseded by 2.x in 2020 and has been unmaintained since 2022, efforts have started to remove it from popular distributions. Babeltrace 2.x offers a very similar 'ctf-writer' library that can be used with minimal changes for the '--to-ctf' feature and has been packaged since Debian 11 and Fedora 32. This patch replaces the 'libbabeltrace' build feature with 'babeltrace2-ctf-writer' using pkgconfig detection, adjusts the naming of the public headers and applies minor API cleanups. There is no changes to the output ctf traces, the ctf-writer API still implements version 1.8 of the CTF specification that can be read by either Babeltrace 1 / 2 or any CTF compliant reader. Also remove some ifdefs in the cli option parsing to allow printing the helpful error message with '--to-ctf' when built without babeltrace2. Reviewed-by: Ian Rogers <irogers@google.com> Signed-off-by: Michael Jeanson <mjeanson@efficios.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Derek Foreman <derek.foreman@collabora.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@linaro.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf lock contention: Allow 'mmap_lock' in -L/--lock-filterNamhyung Kim
The -L/--lock-filter option is to specify target locks by name or address. It's basically for global locks where name or address is known and fixed. But 'mmap_lock' is a per-process lock so it cannot be used for the -L option. $ sudo perf lock con -ab -L mmap_lock ignore unknown symbol: mmap_lock libbpf: map 'addr_filter': failed to create: -EINVAL libbpf: failed to load BPF skeleton 'lock_contention_bpf': -EINVAL Failed to load lock-contention BPF skeleton lock contention BPF setup failed However, it's still a common source of contention especially in a large process so we want to use it for the -L/--lock-filter option. As there is check_lock_type() to check mmap_lock at runtime, let's used it to filter mmap_locks as a special case. Of course, this only works with -b/--use-bpf option. $ sudo perf lock con -b -L mmap_lock -- perf bench mem mmap -f demand -t 2 # Running 'mem/mmap' benchmark: # function 'demand' (Demand loaded mmap()) # Copying 1MB bytes ... 2.679184 GB/sec/thread ( +- 1.78% ) contended total wait max wait avg wait type caller 1 15.22 us 15.22 us 15.22 us rwsem:W __vm_munmap+0x7e 1 7.72 us 7.72 us 7.72 us rwsem:R lock_mm_and_find_vma+0x97 Signed-off-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: James Clark <james.clark@linaro.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Suchit Karunakaran <suchitkarunakaran@gmail.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf test: Remove /usr/bin/cc dependency from Intel PT shell testIan Rogers
In test_intel_pt.sh, the test script compiled two external C programs at runtime using /usr/bin/cc (a thread loop workload and a JIT self- modifying workload). Relying on external C compilers inside shell tests frequently causes failures in continuous integration environments. Create a built-in 'jitdump' workload and switch test_intel_pt.sh to use 'perf test -w thloop' and 'perf test -w jitdump'. Also add multi- architecture compatibility without external C compiler dependencies, the workload instruction arrays dynamically encode CHK_BYTE into opcodes across x86, ARM32, ARM64, RISC-V, PowerPC, MIPS, LoongArch, and s390x. Some minor include fixes for util/jitdump.h. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.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> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf test: Add shell test to validate JUnit XML reporting outputIan Rogers
Add a shell test script (test_test_junit_output.sh) to execute perf test with the -j/--junit option and validate that the generated test report complies perfectly with standard XML formatting using Python's ElementTree XML parser. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.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> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf test: Add -j/--junit option for JUnit XML test reportsIan Rogers
Add a -j/--junit command line option to generate standard JUnit XML format test reports. The generated file defaults to 'test.xml' if no filename is specified, but allows users to override the path (e.g. -jmytest.xml). The XML report captures individual test suite and subtest execution latency, alongside XML-escaped failure logs and skip reasons, while preserving the full multi-process concurrency speed of parallel test execution. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.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> Link: https://lore.kernel.org/r/20260602174129.3192312-15-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf test: Split monolithic 'util' test suite into sub-testsIan Rogers
Refactor the monolithic 'util' test suite into distinct 'String replacement' and 'BLAKE2s hash' sub-tests using the struct test_case framework. This improves test reporting granularity and is used in a subsequent perf test for JUnit XML test result reporting. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.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> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf test: Skip shebang and SPDX comments in shell test descriptionsIan Rogers
When extracting shell test descriptions in tests-scripts.c, the parser skipped the first line assuming it was the shebang (#!/bin/sh) and then read the first comment line on line 2 as the test description. However, checkpatch.pl expects shell scripts to declare their SPDX license identifier on line 2 (# SPDX-License-Identifier: ...). This caused the test harness to extract the SPDX license string as the test description. Refactor shell_test__description to use io__getline, skipping both shebang and SPDX comment lines. This allows shell tests to include standard SPDX headers without breaking test suite description extraction. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.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> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf test: Fix subtest status alignment for multi-digit indexesIan Rogers
When running perf test, the status column (: Ok) became misaligned when subtest indexes reached 2 or 3 digits (e.g. 9.100 vs 9.9 vs 10.1). This occurred because the subtest description field width (subw) was statically fixed to width - 2, assuming all subtest index prefixes were exactly 7 characters wide. Dynamically calculate subw based on the exact character length of the test suite and subtest index prefix. This ensures the status column is perfectly aligned vertically across all test outputs regardless of subtest index digit count. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.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> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf test: Add summary reportingIan Rogers
Currently, when running test suites (perf test), users must scroll through hundreds of lines of console output to manually tally the number of passed, skipped, or failed test cases. Introduce an automated, global execution summary printed at the absolute tail of the test run: 1. Track counts mid-flight inside the print_test_result() accumulator, clearly separating pass counts into standalone main tests vs. individual subtests (where num_test_cases > 1). 2. Accumulate the precise descriptions of all failed test cases directly into a global string buffer, formatted with their suite indices (e.g., 3.1: Parse event definition strings) for effortless cross-referencing. 3. Define a summary printer function print_tests_summary() that emits a colored outline of the final pass, skip, and fail totals, followed by the explicit list of failed tests. 4. Invoke the summary printer right before freeing the test array at the absolute tail of __cmd_test(), guaranteeing that the summary is successfully printed even if an internal emergency signal cleanup occurs or if the user interrupts the run early. Example output: ``` $ sudo perf test -v 1: vmlinux symtab matches kallsyms : Skip 2: Detect openat syscall event : Ok 3: Detect openat syscall event on all cpus : Ok ... 163: perf trace summary : Ok === Test Summary === Passed main tests : 123 Passed subtests : 145 Skipped tests : 22 Failed tests : 6 List of failed tests: 92: perf kvm tests 95: kernel lock contention analysis test 120: perf metrics value validation 124: Check branch stack sampling 143: perftool-testsuite_probe 158: test Intel TPEBS counting mode ``` Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.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> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf test: Show snippet failure output for verbose=1Ian Rogers
Currently, when running tests in verbose mode (-v), if a test case fails, the entire raw standard error buffer is dumped to stderr via fprintf(stderr, "%s", child->err_output.buf). For tests that generate massive amounts of debugging or logging output before dying, this results in multi-page terminal dumps where highly critical diagnostic keywords (error, fail, segv) are easily lost. Implement a smart, bounded snippet string processor to improve failure triaging: 1. Introduce a configurable quota limit static unsigned int failure_snippet_lines = 10; accessible via a new command-line option --failure-snippet-lines <N>. 2. Parse the raw error buffer dynamically into lines and run a three-pass extraction algorithm: - Pass 0: Always select the very first line of the log as an initial outline marker. - Pass 1: Scan forward from the top of the log to pick up to N lines that contain case-insensitive failure keywords (error, fail, segv, abort) to isolate the root cause. Automatically pull in the immediate subsequent line as highly-prioritized context. Allow adjacent matching lines to overlap without dropping context by evaluating keywords for all lines (e.g. when "Failed to report" is followed by "Error:"). - Pass 2: If quota remains, scan backward from the absolute tail of the log to capture trailing crash or abort context. 3. Output the selected lines in their original chronological order, inserting a clear ... separator between non-contiguous line jumps. 4. Wrap matched failure keywords dynamically in bold red (PERF_COLOR_RED) to immediately draw the eye to failures. 5. Invoke the smart processor purely when verbose == 1 && ret == TEST_FAIL in both finish_test and finish_tests_parallel, leaving raw full-output dumping completely untouched when running highly verbose (-vv). Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.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> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf test: Refactor parallel poll loop to drain all pipes simultaneouslyIan Rogers
When running tests in parallel with verbose output (-v), child processes write to pipes. If a test produces significant output (e.g. Granite Rapids metric parsing printing hundreds of lines), it fills the 64KB pipe buffer and blocks. Previously, the parent harness (finish_test) only polled the pipe of the current test waiting to be printed. Other children blocked indefinitely until the parent reached them, severely sequentializing execution. Address this by implementing finish_tests_parallel() to poll and drain output pipes from all running children simultaneously into per-child buffers, employing safe strbuf_addstr string operations alongside thorough variable orderings for strict ISO C90 compliance. Reaping occurs out of order as children finish, while final result printing remains strictly in order. This drops parallel verbose execution time for the PMU events suite from ~35 seconds down to ~5.9 seconds. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.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> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf test pmu-events: A sub-test per metric tableIan Rogers
Break apart the slow "Parsing of PMU event table metrics" tests into one pair of tests (real and fake PMU) per metric table found, storing the specific table pointer in priv data. Implement setup_pmu_events_suite() to dynamically allocate and populate these test cases. Split static parser tests out into a separate test__parsing_fake_static() test case. Update test__parsing() and test__parsing_fake() to retrieve the specific table from priv data and test only that table, maintaining fallback compatibility if priv is NULL. Running these individual tests in parallel significantly reduces overall test execution time. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.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> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf test: Support dynamic test suites with setup callback and private dataIan Rogers
Add void *priv to struct test_case to allow passing per-test context. Add int (*setup)(struct test_suite *) to struct test_suite to allow dynamic generation of test cases. Update build_suites() to invoke the setup callback for each suite if present, ensuring dynamic cases are available before listing or running. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.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> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf test: Drain pipe after child finishes to avoid losing outputIan Rogers
When running tests in parallel, the parent process reads output from the child's pipe. However, it might exit the loop as soon as the child is detected as finished, potentially missing data that arrived in the pipe just after the last poll or before the loop terminated. Address this by draining the pipe after the main loop in finish_test. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.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> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf pmu-events: Add API to get metric table name and iterate tablesIan Rogers
Add name field to struct pmu_metrics_table and populate it in generated tables. Add pmu_metrics_table__name() to retrieve the name. Add pmu_metrics_table__for_each_table() to iterate over all known metric tables. This will be used to break apart slow metric tests per table. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.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> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf jevents.py: Make generated C code more kernel styleIan Rogers
Make jevents.py generate C code that complies with formatting tools: - Add /* clang-format off */ before big_c_string and re-enable it after system mapping tables, bypassing large generated tables while checking functions and early structs. - Make comments more human readable and avoid going over 100 character line length. - Fix spaces indentation to tabs in struct/array initializers. - Fix other checkpatch detected related issues. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.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> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf tpebs: Fix concurrent stop races and PID reuse hazards in tpebs_stopIan Rogers
Parallel verbose test execution can trigger a race condition in tpebs_stop if called concurrently or when PID reuse occurs, causing finish_command() to block or reap the wrong process. Introduce a `tpebs_stopping` flag inside intel-tpebs.c to prevent redundant stop execution paths, and safely restore the `cmd.pid` temporarily only during `finish_command()` to ensure it is properly reaped, while preventing other threads from referencing it. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.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> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf annotate: Fix crashes on empty annotate windowsJames Clark
Annotate can open with an empty window if the disassembly tool fails. After the linked change, the TUI started assuming there was a current annotation line and could assert or segfault in the seek, refresh, and source-toggle paths. Handle empty annotate windows explicitly: set the asm entry count before resetting the browser, return early when refreshing an empty list, and ignore source line toggle when there is no current annotation line. Fixes the following when opening an annotation: perf: ui/browser.c:125: ui_browser__list_head_seek: Assertion `pos != NULL' failed. Aborted Fixes: e201757f7a0a901e ("perf annotate: Fix source code annotate with objdump") Assisted-by: GitHub Copilot:GPT-5.4 Signed-off-by: James Clark <james.clark@linaro.org> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf tools: Ensure event leader stays at head of evlist after sortingIan Rogers
For evlist of a certain event/metric, the HEAD should be the event leader. In some scenarios where uncore_xxx_0 does not exist, the event leader is not the first element after sorting. For example, on my test machine uncore_iio_0 does not exist, the event leader is uncore_iio_2. However, in `evlist__cmp`, it was reordered based on the PMU name, which makes uncore_iio_1 the HEAD of evlist, breaking the following merge logic in `evsel__merge_aliases`. The patch adds a loop at the end of `parse_events__sort_events_and_fix_groups` to make sure the first wildcard match is the earliest entry in the list, updating pointers accordingly without breaking reordering detection. Tested on device lacks uncore_iio_0, and `perf test` looks good. Signed-off-by: Chun-Tse Shao <ctshao@google.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@linaro.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Falcon <thomas.falcon@intel.com> Cc: Thomas Richter <tmricht@linux.ibm.com> Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf stat: Use aggr_nr scaling for Intel uncore miss latency metricsChun-Tse Shao
Update `metric.py` to support the new `aggr_nr` keyword in the python metric generator. Replace the usage of `source_count` with `aggr_nr` in `IntelMissLat` inside `intel_metrics.py` so that uncore latency metrics (like `lpm_miss_lat`) scale correctly on multi-socket and SNC systems when aggregated globally. Additionally, update the validation bypass logic in `CheckEveryEvent()` inside `metric.py` to whitelist 'cha' and 'uncore' events. This prevents validation failures when compiling metrics referencing these PMU-specific uncore events. Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Chun-Tse Shao <ctshao@google.com> Tested-by: Zide Chen <zide.chen@intel.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@linaro.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Leo Yan <leo.yan@arm.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Sandipan Das <sandipan.das@amd.com> Cc: Thomas Falcon <thomas.falcon@intel.com> Cc: Yang Li <yang.lee@linux.alibaba.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf stat: Add aggr_nr metric parser supportChun-Tse Shao
Introduce the `aggr_nr` function to the metric expression parser. `aggr_nr` allows metric formulas to dynamically utilize the number of aggregated targets (`aggr->nr`) instead of relying on the static `source_count` (which represents the static socket or node count). This adds the `AGGR_NR` token to the lexer and parser, updates the expression parsing context helpers to store `aggr_nr`, and feeds `aggr->nr` from the aggregation structure in `prepare_metric`. Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Chun-Tse Shao <ctshao@google.com> Tested-by: Zide Chen <zide.chen@intel.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@linaro.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Leo Yan <leo.yan@arm.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Sandipan Das <sandipan.das@amd.com> Cc: Thomas Falcon <thomas.falcon@intel.com> Cc: Yang Li <yang.lee@linux.alibaba.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf build: Compile BPF skeletons with -mcpu=v3Suchit Karunakaran
The lock_contention BPF program uses __sync_val_compare_and_swap() to atomically update the max_time and min_time fields in contention_data. This builtin lowers to the BPF_CMPXCHG instruction, which is only available in BPF ISA v3. Without an explicit -mcpu flag, Clang targets BPF v1/v2 by default on older toolchains (Clang < 18), causing build errors when v3 instructions are emitted. Add -mcpu=v3 to CLANG_OPTIONS, which is used exclusively in the BPF skeleton compilation rule. Reviewed-by: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Suchit Karunakaran <suchitkarunakaran@gmail.com> Acked-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@linaro.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Suchit Karunakaran <suchitkarunakaran@gmail.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf lock: Fix non-atomic max/time and min_time updates in contention_dataSuchit Karunakaran
The update_contention_data() had a FIXME noting that max_time and min_time updates lacked atomicity. Two CPUs could simultaneously read a stale value, pass the comparison check and race on the write-back, with the smaller value potentially overwriting the larger one and silently corrupting the statistics. Fix this by replacing the bare conditional assignments with a bpf_loop()-based CAS retry loop. Each field tracks its own convergence independently via max_done/min_done flags in cas_ctx, so a successful CAS on one field is never retried even if the other field needs more attempts. Signed-off-by: Suchit Karunakaran <suchitkarunakaran@gmail.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@linaro.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-04perf bench: Add --write-size option to sched pipeBreno Leitao
The default ping-pong uses sizeof(int) (4 bytes) per iteration, which exercises only the pipe-buffer merge path and keeps allocation entirely out of the picture. That makes the bench a useful scheduler / context- switch latency probe but unable to surface anything from the pipe page-allocation hot path. Add a -s/--write-size option that sets the bytes written and read per ping-pong iteration. The buffer is allocated for each side via struct thread_data and replaces the on-stack int previously used. The default remains sizeof(int) so existing invocations are unchanged. With --write-size set above PAGE_SIZE the bench drives anon_pipe_write() through alloc_page() (or the bulk pre-alloc, if the relevant patch is applied), which is what we want when measuring pipe locking and page allocation work. The bench is a ping-pong: both sides call write() before read(), so a single write_size payload must fit entirely in the pipe buffer or both sides deadlock waiting for the other to drain. Resize the pipe via F_SETPIPE_SZ to match write_size (skipped at the sizeof(int) default), and error out cleanly when the request exceeds /proc/sys/fs/pipe-max-size. Committer testing: ⬢ [acme@toolbx perf-tools-next]$ perf bench sched pipe # Running 'sched/pipe' benchmark: # Executed 1000000 pipe operations between two processes Total time: 0.915 [sec] 0.915493 usecs/op 1092307 ops/sec ⬢ [acme@toolbx perf-tools-next]$ perf bench sched pipe --write-size 1024 # Running 'sched/pipe' benchmark: # Executed 1000000 pipe operations between two processes Total time: 0.891 [sec] 0.891915 usecs/op 1121183 ops/sec ⬢ [acme@toolbx perf-tools-next]$ perf bench sched pipe --write-size 4096 # Running 'sched/pipe' benchmark: # Executed 1000000 pipe operations between two processes Total time: 1.366 [sec] 1.366073 usecs/op 732025 ops/sec ⬢ [acme@toolbx perf-tools-next]$ strace -e fcntl perf bench sched pipe --write-size 4096 # Running 'sched/pipe' benchmark: fcntl(4, F_SETPIPE_SZ, 4096) = 4096 fcntl(6, F_SETPIPE_SZ, 4096) = 4096 ^Cstrace: Process 17840 detached ⬢ [acme@toolbx perf-tools-next]$ strace -e fcntl perf bench sched pipe --write-size 1024 # Running 'sched/pipe' benchmark: fcntl(4, F_SETPIPE_SZ, 1024) = 4096 fcntl(6, F_SETPIPE_SZ, 1024) = 4096 ^Cstrace: Process 17845 detached ⬢ [acme@toolbx perf-tools-next]$ strace -e fcntl perf bench sched pipe # Running 'sched/pipe' benchmark: ^Cstrace: Process 17851 detached ⬢ [acme@toolbx perf-tools-next]$ ⬢ [acme@toolbx perf-tools-next]$ perf bench sched pipe --write-size 1048577 # Running 'sched/pipe' benchmark: --write-size 1048577 exceeds /proc/sys/fs/pipe-max-size ⬢ [acme@toolbx perf-tools-next]$ cat /proc/sys/fs/pipe-max-size 1048576 ⬢ [acme@toolbx perf-tools-next]$ acme@number:~/git/perf-tools-next$ Signed-off-by: Breno Leitao <leitao@debian.org> Acked-by: Namhyung Kim <namhyung@kernel.org> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@linaro.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-03perf symbol: Lazily compute idleIan Rogers
Switch from an idle boolean to a helper symbol__is_idle function. In the function lazily compute whether a symbol is an idle function taking into consideration the kernel version and architecture of the machine. As symbols__insert no longer needs to know if a symbol is for the kernel, remove the argument. To protect against drop-filtering of legitimate setup, online, or hotplug management functions (such as intel_idle_init), x86 matches are strictly constrained to exact known run-loops (intel_idle, intel_idle_irq, mwait_idle, mwait_idle_with_hints). If the target environment OS release is unresolvable (such as on guest traces), default to treating psw_idle as idle to prevent false negatives and match legacy trace behavior safely. This change is inspired by mailing list discussion, particularly from Thomas Richter <tmricht@linux.ibm.com> and Heiko Carstens <hca@linux.ibm.com>: https://lore.kernel.org/lkml/20260219113850.354271-1-tmricht@linux.ibm.com/ Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers <irogers@google.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Alexander Gordeev <agordeev@linux.ibm.com> Cc: Heiko Carstens <hca@linux.ibm.com> Cc: Honglei Wang <jameshongleiwang@126.com> Cc: Jan Polensky <japo@linux.ibm.com> Cc: Sumanth Korikkar <sumanthk@linux.ibm.com> Cc: Thomas Richter <tmricht@linux.ibm.com> Cc: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-03perf symbol: Add setters for bitfields sharing a byte to avoid concurrent ↵Ian Rogers
update issues A problem with putting bitfields into struct symbol is that other bits in the symbol could be updated concurrently and only one update to the underlying storage unit happen, leading to lost updates. To avoid this, use atomics to atomically read or set part of 16-bits of flags in the symbol. Add accessors to simplify this. The idle value has 3 values in preparation for a later change that will lazily update it. Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers <irogers@google.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Alexander Gordeev <agordeev@linux.ibm.com> Cc: Heiko Carstens <hca@linux.ibm.com> Cc: Honglei Wang <jameshongleiwang@126.com> Cc: Jan Polensky <japo@linux.ibm.com> Cc: Sumanth Korikkar <sumanthk@linux.ibm.com> Cc: Thomas Richter <tmricht@linux.ibm.com> Cc: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-03perf env: Add helper to lazily compute the os_releaseIan Rogers
In live mode the os_release isn't being initialized, make a lazy initialization helper that assumes when the os_release isn't initialized this is live mode. Signed-off-by: Ian Rogers <irogers@google.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Alexander Gordeev <agordeev@linux.ibm.com> Cc: Heiko Carstens <hca@linux.ibm.com> Cc: Honglei Wang <jameshongleiwang@126.com> Cc: Jan Polensky <japo@linux.ibm.com> Cc: Sumanth Korikkar <sumanthk@linux.ibm.com> Cc: Thomas Richter <tmricht@linux.ibm.com> Cc: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-03perf env: Add mutex to protect lazy environment initializationIan Rogers
Introduce a mutex to 'struct perf_env' to safely protect lazy metadata setup, such as os_release or e_machine resolution, preventing concurrent initialization data races and memory leaks during multi-threaded profiling or symbol loading. Signed-off-by: Ian Rogers <irogers@google.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Alexander Gordeev <agordeev@linux.ibm.com> Cc: Heiko Carstens <hca@linux.ibm.com> Cc: Honglei Wang <jameshongleiwang@126.com> Cc: Jan Polensky <japo@linux.ibm.com> Cc: Sumanth Korikkar <sumanthk@linux.ibm.com> Cc: Thomas Richter <tmricht@linux.ibm.com> Cc: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-03perf env: Remove unused perf_env__raw_archIan Rogers
The switch to using e_machine has made the perf_env__raw_arch function unused so remove it. Signed-off-by: Ian Rogers <irogers@google.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Alexander Gordeev <agordeev@linux.ibm.com> Cc: Heiko Carstens <hca@linux.ibm.com> Cc: Honglei Wang <jameshongleiwang@126.com> Cc: Jan Polensky <japo@linux.ibm.com> Cc: Sumanth Korikkar <sumanthk@linux.ibm.com> Cc: Thomas Richter <tmricht@linux.ibm.com> Cc: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>