From: sashiko-bot@kernel.org
To: "Puranjay Mohan" <puranjay@kernel.org>
Cc: bpf@vger.kernel.org, linux-perf-users@vger.kernel.org
Subject: Re: [PATCH v4 3/4] perf/arm64: Add BRBE support for bpf_get_branch_snapshot()
Date: Wed, 27 May 2026 14:09:47 +0000 [thread overview]
Message-ID: <20260527140948.3D61C1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260527121207.2312181-4-puranjay@kernel.org>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] TOCTOU race in `arm_brbe_snapshot_branch_stack` leads to hardware state corruption.
- [High] Unconditional calls to `brbe_invalidate()` destructively clear hardware branch records, breaking concurrent perf events.
- [High] `bpf_get_branch_snapshot()` unconditionally fails when invoked from a PMU NMI handler.
--
commit 4683208c7439e46b2ca26814f22b69f16e4ad0c2
Author: Puranjay Mohan <puranjay@kernel.org>
perf/arm64: Add BRBE support for bpf_get_branch_snapshot()
This commit enables bpf_get_branch_snapshot() on ARM64 by implementing the
perf_snapshot_branch_stack static call for BRBE. It pauses BRBE, reads the
records into a buffer, invalidates the buffer, and unpauses BRBE.
> diff --git a/drivers/perf/arm_brbe.c b/drivers/perf/arm_brbe.c
> index ba554e0c846c4..aede95e277842 100644
> --- a/drivers/perf/arm_brbe.c
> +++ b/drivers/perf/arm_brbe.c
[ ... ]
> @@ -774,32 +795,96 @@ void brbe_read_filtered_entries(struct perf_branch_stack *branch_stack,
[ ... ]
> +/*
> + * Best-effort BRBE snapshot for BPF tracing. Pause BRBE to avoid
> + * self-recording and return 0 if the snapshot state appears disturbed.
> + */
> +int arm_brbe_snapshot_branch_stack(struct perf_branch_entry *entries, unsigned int cnt)
> +{
> + unsigned long flags;
> + int nr_hw, nr_copied = 0;
> + u64 brbfcr, brbcr;
> +
> + if (!cnt)
> + return 0;
> +
> + /* Guard against running on a CPU without BRBE (e.g. big.LITTLE). */
> + if (!cpu_has_brbe())
> + return 0;
> +
> + /*
> + * Pause BRBE first to avoid recording our own branches. The
> + * sysreg read/write and ISB are branchless, so pausing before
> + * checking BRBCR avoids polluting the buffer with our own
> + * conditional branches.
> + */
> + brbfcr = read_sysreg_s(SYS_BRBFCR_EL1);
> + brbcr = read_sysreg_s(SYS_BRBCR_EL1);
> + write_sysreg_s(brbfcr | BRBFCR_EL1_PAUSED, SYS_BRBFCR_EL1);
> + isb();
> +
> + /* Bail out if BRBE is not enabled (BRBCR_EL1 == 0). */
> + if (!brbcr) {
> + write_sysreg_s(brbfcr, SYS_BRBFCR_EL1);
> + return 0;
> + }
[Severity: High]
Is this check incompatible with PMU NMI handlers?
If a BPF program attaches to a perf event overflow, armv8pmu_handle_irq()
calls armv8pmu_stop() before processing overflows, which calls brbe_disable()
and sets SYS_BRBCR_EL1 to 0.
Would this cause bpf_get_branch_snapshot() to unconditionally fail and return
0 when triggered from these PMU events?
> +
> + /* Block local exception delivery while reading the buffer. */
> + flags = local_daif_save();
[Severity: High]
Is there a TOCTOU race window here that could corrupt hardware state?
The function reads and caches SYS_BRBFCR_EL1 and SYS_BRBCR_EL1 before
disabling local exceptions via local_daif_save().
If an interrupt or NMI arrives in this window (such as a perf_event_disable
IPI) and modifies the BRBE hardware configuration, the function later writes
back the stale cached brbcr and brbfcr values at the end of the function,
overwriting the PMU subsystem's intentional changes.
Does the mitigation check below catch this?
if (!(read_sysreg_s(SYS_BRBFCR_EL1) & BRBFCR_EL1_PAUSED)) {
It looks like it might fail to catch this because brbe_disable() leaves the
PAUSED bit set, leading to the function silently re-enabling BRBE and
corrupting the hardware state when restoring the cached registers.
> +
> + /*
> + * A PMU overflow before local_daif_save() could have re-enabled
> + * BRBE, clearing the PAUSED bit. The overflow handler already
> + * restored BRBE to its correct state, so just bail out.
> + */
> + if (!(read_sysreg_s(SYS_BRBFCR_EL1) & BRBFCR_EL1_PAUSED)) {
> + local_daif_restore(flags);
> + return 0;
> + }
> +
> + nr_hw = FIELD_GET(BRBIDR0_EL1_NUMREC_MASK,
> + read_sysreg_s(SYS_BRBIDR0_EL1));
> +
> + for_each_brbe_entry(i, nr_hw) {
> + if (nr_copied >= cnt)
> + break;
> +
> + if (!perf_entry_from_brbe_regset(i, &entries[nr_copied], NULL))
> + break;
> +
> + nr_copied++;
> + }
> +
> + brbe_invalidate();
[Severity: High]
Does unconditionally clearing hardware branch records here break concurrent
perf events?
Since bpf_get_branch_snapshot() can be invoked asynchronously at any time
(e.g., from a BPF kprobe or tracepoint program), if another perf event is
actively profiling, would this snapshot silently wipe the hardware BRBE
buffer?
When the active perf event later overflows, it would read an empty or severely
truncated branch stack, potentially corrupting the profiling data. Should
snapshots be read-only?
> +
> + /* Restore BRBCR before unpausing via BRBFCR, matching brbe_enable(). */
> + write_sysreg_s(brbcr, SYS_BRBCR_EL1);
> + isb();
> + write_sysreg_s(brbfcr, SYS_BRBFCR_EL1);
> + /* Ensure BRBE is unpaused before returning to the caller. */
> + isb();
> + local_daif_restore(flags);
> +
> + return nr_copied;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260527121207.2312181-1-puranjay@kernel.org?part=3
next prev parent reply other threads:[~2026-05-27 14:09 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-27 12:11 [PATCH v4 0/4] arm64: Add BRBE support for bpf_get_branch_snapshot() Puranjay Mohan
2026-05-27 12:11 ` [PATCH v4 1/4] perf/core: Fix sched_task callbacks for CPU-wide branch stack events Puranjay Mohan
2026-05-27 12:11 ` [PATCH v4 2/4] perf: Use a union to clear branch entry bitfields Puranjay Mohan
2026-05-27 13:00 ` bot+bpf-ci
2026-05-27 12:11 ` [PATCH v4 3/4] perf/arm64: Add BRBE support for bpf_get_branch_snapshot() Puranjay Mohan
2026-05-27 13:01 ` bot+bpf-ci
2026-05-27 14:09 ` sashiko-bot [this message]
2026-06-02 8:56 ` Puranjay Mohan
2026-06-05 13:53 ` Rob Herring
2026-05-27 12:12 ` [PATCH v4 4/4] selftests/bpf: Adjust wasted entries threshold for ARM64 BRBE Puranjay Mohan
2026-06-05 13:02 ` [PATCH v4 0/4] arm64: Add BRBE support for bpf_get_branch_snapshot() Puranjay Mohan
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=20260527140948.3D61C1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=puranjay@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/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