| From b4c89f202789d2e6ba93287ab91270e1c26c7d5f Mon Sep 17 00:00:00 2001 |
| From: Vincent Chen <vincent.chen@sifive.com> |
| Date: Mon, 16 Sep 2019 16:47:41 +0800 |
| Subject: [PATCH] riscv: Avoid interrupts being erroneously enabled in |
| handle_exception() |
| |
| commit c82dd6d078a2bb29d41eda032bb96d05699a524d upstream. |
| |
| When the handle_exception function addresses an exception, the interrupts |
| will be unconditionally enabled after finishing the context save. However, |
| It may erroneously enable the interrupts if the interrupts are disabled |
| before entering the handle_exception. |
| |
| For example, one of the WARN_ON() condition is satisfied in the scheduling |
| where the interrupt is disabled and rq.lock is locked. The WARN_ON will |
| trigger a break exception and the handle_exception function will enable the |
| interrupts before entering do_trap_break function. During the procedure, if |
| a timer interrupt is pending, it will be taken when interrupts are enabled. |
| In this case, it may cause a deadlock problem if the rq.lock is locked |
| again in the timer ISR. |
| |
| Hence, the handle_exception() can only enable interrupts when the state of |
| sstatus.SPIE is 1. |
| |
| This patch is tested on HiFive Unleashed board. |
| |
| Signed-off-by: Vincent Chen <vincent.chen@sifive.com> |
| Reviewed-by: Palmer Dabbelt <palmer@sifive.com> |
| [paul.walmsley@sifive.com: updated to apply] |
| Fixes: bcae803a21317 ("RISC-V: Enable IRQ during exception handling") |
| Cc: David Abdurachmanov <david.abdurachmanov@sifive.com> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Paul Walmsley <paul.walmsley@sifive.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S |
| index bc7a56e1ca6f..9b60878a4469 100644 |
| --- a/arch/riscv/kernel/entry.S |
| +++ b/arch/riscv/kernel/entry.S |
| @@ -166,9 +166,13 @@ ENTRY(handle_exception) |
| move a0, sp /* pt_regs */ |
| tail do_IRQ |
| 1: |
| - /* Exceptions run with interrupts enabled */ |
| + /* Exceptions run with interrupts enabled or disabled |
| + depending on the state of sstatus.SR_SPIE */ |
| + andi t0, s1, SR_SPIE |
| + beqz t0, 1f |
| csrs sstatus, SR_SIE |
| |
| +1: |
| /* Handle syscalls */ |
| li t0, EXC_SYSCALL |
| beq s4, t0, handle_syscall |
| -- |
| 2.7.4 |
| |