[PATCH v7 0/3] perf/core: sched_task() dispatch and branch entry fixes

Puranjay Mohan posted 3 patches 1 month, 2 weeks ago
arch/x86/events/amd/brs.c   |  9 +++--
arch/x86/events/amd/lbr.c   | 16 ++++-----
arch/x86/events/intel/lbr.c | 65 ++++++++++++++++++++-----------------
drivers/perf/arm_brbe.c     |  2 +-
include/linux/perf_event.h  | 17 ----------
kernel/events/core.c        | 15 ++++++---
6 files changed, 58 insertions(+), 66 deletions(-)
[PATCH v7 0/3] perf/core: sched_task() dispatch and branch entry fixes
Posted by Puranjay Mohan 1 month, 2 weeks ago
These three fixes were found while adding BRBE support for
bpf_get_branch_snapshot() on arm64 and were carried in that series until
v6 [1]. They do not depend on it, so they go on their own; the version
number continues from that series to avoid two numbering schemes for the
same patches.

Patch 1 stops __perf_pmu_sched_task() passing a NULL pmu_ctx to
pmu->sched_task(). armv8pmu_sched_task() is the only implementation that
dereferences the argument, so the oops needs BRBE.

Patch 2 makes perf_pmu_sched_task() visit PMUs whose events are all
CPU-wide. They are skipped today on every switch to a task that has a
perf context but no event on that PMU, so branch records leak across the
task boundary with perf record -b -a. intel_pmu_lbr_add() calls
perf_sched_cb_inc() unconditionally, so x86 LBR is affected the same way.

Patch 3 has each caller fill struct perf_branch_entry in one assignment
rather than clearing the bitfields first, and drops
perf_clear_branch_entry_bitfields(). The helper had drifted from the
struct: new_type and priv were never cleared, and arm_pmuv3.c allocates
the per-CPU branch stack with kmalloc().

Tested on a 128 CPU arm64 machine with BRBE. A WARN_ON_ONCE() at the gate
patch 2 adds to perf_ctx_sched_task_cb() fires within seconds of running
perf record -b -a alongside a task-bound event pinned to a different CPU.
Also built for x86, which patch 3 touches.

Changes in v7:
- Patch 1: pass &cpc->epc unconditionally. cpc->task_epc is NULL there
  both before and after patch 2, so the conditional was dead.
- Patch 2: gate perf_pmu_sched_task() on cpc->task_epc alone. It is
  never set without a task context scheduled in, so the cpuctx->task_ctx
  test was redundant and the two gates are now inverses.
- Patch 3: fill the entry at each site instead of renaming the helper,
  as suggested by Peter.
- Dropped the v6 review tags, all three patches changed.

Changes in v6:
- Split the sched_task() fix into patches 1 and 2; the NULL dereference
  and the missed dispatch are separate bugs with different reachability.
- Gate perf_ctx_sched_task_cb() on cpc->task_epc. v5 removed the early
  return in perf_pmu_sched_task() without it, so both paths ran for a
  task whose event for that PMU is pinned to another CPU. Caught by the
  WARN_ON_ONCE() described above.
- Tag patches 1 and 2 for stable.
- Send separately from the BRBE series, rebased onto tip perf/core.

[1] https://lore.kernel.org/all/20260616155716.2631508-1-puranjay@kernel.org/
v6: https://lore.kernel.org/bpf/20260806135224.3267890-1-puranjay@kernel.org/

Puranjay Mohan (3):
  perf/core: Fix NULL pmu_ctx passed to pmu->sched_task()
  perf/core: Run sched_task() for PMUs with only CPU-wide events
  perf/core: Fill branch entries with a single assignment

 arch/x86/events/amd/brs.c   |  9 +++--
 arch/x86/events/amd/lbr.c   | 16 ++++-----
 arch/x86/events/intel/lbr.c | 65 ++++++++++++++++++++-----------------
 drivers/perf/arm_brbe.c     |  2 +-
 include/linux/perf_event.h  | 17 ----------
 kernel/events/core.c        | 15 ++++++---
 6 files changed, 58 insertions(+), 66 deletions(-)

-- 
2.53.0-Meta
Re: [PATCH v7 0/3] perf/core: sched_task() dispatch and branch entry fixes
Posted by Peter Zijlstra 5 days, 21 hours ago
On Mon, Aug 10, 2026 at 06:35:33AM -0700, Puranjay Mohan wrote:

> Puranjay Mohan (3):
>   perf/core: Fix NULL pmu_ctx passed to pmu->sched_task()
>   perf/core: Run sched_task() for PMUs with only CPU-wide events
>   perf/core: Fill branch entries with a single assignment
> 
>  arch/x86/events/amd/brs.c   |  9 +++--
>  arch/x86/events/amd/lbr.c   | 16 ++++-----
>  arch/x86/events/intel/lbr.c | 65 ++++++++++++++++++++-----------------
>  drivers/perf/arm_brbe.c     |  2 +-
>  include/linux/perf_event.h  | 17 ----------
>  kernel/events/core.c        | 15 ++++++---
>  6 files changed, 58 insertions(+), 66 deletions(-)
> 

Found this series ... I'll feed it to the robots and barring them
screaming I'll push it out to -tip.
Re: [PATCH v7 0/3] perf/core: sched_task() dispatch and branch entry fixes
Posted by wuyifan 3 weeks, 4 days ago
Hi Puranjay,

On 8/10/2026 9:35 PM, Puranjay Mohan wrote:
> These three fixes were found while adding BRBE support for
> bpf_get_branch_snapshot() on arm64 and were carried in that series until
> v6 [1]. They do not depend on it, so they go on their own; the version
> number continues from that series to avoid two numbering schemes for the
> same patches.
perf record -C <cpu> -b [<command>] triggers a NULL pointer dereference
in armv8pmu_sched_task().

Commit fa9d27773873 ("perf: arm_pmu: Kill last use of per-CPU cpu_armpmu
pointer") changed armv8pmu_sched_task() from reading the per-CPU
cpu_armpmu variable to dereferencing pmu_ctx->pmu via
to_arm_pmu(pmu_ctx->pmu). Meanwhile, commit bd2756811766 ("perf:
Rewrite core context handling") made __perf_pmu_sched_task() pass
cpc->task_epc to pmu->sched_task(). cpc->task_epc is only non-NULL
while a task context is scheduled in; CPU-bound events do not schedule a
task context, so cpc->task_epc stays NULL. The NULL argument is dereferenced
and crashes.

With the patches applied, perf record -C <cpu> -b no longer crashes,
and system-wide perf record -b -e <event> -a alongside a task-bound event
on a different CPU runs without any WARN_ON.

Tested-by: Yifan Wu <wuyifan50@huawei.com>
Re: [PATCH v7 0/3] perf/core: sched_task() dispatch and branch entry fixes
Posted by Ian Rogers 1 week, 6 days ago
On Thu, Sep 3, 2026 at 7:45 PM wuyifan <wuyifan50@huawei.com> wrote:
>
> Hi Puranjay,
>
> On 8/10/2026 9:35 PM, Puranjay Mohan wrote:
> > These three fixes were found while adding BRBE support for
> > bpf_get_branch_snapshot() on arm64 and were carried in that series until
> > v6 [1]. They do not depend on it, so they go on their own; the version
> > number continues from that series to avoid two numbering schemes for the
> > same patches.
> perf record -C <cpu> -b [<command>] triggers a NULL pointer dereference
> in armv8pmu_sched_task().
>
> Commit fa9d27773873 ("perf: arm_pmu: Kill last use of per-CPU cpu_armpmu
> pointer") changed armv8pmu_sched_task() from reading the per-CPU
> cpu_armpmu variable to dereferencing pmu_ctx->pmu via
> to_arm_pmu(pmu_ctx->pmu). Meanwhile, commit bd2756811766 ("perf:
> Rewrite core context handling") made __perf_pmu_sched_task() pass
> cpc->task_epc to pmu->sched_task(). cpc->task_epc is only non-NULL
> while a task context is scheduled in; CPU-bound events do not schedule a
> task context, so cpc->task_epc stays NULL. The NULL argument is dereferenced
> and crashes.
>
> With the patches applied, perf record -C <cpu> -b no longer crashes,
> and system-wide perf record -b -e <event> -a alongside a task-bound event
> on a different CPU runs without any WARN_ON.
>
> Tested-by: Yifan Wu <wuyifan50@huawei.com>

Hi,

Is there anything that needs doing to land this series? Avoiding a
perf crash seems worthwhile. I believe Peter and Ingo are best placed
to review the changes to kernel/events/core.c.

Thanks,
Ian
Re: [PATCH v7 0/3] perf/core: sched_task() dispatch and branch entry fixes
Posted by Andrii Nakryiko 6 days, 11 hours ago
On Tue, Sep 15, 2026 at 3:47 PM Ian Rogers <irogers@google.com> wrote:
>
> On Thu, Sep 3, 2026 at 7:45 PM wuyifan <wuyifan50@huawei.com> wrote:
> >
> > Hi Puranjay,
> >
> > On 8/10/2026 9:35 PM, Puranjay Mohan wrote:
> > > These three fixes were found while adding BRBE support for
> > > bpf_get_branch_snapshot() on arm64 and were carried in that series until
> > > v6 [1]. They do not depend on it, so they go on their own; the version
> > > number continues from that series to avoid two numbering schemes for the
> > > same patches.
> > perf record -C <cpu> -b [<command>] triggers a NULL pointer dereference
> > in armv8pmu_sched_task().
> >
> > Commit fa9d27773873 ("perf: arm_pmu: Kill last use of per-CPU cpu_armpmu
> > pointer") changed armv8pmu_sched_task() from reading the per-CPU
> > cpu_armpmu variable to dereferencing pmu_ctx->pmu via
> > to_arm_pmu(pmu_ctx->pmu). Meanwhile, commit bd2756811766 ("perf:
> > Rewrite core context handling") made __perf_pmu_sched_task() pass
> > cpc->task_epc to pmu->sched_task(). cpc->task_epc is only non-NULL
> > while a task context is scheduled in; CPU-bound events do not schedule a
> > task context, so cpc->task_epc stays NULL. The NULL argument is dereferenced
> > and crashes.
> >
> > With the patches applied, perf record -C <cpu> -b no longer crashes,
> > and system-wide perf record -b -e <event> -a alongside a task-bound event
> > on a different CPU runs without any WARN_ON.
> >
> > Tested-by: Yifan Wu <wuyifan50@huawei.com>
>
> Hi,
>
> Is there anything that needs doing to land this series? Avoiding a
> perf crash seems worthwhile. I believe Peter and Ingo are best placed
> to review the changes to kernel/events/core.c.
>

another ping... seems like worthwhile problems to fix

> Thanks,
> Ian
>