From: Guo Ren guoren@linux.alibaba.com
The irqentry_nmi_enter/exit would force the current context into in_interrupt. That would trigger the kernel to dead panic, but the kdb still needs "ebreak" to debug the kernel.
Move irqentry_nmi_enter/exit to exception_enter/exit could correct handle_break of the kernel side.
Before the fixup: $echo BUG > /sys/kernel/debug/provoke-crash/DIRECT lkdtm: Performing direct entry BUG ------------[ cut here ]------------ kernel BUG at drivers/misc/lkdtm/bugs.c:78! handle_break, 256. Kernel BUG [#1] Modules linked in: CPU: 0 PID: 104 Comm: echo Not tainted 6.4.0-rc1-00055-g0ca05a4b079f-dirty #30 Hardware name: riscv-virtio,qemu (DT) epc : lkdtm_BUG+0x6/0x8 ra : lkdtm_do_action+0x14/0x1c epc : ffffffff8055c730 ra : ffffffff8087e188 sp : ff200000007dbd40 gp : ffffffff81500878 tp : ff600000028ebac0 t0 : 6500000000000000 t1 : 000000000000006c t2 : 6550203a6d74646b s0 : ff200000007dbd50 s1 : ffffffff814bfc80 a0 : ffffffff814bfc80 a1 : ff6000001ffd8608 a2 : ff6000001ffdb870 a3 : 0000000000000000 a4 : 0000000000000000 a5 : ffffffff8055c72a a6 : 0000000000000032 a7 : 0000000000000038 s2 : 0000000000000004 s3 : 00000000556371a0 s4 : ff200000007dbe70 s5 : ff60000002090000 s6 : 00000000556371a0 s7 : 0000000000000030 s8 : 000000007fffec78 s9 : 0000000000000007 s10: 0000000055637530 s11: 0000000000000001 t3 : ffffffff81513ed7 t4 : ffffffff81513ed7 t5 : ffffffff81513ed8 t6 : ff200000007dbb88 status: 0000000100000120 badaddr: 0000000000000000 cause: 0000000000000003 [<ffffffff8055c730>] lkdtm_BUG+0x6/0x8 Code: 0513 6b05 b097 0031 80e7 e960 b705 1141 e422 0800 (9002) 1141 ---[ end trace 0000000000000000 ]--- Kernel panic - not syncing: Aiee, killing interrupt handler! ---[ end Kernel panic - not syncing: Aiee, killing interrupt handler! ]---
(Dead in the kernel side.)
After the fixup: $echo BUG > /sys/kernel/debug/provoke-crash/DIRECT lkdtm: Performing direct entry BUG ------------[ cut here ]------------ kernel BUG at drivers/misc/lkdtm/bugs.c:78! Kernel BUG [#13] Modules linked in: CPU: 0 PID: 129 Comm: echo Tainted: G D 6.4.0-rc1-00055-g0ca05a4b079f-dirty #34 Hardware name: riscv-virtio,qemu (DT) epc : lkdtm_BUG+0x6/0x8 ra : lkdtm_do_action+0x14/0x1c epc : ffffffff8055c71c ra : ffffffff8087e170 sp : ff200000007e3d40 gp : ffffffff81500878 tp : ff600000028ebac0 t0 : 6500000000000000 t1 : 000000000000006c t2 : 6550203a6d74646b s0 : ff200000007e3d50 s1 : ffffffff814bfc80 a0 : ffffffff814bfc80 a1 : ff6000001ffd8608 a2 : ff6000001ffdb870 a3 : 0000000000000000 a4 : 0000000000000000 a5 : ffffffff8055c716 a6 : 0000000000000032 a7 : 0000000000000038 s2 : 0000000000000004 s3 : 00000000556371a0 s4 : ff200000007e3e70 s5 : ff60000002090000 s6 : 00000000556371a0 s7 : 0000000000000030 s8 : 000000007fffec78 s9 : 0000000000000007 s10: 0000000055637530 s11: 0000000000000001 t3 : ffffffff81513ed7 t4 : ffffffff81513ed7 t5 : ffffffff81513ed8 t6 : ff200000007e3b88 status: 0000000100000120 badaddr: 0000000000000000 cause: 0000000000000003 [<ffffffff8055c71c>] lkdtm_BUG+0x6/0x8 Code: 0513 6945 b097 0031 80e7 e920 b705 1141 e422 0800 (9002) 1141 ---[ end trace 0000000000000000 ]--- note: echo[129] exited with irqs disabled Segmentation fault
(Resume to the shell normally.)
Fixes: f0bddf50586d ("riscv: entry: Convert to generic entry") Reported-by: Daniel Thompson daniel.thompson@linaro.org Signed-off-by: Guo Ren guoren@linux.alibaba.com Signed-off-by: Guo Ren guoren@kernel.org Cc: stable@vger.kernel.org --- arch/riscv/kernel/traps.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c index efc6b649985a..ed0eb9452f9e 100644 --- a/arch/riscv/kernel/traps.c +++ b/arch/riscv/kernel/traps.c @@ -18,6 +18,7 @@ #include <linux/irq.h> #include <linux/kexec.h> #include <linux/entry-common.h> +#include <linux/context_tracking.h>
#include <asm/asm-prototypes.h> #include <asm/bug.h> @@ -257,11 +258,11 @@ asmlinkage __visible __trap_section void do_trap_break(struct pt_regs *regs)
irqentry_exit_to_user_mode(regs); } else { - irqentry_state_t state = irqentry_nmi_enter(regs); + enum ctx_state prev_state = exception_enter();
handle_break(regs);
- irqentry_nmi_exit(regs, state); + exception_exit(prev_state); } }