Linux Perf Users
 help / color / mirror / Atom feed
From: Amir Ayupov <aaupov@fb.com>
To: <linux-perf-users@vger.kernel.org>, <coresight@lists.linaro.org>,
	<linux-arm-kernel@lists.infradead.org>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	James Clark <james.clark@linaro.org>, Leo Yan <leo.yan@arm.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>,
	Arnaldo Carvalho de Melo <acme@kernel.org>,
	Namhyung Kim <namhyung@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Jiri Olsa <jolsa@kernel.org>, Ian Rogers <irogers@google.com>,
	Adrian Hunter <adrian.hunter@intel.com>,
	John Garry <john.g.garry@oracle.com>,
	Will Deacon <will@kernel.org>
Cc: <linux-doc@vger.kernel.org>, Mike Leach <mike.leach@arm.com>,
	Jonathan Corbet <corbet@lwn.net>,
	Shuah Khan <skhan@linuxfoundation.org>,
	Swapnil Sapkal <swapnil.sapkal@amd.com>
Subject: [PATCH 0/9] perf cs-etm: Add branch history to existing samples
Date: Mon, 3 Aug 2026 02:01:53 -0700	[thread overview]
Message-ID: <20260803090202.2324641-1-aaupov@fb.com> (raw)

This series implements --itrace=L for Arm CoreSight ETM: decoded branch
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
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

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
-- 
2.52.0


                 reply	other threads:[~2026-08-03  9:02 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260803090202.2324641-1-aaupov@fb.com \
    --to=aaupov@fb.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=corbet@lwn.net \
    --cc=coresight@lists.linaro.org \
    --cc=irogers@google.com \
    --cc=james.clark@linaro.org \
    --cc=john.g.garry@oracle.com \
    --cc=jolsa@kernel.org \
    --cc=leo.yan@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mike.leach@arm.com \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    --cc=skhan@linuxfoundation.org \
    --cc=suzuki.poulose@arm.com \
    --cc=swapnil.sapkal@amd.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox