From: Amir Ayupov <aaupov@fb.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Namhyung Kim <namhyung@kernel.org>,
Adrian Hunter <adrian.hunter@intel.com>,
Alexander Shishkin <alexander.shishkin@linux.intel.com>,
Mark Rutland <mark.rutland@arm.com>, Jiri Olsa <jolsa@kernel.org>
Cc: Ian Rogers <irogers@google.com>,
Kan Liang <kan.liang@linux.intel.com>,
Will Deacon <will@kernel.org>,
James Clark <james.clark@linaro.org>, Leo Yan <leo.yan@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Mike Leach <mike.leach@arm.com>,
<linux-perf-users@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>,
<linux-kernel@vger.kernel.org>, <coresight@lists.linaro.org>
Subject: [RFC] perf: SW strobing for AUX trace windows
Date: Thu, 12 Nov 2026 23:41:18 -0800 [thread overview]
Message-ID: <20261113074125.4146687-1-aaupov@fb.com> (raw)
Hello,
I'm reaching out for an input on the preferred approach to add perf
support for "software strobing": AUX trace windows started and stopped
by PMU events. The context for this ask is context-sensitive sampling
with ARM ETM: https://aaupov.github.io/blog/2026/10/02/csspgo-etm.
I've prototyped three approaches explained below, but I'm open to
alternatives (I'm not an expert and all options were explored with AI).
Motivation
--------
Context-sensitive profile needs "hybrid" samples with synchronized
call- and branch stacks as input. On Intel, they're collected with LBR+
PEBS. With tracing (ETM), sampling event needs to take a callchain
sample (with fp or dwarf unwinder), and pause tracing. After trace
decoding, synthesized branch stacks are attached to the pause event.
AUX pause/resume _almost_ supports this:
```
perf record -a -e '{cs_etm/aux-action=start-paused/,
cycles/aux-action=resume/,
cycles/aux-action=pause,call-graph=fp/}' -c 10000000
```
The problem is that there's no notion of tracing window:
pause and resume events are unrelated, so the effective "window"
can be of any length. What's worse, pause events falling into paused
trace don't get the branch stack but still have overhead.
What we need is some mechanism of setting those tracing windows with
PMU events. There are several options how to achieve that, but they
all need perf changes.
pmu_pulse (coresight-only)
----------------------------------------------
The first attempt was to try to avoid perf/core entirely, and extend
a coresight config with pulsing ETE external output on every cycle
while tracing is enabled [1]. This way, pause event on TRCEXTOUTn
ends the window after exacly N traced cycles. The use of ETE external
output is pure coincidence, just a way to count cycles only while
tracing is enabled.
However, the review has raised that the config is not self-contained
and requires a lot of checks to only enable it on capable HW:
- needs a helper in the arm64 PMUv3 header and a move of PMU
definitions - needs arm64 maintainer's approval;
- only works on ETE whose PMU counts TRCEXTOUTn,
- the window is always measured in traced cycles;
- is restricted to ETM, doesn't help Intel PT,
- the further it is from a pure config change, the less understanding
I have to support the patch series further.
I decided to abandon that approach and ask for a better/more general
solution, hence this RFC.
Option 1: userspace stagger, PERF_EVENT_IOC_PERIOD-based
---------------------------------------------------------------------------
I prototyped this as `perf record --aux-action-stagger=W`:
- pause and resume count the same event with the same period,
- opened with a long "guard" period,
- on each cpu:
- perf sets the resume period via ioc_period,
- spins for W cycles in a busy loop,
- sets pause period.
Then both counters stay fixed window apart (not exact from run to run).
Related: this approach is hit by an issue fixed for Intel PT
in 2e17bf3a469a "perf/x86/intel/pt: Fix stop/start with no update".
ARM coresight needs an equivalent fix.
Cons:
- It only works per CPU or system-wide, no pid targeting.
- Inherited children start without the offset.
- Minimum window is ~2000 cycles on neoverse v2
- The code implementing "arming" is large/ugly because it does
an atomic kernel action in userspace.
As a curiosity, the documentation lists that old ioc_period would make
this stagger trivial:
> PERF_EVENT_IOC_PERIOD
This updates the overflow period for the event.
Since Linux 3.7 (on ARM) and Linux 3.14 (all other
architectures), the new period takes effect immediately.
On older kernels, the new period did not take effect until
after the next overflow.
- Open resume event with period T (without starting it),
- Open pause event with first staggered period T+W,
- Change second and subsequent pause periods to T using ioctl,
- Enable the group, both counters start together on every CPU.
Inheriting stagger in children would still be an issue though.
Option 2: attr.first_period (small uapi change)
---------------------------------------------------------
To support this fixed stagger, we could add a new first_period field:
if set, the first overflow would be set to first_period, then reloaded
to sample_period.
It addresses shortcomings of ioc stagger:
- children inherit the field,
- event group is scheduled together.
The core change is starting period_left (and last_period) from
first_period. PMUs opt in with a new capability, because software events
and some PMUs set up period_left themselves; other PMUs return
-EOPNOTSUPP. The arm PMU opts in. The attr grows to
PERF_ATTR_SIZE_VER11.
Cons: the window is in units of the sampling event.
Option 3: cross-event "arming" (attr.aux_pause_armed)
---------------------------------------------------------------------
This extends aux-action with a new bit (aux_pause_armed):
- aux pause event period is set in an overflow of aux resume in group,
- restarts from the full period,
- on overflow, pauses aux tracing:
This is the most flexible and general solution:
```
# resume every 10M cycles, trace 5000 cycles
-e '{cs_etm/aux-action=start-paused/,
cycles/aux-action=resume,period=10000000/,
cycles/aux-action=pause-armed,period=5000,call-graph=fp/}'
# resume on page faults, trace 100k instructions
-e '{intel_pt/aux-action=start-paused/,
page-faults/aux-action=resume/,
instructions/aux-action=pause-armed,period=100000/}'
```
Compared with second option:
- The trigger and the window can count different events.
- The pause event raises one interrupt per window.
- It works with any hardware event, on any architecture with an AUX
tracer that supports pause (PT and ETM today).
- It needs no PMU driver changes.
The prototype adds about 60 lines to kernel/events/core.c, plus the
uapi bit and perf support.
Cons:
1. the core has to keep a disarmed event stopped across group
scheduling, throttling, ioc_period, power mgmt.
2. rearming happens in the overflow handler (in NMI/IRQ).
3. Software pause events are not supported.
Question
---------
Does it sound reasonable for perf to support this, or it's better
to pursue pt/coresight-specific solutions? In the end, my use case
is about tracing.
If yes, which option is preferable?
- Option 1 with restoring first period behavior that was already there,
- option 2 as cleaner fix,
- option 3 as completely general but with more core state to track,
- something else?
[1] https://lore.kernel.org/r/cover.1792989860.git.aaupov@fb.com
Thanks,
Amir
reply other threads:[~2026-11-13 7:45 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=20261113074125.4146687-1-aaupov@fb.com \
--to=aaupov@fb.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=alexander.shishkin@linux.intel.com \
--cc=coresight@lists.linaro.org \
--cc=irogers@google.com \
--cc=james.clark@linaro.org \
--cc=jolsa@kernel.org \
--cc=kan.liang@linux.intel.com \
--cc=leo.yan@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@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=suzuki.poulose@arm.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
all inboxes | Powered by JetHome®