Currently, arch__dwarf_regnum() assumes that all architectures use a
register prefix character (e.g., '%' for x86) defined by
arch->objdump.register_char, and uses it to match register names in
objdump output. However, this assumption does not hold for arm64,
where assembly syntax uses bare register names like 'x0', 'w1'
without any prefix.
As a result, arm64 builds may fail to correctly recognize register
names from objdump disassembly, leading to incomplete or incorrect
annotation output.
To address this:
- Make the register prefix check optional, allowing architectures
without a prefix character to be parsed correctly.
- Extend the delimiter set in strpbrk() to include the closing square
bracket ']'. In arm64 assembly, memory operands often use bracketed
syntax such as '[x1, #16]' or '[x2]'. Adding ']' ensures clean
extraction of register names like 'x2' without trailing characters.
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 current arm64 DWARF register lookup relies on 'aarch64_regstr_tbl',
a static string table. While this works for kprobe-tracer where register
names start with '%', it is insufficient for parsing register numbers
directly from raw instructions (e.g., extracting '6' from 'x6' or 'w6')
during annotation.
Since get_dwarf_regnum() is currently used only by 'perf annotate' and
does not affect kprobe-tracer, replace the limited table-based lookup
with a programmatic implementation in __get_dwarf_regnum_arm64(). This
allows resolving arm64 register names (x0-x30, w0-w30, sp, etc.) directly
into their corresponding DWARF register numbers.
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>
Assembly syntax for operands varies significantly across different
architectures, which prevents the operand location (op_loc) parsing
logic in annotate_get_insn_location() from being directly reused.
To simplify the core logic and improve maintainability, move the
operand parsing inside the for_each_insn_op_loc loop into arch-specific
extract_op_location callbacks. This refactoring is intended to be a
cleanup with no functional changes.
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>
arch__dwarf_regnum() returns inconsistent error values: early path
returns -1 while the main lookup returns -ENOENT/-EINVAL from
get_dwarf_regnum(). Callers only check for -1, so genuine failures
can slip through.
Normalize all failures to -1 to match the callers' expectation.
Suggested-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>
Add ldst_ops to handle load and store instructions in order to parse
the data types and offsets associated with PMU events for memory access
instructions. There are many variants of load and store instructions in
arm64, making it difficult to match all of these instruction names
completely. Therefore, only the instruction prefixes are matched. The
prefix 'ld|st' covers most of the memory access instructions, 'cas|swp'
matches atomic instructions, and 'prf' matches memory prefetch
instructions.
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>
As the default parser for arm64 instructions, arm64_mov__parse()
currently only supports parsing instructions with the 'addr <symbol>'
suffix. Other instructions are not supported, causing a lack of
source and target information for most regular instructions.
Generalize arm64_mov__parse to extend its parsing capabilities:
1. Parse 'ops->target.raw' and 'ops->source.raw' by default.
2. Utilize arm64__check_multi_regs() to identify if source and
target contain multiple registers.
3. Maintain backward compatibility for instructions containing the
'addr <symbol>' suffix.
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The operands of 'adrp' instructions parsed by libllvm are currently
represented as raw immediates rather than the "address <symbol+offset>"
format used by objdump. This inconsistency causes arm64_mov__parse()
to fail when parsing these instructions during post-processing.
Example of the mismatch:
Current: adrp x18, 8014
Objdump: adrp x18, ffff800081f5f000 <this_cpu_vector>
Fix this by manually extracting the target address from the raw adrp
instruction via symbol_lookup_callback(). The address is then converted
to a specific symbol during symbol__disassemble_llvm() and formatted
to match objdump's output, ensuring compatibility with existing
parsers.
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Capstone currently outputs address-bearing instructions with a raw hex
value prefixed by '#', without symbolic resolution. This differs from
objdump output and leads to parse failures in jump__parse() and
arm64_mov__parse() on arm64.
Example of the mismatch:
Current: b #0xffff8000800114c8
Objdump: b ffff8000800114c8 <el0t_64_sync+0x108>
Current: adrp x18, #0xffff800081f5f000
Objdump: adrp x18, ffff800081f5f000 <this_cpu_vector>
Fix this by extending symbol__disassemble_capstone() to:
- Enable CS_OPT_DETAIL for arm64 to access instruction group info.
- Detect instructions with address operands requiring symbolization
(jump/call/branch/adr/adrp) via opcode or Capstone group ID.
- Resolve target addresses to symbols via find_symbol_from_addr().
- Format output to match objdump's style (strip '#' prefix, add
symbol and offset).
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The flex array members are located beyond the original type size. Also
it needs to adjust the offset in an array to find a corresponding
element using module operation. Note that we focus on access to type and
field, so array index is not important.
Make sure to find a field name for flex arrays.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Structs that have a flex array will have accesses beyond its original
size as the array was declared as 0 sized. For now, it just allow any
offset bigger than the size. It could be refined later.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Check return value of strbuf_init() and die_get_typename() to make sure
if typename of a member gets never NULL.
Also remove the check for typedef by just using die_get_real_type().
It can get rid of member_type variable as well.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The die_has_flex_array() returns true when the given type is a compound
type and contains an array at the end. To prevent an infinite recursion
add a depth field to the internal function.
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Running 'perf test' should not inherit the user's ~/.perfconfig
environment as customizing core properties (like core.hybrid-merge)
will trivially break stdout matching checks across the shell suite.
Explicitly set PERF_CONFIG to /dev/null inside cmd_test to globally
sandbox the environment for the entire test workflow. Test specific
config, like annotate.objdump, is read before the sandboxing so that
'perf test' still honors it.
Signed-off-by: Ian Rogers <irogers@google.com>
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Add a "Hybrid event merging" test that checks evlist__can_merge_hybrid()
and evlist__merge_hybrid() directly, covering the events a wildcard
expanded to over two core PMUs, the same over three, and events that
must not be merged.
Add a report_hybrid_merge.sh shell test that records and then reports
with --hybrid-merge, and extend top.sh to cover perf top with it.
Signed-off-by: Ian Rogers <irogers@google.com>
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Provide a core.hybrid-merge configuration option in .perfconfig to allow
enabling hybrid event aggregation by default, avoiding the need to pass
--hybrid-merge explicitly on every invocation.
The config value is a default rather than an explicit request, so with
--hierarchy it is ignored with a warning, while giving both --hierarchy
and --hybrid-merge on the command line remains an error. For the same
reason it is silently ignored when there are no events to merge, as
would be the case on any machine with a single core PMU, whereas an
explicit --hybrid-merge still warns. Record whether the option came from
the command line in symbol_conf so both can tell the two apart.
'perf stat' has its own merging options for counting, the sampling
core.hybrid-merge deliberately doesn't alter it and its --hybrid-merge
must still be given explicitly.
Signed-off-by: Ian Rogers <irogers@google.com>
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Add dynamic TUI hints prompting users to restart with --hybrid-merge
when heterogeneous core PMU events are populated in the sample view.
Signed-off-by: Ian Rogers <irogers@google.com>
Assisted-by: Antigravity:gemini-3.1-pro
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Merging makes the merged event the leader of the events of the other
core PMUs so their histograms can be linked, but the result isn't a real
event group. Each event keeps its own file descriptor and has to be
enabled and disabled in its own right.
__evlist__enable(), __evlist__disable() and evlist__is_enabled() skip
anything that isn't a group leader, and the first two then walk the
group members of the events they do act on. For a merged set that is
backwards: the members are skipped by the leader test, so their file
descriptors are never touched, and the walk over the leader's members
only updates the bookkeeping in evsel->disabled.
Treat an evsel with merged_hybrid_group set as a leader so that it is
enabled and disabled in its own right via its own file descriptors.
'perf top' enables and disables by event name. A merged member carries
the name of its own PMU rather than the name that was asked for, so also
match it against its leader's name, otherwise naming the event toggles
only part of the merged set.
Signed-off-by: Ian Rogers <irogers@google.com>
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Add informative text outlining the IPC imbalances associated with
merging cross-hybrid core events like cycles.
Signed-off-by: Ian Rogers <irogers@google.com>
Assisted-by: Antigravity:gemini-3.1-pro
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Add --hybrid-merge to perf report and perf top. It merges the events a
wildcard expanded to across the core PMUs, and their histograms, so
that a symbol which ran on more than one kind of core is reported once
with the total rather than once per PMU.
evlist__merge_hybrid() links the events and evlist__merge_hists_hybrid()
links the histograms. There is nothing to merge on a machine with a
single core PMU, or when the events didn't come from a wildcard, so
warn in that case rather than quietly producing an unmerged report.
Merging collapses the per-PMU entries into one set, which doesn't
combine with the per-level breakdown of --hierarchy, so asking for both
is an error.
Signed-off-by: Ian Rogers <irogers@google.com>
Assisted-by: Antigravity:gemini-3.1-pro
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Add the histogram side of hybrid event merging.
When events are merged the entries of the other events are linked to
the leader's entries as pairs, and a row is then displayed as the sum
over an entry and its pairs. Teach the hpp code to work on that sum:
- The formatting and sorting routines add up the value of an entry and
of each of its pairs, so a row shows, and is sorted by, the total
across the core PMUs rather than the leader's value alone.
- Percentages are taken against the summed total_period of the merged
hists. Computing each event's share against its own PMU's total
would leave the column not adding up to 100%.
hist_entry__get_percent_limit_merged() does the same for
--percent-limit, which would otherwise compare against the wrong
total and filter out the wrong entries.
- A header and column width are reserved for the "Total" the merged
value is shown under.
evlist__merge_hists_hybrid() links the hists together and resorts the
result so that it is ordered by the merged total.
hists__link() is run once for every event merged into the leader, so an
entry can be offered as a pair more than once. hist_entry__add_pair()
used list_add_tail() unconditionally, which corrupts the list when the
entry is already on one. Return early if the entry is already paired
with this one, and use list_move_tail() so that an entry linked
elsewhere is moved rather than added a second time.
Merging is never combined with --hierarchy, which the merge_entries
tests rely on.
Signed-off-by: Ian Rogers <irogers@google.com>
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Add logic to dynamically identify mergeable events spawned from the
same wildcard alias via first_wildcard_match. first_wildcard_match is
populated when events are parsed, in `perf report` the events come
from a file and so the first_wildcard_match is computed by matching
event names.
evlist__can_merge_hybrid only tests whether merging is possible and
doesn't modify the evlist, so that it may be used as a predicate, for
example, to decide whether to display a hint. The linking of all the
matching events is done by evlist__merge_hybrid.
is_pmu_core_len identifies core PMUs using the hybrid topology of the
perf.data file. Should the file lack the topology, the PMUs of this
machine are scanned but only when the file was recorded on the same
architecture, as PMU names like "cpu_core" are architecture specific.
Signed-off-by: Ian Rogers <irogers@google.com>
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
libbfd__addr2line() only reports success when the caller asked for a file
name. addr2inlines() passes a NULL file as it just wants the inline_node
populating, so libbfd__addr2line() returns 0 for it unless
bfd_find_inliner_info() happened to find an inline frame.
addr2line() in srcline.c treats 0 as a failure and tries the next
addr2line implementation, which appends its own frames to the
inline_node libbfd already appended to.
Every frame that isn't inlined is then reported twice, which happens by
default when perf is built with libbfd but without libdw as the fallback
order is then libbfd followed by the addr2line command:
$ perf record --call-graph dwarf -- perf test -w inlineloop 1
$ perf script --fields +srcline
...
56051a994f8e parent+0x2e (perf)
inlineloop.c:32
56051a99503a inlineloop+0x8a (perf)
inlineloop.c:47
56051a99503a inlineloop+0x8a (perf)
inlineloop.c:47
56051a95841a cmd_test+0xb7a (perf)
??:0
56051a95841a cmd_test+0xb7a (perf)
??:0
...
Report success whenever the address is found, like libdw__addr2line()
does, and clear the frames appended so far when appending fails so that a
following implementation starts from an empty node.
Fixes: 257046a367 ("perf srcline: Fallback between addr2line implementations")
Signed-off-by: Ian Rogers <irogers@google.com>
Assisted-by: Antigravity:gemini-3.1-pro
Cc: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
When a dso executes addr2line via libbfd it instantiates an a2l_data
pointer. If the DSO later executes via the command-line fallback due
to an inlined bug, the a2l pointer is unconditionally populated with a
child_process process wrapper.
If libbfd is queried again, the offline reader attempts to cast struct
a2l_data into child_process, coercing random arbitrary instruction
addresses and causing silent aborts. This cleanly splits the caches.
Fixes: 257046a367 ("perf srcline: Fallback between addr2line implementations")
Signed-off-by: Ian Rogers <irogers@google.com>
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
dso__libdw_dwfl() opens the Dwfl with dso__long_name(), the file the
samples came from. When the debug information lives in a separate file,
symbol loading finds it and records it as the dso's symsrc filename, but
the Dwfl still refers to the original file, so libdw has no DWARF to
resolve addresses against.
Open the Dwfl with the symsrc filename when one is known and fall back
to the long name when it isn't.
The symsrc file is found while symbols are loaded, which can happen
after the Dwfl has been created and cached, so drop the cached Dwfl and
the addr2line cache built from it when the symsrc filename is set. That
teardown can run while another thread is using the cache, so take the
dso lock across both the teardown and the Dwfl accessors, and re-read
dso__symsrc_filename() under the dso lock in libbfd__addr2line() and
cmd__addr2line() to prevent a TOCTOU race with cache invalidation.
Fixes: b7a2b011e9 ("perf powerpc: Unify the skip-callchain-idx libdw with that for addr2line")
Signed-off-by: Ian Rogers <irogers@google.com>
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
arch_is_topdown_slots() requires config1 == 0, so it misidentified
"cpu/slots,metrics_clear=1/" as not being the slots event, and an
additional slots event gets inserted, which fails event scheduling
since the group now needs two fixed counter 3.
$ perf stat -e "{cpu/slots,metrics_clear=1/,cpu/topdown-retiring/}" -- sleep 1
WARNING: events were regrouped to match PMUs
<not counted> slots
<not supported> cpu/slots,metrics_clear=1/
<not counted> cpu/topdown-retiring/
Drop the config1 == 0 check from arch_is_topdown_slots(). This is
safe: config1 has no bearing on the event's identifying config value
(TOPDOWN_SLOTS, 0x0400).
The attr.type == PERF_TYPE_RAW check is what actually matters: only the
core PMU is registered with PERF_TYPE_RAW, and on x86, 0x400 is
guaranteed to be slots event on core CPU.
arch_is_topdown_metrics() keeps its own config1 == 0 check, since
genuine metrics events have no "metrics_clear" and config1 remains 0.
Add a test verifying that an explicit "slots,metrics_clear=1" event in
a group does not trigger an extra slots event injection.
Fixes: 5b546de9cc ("perf topdown: Use attribute to see an event is a topdown metic or slots")
Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Zide Chen <zide.chen@intel.com>
Cc: Namhyung Kim <namhyung@kernel.org>
[ Add missing stdio.h and string.h as noticed by Sashiko ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
It parses fdinfo with PMU type, comparing with the event which failed to
open, and report the processes causing EBUSY error.
Testing cycles and intel_pt//
$ ./perf stat -e cycles &
[1] 55569
$ ./perf stat -e intel_pt// &
[2] 55683
$ ./perf stat -e intel_pt//
Error:
The PMU intel_pt counters are busy and in use by another process.
Possible processes:
55683 ./perf stat -e intel_pt//
Only perf with intel_pt was reported.
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Chun-Tse Shao <ctshao@google.com>
Assisted-by: Gemini:gemini-3.1-pro-preview
[ Added a few missing includes as per Sashiko's review ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The unsigned int type should use the %u format specifier when
printing with printf or related functions.
Signed-off-by: liujing <liujing@cmss.chinamobile.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
When processing POLLHUP on a non_perf_event control descriptor,
evlist__finalize_ctlfd() is invoked to finalize the setup, correctly
setting the core evlist's poll array file descriptor to -1. However,
this finalized teardown state is never propagated back to the
individual thread's local replica of the pollfd array.
Consequently, on the next iteration of the main recording loop,
record__update_evlist_pollfd_from_thread() performs a strict
equivalence check between the core evlist's array and the thread's
localized poll array, detecting that the fd values no longer match.
This causes an immediate -EINVAL abort and a premature teardown.
Fix the underlying logic within
record__update_evlist_pollfd_from_thread() to sustainably propagate
the finalized teardown statuses (-1) originating from the core evlist
back to the thread's localized poll structure. This correctly
maintains synchronization and entirely prevents the unhandled
index mismatch crashes.
Additionally, add a unit test that explicitly validates that
fdarray__filter() preserves its invariants regarding
fdarray_flag__nonfilterable items to guard against regressions.
Fixes: fb4751e79c ("perf record: Fix teardown hang on system-wide multi-threaded sessions")
Signed-off-by: Ian Rogers <irogers@google.com>
Assisted-by: Gemini:gemini-3.1-pro
Cc: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The test's only guard matches "failed: no PMU supports the memory
events", but a PMU that has memory events and refuses them per-thread,
such as AMD IBS on kernels without the swfilt filter, falls through:
the script runs under 'set -e' and the bare 'perf mem record' aborts it
through the EXIT trap, reporting a signal that never happened and
turning "this PMU cannot record these events" into a test failure.
Skip when a trivial per-thread 'perf mem record' fails, and put the
record and annotate calls in the condition of an 'if', where 'set -e'
leaves them alone, so the remaining cases report their own failures
instead of the first one aborting the run.
Fixes: f60a5c2296 ("perf tests: Test annotate with data type profiling and rust")
Acked-by: Namhyung Kim <namhyung@kernel.org>
Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The type histogram maintains sample counts and periods per offset. Use
a hashmap instead of an array to reduce the memory overhead.
No functional changes intended.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Reviewed-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Validate that SIMD registers (XMM/YMM/ZMM/OPMASK on x86) can be sampled
correctly with hardware support.
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Validate that eGPRs (extended general purpose registers) and SSP
(shadow stack pointer) registers can be sampled correctly on x86
platforms.
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Enhance the x86-specific DWARF register handling by adding support for
SIMD and eGPRs registers.
This update is based on the "DWARF Register Number Mapping" table from
the "System V Application Binary Interface AMD64 Architecture Processor
Supplement" (version 1.0).
Modifications include:
- Updating the x86_64_regidx_table[] array to incorporate SIMD and eGPRs
registers.
- Enhancing the __get_dwarf_regnum_for_perf_regnum_x86_64() function to
retrieve the DWARF register index for eGPRs.
Since currently libdw doesn't support SIMD and APX eGPRs registers yet,
still keep the original return value for get_libdw_frame_nregs() helper.
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Add support for the newly introduced SIMD register sampling format by
adding the following 5 functions:
uint64_t perf_intr_simd_reg_class_mask(uint16_t e_machine, bool pred);
uint64_t perf_user_simd_reg_class_mask(uint16_t e_machine, bool pred);
uint64_t perf_intr_simd_reg_class_bitmap_qwords(uint16_t e_machine, int reg_c,
uint16_t *qwords, bool pred);
uint64_t perf_user_simd_reg_class_bitmap_qwords(uint16_t e_machine, int reg_c,
uint16_t *qwords, bool pred);
const char *perf_simd_reg_class_name(uint16_t e_machine, int id, bool pred);
The perf_{intr|user}_simd_reg_class_mask() functions retrieve the bitmap
of kernel supported SIMD/PRED register classes on current platform for
intr-regs and user-regs sampling, such as OPMASK/XMM/YMM/ZMM on
x86 platforms.
The perf_{intr|user}_simd_reg_class_bitmap_qwords() functions retrieve
the bitmap and qwords length of a certain class of SIMD/PRED register
on current platform for intr-regs and user-regs sampling. For example,
for the XMM registers on x86 platforms, the returned bitmap is 0xffff
(XMM0 ~ XMM15) and the qwords length is 2 (128 bits for each XMM
register).
The perf_simd_reg_class_name() function gets the register class name for
a certain register class index.
Additionally, the function __parse_regs() is enhanced to support parsing
these newly introduced SIMD/PRED registers. Currently, each class of
register can only be sampled collectively; sampling a specific SIMD
register is not supported. For example, all XMM registers are sampled
together rather than sampling only XMM0.
When multiple overlapping register types, such as XMM and YMM, are
sampled simultaneously, only the superset (YMM registers) is sampled.
With this patch, all supported sampling registers on x86 platforms are
displayed as follows.
$perf record --intr-regs=?
available registers: AX BX CX DX SI DI BP SP IP FLAGS CS SS R8 R9 R10
R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28
R29 R30 R31 SSP XMM0-15 YMM0-15 ZMM0-31 OPMASK0-7
$perf record --user-regs=?
available registers: AX BX CX DX SI DI BP SP IP FLAGS CS SS R8 R9 R10
R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28
R29 R30 R31 SSP XMM0-15 YMM0-15 ZMM0-31 OPMASK0-7
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Add support for sampling x86 extended GP registers (R16-R31) and the
shadow stack pointer (SSP) register.
The original XMM registers space in sample_regs_user/sample_regs_intr is
reclaimed to represent the eGPRs and SSP when SIMD registers sampling is
supported with the new SIMD sampling fields in the perf_event_attr
structure. This necessitates a way to distinguish which register layout
is used for the sample_regs_user/sample_regs_intr bitmap.
To address this, a new "abi" argument is added to the helpers
perf_intr_reg_mask(), perf_user_reg_mask(), and perf_reg_name(). When
"abi & PERF_SAMPLE_REGS_ABI_SIMD" is true, it indicates the eGPRs and SSP
layout is represented; otherwise, the legacy XMM registers are
represented.
Please note that PERF_SAMPLE_REGS_ABI_SIMD is set by default on platforms
that support SIMD register sampling, even when no eGPR or SSP register is
requested (for example, -Iax). As a result, sample_regs_intr and
sample_regs_usr always use the new GPR layout on platforms with SIMD
register sampling support.
The patch only supports eGPRs and SSP sampling, the complete SIMD
registers sampling would be supported in the next patch.
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Sync the UAPI header changes of supporting SIMD/eGPRs/SSP sampling into
corresponding tools UAPI headers.
Additionally, support the new introduced perf_event_attr fields in the
perf_event_attr__fprintf and perf_event__attr_swap() helpers, and add
sanity check for the new introduced __reserved_4 field in
perf_attr_check().
Co-developed-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Some new introduced perf_event_attr fields, like config3 and config4,
are forgotten to add into perf_event_attr__fprintf() and
perf_event__attr_swap() helpers. Add these missed fields into these 2
helpers.
The aux_action is an exception. aux_action aliases bitfields
(e.g. aux_start_paused) in a union. Bitfields and plain u32 fields
follow different endian rules, so both views cannot be swapped
correctly at the same time. Leave aux_action unswapped until the ABI
is represented in a byte-order-safe form.
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Tighten bounds validation in __get_dwarf_regnum_for_perf_regnum_xxx()
helpers by changing perf_regnum > ARRAY_SIZE() to
perf_regnum >= ARRAY_SIZE().
This fixes an off-by-one condition where perf_regnum == ARRAY_SIZE()
could pass validation and cause out-of-bounds access for
dwarf_xxx_regnums[].
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Extend the mesh bandwidth saturation's list of events to include events
from clearwaterforest, emeraldrapids, grandridge, graniterapids,
sapphirerapids and sierraforest. This makes the lpm_mem_sat metric
available for those CPU models.
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The %S conversion in fix_escape_fprintf() calls strlen(s) in the loop
condition while escaping each character. GCC 14.2.0 retains this call
inside the loop in a normal DEBUG=0 (-O3) perf build, repeatedly
scanning the whole string.
Test the current character for NUL instead. This processes the same
bytes without rescanning the string. Escaping and buffer growth are
unchanged.
Full-command wall-clock measurements on an Apple M5 Pro host running an
aarch64 Linux container with GCC 14.2.0 and glibc 2.41 gave these
medians:
perf list --json metrics Before (ms) After (ms)
Default catalog 0.5969 0.5855
PERF_CPUID=0x00000000410fd830 0.7818 0.7033
Each workload used 50 randomized before/after pairs. Each sample
averages the time per invocation across five fresh processes, with
stdout sent to /dev/null and no single-CPU pinning. PERF_CPUID selects
the shipped V3 catalog on the same host; these are not measurements on
V3 hardware. The measurements include process startup and do not
establish a gain on other machines or perf commands.
These observations come from one short run. Relinking also changes code
layout: .text grows from 2,013,172 to 2,017,236 bytes in this build. The
timings do not isolate scan removal from the changed layout.
The existing list shell test passes for both binaries. Source-extracted
functions linked to perf's strbuf implementation pass 906 equivalence
cases with ASan and UBSan. Full-command outputs are byte-identical.
Codex assisted with identifying the redundant scan, preparing the change,
and running the comparisons.
Assisted-by: LLM
Signed-off-by: Qerogram <qerogram@naver.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Avoid a checkpatch.pl warning on the use of asm/bug.h by switching the
use of WARN macros to explicit tests and then using pr_warning from
debug.h.
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
strim() may advance the pointer assigned to cache->size which causes
later frees to crash.
Fix by performing the strim and then memmove-ing the potentially shifted
string back over the original string.
The bug was introduced by the transition from rtrim() to strim(), as
rtrim() wouldn't move on the left.
Fixes: 13c230ab6e ("perf tools: Ditch rtrim(), use strim() from tools/lib")
Signed-off-by: Ian Rogers <irogers@google.com>
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit updates process_compressed() to ignore comp_mmap_len == 0
when validating the compressed header. A zero size is valid and may
occur during testing.
Sashiko review flagged string.h was missing (preexisting problem) and
so I opportunistically fixed this and sorted the header files.
Signed-off-by: Ian Rogers <irogers@google.com>
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Updates Tree type hints to correctly use TreeNode[TreeValue]
across all assignments preventing mypy strictness mismatches.
Address some other minor stylistic issues reported by mypy, pylint and
Sashiko.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Clang's uninitialized-const-pointer warning causes a feature test to
fail when building perf with clang. This disables support for 'perf
kvm stat live'. Add default initialization to new_value as a
workaround.
test-timerfd.c:15:30: error: variable 'new_value' is uninitialized when passed
as a const pointer argument here
[-Werror,-Wuninitialized-const-pointer]
15 | if (timerfd_settime(fd, 0, &new_value, NULL) != 0)
| ^~~~~~~~~
1 error generated.
Signed-off-by: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20260910213907.3206529-1-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
__msan_unpoison may need the sanitizer header including for its
definition.
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Implement a flamegraph widget that recursively walks down a tree
splitting line segments based on their value (summed up periods across
call chains). A visitor pattern is used so that the same logic can
both draw the line segments and locate which segment had a mouse
click.
Add a tab for the flame graph widget.
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Co-developed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Alice Rogers <alice.mei.rogers@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
A textual app that displays the results of processing samples similar
to perf report. The app displays a tree of first processes and then
functions which drop down to show more detail on the functions they
call. The functions with the largest number of samples are sorted
first, after each function the percentage of time spent within it is
highlighted. If more than one event is recorded then each event
appears first, with the processes and functions sorted for that event
beneath it.
The app is written in python and requires the textual framework. Using
the textual framework means that in most modern terminals the mouse is
supported, the color scheme can be configured, and screenshots made.
With perf report:
```
$ perf record -e cycles:u -g perf test -w brstack
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.008 MB perf.data (57 samples) ]
$ perf report
...
Samples: 57 of event 'cycles:u', Event count (approx.): 15907831
Children Self Command Shared Object Symbol
- 88.86% 0.00% perf libc.so.6 [.] 0x000079b17df69ca8
0x79b17df69ca8
main
handle_internal_command
cmd_test
- brstack
- 84.27% brstack_bench
- 40.69% brstack_foo
brstack_bar
3.32% brstack_bar
3.31% brstack_bar
1.27% brstack_foo
+ 88.86% 0.00% perf perf [.] main
+ 88.86% 0.00% perf perf [.] handle_internal_command
+ 88.86% 0.00% perf perf [.] cmd_test
+ 88.86% 0.00% perf perf [.] brstack
+ 84.27% 40.26% perf perf [.] brstack_bench
+ 41.96% 30.71% perf perf [.] brstack_foo
+ 17.89% 17.89% perf perf [.] brstack_bar
```
With the treport script:
```
$ perf record -e cycles:u -g perf test -w brstack
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.008 MB perf.data (57 samples) ]
$ tools/perf/python/treport.py
O ReportApp
Report
╸━━━━━━╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
▼ Profile
└── ▼ cycles:u 100%
└── ▼ perf (32963) 100%
├── ▼ /usr/lib/x86_64-linux-gnu/libc.so.6 0x79b17df6
│ └── ▼ main 56.1%
│ └── ▼ handle_internal_command 56.1%
│ └── ▼ cmd_test 56.1%
│ └── ▼ brstack 56.1% ▁▁
│ ├── ▼ brstack_bench 52.6%
│ │ ├── ▶ brstack_foo 24.6%
│ │ └── brstack_bar 1.75%
│ ├── brstack_foo 1.75%
│ └── brstack_bar 1.75%
├── ▶ /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
▌
^q Quit ▏^p palette
```
Committer testing:
One needs to install 'python-textual' to have this working.
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Co-developed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Alice Rogers <alice.mei.rogers@gmail.com>
Link: https://lore.kernel.org/r/20260809051820.2436530-2-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>