Skip to content

Commit

Permalink
Blackfin arch: Fix bug - skip single step in high priority interrupt …
Browse files Browse the repository at this point in the history
…handler instead of disabling all interrupts in single step debugging.

Skip single step if event priority of current instruction is higher than
that of the first instruction, from which gdb starts single step.

Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
  • Loading branch information
Sonic Zhang authored and Bryan Wu committed Jul 26, 2008
1 parent 3a2521f commit 0d1cdd7
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 13 deletions.
16 changes: 15 additions & 1 deletion arch/blackfin/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ struct hw_breakpoint {

int kgdb_arch_init(void)
{
debugger_step = 0;

kgdb_remove_all_hw_break();
return 0;
}
Expand Down Expand Up @@ -368,6 +370,7 @@ int kgdb_arch_handle_exception(int exceptionVector, int signo,
char *ptr;
int newPC;
int wp_status;
int i;

switch (remcom_in_buffer[0]) {
case 'c':
Expand All @@ -392,7 +395,18 @@ int kgdb_arch_handle_exception(int exceptionVector, int signo,
/* set the trace bit if we're stepping */
if (remcom_in_buffer[0] == 's') {
linux_regs->syscfg |= 0x1;
debugger_step = 1;
debugger_step = linux_regs->ipend;
debugger_step >>= 6;
for (i = 10; i > 0; i--, debugger_step >>= 1)
if (debugger_step & 1)
break;
/* i indicate event priority of current stopped instruction
* user space instruction is 0, IVG15 is 1, IVTMR is 10.
* debugger_step > 0 means in single step mode
*/
debugger_step = i + 1;
} else {
debugger_step = 0;
}

wp_status = bfin_read_WPSTAT();
Expand Down
50 changes: 38 additions & 12 deletions arch/blackfin/mach-common/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -158,23 +158,45 @@ ENTRY(_ex_single_step)
cc = r7 == r6;
if cc jump _bfin_return_from_exception;

/* Don't do single step in hardware exception handler */
p5.l = lo(IPEND);
p5.h = hi(IPEND);
r6 = [p5];
cc = bittst(r6, 5);
if cc jump _bfin_return_from_exception;

#ifdef CONFIG_KGDB
/* skip single step if current interrupt priority is higher than
* that of the first instruction, from which gdb starts single step */
r6 >>= 6;
r7 = 10;
.Lfind_priority_start:
cc = bittst(r6, 0);
if cc jump .Lfind_priority_done;
r6 >>= 1;
r7 += -1;
cc = r7 == 0;
if cc jump .Lfind_priority_done;
jump.s .Lfind_priority_start;
.Lfind_priority_done:
p4.l = _debugger_step;
p4.h = _debugger_step;
r6 = [p4];
cc = r6 == 0;
if cc jump .Ldo_single_step;
r6 += -1;
cc = r6 < r7;
if cc jump _bfin_return_from_exception;
.Ldo_single_step:
#endif

/* If we were in user mode, do the single step normally. */
p5.l = lo(IPEND);
p5.h = hi(IPEND);
r6 = [p5];
r7 = 0xffe0 (z);
r7 = r7 & r6;
cc = r7 == 0;
if !cc jump 1f;

/* Single stepping only a single instruction, so clear the trace
* bit here. */
r7 = syscfg;
bitclr (r7, 0);
syscfg = R7;
jump _ex_trap_c;
if cc jump 1f;

1:
/*
* We were in an interrupt handler. By convention, all of them save
* SYSCFG with their first instruction, so by checking whether our
Expand Down Expand Up @@ -202,11 +224,15 @@ ENTRY(_ex_single_step)
cc = R7 == R6;
if !cc jump _bfin_return_from_exception;

1:
/* Single stepping only a single instruction, so clear the trace
* bit here. */
r7 = syscfg;
bitclr (r7, 0);
syscfg = R7;

/* Fall through to _bfin_return_from_exception. */
jump _ex_trap_c;

ENDPROC(_ex_single_step)

ENTRY(_bfin_return_from_exception)
Expand Down

0 comments on commit 0d1cdd7

Please sign in to comment.