[RFC PATCH 2/2] Aarch64: KGDB: Add Step debugging support
Sandeepa Prabhu
sandeepa.prabhu at linaro.org
Mon Sep 16 09:06:52 EDT 2013
On 16 September 2013 17:00, Will Deacon <will.deacon at arm.com> wrote:
> 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));
I think right way to update step address would be update
instruction_pointer(regs) from your kgdb handler and "kernel_exit"
should take care of rest. With this, you don't need to change the low
level handlers in entry.S/debug-monitors.c) at all.
>> + 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