Skip to content

Commit 969f028

Browse files
covanampalmer-dabbelt
authored andcommitted
riscv: Enable interrupt during exception handling
force_sig_fault() takes a spinlock, which is a sleeping lock with CONFIG_PREEMPT_RT=y. However, exception handling calls force_sig_fault() with interrupt disabled, causing a sleeping in atomic context warning. This can be reproduced using userspace programs such as: int main() { asm ("ebreak"); } or int main() { asm ("unimp"); } There is no reason that interrupt must be disabled while handling exceptions from userspace. Enable interrupt while handling user exceptions. This also has the added benefit of avoiding unnecessary delays in interrupt handling. Fixes: f0bddf5 ("riscv: entry: Convert to generic entry") Suggested-by: Sebastian Andrzej Siewior <[email protected]> Signed-off-by: Nam Cao <[email protected]> Reviewed-by: Alexandre Ghiti <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent e3f16d6 commit 969f028

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

arch/riscv/kernel/traps.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/cpu.h>
77
#include <linux/kernel.h>
88
#include <linux/init.h>
9+
#include <linux/irqflags.h>
910
#include <linux/randomize_kstack.h>
1011
#include <linux/sched.h>
1112
#include <linux/sched/debug.h>
@@ -151,7 +152,9 @@ asmlinkage __visible __trap_section void name(struct pt_regs *regs) \
151152
{ \
152153
if (user_mode(regs)) { \
153154
irqentry_enter_from_user_mode(regs); \
155+
local_irq_enable(); \
154156
do_trap_error(regs, signo, code, regs->epc, "Oops - " str); \
157+
local_irq_disable(); \
155158
irqentry_exit_to_user_mode(regs); \
156159
} else { \
157160
irqentry_state_t state = irqentry_nmi_enter(regs); \
@@ -173,17 +176,14 @@ asmlinkage __visible __trap_section void do_trap_insn_illegal(struct pt_regs *re
173176

174177
if (user_mode(regs)) {
175178
irqentry_enter_from_user_mode(regs);
176-
177179
local_irq_enable();
178180

179181
handled = riscv_v_first_use_handler(regs);
180-
181-
local_irq_disable();
182-
183182
if (!handled)
184183
do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->epc,
185184
"Oops - illegal instruction");
186185

186+
local_irq_disable();
187187
irqentry_exit_to_user_mode(regs);
188188
} else {
189189
irqentry_state_t state = irqentry_nmi_enter(regs);
@@ -308,9 +308,11 @@ asmlinkage __visible __trap_section void do_trap_break(struct pt_regs *regs)
308308
{
309309
if (user_mode(regs)) {
310310
irqentry_enter_from_user_mode(regs);
311+
local_irq_enable();
311312

312313
handle_break(regs);
313314

315+
local_irq_disable();
314316
irqentry_exit_to_user_mode(regs);
315317
} else {
316318
irqentry_state_t state = irqentry_nmi_enter(regs);

0 commit comments

Comments
 (0)