On Wed, Jul 5, 2023 at 12:40 AM Peter Zijlstra peterz@infradead.org wrote:
On Sat, Jul 01, 2023 at 10:57:07PM -0400, guoren@kernel.org wrote:
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.
This doesn't explain much if anything :/
I'm confused (probably because I don't know RISC-V very well), what's EBREAK and how does it happen?
EBREAK is just an instruction of riscv which would rise breakpoint exception.
Specifically, if EBREAK can happen inside an local_irq_disable() region, then the below change is actively wrong. Any exception/interrupt that can happen while local_irq_disable() must be treated like an NMI.
When the ebreak happend out of local_irq_disable region, but __nmi_enter forces handle_break() into in_interupt() state. So how about:
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c index f910dfccbf5d..69f7043a98b9 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> @@ -285,12 +286,18 @@ asmlinkage __visible __trap_section void do_trap_break(struct pt_regs *regs) handle_break(regs);
irqentry_exit_to_user_mode(regs); - } else { + } else if (in_interrupt()){ irqentry_state_t state = irqentry_nmi_enter(regs);
handle_break(regs);
irqentry_nmi_exit(regs, state); + } else { + enum ctx_state prev_state = exception_enter(); + + handle_break(regs); + + exception_exit(prev_state); } }
If that makes kdb unhappy, fix kdb.
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); }
}
-- 2.36.1
-- Best Regards Guo Ren