| Age | Commit message (Collapse) | Author | Files | Lines |
|
git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next
Pull perf tool updates from Arnaldo Carvalho de Melo:
- Support instruction tracking on arm64 for data type profiling,
resolving stack, global, per-CPU and 'current' variable accesses, so
that 'perf annotate --data-type' resolves types on arm64 the way it
does on x86.
- Port the Python scripts to the perf module and standalone execution,
and improve the module: lazy sample callchains and event copies, GIL
handling, better session/thread lookup, new treport, flamegraph and
sqlite/postgres exporters.
- Reenable and fix the attribute expectation test suite: per-PMU bit
masks, other core PMUs' events, dummy tracking events, group checks
and spelled out skip reasons.
- perf trace: filter the target's tasks in BPF, open the BPF output
event on every CPU, add an option to disable syscall augmentation and
raise TRACE_AUG_MAX_BUF.
- perf jitdump: harden record parsing, validating unwinding sizes and
symbol names, byte-swapping debug entries via safe accessors and
fixing frees on error paths.
- perf annotate-data fixes: bound the member nesting recursion, resolve
type DIEs in the debug file they came from, adjust the offset for
flex-arrays and show the sample count in the data-type browser.
- perf symbol and debug info: try linked debug files for DSOs, avoid
repeated failing searches, set binary/symtab types for split
kallsyms, JIT maps and the build-id cache, fix libbfd symbol loading.
- perf config: serialize config file access with a mutex, add the
DEFINE_MUTEX() and DO_ONCE() primitives and a robust process shared
mutex, add the core.hybrid-merge option.
- perf report: add --progress and --no-progress options.
- perf mem: add a false sharing workload to 'perf test', request
PERF_SAMPLE_CPU by default, use the IBS swfilt filter when available
and decode L0 in the memory level.
- perf test: take turns using the perf mlock budget in the mmaping
tests, add the 'needs_mlock' suite flag, scope the probe based tests
to their PID and make more tests non-exclusive.
- perf vendor events intel: update events and metrics to TMA 5.2,
refresh the event tables and fix umask encodings.
- perf build: run shellcheck, mypy and pylint in parallel, make pylint
opt-out with NO_PYLINT=1, fix clean and install dependencies.
- Add a script and a 'make sync-headers' target to sync the tools/
copies of kernel headers with the kernel sources, plus the resulting
syncs of the cpufeatures, KVM, fs, mount, fcntl, socket, rtnetlink,
if_addr and sound headers.
- Fix cs-etm HW_ID mapping synthesis for raw trace, queue teardown
leaks and duplicate v0 global mappings.
- Add a 'perf bench atomic' benchmark for atomic operations.
- Filter events before creating lock_stat in 'perf lock contention'.
- Add a 'perf test' case for events re-armed with
PERF_EVENT_IOC_REFRESH.
- Fix memory leaks on 'perf c2c' output fields and add function view
stdio coverage to its test.
- Fix a NULL dereference resolving callchains in 'perf machine'.
- Optimize the libdw fallback when DWARF is missing and try the symbol
file first when checking for debuginfo.
- Don't call eprintf() in pr_debugN() when not verbose.
- Don't delete cumulative caller entries before the stat_acc decays in
'perf report'.
- Fix ring buffer cursor handling: keep the consumed cursor in forward
mode and use the head selected by read_init.
- Fix 'perf test mmap-basic' user rdpmc detection and only test
userspace reading on supported platforms.
- Build fixes: include sys/types.h for ssize_t, errno.h before kernel
headers and fix jevents.py type annotations for mypy 2.x.
* tag 'perf-tools-for-v7.4-1-2026-10-30' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next: (425 commits)
perf machine: Fix NULL deref in thread__resolve_callchain_sample()
perf pmu-events: Fix jevents.py type annotations for mypy 2.x
perf parse-events: Include errno.h before kernel headers
perf print_insn: Include sys/types.h for ssize_t
perf tests mmap-basic: Fix user rdpmc detection logic
perf tests mmap-basic: Only test userspace reading on supported platforms
perf mmap: Preserve the consumed cursor in forward mode
perf mmap: Use the head selected by read_init
perf hist: Do not delete cumulative caller entries before stat_acc decays
perf debug: Avoid calling eprintf() in pr_debugN() when verbose < n
perf libdw: Optimize fallback logic for missing DWARF
tools headers: Sync KVM headers with the kernel sources
tools headers: Sync UAPI sound/asound.h with the kernel sources
tools headers: Sync UAPI linux/mount.h with the kernel sources
tools headers: Sync UAPI linux/fs.h with the kernel sources
tools headers: Sync UAPI linux/fcntl.h with the kernel sources
tools headers: Sync linux/socket.h with the kernel sources
tools arch x86: Sync the cpufeatures.h copy with the kernel sources
tools headers UAPI: Sync linux/rtnetlink.h with the kernel sources
tools headers UAPI: Sync linux/if_addr.h with the kernel sources
...
|
|
When recording with -j stack, resolve_lbr_callchain_sample() can
dereference a NULL 'chain' pointer while resolving the branch
stack.
$ perf record -j stack -e branches:u uname
perf: Segmentation fault
Fix it by checking 'chain' for NULL before dereferencing it.
Fixes: 29be60c93d2d9300 ("perf build-id: Mark DSO in sample callchains")
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Shengming Hu <hu.shengming@zte.com.cn>
Signed-off-by: lvyating <lv.yating@zte.com.cn>
Tested-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Dai Hualiang <dai.hualiang@zte.com.cn>
Cc: he.yilin@zte.com.cn
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: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Qingtao Liu <liu.qingtao2@zte.com.cn>
Cc: Shen Lin <shen.lin1@zte.com.cn>
Cc: stable@vger.kernel.org
Cc: ye.zhihao1@zte.com.cn
Cc: zhang.cheng35@zte.com.cn
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Building perf against uClibc fails in config_term_common():
util/parse-events.c:954:30: error: 'ERANGE' undeclared
The kernel headers included before errno.h pull in asm/errno.h. uClibc's
bits/errno.h undefines EDOM, EILSEQ and ERANGE before including
linux/errno.h, but the kernel header include guards prevent these macros
from being defined again.
Include errno.h before the kernel headers so ERANGE remains defined.
Fixes: 6b9c0261b3fb298b ("perf record: Add ratio-to-prev term")
Reviewed-by: James Clark <james.clark@linaro.org>
Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Faisal Bukhari <faisalbukhari523@gmail.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: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Qinxin Xia <xiaqinxin@huawei.com>
Cc: Thomas Falcon <thomas.falcon@intel.com>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
print_insn.h declares fprintf_insn_asm() with an ssize_t return type but
does not include the header defining that type. This causes builds where
stdio.h does not provide ssize_t to fail when compiling util/print_insn.c:
util/print_insn.h:21:1: error: unknown type name 'ssize_t'
Include sys/types.h so the header provides its own dependency for ssize_t.
Fixes: 218c200f677d8af4 ("perf script: Consolidate capstone print functions")
Reviewed-by: James Clark <james.clark@linaro.org>
Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@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: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
perf_mmap__push() reads the producer head before calling
perf_mmap__read_init(), which reads it again to select the range to
copy.
If the producer advances between those reads, push() copies through the
newer head but stores the earlier head in prev. The next drain starts at
that earlier position and can write the same records to perf.data again.
Use the head selected by read_init(): end for forward buffers and start
for overwrite buffers. Save it before the copy loop advances start so
prev matches the range that was copied.
Fixes: 8872481bd04850b1 ("perf mmap: Introduce perf_mmap__read_init()")
Signed-off-by: Paul Moses <p@1g4.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: Kan Liang <kan.liang@intel.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
When symbol_conf.cumulate_callchain is enabled (the default in
'perf top -g'), callchain parent/caller entries have he->stat.period == 0
and accumulate their period in he->stat_acc->period.
hists__decay_entry() decays both he->stat.period and he->stat_acc->period,
but only checks if he->stat.period == 0 as the return condition for
deleting the entry in hists__decay_entries(). As a result, every callchain
caller entry with 0 self-period is unconditionally deleted from the
histogram on the first decay pass, destroying its callchain tree while it
still has non-zero cumulative period.
Only mark an entry for deletion in hists__decay_entry() when both
he->stat.period == 0 and (when cumulate_callchain is active)
he->stat_acc->period == 0.
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alessio Podda <aleph.pi.gh@gmail.com>
Cc: Alireza Haghdoost <haghdoost@uber.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Michael Liang <mliang@purestorage.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Shimin Guo <shimin.guo@skydio.com>
Cc: Tanushree Shah <tshah@linux.ibm.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
pr_debugN() unconditionally evaluated its arguments and called eprintf()
-> veprintf() before checking if verbose >= n. In hot paths such as
dso__load_sym_internal(), two pr_debug4() calls per symbol accounted for
~15% of total CPU time in 'perf top' even at the default verbose == 0.
Guard eprintf() in pr_debugN() with unlikely(verbose >= (n)) and define
pr_debug() in terms of pr_debugN(1, ...).
In test__parsing_callback() (tools/perf/tests/pmu-events.c), move the
test_generic_metric(mexp, 0) call out of the pr_debug() argument list so
the metric evaluation continues to run during 'perf test' when verbose
== 0.
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alessio Podda <aleph.pi.gh@gmail.com>
Cc: Alireza Haghdoost <haghdoost@uber.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Michael Liang <mliang@purestorage.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Shimin Guo <shimin.guo@skydio.com>
Cc: Tanushree Shah <tshah@linux.ibm.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
When libdw encounters a DWARF definition it cannot accurately un-inline
or an address block natively missing structural line maps,
dwfl_module_getsrc() returns NULL.
Previously, libdw__addr2line() returned -1 in both dwfl_module_getdwarf()
and dwfl_module_getsrc() failure paths while addr2line() in srcline.c
only stopped its fallback loop on ret > 0.
This caused perf's addr2line_style loop to fall back to llvm, libbfd,
and the cmd__addr2line() subprocess wrapper on every unmapped address or
stripped DSO.
Update the addr2line_style pipeline return semantics consistently:
1. Backends return 0 to denote conclusively missing information
(e.g. valid ELF but no DWARF inside, or parsed DWARF with no mapped
lines), stopping the fallback loop.
2. Backends (and uncompiled stubs) return < 0 to denote initialization
or backend errors, instructing the loop to iterate to the next
configured fallback.
3. Backends return > 0 on successful source line resolution.
Fixes: bf96e296d52d74a1 ("perf libdw: Fix Dwfl discovery with split files")
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alessio Podda <aleph.pi.gh@gmail.com>
Cc: Alireza Haghdoost <haghdoost@uber.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Michael Liang <mliang@purestorage.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Shimin Guo <shimin.guo@skydio.com>
Cc: Tanushree Shah <tshah@linux.ibm.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
git://git.kernel.org/pub/scm/linux/kernel/git/modules/linux
Pull module updates from Petr Pavlu:
- Ignore local labels and mapping symbols during module load
These symbols were already ignored during kallsyms address-to-symbol
lookups. Filter them out earlier during module loading to reduce
lookup overhead and prevent them from appearing in /proc/kallsyms.
- Fix potentially incorrect access of SetOnce<T> when setting Rust
module parameters.
- Fix a potential read of an uninitialized count when printing taint
information for unloaded modules.
- Allocate the kmod argument array using kmalloc_array() in preparation
for conversion to type-aware allocators.
- Clean up includes in linux/kmod.h
Add explicit includes of linux/umh.h to files that use usermode
helpers. Then clean up the #include list in linux/kmod.h, notably
removing the compatibility linux/umh.h include.
- Remove the error-injection.h include from linux/module.h
Add explicit includes of linux/error-injection.h to files that use
the ALLOW_ERROR_INJECTION() macro and currently rely on it being
provided indirectly via linux/module.h. Then remove the unnecessary
linux/error-injection.h include from linux/module.h.
- Replace __MODULE_STRING() with __stringify() in various drivers in
preparation for removing the former macro.
* tag 'modules-7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/modules/linux:
drivers: Replace __MODULE_STRING() with __stringify()
module: Fix uninitialized count read of unloaded taint tracking record
rust: module_param: Fix potentially incorrect access of `SetOnce<T>`
module: Remove the error-injection.h include from linux/module.h
drm/xe: Include error-injection.h for ALLOW_ERROR_INJECTION()
drm/i915: Include error-injection.h for ALLOW_ERROR_INJECTION()
syscalls: Include error-injection.h for ALLOW_ERROR_INJECTION()
net: Include error-injection.h for ALLOW_ERROR_INJECTION()
block: Include error-injection.h for ALLOW_ERROR_INJECTION()
module: Bring includes in linux/kmod.h up to date
time/jiffies: Include linux/sysctl.h for proc_int_u2k_conv_uop(), ...
umh, treewide: Explicitly include linux/umh.h where needed
modules/kmod: Allocate argv with kmalloc_array()
module/kallsyms: Ignore local labels and mapping symbols during module load
module/kallsyms: Refactor current symbol filtering into is_core_symbol()
module/kallsyms: Rename is_mapping_symbol() to is_ignored_kernel_symbol()
|
|
Extend update_insn_state_arm64() to handle the 'mrs' instruction,
enabling the tracking of the 'current' task pointer in the kernel.
On arm64, the kernel uses the 'sp_el0' system register to store the
address of the currently executing 'struct task_struct'. This is
typically accessed via the 'get_current()' inline function, resulting
in the instruction 'mrs xN, sp_el0'.
To resolve the data type of the target register, first verify the
access is to 'sp_el0' within a kernel DSO. Then, locate the
'get_current()' inline function's DWARF Die at the current PC and
extract its return type (which should be 'struct task_struct*').
A real-world example is shown below:
ffff8000800deee8 <kthread_blkcg>:
ffff8000800deef0: mrs x0, sp_el0 // x0 = current
* ffff8000800deef4: ldr w1, [x0, #44]
Before this commit, the type flow starts with no information:
chk [c] reg0 offset=0x2c ok=0 kind=0 cfa : no type information
final result: no type information
After this commit, the tracker identifies the 'current' pointer
from the system register:
mrs [8] sp_el0 -> reg0 type='struct task_struct*'
chk [c] reg0 offset=0x2c ok=1 kind=1 (struct task_struct*) : Good!
found by insn track: 0x2c(reg0) type-offset=0x2c
final result: type='struct task_struct'
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Li Huafei <lihuafei1@huawei.com>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Extend update_insn_state_arm64() to handle per-cpu variable addressing.
On arm64, per-cpu variables are accessed by adding a per-cpu offset
(typically from the '__per_cpu_offset' array) to the address of a global
variable or a structure field with '__percpu' modifier (e.g.,
's32 __percpu *counters' in struct percpu_counter). This results in
instruction patterns like:
ldr x0, [x6, x5] // Pattern A: direct load per-cpu instance
add x0, x6, x5 // Pattern B: compute per-cpu address
where x6 holds the per-cpu offset retrieved from:
adrp x4, <page>
add x4, x4, #offset // x4 = &__per_cpu_offset
ldr x6, [x4, w0, sxtw #3] // x6 = __per_cpu_offset[cpu]
And x5 holds the base address being offset, which can come from one of
two cases:
Case 1: global variable
adrp x5, <page>
add x5, x5, #offset // x5 = &global_var
Case 2: '__percpu' field embedded in a structure
ldr x5, [x25, #32] // x5 = &percpu_field
To handle such cases:
1. Identify per-cpu base initialization: Detect 'adrp + ldr' pairs that
resolve to the '__per_cpu_offset' symbol and mark the destination
register as TSR_KIND_PERCPU_BASE.
2. Propagate type information: During subsequent 'ldr' or 'add'
instructions, if one register is TSR_KIND_PERCPU_BASE, attempt to
resolve the type from the other register.
A real-world example is shown below:
ffff8000808f2d28 <cppc_set_perf>:
ffff8000808f2d38: adrp x2, ffff800082033000
ffff8000808f2d3c: add x5, x2, #0x3f8 // x5 = &__per_cpu_offset
ffff8000808f2d44: adrp x2, ffff800081f73000
ffff8000808f2d48: add x2, x2, #0x6b8 // x2 = &cpu_pcc_subspace_idx
ffff8000808f2d6c: ldr x5, [x5, w0, sxtw #3] // x5 = __per_cpu_offset[cpu]
* ffff8000808f2d80: ldr w23, [x5, x2] // per_cpu_var(cpu_pcc_subspace_idx)
Before this commit, the tracker could not link x5 back to a per-cpu
context, resulting in an incorrect data type resolution:
adrp [10] global addr=0xffff800082033000 -> reg2
add [14] global 0x3f8(reg2) -> reg5
adrp [1c] global addr=0xffff800081f73000 -> reg2
add [20] global 0x6b8(reg2) -> reg2
ldr [44] global (reg5, reg0) -> reg5 type='long unsigned int[]' size=0x1000
chk [58] reg5 offset=0 ok=1 kind=1 (long unsigned int[]) : Good!
found by insn track: 0(reg5, reg2) type-offset=0
final result: type='long unsigned int' size=0x8
After this commit, the tracker correctly identifies the per-cpu flow and
resolves the actual variable type:
ldr [44] global (reg5, reg0) -> reg5 percpu base
chk [58] reg5 offset=0 ok=1 kind=2 percpu var : retry
chk [58] reg2 offset=0 ok=1 kind=7 global addr : Good!
found by insn track: 0(reg5, reg2) type-offset=0
final result: type='int' size=0x4
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Extend update_insn_state_arm64() to track global variable types
calculated via page-relative addressing.
On arm64, global variables are typically accessed by first calculating
the page address using 'adrp', followed by an 'add' or 'ldr' to get the
specific symbol address. Without tracking 'adrp', the instruction
tracker loses the base address, making it impossible to resolve
global symbols and their associated DWARF types.
Introduce TSR_KIND_GLOBAL_ADDR to represent a partial global address
state. When encountering 'adrp', store the page-aligned target address
in the register's type state. Upon a subsequent 'add' or 'ldr'
instruction that references a TSR_KIND_GLOBAL_ADDR register, combine
the page address with the immediate offset.
A real-world example is shown below:
ffff80008032e008 <folios_put_refs>:
ffff80008032e048: adrp x24, ffff80008202f000 <nr_cpu_ids>
ffff80008032e050: add x24, x24, #0xd40
* ffff80008032e078: ldr x0, [x24]
Before this commit, x24 was unknown, leading to no type information:
chk [70] reg24 offset=0 ok=0 kind=0 cfa : no type information
final result: no type information
After this commit, the tracker correctly follows the adrp/add flow:
adrp [40] global addr=0xffff80008202f000 -> reg24
add [48] global 0xd40(reg24) -> reg24
chk [70] reg24 offset=0 ok=1 kind=7 global addr : Good!
final result: type='struct folio*'
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Li Huafei <lihuafei1@huawei.com>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Extend update_insn_state_arm64() to track 'add' instructions for
structure member address calculation.
Unlike x86, the arm64 'add' instruction has an extra base register among
its source operands. Therefore, in terms of propagating the data type,
it is essentially performing a 'mov', except that before the 'mov', it
first needs to be updated by adding the offset or reg2.
A real-world example is shown below:
ffff80008001c9a8 <flush_ptrace_hw_breakpoint>:
ffff80008001c9c4: add x19, x0, #0xeb8 // x0 (task_struct*) + 0xeb8 -> x19
* ffff80008001c9d0: ldr x0, [x19]
Before this commit, the type flow broke at the 'add' instruction,
leaving the subsequent load with no type information:
chk [28] reg19 offset=0 ok=0 kind=0 cfa : no type information
final result: no type information
After this commit, the tracker correctly follows the member address
calculation:
var [0] reg0 offset 0 type='struct task_struct*'
add [1c] address of 0xeb8(reg0) -> reg19 type='struct task_struct*'
chk [28] reg19 offset=0 ok=1 kind=1 (struct task_struct*) : Good!
found by insn track: 0(reg19) type-offset=0xeb8
final result: type='struct task_struct'
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Extend update_insn_state_arm64() to support register-to-register and
immediate-to-register 'mov' instructions.
For register-to-register 'mov' (e.g., mov dreg, sreg), propagate data type
information from the source register to the destination register.
For immediate-to-register 'mov' (e.g., mov dreg, #imm), store the immediate
value in the destination register's imm_value field and set its kind to
TSR_KIND_CONST, allowing subsequent instructions to resolve it as a
constant.
A real-world example is shown below:
ffff8000803eebf8 <get_vma_policy>:
ffff8000803eec20: mov x21, x0 // x0 (struct vm_area_struct*) -> x21
ffff8000803eec28: ldr x2, [x0, #112]
ffff8000803eec2c: cbz x2, ffff8000803eec94 <get_vma_policy+0x9c>
* ffff8000803eec94: ldr x0, [x21, #152]
Before this commit, the type of x21 was unknown, causing the subsequent
inference to fail:
var [0] reg0 offset 0 type='struct vm_area_struct*' size=0x8
chk [9c] reg21 offset=0x98 ok=0 kind=0 cfa : no type information
final result: no type information
After this commit, the type of x21 is correctly inferred as 'vm_area_struct':
var [0] reg0 offset 0 type='struct vm_area_struct*' size=0x8
mov [28] reg0 -> reg21 type='struct vm_area_struct*' size=0x8
chk [9c] reg21 offset=0x98 ok=1 kind=1 (struct vm_area_struct*) : Good!
found by insn track: 0x98(reg21) type-offset=0x98
final result: type='struct vm_area_struct' size=0xb0
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Extend update_insn_state_arm64() to track data types stored on the
stack.
The implementation handles:
1. Stack Loads: Identify when a register is loaded from a stack
slot and update the register's type state based on the tracked
stack content or compound member types.
2. Stack Stores: Update or create new stack state entries when
a tracked register type is stored to the stack.
Similar to loads, stores also support saving one or two registers
(in the case of 'stp'). Therefore, propagate_store_reg_state() is
introduced.
With these changes, the instruction tracker can now follow data types
as they move between registers and memory, specifically for function
local variables and compiler-spilled values on arm64.
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
When a register without a tracked type is stored to a stack slot that
previously held a valid type, the code currently performs an early return.
This leaves the old type information intact in the stack state.
As a result, a stale type bug occurs:
1. A tracked register is stored into a stack slot.
2. The register becomes untracked/invalid (e.g., across a function call).
3. The now-untracked register is stored into the same stack slot.
4. Subsequent loads from that slot erroneously pick up the old stale type
because the stack entry was never invalidated.
Fix this by introducing delete_stack_state() to search and free a stack
entry for a given offset. When storing an untracked or invalid source
register into a stack location, call delete_stack_state() to delete the
stale entry before returning.
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Currently, imm_value is tracked in registers but dropped when values
are saved to or loaded from stack variables during type profiling.
If a register of type TSR_KIND_CONST is stored to the stack, its value
will be lost.
Add an imm_value field to struct type_state_stack and update
set_stack_state() and findnew_stack_state() to accept and preserve the
immediate value when updating stack state.
Reviewed-by: Shuai Xue <xueshuai@linux.alibaba.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
The arm64 'adrp + add/ldr' instruction pair involves global variable address
calculation and passing, which requires storing the 64-bit address in
type_state_reg. Currently, there is no field in type_state_reg that can
hold such an address. The most likely candidate for reuse is imm_value,
but it is defined as u32, which limits the size of values it can carry.
To address this, expand imm_value from u32 to u64. Also update related
compilation warnings and fix the sign-extension issue introduced by this
change.
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Extend update_insn_state_arm64() to handle standard store instructions
(str, stur, stlr, stp). Exclusive stores (e.g., stxr, stxp) are excluded
from this path since their operand semantics differ.
Unlike load instructions, a store instruction writes a value into the
memory location addressed by the destination register, without changing
that register's type. As a result, no type transfer is needed here.
The only thing to keep in mind is that store instructions support
pre-index and post-index addressing modes, so adjust_reg_index_state()
still needs to be called to handle their addressing.
In addition, exclusive stores (stxr, stxp, stlxr, stlxp, etc.) write
their execution status (0 or 1) into the status register, which is
parsed into src->reg1. Invalidate this status register in
invalidate_unhandled_insn_regs() so that stale types are not propagated.
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Extend update_insn_state_arm64() to handle load instructions, tracking
register state changes when data is loaded from memory to registers.
Two main categories are considered: standard load (e.g, ldr variants)
and load pair (ldp), for example:
ldr dst, [src, #imm]
ldp dst1, dst2, [src, #imm]
For data type propagation, a load pair can be treated as two standard
loads combined, first loading dst1 and then dst2. The difference is
that when loading dst2, an additional memory spacing 'mem_spacing' after
the first load must be added. This mem_spacing can be derived from the
instruction mnemonic and the size of the dst register. Each load operation
is handled by introducing propagate_load_reg_state().
When processing a load pair, the case where dst and src registers are
the same (e.g., ldp x0, x1, [x0]) also needs to be considered. Therefore,
before propagating data types, a snapshot of the src register's state
must be saved and then passed to propagate_load_reg_state().
Finally, handle the side effects of pre-index and post-index addressing
via adjust_reg_index_state().
A real-world example is shown below:
ffff80008011f5b0 <pick_task_stop>:
ffff80008011f5b8: ldr x0, [x0, #2712] // x0: struct rq* -> task_struct*
* ffff80008011f5c0: ldr w1, [x0, #104]
Before this commit, the type of x0 was incorrectly inferred as 'struct rq':
find data type for 0x68(reg0) at pick_task_stop+0x10
var [8] reg0 offset 0 type='struct rq*'
chk [10] reg0 offset=0x68 ok=1 kind=1 (struct rq*) : Good!
final result: type='struct rq'
After this commit, the type of x0 is correctly inferred as 'struct task_struct':
find data type for 0x68(reg0) at pick_task_stop+0x10
var [8] reg0 offset 0 type='struct rq*'
ldr [8] 0xa98(reg0) -> reg0 type='struct task_struct*'
chk [10] reg0 offset=0x68 ok=1 kind=1 (struct task_struct*) : Good!
final result: type='struct task_struct'
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Li Huafei <lihuafei1@huawei.com>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Enable data type profiling to track function return values in arm64
annotations by looking up the DWARF return type of called functions.
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Add a helper to compute the effective offset from a base register
for instruction operands. Currently handles arm64 addressing modes
including post-indexed, single-register, SIB-style indexed with
shift/extension, and constant-offset register pairs.
Fallback to instruction's raw offset for other architectures.
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Enable basic instruction tracking for arm64 by implementing three
essential functions in the find_data_type_block() call path:
find_data_type_block
-> arch_supports_insn_tracking (1)
-> find_data_type_insn
-> init_type_state (2)
-> update_var_state
-> update_insn_state (3)
Changes:
* arch_supports_insn_tracking(): add arm64 to the list of supported
architectures, allowing find_data_type_block() to proceed with data
type analysis.
* init_type_state(): correctly identify ret_reg, stack_reg, and
caller-saved registers for arm64 during type state initialization.
* update_insn_state(): add the update_insn_state_arm64() callback with
conservative register invalidation for call instructions and those with
destination register(s), preventing stale type propagation.
For now the invalidation path does not treat special instructions
individually; doing so for every such instruction up front would be
costly. A TODO is therefore left in invalidate_unhandled_insn_regs()
marking where per-instruction invalidation handling is to be extended
in future patches.
With these changes, arm64 gains support for basic variable type
inference during instruction tracking.
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Li Huafei <lihuafei1@huawei.com>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
The invalidate_reg_state() function is currently static and only used
within the x86 data type profiling implementation. To prepare for adding
arm64 instruction tracking support, extract it as a common helper that
can be shared across architectures.
No functional change intended.
Reviewed-by: Shuai Xue <xueshuai@linux.alibaba.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
If there is a bug in decoding then Perf will exit early and you can't
investigate by using the raw dump mode. Make the --no-itrace option stop
Coresight decoding after printing the aux header so decode errors don't
stop the rest of the samples being printed.
pmu_type and evsel_is_auxtrace need to be set so that the
unleader_auxtrace() behavior is the same as without --no-itrace.
Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Leo Yan <leo.yan@arm.com>
Signed-off-by: James Clark <james.clark@linaro.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
The CoreSight driver emits PERF_RECORD_AUX_OUTPUT_HW_ID via
perf_report_aux_output_id(). If the perf ring buffer is full,
perf_report_aux_output_id() can fail to emit the record and return
silently.
When at least one HW_ID record is present in the file, perf skips the
legacy metadata-only trace ID mapping path. Therefore any raw AUX queue
whose HW_ID record was dropped can be left with an empty traceid_list,
and cs_etm__create_queue_decoders() will not create a decoder for that
queue.
Fix it by ignoring all HW_IDs for unformatted queues and always create
one decoder per queue unconditionally. Trace ID is unused so we can hard
code it to 1 (0 is a special value used in
'pending_timestamp_chan_id' to indicate not pending). We also need put
the same trace ID in the CPU metadata because the relationship between
CPU metadata and traceid_list is bidirectional. Moving
cs_etm__metadata_set_trace_id() into the mapping function solves this
and simplifies existing code. cs_etm__insert_trace_id_node() now does
two things, so rename it to a more generic cs_etm__map_trace_id().
Signed-off-by: Leo Yan <leo.yan@arm.com>
Signed-off-by: James Clark <james.clark@linaro.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
cs_etm__create_decoders() can fail half way through and the
err_free_queues label won't free them. Call the full queue free function
here instead. If no decoders were created it's a nop.
Reviewed-by: Leo Yan <leo.yan@arm.com>
Signed-off-by: James Clark <james.clark@linaro.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
In the case of mixed formatted and unformatted trace with v0 HW_IDs, or
no HW_IDs at all resulting in the cs_etm__map_trace_ids_metadata()
fallback, formatted queues will write their HW_IDs to unformatted
queues. This will result in an assert because of multiple decoders on an
unformatted queue.
Fix it by not inserting trace ID nodes on other unformatted queues. This
isn't an issue for v0.1 HW_IDs because they aren't global so will only
add to their own queue.
Fixes: 19c3e4db38c5bf30 ("perf: cs-etm: Create decoders based on the trace ID mappings")
Reviewed-by: Leo Yan <leo.yan@arm.com>
Signed-off-by: James Clark <james.clark@linaro.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
A mutex held by a process that can die before unlocking it, like the
tests forked by 'perf test' that will take turns using the per user
budget set in kernel.perf_event_mlock_kb, has to be taken over by the
next locker instead of staying locked forever.
Robust mutexes, on top of the kernel's robust futexes, do that: when an
owner dies while holding it the kernel marks the futex word owner-died
and the next pthread_mutex_lock() returns EOWNERDEAD, then mutex_lock()
makes it consistent and takes it over; mutex_trylock() and cond_wait()
come back with EOWNERDEAD too, so they take it over the same way, with
mutex_trylock() giving the mutex back when it can't be taken over: it
is held all the same, and a failed trylock must not leak it.
Add mutex_init_pshared_robust(), returning false when robust mutexes
aren't available: from libcs without the API, gated by a feature check,
to musl and glibc refusing them at runtime, when get_robust_list(2) or
set_robust_list(2) aren't usable. glibc only sets a flag in
pthread_mutexattr_setrobust(), refusing the mutex itself in
pthread_mutex_init() with ENOTSUP instead, other errors from it still
being reported. Robust mutexes being unavailable isn't an error, just a
debug message for whoever then falls back.
Reviewed-by: Ian Rogers <irogers@google.com>
Tested-by: Ian Rogers <irogers@google.com>
Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
evsel__open_cpu() opens the events one by one and, when an open fails
with EINVAL and evsel__detect_missing_features() has a feature to leave
out, goes back to fallback_missing_features to open them all again from
start_cpu_map_idx, without closing what the abandoned attempt opened:
the fd of every CPU or thread that was opened before the failing one is
overwritten in the FD() array, leaking it.
Close them first, the same way out_close does when returning an error,
leaving the entries at -1 for the retry.
Fixes: af954f76eea5 ("perf tools: Check fallback error and order")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/r/sashiko-outbox-173532@kernel.org
Reviewed-by: Ian Rogers <irogers@google.com>
Tested-by: Ian Rogers <irogers@google.com>
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Events opened just to ask if they are supported, i.e. the ones in
is_event_supported() and is_libpfm_event_supported(), go through the
regular evsel__open() path and thus end up in the event files written to
$PERF_TEST_ATTR, with everything but type, config and disabled zeroed:
[event-0-38654705664-3]
fd=3
cpu=-1
pid=0
type=0
size=0
config=38654705664
sample_type=0
...
which 'perf test attr' then takes as one of the events that were asked
for, failing with:
expected cpu=0, got -1
expected size=176, got 0
expected sample_type=65927, got 0
expected freq=1, got 0
This started showing up when there is more than one core PMU, as
perf_pmus__supports_extended_type() probes one such event per core PMU,
but these records were always bogus: nothing asked for them.
Flag those evsels as support probes, keeping the name clear of the
kprobe/uprobe meaning probe already has in evsel, and leave them out of
the dump.
Reported-by: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/linux-perf-users/asWQvXRdqp_RK85c@google.com/
Reviewed-by: Ian Rogers <irogers@google.com>
Tested-by: Ian Rogers <irogers@google.com>
Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Opening a group with perf record on a machine with perf_event_paranoid >
1 and no CAP_PERFMON fails the first perf_event_open() with EACCES, after
which evsel__open_cpu() clears evsel->supported; evsel__fallback() then
adds exclude_kernel and record__open() retries, and the retry succeeds
with supported left false. get_group_fd() treats unsupported events as
ungroupable, so the retry opens the group members without their leader:
sys_perf_event_open: pid 12345 cpu 0 group_fd -1
FAILED '.../test-record-group-sampling1' - group failure
which fails the group subtests of "perf test 82", the Perf attribute
expectations test, when it is run as a regular user, while it passes as
root or with CAP_PERFMON, where the first open doesn't fail.
commit 2cc7aa995ce9 ("perf stat: Refactor retry/skip/fatal error handling")
dropped the pos->supported = true that record__open() did after a
successful open and moved the resets into the stat code only, while
saying "When an event is tried the supported is set to true again". Do
that in evsel__open_cpu(), which every open entry point funnels through,
so that a retry describes its own try instead of the previous failure.
Fixes: 2cc7aa995ce9ecd8 ("perf stat: Refactor retry/skip/fatal error handling")
Reviewed-by: Ian Rogers <irogers@google.com>
Tested-by: Ian Rogers <irogers@google.com>
Cc: Ian Rogers <irogers@google.com>
Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
pyrf__parse_events() prints the entries parse_events_error__print()
receives with the details of a failed parse, but returns without freeing
them, leaking whatever parse_events_error__handle() allocated, so call
parse_events_error__exit() on both paths, as the other parse_events()
callers do.
The perf test attr core PMU probe takes this failure path on machines
without a core PMU, where the leak then happens on every test run.
Fixes: f081defccd93 ("perf python: Add parse_events function")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/r/sashiko-outbox-173525@kernel.org
Reviewed-by: Ian Rogers <irogers@google.com>
Tested-by: Ian Rogers <irogers@google.com>
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Now it should set the binary type of a DSO properly. No need to figure
out a filename suitable for disassembly.
Just call dso__find_binary_type() and dso__get_filename() for that type.
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|