Concurrent per-thread events results in a WARN on N1SDP which leads to
the realization that per-thread events shouldn't have been sharing sinks
in the first place.
This slips through because different per-thread events will have the
same PID if owned by the same process, and we only check the PID and
nothing else. That results in unexpected WARNs because it looks like we
assumed it couldn't happen (although exclusive PMU rules allow it). But
even if it was supported it would result in trace from the wrong thread
in another event's per-thread buffer, so we should disallow it.
Fix it everywhere the same PID checking logic was copy pasted. Then the
PIDs can be dropped from a few structs as they are now unused.
Signed-off-by: James Clark <james.clark(a)linaro.org>
---
Changes in v3:
- Storing and accessing event owners at runtime causes problems due to
various scenarios of: events (and sibling events) exiting, children
inheriting event FDs, PID reuse, CPU affine events that also have a
target process set but different inherit settings. Fix it by creating
a session ID in etm_setup_aux() and holding the references in it for
the duration of the whole session. (Leo)
- Make the ETR buffer allocator consistent with sink sharing rules by
not doing numeric PID comparisons there either.
- Fix up some Sashiko reports that it sees after interacting with cscfg
and taking extra references to tasks and PIDs.
- Link to v2: https://lore.kernel.org/r/20260709-james-cs-multiple-per-threads-v2-0-10ac7…
Changes in v2:
- Fix inherited events by following event->parent
- Link to v1: https://lore.kernel.org/r/20260709-james-cs-multiple-per-threads-v1-0-d384e…
---
James Clark (8):
coresight: tmc-etr: Don't stop Perf cleanup for active sysfs reads
coresight: configfs: Don't assume active until cscfg_mgr is set
coresight: etm-perf: Flush workqueue before unloading module
coresight: tmc-etr: Prevent per-thread events from sharing a sink
coresight: tmc-etr: Use session ID for buffer ownership
coresight: tmc-etf: Prevent per-thread events from sharing a sink
coresight: etb10: Prevent per-thread events from sharing a sink
coresight: ultrasoc-smb: Prevent per-thread events from sharing a sink
drivers/hwtracing/coresight/coresight-core.c | 28 +--
drivers/hwtracing/coresight/coresight-etb10.c | 33 ++--
drivers/hwtracing/coresight/coresight-etm-perf.c | 79 ++++++++-
drivers/hwtracing/coresight/coresight-etm-perf.h | 15 ++
drivers/hwtracing/coresight/coresight-priv.h | 2 -
drivers/hwtracing/coresight/coresight-syscfg.c | 6 +-
drivers/hwtracing/coresight/coresight-tmc-core.c | 6 +-
drivers/hwtracing/coresight/coresight-tmc-etf.c | 44 ++---
drivers/hwtracing/coresight/coresight-tmc-etr.c | 207 +++++++++++++----------
drivers/hwtracing/coresight/coresight-tmc.h | 30 ++--
drivers/hwtracing/coresight/coresight-trbe.c | 3 +-
drivers/hwtracing/coresight/ultrasoc-smb.c | 25 +--
drivers/hwtracing/coresight/ultrasoc-smb.h | 6 +-
include/linux/coresight.h | 5 +-
14 files changed, 294 insertions(+), 195 deletions(-)
---
base-commit: 98495b5a4d77dd22e106f462b76e1093a55b29a7
change-id: 20260708-james-cs-multiple-per-threads-ed1d25ed1734
Best regards,
--
James Clark <james.clark(a)linaro.org>
On 03/08/2026 10:06, Amir Ayupov wrote:
> --itrace=L adds decoded branch history to existing samples, but a sample
> that was recorded while the decoder had no trace for that thread keeps an
> empty branch stack. Consumers of the resulting perf script output, such
> as profile generators for context-sensitive PGO, have no use for those
> samples.
>
> Add an opt-in dlfilter that drops samples whose parsed branch stack is
> empty, so users can exclude them without changing default sample
> semantics. Build and install it alongside perf's existing dlfilters.
>
> Signed-off-by: Amir Ayupov <aaupov(a)fb.com>
> ---
> tools/perf/Makefile.perf | 1 +
> .../dlfilters/dlfilter-nonempty-brstack.c | 26 +++++++++++++++++++
> 2 files changed, 27 insertions(+)
> create mode 100644 tools/perf/dlfilters/dlfilter-nonempty-brstack.c
>
> diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
> index 0031112c036e8..aeb8085b0756d 100644
> --- a/tools/perf/Makefile.perf
> +++ b/tools/perf/Makefile.perf
> @@ -427,6 +427,7 @@ PROGRAMS += $(OUTPUT)$(LIBJVMTI)
> endif
>
> DLFILTERS := dlfilter-test-api-v0.so dlfilter-test-api-v2.so dlfilter-show-cycles.so
> +DLFILTERS += dlfilter-nonempty-brstack.so
> DLFILTERS := $(patsubst %,$(OUTPUT)dlfilters/%,$(DLFILTERS))
>
> # what 'all' will build and 'install' will install, in perfexecdir
> diff --git a/tools/perf/dlfilters/dlfilter-nonempty-brstack.c b/tools/perf/dlfilters/dlfilter-nonempty-brstack.c
> new file mode 100644
> index 0000000000000..9e66205b841d5
> --- /dev/null
> +++ b/tools/perf/dlfilters/dlfilter-nonempty-brstack.c
> @@ -0,0 +1,26 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * dlfilter-nonempty-brstack.c: Filter out samples with no branch stack
> + * Copyright (c) 2026, Meta Platforms, Inc.
> + */
> +#include <stddef.h>
> +
> +#include <perf/perf_dlfilter.h>
> +
> +int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx)
> +{
> + /* Return 1 to filter out the sample, 0 to keep it */
> + return !sample->brstack_nr;
> +}
> +
> +const char *filter_description(const char **long_description)
> +{
> + static char *long_desc =
> + "Instruction trace decoders can add branch history to existing "
> + "samples, but samples that were recorded while no trace was "
> + "being collected get an empty branch stack. Filter those out so "
> + "that only samples carrying branch history remain.";
> +
> + *long_description = long_desc;
> + return "Keep only samples with a non-empty branch stack";
> +}
Reviewed-by: James Clark <james.clark(a)linaro.org>
On Wed, Aug 12, 2026 at 06:48:24PM +0300, Adrian Hunter wrote:
> On 11/08/2026 18:58, Adrian Hunter wrote:
> > On 03/08/2026 12:06, Amir Ayupov wrote:
> >> thread_stack__br_sample() and thread_stack__br_sample_late() fill a
> >> caller-supplied branch_stack that is typically allocated with zalloc(),
> >> leaving hw_idx as 0. Zero is a valid hardware index, so consumers that
> >> honour PERF_SAMPLE_BRANCH_HW_INDEX see a reconstructed branch stack
> >> claiming to start at LBR TOS entry 0.
> >>
> >> These branch stacks are reconstructed from instruction trace and have no
> >> hardware index at all. Set hw_idx to -1ULL, which is the established way
> >> to say "not available" and matches what intel-pt and cs-etm already put
> >> in the branch stacks they synthesise directly.
> >>
> >> Signed-off-by: Amir Ayupov <aaupov(a)fb.com>
> >
> > Fixes tag?
> >
> > Otherwise:
> >
> > Reviewed-by: Adrian Hunter <adrian.hunter(a)intel.com>
>
> On second thoughts, it seems that hw_idx is only used for stitching
> LBRs which is anyway disabled by default and only enabled by --stitch-lbr.
>
> Setting -1ULL will prevent has_stitched_lbr() making a match, but we can
> rely on the user to decide that for themselves via --stitch-lbr.
This is one of those options that few people use as its so specialized,
do you think we could auto-enable it if we notice it is a good idea for
some specific machine and request from the user? I.e. user requests
callchains, unlimited or with a limit that is more than what we can do
without stitching: we auto stich?
- Arnaldo
> So, in fact, it doesn't look like this change should be needed?
>
> >
> >> ---
> >> tools/perf/util/thread-stack.c | 2 ++
> >> 1 file changed, 2 insertions(+)
> >>
> >> diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
> >> index c5ce741b07446..1a3dffa83bde2 100644
> >> --- a/tools/perf/util/thread-stack.c
> >> +++ b/tools/perf/util/thread-stack.c
> >> @@ -624,6 +624,7 @@ void thread_stack__br_sample(struct thread *thread, int cpu,
> >> unsigned int nr;
> >>
> >> dst->nr = 0;
> >> + dst->hw_idx = -1ULL;
> >>
> >> if (!ts)
> >> return;
> >> @@ -686,6 +687,7 @@ void thread_stack__br_sample_late(struct thread *thread, int cpu,
> >> bool start = false;
> >>
> >> dst->nr = 0;
> >> + dst->hw_idx = -1ULL;
> >>
> >> if (!ts)
> >> return;
> >
On 03/08/2026 10:06, Amir Ayupov wrote:
> Add a CoreSight shell test for --itrace=L. Record timestamped ETM trace
> with explicit -T sample timestamps and AUX pause/resume events, then
> check that the pause samples carry both a multi-frame callchain and a
> non-empty branch stack for each of the workload's two processes.
>
> Decode the same recording with L4 and L64 and reject any branch stack
> deeper than the requested depth.
>
> The test skips when cs_etm is absent, when not run as root, or when the
> recording turns out to lack virtual timestamps. It exercises the
> timestamp-gated path and the requested-depth bound; it does not attempt
> to verify that the attached history is correlated to the sample.
>
> Signed-off-by: Amir Ayupov <aaupov(a)fb.com>
> ---
> .../tests/shell/coresight/add_last_branch.sh | 175 ++++++++++++++++++
> 1 file changed, 175 insertions(+)
> create mode 100755 tools/perf/tests/shell/coresight/add_last_branch.sh
>
> diff --git a/tools/perf/tests/shell/coresight/add_last_branch.sh b/tools/perf/tests/shell/coresight/add_last_branch.sh
> new file mode 100755
> index 0000000000000..4654069ad651f
> --- /dev/null
> +++ b/tools/perf/tests/shell/coresight/add_last_branch.sh
> @@ -0,0 +1,175 @@
> +#!/bin/bash -e
> +# SPDX-License-Identifier: GPL-2.0
> +# CoreSight branch history on existing samples (exclusive)
> +
> +perf list pmu | grep -q 'cs_etm//' || exit 2
> +
> +if [ "$(id -u)" != 0 ]; then
> + echo "[Skip] No root permission"
> + exit 2
> +fi
Is this so you can use -C 0? It's not completely obvious what that has
to do with the test. Can you not drop the -C option or use --per-thread
mode with a simpler non-forking workload?
I don't mind keeping it for some variety in the tests, but it should be
documented.
> +
> +tmpdir=$(mktemp -d /tmp/perf-cs-add-last-branch.XXXXX)
> +
> +cleanup()
> +{
> + rm -rf "$tmpdir"
> + trap - EXIT TERM INT
> +}
> +
> +# shellcheck disable=SC2317 # Called through trap.
> +trap_cleanup()
> +{
> + cleanup
> + exit 1
> +}
> +trap trap_cleanup EXIT TERM INT
> +
> +record_data()
> +{
> + if perf record -T -o "$tmpdir/data" -C 0 \
> + -e cs_etm/aux-action=start-paused,timestamp/u \
Timestamp needs a value on newer kernels or Perf returns an error. But
do you need to provide the option at all? It's on by default for per-CPU
mode.
> + -e cycles/aux-action=resume,period=550019/u \
> + -e cycles/aux-action=pause,period=100003,call-graph=fp/u -- \
> + taskset --cpu-list 0 perf test -w context_switch_loop 100000 \
The other Coresight tests use --workload-ctl to record less data and
save some decode time. I think this test might benefit from it too.
> + >/dev/null 2>"$tmpdir/stderr"; then
> + return 0
> + fi
> +
> + echo "Failed to record ETM trace with AUX pause/resume" >&2
> + cat "$tmpdir/stderr" >&2
> + return 1
> +}
> +
> +decode()
> +{
> + local size=$1
> + local output=$2
> +
> + if perf script -i "$tmpdir/data" --itrace="L$size" \
> + -F comm,pid,tid,event,ip,brstack >"$output" \
> + 2>"$tmpdir/stderr"; then
> + return 0
> + fi
> +
> + if grep -q "itrace=L requires virtual timestamped trace" \
> + "$tmpdir/stderr"; then
> + echo "[Skip] Virtual CoreSight timestamps are not available"
> + cleanup
> + exit 2
> + fi
> +
> + cat "$tmpdir/stderr" >&2
> + return 1
> +}
> +
> +check_process_samples()
> +{
> + local output=$1
> + local comm
> +
> + for comm in proc1 proc2; do
> + awk -v comm="$comm" '
> + $1 == comm && /cycles\/aux-action=pause/ {
> + in_sample = 1
> + next
> + }
> + !NF {
> + in_sample = 0
> + next
> + }
> + in_sample && /0x[[:xdigit:]]+\/0x[[:xdigit:]]+\// {
> + found = 1
> + }
> + END { exit !found }
> + ' "$output" || {
> + echo "No pause-event branch stack found for $comm" >&2
> + return 1
> + }
> + done
> +}
> +
> +check_callchains()
> +{
> + local output="$tmpdir/script-callchain"
> +
> + perf script -i "$tmpdir/data" -F comm,event,ip >"$output" 2>/dev/null
> +
> + awk '
> + /cycles\/aux-action=pause/ {
> + in_sample = 1
> + frames = 0
> + next
> + }
> + !NF {
> + if (in_sample && frames >= 2)
> + found = 1
> + in_sample = 0
> + next
> + }
> + in_sample && /^[[:space:]]+[[:xdigit:]]+([[:space:]]|$)/ {
> + frames++
> + }
> + END {
> + if (in_sample && frames >= 2)
> + found = 1
> + exit !found
> + }
> + ' "$output" || {
> + echo "No multi-frame pause-event callchain found" >&2
> + return 1
> + }
Can you add some example output in the test saying what these awks are
looking for. It failed for me but I wasn't sure why. I've attached my
script-callchain file if that helps.
> +}
> +
> +check_branch_stacks()
> +{
> + local output=$1
> + local max_entries=$2
> +
> + local ret
> +
> + if awk -v max="$max_entries" '
> + /0x[[:xdigit:]]+\/0x[[:xdigit:]]+\// {
> + entries = 0
> + for (i = 1; i <= NF; i++)
> + if ($i ~ /^0x[[:xdigit:]]+\/0x[[:xdigit:]]+\//)
> + entries++
> + if (entries)
> + found = 1
> + if (entries > max) {
> + status = 2
> + exit
> + }
> + }
> + END {
> + if (status)
> + exit status
> + if (!found)
> + exit 1
> + }
> + ' "$output"; then
> + return 0
> + else
> + ret=$?
> + fi
> +
> + case $ret in
> + 1) echo "No ETM branch stacks found" >&2 ;;
> + 2) echo "Branch stack exceeds requested L$max_entries depth" >&2 ;;
> + esac
> + return 1
> +}
> +
> +record_data
> +check_callchains
> +
> +decode 4 "$tmpdir/script-l4"
> +check_process_samples "$tmpdir/script-l4"
> +check_branch_stacks "$tmpdir/script-l4" 4
> +
> +decode 64 "$tmpdir/script-l64"
> +check_process_samples "$tmpdir/script-l64"
> +check_branch_stacks "$tmpdir/script-l64" 64
> +
> +cleanup
> +exit 0
On 03/08/2026 10:01, Amir Ayupov wrote:
> This series implements --itrace=L for Arm CoreSight ETM: decoded branch
Hi Amir,
How did you send this? The cover letter seems to be on a different
thread to the patches.
> history is attached to the PMU samples already present in the recording,
> rather than to synthesised instruction samples.
>
> The motivating use case is context-sensitive PGO, which wants a callchain
> and a branch stack describing the same point in time. Recording a cycles
> event with call-graph=fp and aux-action=pause supplies the callchain, and
> the ETM trace leading up to that sample supplies the branch stack, without
> having to trace a long-running process continuously.
>
> Intel PT has had this since commit f0a0251cee80 ("perf intel-pt: Add
> support for synthesizing branch stacks for regular events"), so this
> deliberately follows intel-pt: the same --itrace=L option and the same
> thread_stack__br_sample_late() call.
>
> Patches 1 to 4 are independent fixes and infrastructure the feature needs:
>
> 1 makes an inconsistent HEADER_GROUP_DESC non-fatal. AUX recordings
> using aux-action pause/resume produce a group descriptor the strict
> reader rejects, which makes an otherwise readable perf.data
> unreadable, so without this the recipe in patch 9 cannot be decoded
> at all. Useful on its own.
> 2 reports hw_idx as -1 rather than 0 in reconstructed branch stacks,
> since they have no hardware index.
> 3 bounds a wrapped memcpy in thread_stack__br_sample(). Latent today,
> reachable once a caller keeps a ring larger than the requested output
> depth.
> 4 adds a dlfilter that drops samples with an empty branch stack.
>
> Patch 5 is a no-functional-change refactor splitting
> cs_etm__process_timestamped_queues() into its three parts. Heap seeding
> moves to cs_etm__update_queues(), gated on queues.new_data and mirroring
> intel_pt_update_queues(); the end-of-session flush moves to
> cs_etm__flush_timestamped_queues(); and the decode loop is left on its own
> so patch 6 can drive it once per sample. Neither seeding nor flushing can
> be repeated, which is why they have to come out first. The moved code is
> unchanged, so both loops appear as context in the diff.
>
> Patch 6 is the feature and patch 7 adds a shell test.
>
> Patch 8 is where review attention is most useful. --itrace=L attaches
> whatever the thread stack holds when a sample is processed. With a duty
> cycled trace most samples fire while the trace is off; they have nothing
> newly decoded, but the thread stack still holds the previous window, so
> they were being given branches that ran an arbitrary amount of time
> earlier. On a 12 s capture with pause period 100003 and resume period
> 8350251, of 335291 samples that received branch history only 3371 were
> backed by trace decoded for that sample.
>
> A trace window belongs to exactly one sample, and with AUX pause and
> resume the sample is what stops the trace, so the pairing is one to one by
What happens when aux-pause isn't used and there isn't a 1:1 pairing?
There is a lot of description of that which implies that it doesn't work
if there isn't. But as far as I can tell it works just as well by using
the timestamps?
> construction. Patch 8 therefore takes the branch history when attaching it
> instead of copying it, and a later sample with nothing newly decoded finds
> an empty branch stack, which the dlfilter removes.
> thread_stack__br_sample() is unchanged, so lowercase --itrace=l keeps the
> overlapping branch stacks it produces today.
>
> Patch 9 documents the workflow.
>
> Because the sample is what stops the trace, the history attached to it
> lines up well with the callchain: on a brstack capture the leaf of the
> callchain matched the function containing the newest branch stack entry's
> target for 93.5% of attached samples. The residual comes from the decode
> loop stopping on interpolated timestamps, so a few branches that ran just
> after the sample can still be included. Trimming those with the sample ip
> raises it to 96.8%, but that matters far more for free-running ETM
> strobing than for pause and resume, so I have left it out of this series
> and will send it separately.
>
> Patch 8 could be squashed into patch 6, since patch 6 on its own produces
> mostly stale history. I kept them apart so the decode mechanism and the
> attachment policy can be reviewed separately, but I am happy to fold them.
>
> Testing
> -------
>
> Built with:
>
> make -C tools/perf NO_LIBELF=1 NO_LIBTRACEEVENT=1 CORESIGHT=1
>
> Every patch builds individually. checkpatch reports only "does MAINTAINERS
> need updating?" for the two new files and "quoted string split across
> lines" for the dlfilter description string, which matches how
> dlfilter-show-cycles.c already writes it.
>
> Tested on Arm Neoverse V2 with CoreSight ETM:
>
> - perf test "CoreSight branch history on existing samples": Ok, 3 for 3
> - captures from 5 MiB to 2.5 GiB decoded with --itrace=L64, no decode
> errors
> - the other CoreSight tests are unchanged by this series; four of them
> fail identically at the base commit on this machine
Can you report or investigate these failures please. None of the tests
should be failing on TRBE hardware, at least on the latest
perf-tools-next branch. You can try applying "[PATCH 00/14] perf cs-etm:
Per-thread mode fixes and snapshot wrap support" to be sure, but I don't
think that fixes any current failures.
>
> Amir Ayupov (9):
> perf header: Tolerate inconsistent HEADER_GROUP_DESC
> perf thread-stack: Report branch stack hw_idx as not available
> perf thread-stack: Bound wrapped branch stack copy
> perf dlfilter: Add non-empty branch stack filter
> perf cs-etm: Split up cs_etm__process_timestamped_queues()
> perf cs-etm: Add branch history to existing samples
> perf test cs-etm: Test branch history on existing samples
> perf cs-etm: Consume branch history when attaching it to a sample
> Documentation: coresight: Document context-sensitive PGO workflow
>
> .../trace/coresight/coresight-perf.rst | 62 +++++
> tools/perf/Makefile.perf | 1 +
> .../dlfilters/dlfilter-nonempty-brstack.c | 26 ++
> .../tests/shell/coresight/add_last_branch.sh | 175 +++++++++++++
> tools/perf/util/cs-etm.c | 242 ++++++++++++++++--
> tools/perf/util/header.c | 42 ++-
> tools/perf/util/thread-stack.c | 21 +-
> tools/perf/util/thread-stack.h | 1 +
> 8 files changed, 544 insertions(+), 26 deletions(-)
> create mode 100644 tools/perf/dlfilters/dlfilter-nonempty-brstack.c
> create mode 100755 tools/perf/tests/shell/coresight/add_last_branch.sh
>
>
> base-commit: da85966dfd23a3b03e00ee3bce6ad301f0a2b229
On 03/08/2026 10:06, Amir Ayupov wrote:
> Add a CoreSight shell test for --itrace=L. Record timestamped ETM trace
> with explicit -T sample timestamps and AUX pause/resume events, then
> check that the pause samples carry both a multi-frame callchain and a
> non-empty branch stack for each of the workload's two processes.
>
> Decode the same recording with L4 and L64 and reject any branch stack
> deeper than the requested depth.
>
> The test skips when cs_etm is absent, when not run as root, or when the
> recording turns out to lack virtual timestamps. It exercises the
> timestamp-gated path and the requested-depth bound; it does not attempt
> to verify that the attached history is correlated to the sample.
>
> Signed-off-by: Amir Ayupov <aaupov(a)fb.com>
> ---
> .../tests/shell/coresight/add_last_branch.sh | 175 ++++++++++++++++++
> 1 file changed, 175 insertions(+)
> create mode 100755 tools/perf/tests/shell/coresight/add_last_branch.sh
>
[...]
> +
> +record_data
> +check_callchains
> +
> +decode 4 "$tmpdir/script-l4"
> +check_process_samples "$tmpdir/script-l4"
Minor nit, but these should be capital L. l is a different option.
> +check_branch_stacks "$tmpdir/script-l4" 4
> +
> +decode 64 "$tmpdir/script-l64"
> +check_process_samples "$tmpdir/script-l64"
> +check_branch_stacks "$tmpdir/script-l64" 64
> +
> +cleanup
> +exit 0
On Wed, Aug 12, 2026 at 05:13:14PM +0800, Junrui Luo via B4 Relay wrote:
> Mark parameters that can hold a kernel address, and give those a
> config_item_type whose 'value' attribute is 0600. Parameters holding
> plain numbers, such as the strobing 'window' and 'period' counts, keep
> the existing mode.
Thanks for reporting the issue.
The patch seems overly complex to me. I'd suggest:
--- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
@@ -281,9 +281,16 @@ static ssize_t cscfg_param_value_show(struct config_item *item, char *page)
{
struct cscfg_fs_param *param_item = container_of(to_config_group(item),
struct cscfg_fs_param, group);
- u64 value = param_item->feat_desc->params_desc[param_item->param_idx].value;
-
- return scnprintf(page, PAGE_SIZE, "0x%llx\n", value);
+ struct cscfg_parameter_desc *param_desc =
+ param_item->feat_desc->params_desc + param_item->param_idx;
+ const char *name = param_desc->name;
+ u64 value = param_desc->value;
+
+ /* The kernel address should print with the "%pK" specifier */
+ if (!strncmp(name, "address"))
+ return scnprintf(page, PAGE_SIZE, "0x%pK\n", value);
+ else
+ return scnprintf(page, PAGE_SIZE, "0x%llx\n", value);
}
We can add a flag (e.g., is_addr) in cscfg_parameter_desc to indicate
a parameter presents an address. Since currently only pstop's "address"
parameter has this issue, adding a general flag can be deferred until
it is actually needed.
Thanks,
Leo
On 03/08/2026 10:06, Amir Ayupov wrote:
> thread_stack__br_sample() and thread_stack__br_sample_late() fill a
> caller-supplied branch_stack that is typically allocated with zalloc(),
> leaving hw_idx as 0. Zero is a valid hardware index, so consumers that
> honour PERF_SAMPLE_BRANCH_HW_INDEX see a reconstructed branch stack
> claiming to start at LBR TOS entry 0.
>
> These branch stacks are reconstructed from instruction trace and have no
> hardware index at all. Set hw_idx to -1ULL, which is the established way
> to say "not available" and matches what intel-pt and cs-etm already put
> in the branch stacks they synthesise directly.
>
This fix makes sense in case someone doesn't overwrite it, but I think
"matches what cs-etm already puts in the branch stacks" isn't quite
right. Based on the hw_id docs, cs-etm should be setting 0 shouldn't it?
* For the architectures whose raw branch records are
* already stored in age order, the hw_idx should be 0.
-1 "unknown" isn't accurate as we do know what the order is because we
generate them in order. If anyone is reading the field 0 is much more
useful than -1.
Can we change cs_etm__synth_branch_sample() to 0 and update this commit
message to not say that -1 is right for cs-etm?
> Signed-off-by: Amir Ayupov <aaupov(a)fb.com>
> ---
> tools/perf/util/thread-stack.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
> index c5ce741b07446..1a3dffa83bde2 100644
> --- a/tools/perf/util/thread-stack.c
> +++ b/tools/perf/util/thread-stack.c
> @@ -624,6 +624,7 @@ void thread_stack__br_sample(struct thread *thread, int cpu,
> unsigned int nr;
>
> dst->nr = 0;
> + dst->hw_idx = -1ULL;
>
> if (!ts)
> return;
> @@ -686,6 +687,7 @@ void thread_stack__br_sample_late(struct thread *thread, int cpu,
> bool start = false;
>
> dst->nr = 0;
> + dst->hw_idx = -1ULL;
>
> if (!ts)
> return;
The current ETMx configuration via sysfs can lead to the following
inconsistencies:
- If a configuration is modified via sysfs while a perf session is
active, the running configuration may differ between before
a sched-out and after a subsequent sched-in.
- If a perf session and sysfs session tries to enable concurrently,
configuration from configfs could be corrupted (etm4).
- There is chance to corrupt drvdata->config if perf session tries
to enabled among handling cscfg_csdev_disable_active_config()
in etm4_disable_sysfs() (etm4).
To resolve these inconsistencies, the configuration should be separated into:
- active_config, which is applied configuration for the current session
- config, which stores the settings configured via sysfs.
and apply configuration from configfs after taking a mode.
Also, This patch set includes some small fixes:
- missing trace id release in etm4x.
- underflow issue for nrseqstate.
- wrong check in etm4x_sspcicrn_present().
- missing call of cscfg_csdev_disable_active_config()
This patch based on coresight tree's next
Patch History
=============
from v8 to v9:
- add feat_csdev_lock guard interface.
- set feat_csdev->drv_spinlock as NULL for etmv4_drvdata.
- https://lore.kernel.org/all/20260629090007.1718746-1-yeoreum.yun@arm.com/
from v7 to v8:
- accept @Leo Yan' suggestion to handle error.
- small minor fixes following @Suzuki' suggestion.
- https://lore.kernel.org/all/20260519154812.254884-1-yeoreum.yun@arm.com/
from v6 to v7:
- rebase on coresight/next
- add ETM_MAX_SEQ_TRANSITIONS define
- remove redundant patch relavent cpu-hotplug as coresight-pm patch
merged.
- https://lore.kernel.org/all/20260422132203.977549-1-yeoreum.yun@arm.com/
from v5 to v6:
- fix missing of calling cscfg_csdev_disable_active_config()
- add rb & fixes tags.
- add ss_status field in etm4x_drvdata to expose STATUS and PENDING bits.
- https://lore.kernel.org/all/20260415165528.3369607-1-yeoreum.yun@arm.com/
from v4 to v5:
- add rb-tag.
- fix underflow issue for nrseqstate.
- fix wrong check in etm4_sspcicrn_present().
- remove redundant fields on etmv4_save_state.
- rename caps->ss_status to ss_cmp.
- fix wrong location of etm4_release_trace_id.
- https://lore.kernel.org/all/20260413142003.3549310-1-yeoreum.yun@arm.com/
from v3 to v4:
- change etm_drvdata->spinlock type to raw_spin_lock_t
- remove redundant call etmX_enable_hw() with starting_cpu() callsback.
- fix missing trace id release.
- add missing docs.
- https://lore.kernel.org/all/20260412175506.412301-1-yeoreum.yun@arm.com/
from v2 to v3:
- fix build error for etm3x.
- fix checkpatch warning.
- https://lore.kernel.org/all/20260410074310.2693385-1-yeoreum.yun@arm.com/
from v1 to v2
- rebased to v7.0-rc7.
- introduce etmX_caps structure to save etmX's capabilities.
- remove ss_status from etmv4_config.
- modify active_config after taking a mode (perf/sysfs).
- https://lore.kernel.org/all/20260317181705.2456271-1-yeoreum.yun@arm.com/
Yeoreum Yun (13):
coresight: etm4x: fix wrong check of etm4x_sspcicrn_present()
coresight: etm4x: fix underflow for usage of (nrseqstate - 1)
coresight: etm4x: fix leaked trace id
coresight: etm4x: fix inconsistencies with sysfs configuration
coresight: etm4x: missing cscfg_csdev_disable_active_config() in perf
enable
coresight: etm3x: fix inconsistencies with sysfs configuration
coresight: etm3x: change drvdata->spinlock type to raw_spin_lock_t
coresight: etm3x: remove redundant cpu online check on
etm_enable_sysfs()
coresight: etm4x: introduce struct etm4_caps
coresight: etm4x: exclude ss_status from drvdata->config
coresight: etm4x: remove s_ex_level from config
coresight: etm4x: remove redundant fields in etmv4_save_state
coresight: etm3x: introduce struct etm_caps
.../hwtracing/coresight/coresight-config.c | 18 +-
.../hwtracing/coresight/coresight-config.h | 26 +
drivers/hwtracing/coresight/coresight-etm.h | 48 +-
.../coresight/coresight-etm3x-core.c | 96 ++--
.../coresight/coresight-etm3x-sysfs.c | 159 +++---
.../hwtracing/coresight/coresight-etm4x-cfg.c | 16 +-
.../coresight/coresight-etm4x-core.c | 454 ++++++++++--------
.../coresight/coresight-etm4x-sysfs.c | 204 ++++----
drivers/hwtracing/coresight/coresight-etm4x.h | 204 ++++----
9 files changed, 682 insertions(+), 543 deletions(-)
base-commit: 98495b5a4d77dd22e106f462b76e1093a55b29a7
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
Fix a few issues with per-thread mode:
- With TRBE, thread migrations hit a queue without a decoder assert
- On nVHE, everything looks like guest trace instead of host
- Tracing multiple threads didn't really work
After adding a tests for those, it turns out there were some snapshot
bugs not picked up by the other snapshot tests. That showed that the
different snapshot searches for Intel BTS and Arm SPE were inconsistent
and I think all tracers can benefit from using the same pointer fixup
logic, so that gets refactored into the common auxtrace.c. Then SPE can
just share the Intel BTS search as it was obviously copied from it
originally. IntelPT keeps the more advanced duplicate data search, but
in the future that could probably be made the common one and all tracers
would benefit from using it (except maybe BTS if it always has a very
small buffer, but I doubt the overhead of the duplicate search would be
an issue). For now this is more of a refactor rather than behavioral
change so don't do that yet.
Signed-off-by: James Clark <james.clark(a)linaro.org>
---
James Clark (14):
perf cs-etm: Fix nVHE per-thread decoding
perf cs-etm: Warn for invalid timestamp option
perf cs-etm: Turn on context packet timestamps in per-thread mode
perf cs-etm: Use per-CPU queues for per-thread mode
perf cs-etm: Increase default timestamp generation period
perf auxtrace: Turn Intel BTS snapshot search into a generic one
perf arm-spe: Use generic snapshot search
perf auxtrace: intel-pt: Use new snapshot_has_wrapped callback
perf cs-etm: Queue partial AUX records
perf cs-etm: Don't print missing buffers in snapshot mode
perf auxtrace: cs-etm: Capture wrapped snapshots
perf test: Allow infinite named_thread loops
perf test: Add test for per-thread mode
perf cs-etm: Test multiple per-thread threads
Documentation/userspace-api/perf_ring_buffer.rst | 6 +-
tools/perf/Documentation/perf-test.txt | 2 +-
tools/perf/arch/arm/util/cs-etm.c | 30 ++++-
tools/perf/arch/arm64/util/arm-spe.c | 147 +--------------------
tools/perf/arch/x86/util/intel-bts.c | 115 +---------------
tools/perf/arch/x86/util/intel-pt.c | 58 +++-----
.../perf/tests/shell/coresight/per-thread-multi.sh | 78 +++++++++++
tools/perf/tests/shell/coresight/per-thread.sh | 48 +++++++
.../perf/tests/shell/coresight/raw_dump_stress.sh | 5 -
tools/perf/tests/workloads/named_threads.c | 7 +-
tools/perf/util/auxtrace.c | 136 +++++++++++++++++--
tools/perf/util/auxtrace.h | 20 ++-
tools/perf/util/cs-etm.c | 98 ++++++++++----
13 files changed, 382 insertions(+), 368 deletions(-)
---
base-commit: bf10e6ee2ac3034c9068e03eed418fd16961984e
change-id: 20260605-james-cs-unformatted-per-thread-fix-50e723aa7f0e
Best regards,
--
James Clark <james.clark(a)linaro.org>