[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