public inbox for linux-perf-users@vger.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Puranjay Mohan" <puranjay@kernel.org>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [PATCH v3 3/4] perf/arm64: Add BRBE support for bpf_get_branch_snapshot()
Date: Mon, 13 Apr 2026 20:31:44 +0000	[thread overview]
Message-ID: <20260413203144.EA85BC2BCAF@smtp.kernel.org> (raw)
In-Reply-To: <20260413185740.3286146-4-puranjay@kernel.org>

Sashiko AI review found 4 potential issue(s):
- [High] arm_brbe_snapshot_branch_stack executes BRBE system register reads without validating CPU support, leading to an Undefined Instruction kernel panic on asymmetric systems.
- [High] arm_brbe_snapshot_branch_stack destructively clears the hardware branch buffer, corrupting data for concurrent perf sessions.
- [High] A TOCTOU race can unintentionally re-enable BRBE after it was explicitly disabled by a PMU interrupt, corrupting hardware state.
- [Medium] Missing isb() context synchronization after unpausing BRBE causes missed branch records.
--

commit ce06705327b522bc73c923ff4219c198fe71f3b4
Author: Puranjay Mohan <puranjay@kernel.org>
Subject: 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, masks
exceptions, reads branch records, and then invalidates the buffer.

> diff --git a/drivers/perf/arm_brbe.c b/drivers/perf/arm_brbe.c
> index ba554e0c846c4..fd62019ddc839 100644
> --- a/drivers/perf/arm_brbe.c
> +++ b/drivers/perf/arm_brbe.c

[ ... ]

> +/*
> + * 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;
> +
> +	/*
> +	 * 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);

On asymmetric systems (like big.LITTLE) where only a subset of CPU cores
implement BRBE, the perf_snapshot_branch_stack static call is enabled
globally. If a BPF program invokes this snapshot on a CPU lacking BRBE,
will this unconditionally execute read_sysreg_s(SYS_BRBFCR_EL1) and
trigger an Undefined Instruction exception kernel panic?

Does this need a local CPU feature check before accessing these registers?

> +	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;
> +	}
> +
> +	/* Block local exception delivery while reading the buffer. */
> +	flags = local_daif_save();
> +
> +	/*
> +	 * 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)) {

Can a TOCTOU race unintentionally re-enable BRBE if a PMU interrupt fires
before exceptions are masked?

If the PMU overflow interrupt decides to stop the event, it calls
brbe_disable(), which sets SYS_BRBCR_EL1 to 0 and sets the PAUSED bit in
SYS_BRBFCR_EL1.

Upon returning from the interrupt, the PAUSED bit would still be set, so
this check evaluates to false and proceeds. At the end of the function,
the cached brbcr (which was > 0) and brbfcr are written back, which would
unintentionally re-enable BRBE in hardware without an active perf event.

> +		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();

Does calling brbe_invalidate() here destructively clear the hardware branch
buffer?

Since BPF branch snapshots are intended to be non-destructive observations,
wiping out the hardware branch buffer could permanently destroy the branch
history for a concurrently active perf session.

> +
> +	/* Restore BRBCR before unpausing via BRBFCR, matching brbe_enable(). */
> +	write_sysreg_s(brbcr, SYS_BRBCR_EL1);
> +	isb();
> +	write_sysreg_s(brbfcr, SYS_BRBFCR_EL1);

Is an explicit isb() missing after writing to SYS_BRBFCR_EL1?

Since MSR instructions to system registers are not context synchronizing,
the processor may delay unpausing BRBE. Could this result in missed
branch records until the next context synchronization event naturally occurs?

> +	local_daif_restore(flags);
> +
> +	return nr_copied;
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260413185740.3286146-1-puranjay@kernel.org?part=3

  reply	other threads:[~2026-04-13 20:31 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-13 18:57 [PATCH v3 0/4] arm64: Add BRBE support for bpf_get_branch_snapshot() Puranjay Mohan
2026-04-13 18:57 ` [PATCH v3 1/4] perf/core: Fix NULL pmu_ctx passed to PMU sched_task callback Puranjay Mohan
2026-04-13 19:31   ` sashiko-bot
2026-04-13 18:57 ` [PATCH v3 2/4] perf: Use a union to clear branch entry bitfields Puranjay Mohan
2026-04-13 19:46   ` sashiko-bot
2026-04-13 18:57 ` [PATCH v3 3/4] perf/arm64: Add BRBE support for bpf_get_branch_snapshot() Puranjay Mohan
2026-04-13 20:31   ` sashiko-bot [this message]
2026-04-13 18:57 ` [PATCH v3 4/4] selftests/bpf: Adjust wasted entries threshold for ARM64 BRBE 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=20260413203144.EA85BC2BCAF@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=puranjay@kernel.org \
    --cc=sashiko@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