This is easily triggered with: perf record -b -e cycles -a -- ls which crashes on the first context switch with: Unable to handle kernel NULL pointer dereference at virtual address 00[.] PC is at armv8pmu_sched_task+0x14/0x50 LR is at perf_pmu_sched_task+0xac/0x108 Call trace: armv8pmu_sched_task+0x14/0x50 (P) perf_pmu_sched_task+0xac/0x108 __perf_event_task_sched_out+0x6c/0xe0 prepare_task_switch+0x120/0x268 __schedule+0x1e8/0x828 ... perf_pmu_sched_task() invokes the PMU sched callback with cpc->task_epc, which is NULL when no per-task events exist for this PMU. With CPU-wide branch-stack events, armv8pmu_sched_task() is still registered and dereferences pmu_ctx->pmu unconditionally, causing the crash. The bug was introduced by commit fa9d27773873 ("perf: arm_pmu: Kill last use of per-CPU cpu_armpmu pointer") which changed the function from using the per-CPU cpu_armpmu pointer (always valid) to dereferencing pmu_ctx->pmu without adding a NULL check. Add a NULL check for pmu_ctx to avoid the crash. Fixes: fa9d27773873 ("perf: arm_pmu: Kill last use of per-CPU cpu_armpmu pointer") Signed-off-by: Puranjay Mohan --- drivers/perf/arm_pmuv3.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c index 8014ff766cff..2d097fad9c10 100644 --- a/drivers/perf/arm_pmuv3.c +++ b/drivers/perf/arm_pmuv3.c @@ -1074,8 +1074,15 @@ static int armv8pmu_user_event_idx(struct perf_event *event) static void armv8pmu_sched_task(struct perf_event_pmu_context *pmu_ctx, struct task_struct *task, bool sched_in) { - struct arm_pmu *armpmu = to_arm_pmu(pmu_ctx->pmu); - struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events); + struct arm_pmu *armpmu; + struct pmu_hw_events *hw_events; + + /* cpc->task_epc is NULL when no per-task events exist for this PMU */ + if (!pmu_ctx) + return; + + armpmu = to_arm_pmu(pmu_ctx->pmu); + hw_events = this_cpu_ptr(armpmu->hw_events); if (!hw_events->branch_users) return; -- 2.52.0