ARM PMU interrupt is not threaded and we run all handlers with interrupts disabled, but irq_work_run() would be called at the end of the interrupt handler, so below warning would be triggered by the sleeppable spin_lock when run 'perf top' command: BUG: sleeping function called from invalid context at linux/kernel/rtmutex.c:658 in_atomic(): 1, irqs_disabled(): 128, pid: 1731, name: perf [<80017d6c>] (unwind_backtrace+0x0/0x104) from [<806416c4>] (dump_stack+0x20/0x24) [<806416c4>] (dump_stack+0x20/0x24) from [<80061208>] (__might_sleep+0xf4/0x108) [<80061208>] (__might_sleep+0xf4/0x108) from [<8064a74c>] (rt_spin_lock+0x2c/0x38) [<8064a74c>] (rt_spin_lock+0x2c/0x38) from [<800642e8>] (__wake_up+0x34/0x60) [<800642e8>] (__wake_up+0x34/0x60) from [<800e2610>] (perf_event_wakeup+0x40/0x84) [<800e2610>] (perf_event_wakeup+0x40/0x84) from [<800e2690>] (perf_pending_event+0x3c/0x60) [<800e2690>] (perf_pending_event+0x3c/0x60) from [<800dd36c>] (irq_work_run+0x74/0xa4) [<800dd36c>] (irq_work_run+0x74/0xa4) from [<8001b018>] (armv7pmu_handle_irq+0x12c/0x19c) [<8001b018>] (armv7pmu_handle_irq+0x12c/0x19c) from [<800a87b0>] (handle_irq_event_percpu+0xf0/0x438) [<800a87b0>] (handle_irq_event_percpu+0xf0/0x438) from [<800a8b70>] (handle_irq_event+0x78/0xa0) [<800a8b70>] (handle_irq_event+0x78/0xa0) from [<800abdac>] (handle_fasteoi_irq+0xd4/0x18c) [<800abdac>] (handle_fasteoi_irq+0xd4/0x18c) from [<800a7e70>] (generic_handle_irq+0x40/0x50) [<800a7e70>] (generic_handle_irq+0x40/0x50) from [<8000f7a4>] (handle_IRQ+0x68/0xbc) [<8000f7a4>] (handle_IRQ+0x68/0xbc) from [<800084e8>] (gic_handle_irq+0x38/0x68) [<800084e8>] (gic_handle_irq+0x38/0x68) from [<8064b100>] (__irq_svc+0x40/0x70)
Inspired by upstream(git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git) commit 8baf86762 "x86-no-perf-irq-work-rt.patch", we can run the irq-work under softirq context in rt kernel to resolve this problem. Signed-off-by: Xufeng Zhang <[email protected]> --- arch/arm/kernel/perf_event_v6.c | 2 ++ arch/arm/kernel/perf_event_v7.c | 2 ++ arch/arm/kernel/perf_event_xscale.c | 4 ++++ 3 files changed, 8 insertions(+), 0 deletions(-) diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c index b78af0c..b432a65 100644 --- a/arch/arm/kernel/perf_event_v6.c +++ b/arch/arm/kernel/perf_event_v6.c @@ -524,7 +524,9 @@ armv6pmu_handle_irq(int irq_num, * platforms that can have the PMU interrupts raised as an NMI, this * will not work. */ +#ifndef CONFIG_PREEMPT_RT_FULL irq_work_run(); +#endif return IRQ_HANDLED; } diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 00755d8..4331eab 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -1112,7 +1112,9 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) * platforms that can have the PMU interrupts raised as an NMI, this * will not work. */ +#ifndef CONFIG_PREEMPT_RT_FULL irq_work_run(); +#endif return IRQ_HANDLED; } diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c index 71a21e6..9bb9a0f 100644 --- a/arch/arm/kernel/perf_event_xscale.c +++ b/arch/arm/kernel/perf_event_xscale.c @@ -271,7 +271,9 @@ xscale1pmu_handle_irq(int irq_num, void *dev) cpu_pmu->disable(hwc, idx); } +#ifndef CONFIG_PREEMPT_RT_FULL irq_work_run(); +#endif /* * Re-enable the PMU. @@ -611,7 +613,9 @@ xscale2pmu_handle_irq(int irq_num, void *dev) cpu_pmu->disable(hwc, idx); } +#ifndef CONFIG_PREEMPT_RT_FULL irq_work_run(); +#endif /* * Re-enable the PMU. -- 1.7.1 _______________________________________________ linux-yocto mailing list [email protected] https://lists.yoctoproject.org/listinfo/linux-yocto
