On 16/06/2026 16:57, Puranjay Mohan wrote:
> perf_pmu_sched_task() returns early when cpuctx->task_ctx is non-NULL,
> deferring to perf_ctx_sched_task_cb() in the context sched_in/out
> paths. But perf_ctx_sched_task_cb() only walks the task context's
> pmu_ctx_list -- PMUs that have only CPU-wide events are not on that
> list and their sched_task callback is silently skipped.
>
> On ARM64 with CPU-wide branch recording:
>
> perf record -b -e cycles -a -- ls
>
> armv8pmu_sched_task() is skipped whenever the scheduled task has an
> unrelated perf event (e.g. a software event), and branch records leak
> across task boundaries.
>
> A second problem exists in __perf_pmu_sched_task(): it passes
> cpc->task_epc directly to pmu->sched_task(), but task_epc is NULL for
> PMUs with only CPU-wide events. When perf_pmu_sched_task() does reach
> the loop (because cpuctx->task_ctx is NULL), this causes a NULL
> pointer dereference:
>
> Unable to handle kernel NULL pointer dereference at virtual address 00[.]
> PC is at armv8pmu_sched_task+0x14/0x50
> Call trace:
> armv8pmu_sched_task+0x14/0x50 (P)
> perf_pmu_sched_task+0xac/0x108
> __perf_event_task_sched_out+0x6c/0xe0
>
> Fix both:
>
> - Remove the blanket early return in perf_pmu_sched_task() when
> cpuctx->task_ctx is set. Instead, skip individual CPCs that have a
> task_epc (those are handled by perf_ctx_sched_task_cb()). CPCs
> without a task_epc are CPU-only and must be handled here.
>
> - Fall back to &cpc->epc in __perf_pmu_sched_task() when task_epc is
> NULL, so the callback always gets a valid pmu_ctx.
>
> Fixes: bd2756811766 ("perf: Rewrite core context handling")
> Signed-off-by: Puranjay Mohan <[email protected]>
> ---
> kernel/events/core.c | 17 +++++++++++++----
> 1 file changed, 13 insertions(+), 4 deletions(-)
>
Acked-by: Usama Arif <[email protected]>