[RFC PATCH 2/2] Aarch64: KGDB: Add Step debugging support

Will Deacon will.deacon at arm.com
Mon Sep 16 07:30:56 EDT 2013


On Mon, Sep 16, 2013 at 09:55:50AM +0100, vijay.kilari at gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar at caviumnetworks.com>
> 
> Add KGDB software step debugging support for EL1 debug
> in Aarch64 mode.
> 
> KGDB registers step debug handler with debug monitor.
> On receiving 'step' command from GDB tool, target enables
> software step debugging and step address is written to ELR
> register. If not step address is received from GDB tool,
> target assumes next step address is PC and ERET is
> executed as part of exception return.
> 
> ELR register content is protected against context restore in
> exception return by checking against Software Step debug
> bit MDSCR.SS
> 
> Software Step debugging is disabled when 'continue' command
> is received
> 
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar at caviumnetworks.com>
> ---
>  arch/arm64/include/asm/debug-monitors.h |    3 +++
>  arch/arm64/kernel/debug-monitors.c      |   15 +++++++++++++
>  arch/arm64/kernel/entry.S               |    9 +++++++-
>  arch/arm64/kernel/kgdb.c                |   36 +++++++++++++++++++++++++++++++
>  4 files changed, 62 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
> index aff3a76..3e4ac0d 100644
> --- a/arch/arm64/include/asm/debug-monitors.h
> +++ b/arch/arm64/include/asm/debug-monitors.h
> @@ -94,6 +94,9 @@ void kernel_enable_single_step(struct pt_regs *regs);
>  void kernel_disable_single_step(void);
>  int kernel_active_single_step(void);
>  
> +void elr_write(unsigned long elr);
> +unsigned long elr_read(void);
> +
>  #ifdef CONFIG_HAVE_HW_BREAKPOINT
>  int reinstall_suspended_bps(struct pt_regs *regs);
>  #else
> diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
> index f8b90c0..0408490 100644
> --- a/arch/arm64/kernel/debug-monitors.c
> +++ b/arch/arm64/kernel/debug-monitors.c
> @@ -64,6 +64,21 @@ static u32 mdscr_read(void)
>  	return mdscr;
>  }
>  
> +void elr_write(unsigned long elr)
> +{
> +	unsigned long flags;
> +	local_dbg_save(flags);
> +	asm volatile("msr elr_el1, %0" :: "r" (elr));
> +	local_dbg_restore(flags);
> +}
> +
> +unsigned long elr_read(void)
> +{
> +	unsigned long elr;
> +	asm volatile("mrs %0, elr_el1" : "=r" (elr));
> +	return elr;
> +}

What?! Why are you writing the ELR here, instead of setting up the pc in
current saved regs?

> +
>  /*
>   * Allow root to disable self-hosted debug from userspace.
>   * This is useful if you want to connect an external JTAG debugger.
> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
> index 226be77..23d91f1 100644
> --- a/arch/arm64/kernel/entry.S
> +++ b/arch/arm64/kernel/entry.S
> @@ -100,7 +100,14 @@
>  	pop	x4, x5
>  	pop	x6, x7
>  	pop	x8, x9
> -	msr	elr_el1, x21			// set up the return data
> +	.if     \el == 1
> +	mrs     x10, mdscr_el1			// check if step debug is enabled
> +	tbnz    x10, #0, 1f
> +	msr     elr_el1, x21
> +	.else
> +	msr     elr_el1, x21			// set up the return data
> +	.endif
> +1:

This is horrible -- if the pt_regs being restored was set up correctly,
you wouldn't need the conditional code.

>  	msr	spsr_el1, x22
>  	.if	\el == 0
>  	msr	sp_el0, x23
> diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
> index a3a7712..d5e5884 100644
> --- a/arch/arm64/kernel/kgdb.c
> +++ b/arch/arm64/kernel/kgdb.c
> @@ -164,9 +164,31 @@ int kgdb_arch_handle_exception(int exception_vector, int signo, int err_code,
>  			linux_regs->pc += 4;
>  
>  		compiled_break = 0;
> +
> +		/* Disable single step if enabled */
> +		if (kernel_active_single_step())
> +			kernel_disable_single_step();
> +
>  		err = 0;
>  		break;
> +	case 's':
> +		/* 
> +		 * Update ESR value with step address passed
> +		 */

Well, the comment is wrong, but I don't think you should be doing this anyway :)

Will



More information about the linux-arm-kernel mailing list