summaryrefslogtreecommitdiffstats
path: root/arch/blackfin/mach-common/entry.S
diff options
context:
space:
mode:
authorSonic Zhang2008-07-26 12:54:38 +0200
committerBryan Wu2008-07-26 12:54:38 +0200
commit0d1cdd7ab6e0e7ccaf9f3b1d2afa0ddeead23ccc (patch)
treeb9afaa46540a46be141f84aa286acd0dc7f4e65c /arch/blackfin/mach-common/entry.S
parentBlackfin arch: cache the values of vco/sclk/cclk as the overhead of doing so ... (diff)
downloadkernel-qcow2-linux-0d1cdd7ab6e0e7ccaf9f3b1d2afa0ddeead23ccc.tar.gz
kernel-qcow2-linux-0d1cdd7ab6e0e7ccaf9f3b1d2afa0ddeead23ccc.tar.xz
kernel-qcow2-linux-0d1cdd7ab6e0e7ccaf9f3b1d2afa0ddeead23ccc.zip
Blackfin arch: Fix bug - skip single step in high priority interrupt 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>
Diffstat (limited to 'arch/blackfin/mach-common/entry.S')
-rw-r--r--arch/blackfin/mach-common/entry.S50
1 files changed, 38 insertions, 12 deletions
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index 038f70e0be65..eceb484d90f9 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -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
@@ -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)