| From 6f44a0bacb79a03972c83759711832b382b1b8ac Mon Sep 17 00:00:00 2001 |
| From: Qiao Zhou <qiaozhou@asrmicro.com> |
| Date: Fri, 7 Jul 2017 17:29:34 +0800 |
| Subject: arm64: traps: disable irq in die() |
| |
| From: Qiao Zhou <qiaozhou@asrmicro.com> |
| |
| commit 6f44a0bacb79a03972c83759711832b382b1b8ac upstream. |
| |
| In current die(), the irq is disabled for __die() handle, not |
| including the possible panic() handling. Since the log in __die() |
| can take several hundreds ms, new irq might come and interrupt |
| current die(). |
| |
| If the process calling die() holds some critical resource, and some |
| other process scheduled later also needs it, then it would deadlock. |
| The first panic will not be executed. |
| |
| So here disable irq for the whole flow of die(). |
| |
| Signed-off-by: Qiao Zhou <qiaozhou@asrmicro.com> |
| Signed-off-by: Will Deacon <will.deacon@arm.com> |
| Signed-off-by: Arnd Bergmann <arnd@arndb.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/arm64/kernel/traps.c | 8 ++++++-- |
| 1 file changed, 6 insertions(+), 2 deletions(-) |
| |
| --- a/arch/arm64/kernel/traps.c |
| +++ b/arch/arm64/kernel/traps.c |
| @@ -266,10 +266,12 @@ void die(const char *str, struct pt_regs |
| { |
| struct thread_info *thread = current_thread_info(); |
| int ret; |
| + unsigned long flags; |
| + |
| + raw_spin_lock_irqsave(&die_lock, flags); |
| |
| oops_enter(); |
| |
| - raw_spin_lock_irq(&die_lock); |
| console_verbose(); |
| bust_spinlocks(1); |
| ret = __die(str, err, thread, regs); |
| @@ -279,13 +281,15 @@ void die(const char *str, struct pt_regs |
| |
| bust_spinlocks(0); |
| add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); |
| - raw_spin_unlock_irq(&die_lock); |
| oops_exit(); |
| |
| if (in_interrupt()) |
| panic("Fatal exception in interrupt"); |
| if (panic_on_oops) |
| panic("Fatal exception"); |
| + |
| + raw_spin_unlock_irqrestore(&die_lock, flags); |
| + |
| if (ret != NOTIFY_STOP) |
| do_exit(SIGSEGV); |
| } |