[PATCH] arm64: kgdb: Fix interrupt-induced single-step exception
Mark Rutland
mark.rutland at arm.com
Tue Jun 16 05:54:33 PDT 2026
On Mon, Jun 15, 2026 at 01:29:03PM +0800, liuqiqi at kylinos.cn wrote:
> From: Qiqi Liu <liuqiqi at kylinos.cn>
>
> After entering kdb due to breakpoint, when we execute 'ss' or 'go'
> (will delay installing breakpoints, do single-step first),
> and it will enter kdb again.
> We found that due to context switching caused by interrupt,
> the instruction at ss is no longer the original breakpoint instruction.
>
> Before the patch:
> [root at localhost ~]# echo g > /proc/sysrq-trigger
> Entering kdb (current=0xffff030004f2bc00, pid 8818) on processor 15 due to Keyboard Entry
> [15]kdb> bp sysctl_vm_numa_stat_handler
> Instruction(i) BP #0 at 0xffffae550650c810 (sysctl_vm_numa_stat_handler)
> is enabled addr at 0xffffae550650c810, hardtype=0 installed=0
> [15]kdb> g
> [root at localhost ~]# echo 1 > /proc/sys/vm/numa_stat
> Entering kdb (current=0xffff030004f2bc00, pid 8818) on processor 12 due to Breakpoint @ 0xffffae550650c810
> [12]kdb> g
> Entering kdb (current=0xffff030004f2bc00, pid 8818) on processor 12 due to Breakpoint @ 0xffffae550650c810
> [12]kdb> g
>
> After the patch:
> [root at localhost ~]# echo g > /proc/sysrq-trigger
> Entering kdb (current=0xfffff010012c36400, pid 6488) on processor 41 due to Keyboard Entry
> [41]kdb> bp sysctl_vm_numa_stat_handler
> Instruction(i) BP #0 at 0xfffffd1768c2dc7c8 (sysctl_vm_numa_stat_handler)
> is enabled addr at ffffdf1768c2dc7c8, hardtype=0 installed=0
> [41]kdb> g
> [root at localhost ~]# echo 1 > /proc/sys/vm/numa_stat
> Entering kdb (current=0xfffff010012c36400, pid 6488) on processor 7 due to Breakpoint @ 0xfffffd1768c2dc7c8
> [7]kdb> g
> [root at localhost ~]#
>
> Fixes: 44679a4f142b ("arm64: KGDB: Add step debugging support")
> Co-developed-by: Tongbo Wei <kf.weitongbo at h3c.com>
> Signed-off-by: Tongbo Wei <kf.weitongbo at h3c.com>
> Signed-off-by: Qiqi Liu <liuqiqi at kylinos.cn>
> ---
> arch/arm64/kernel/kgdb.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
> index 968324a79a89..e9a246a0c34f 100644
> --- a/arch/arm64/kernel/kgdb.c
> +++ b/arch/arm64/kernel/kgdb.c
> @@ -101,6 +101,8 @@ struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
> { "fpcr", 4, -1 },
> };
>
> +static DEFINE_PER_CPU(unsigned int, kgdb_pstate);
> +
> char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
> {
> if (regno >= DBG_MAX_REG_NUM || regno < 0)
> @@ -207,6 +209,8 @@ int kgdb_arch_handle_exception(int exception_vector, int signo,
> err = 0;
> break;
> case 's':
> + __this_cpu_write(kgdb_pstate, linux_regs->pstate);
> + linux_regs->pstate |= PSR_I_BIT;
> /*
> * Update step address value with address passed
> * with step packet.
> @@ -252,9 +256,17 @@ NOKPROBE_SYMBOL(kgdb_compiled_brk_handler);
>
> int kgdb_single_step_handler(struct pt_regs *regs, unsigned long esr)
> {
> + unsigned int pstate;
> if (!kgdb_single_step)
> return DBG_HOOK_ERROR;
>
> + /* restore interrupt mask status */
> + pstate = __this_cpu_read(kgdb_pstate);
> + if (pstate & PSR_I_BIT)
> + regs->pstate |= PSR_I_BIT;
> + else
> + regs->pstate &= ~PSR_I_BIT;
I don't think this is sufficient; see the comments from last time this
approach was proposed:
https://lore.kernel.org/linux-arm-kernel/aNPiUbdRhaRklebF@J2N7QTR9R3/
I don't think we can solve this without enlightening the entry code.
Mark.
More information about the linux-arm-kernel
mailing list