aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSonic Zhang <sonic.zhang@analog.com>2008-07-26 06:54:38 -0400
committerBryan Wu <cooloney@kernel.org>2008-07-26 06:54:38 -0400
commit0d1cdd7ab6e0e7ccaf9f3b1d2afa0ddeead23ccc (patch)
treeb9afaa46540a46be141f84aa286acd0dc7f4e65c
parent3a2521fa75359450f5ec7e6b76847f933b7ee680 (diff)
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>
-rw-r--r--arch/blackfin/kernel/kgdb.c16
-rw-r--r--arch/blackfin/mach-common/entry.S50
2 files changed, 53 insertions, 13 deletions
diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c
index a9c15515bfd7..a1f9641a6425 100644
--- a/arch/blackfin/kernel/kgdb.c
+++ b/arch/blackfin/kernel/kgdb.c
@@ -203,6 +203,8 @@ struct hw_breakpoint {
203 203
204int kgdb_arch_init(void) 204int kgdb_arch_init(void)
205{ 205{
206 debugger_step = 0;
207
206 kgdb_remove_all_hw_break(); 208 kgdb_remove_all_hw_break();
207 return 0; 209 return 0;
208} 210}
@@ -368,6 +370,7 @@ int kgdb_arch_handle_exception(int exceptionVector, int signo,
368 char *ptr; 370 char *ptr;
369 int newPC; 371 int newPC;
370 int wp_status; 372 int wp_status;
373 int i;
371 374
372 switch (remcom_in_buffer[0]) { 375 switch (remcom_in_buffer[0]) {
373 case 'c': 376 case 'c':
@@ -392,7 +395,18 @@ int kgdb_arch_handle_exception(int exceptionVector, int signo,
392 /* set the trace bit if we're stepping */ 395 /* set the trace bit if we're stepping */
393 if (remcom_in_buffer[0] == 's') { 396 if (remcom_in_buffer[0] == 's') {
394 linux_regs->syscfg |= 0x1; 397 linux_regs->syscfg |= 0x1;
395 debugger_step = 1; 398 debugger_step = linux_regs->ipend;
399 debugger_step >>= 6;
400 for (i = 10; i > 0; i--, debugger_step >>= 1)
401 if (debugger_step & 1)
402 break;
403 /* i indicate event priority of current stopped instruction
404 * user space instruction is 0, IVG15 is 1, IVTMR is 10.
405 * debugger_step > 0 means in single step mode
406 */
407 debugger_step = i + 1;
408 } else {
409 debugger_step = 0;
396 } 410 }
397 411
398 wp_status = bfin_read_WPSTAT(); 412 wp_status = bfin_read_WPSTAT();
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)
158 cc = r7 == r6; 158 cc = r7 == r6;
159 if cc jump _bfin_return_from_exception; 159 if cc jump _bfin_return_from_exception;
160 160
161 /* Don't do single step in hardware exception handler */
162 p5.l = lo(IPEND);
163 p5.h = hi(IPEND);
164 r6 = [p5];
165 cc = bittst(r6, 5);
166 if cc jump _bfin_return_from_exception;
167
168#ifdef CONFIG_KGDB
169 /* skip single step if current interrupt priority is higher than
170 * that of the first instruction, from which gdb starts single step */
171 r6 >>= 6;
172 r7 = 10;
173.Lfind_priority_start:
174 cc = bittst(r6, 0);
175 if cc jump .Lfind_priority_done;
176 r6 >>= 1;
177 r7 += -1;
178 cc = r7 == 0;
179 if cc jump .Lfind_priority_done;
180 jump.s .Lfind_priority_start;
181.Lfind_priority_done:
182 p4.l = _debugger_step;
183 p4.h = _debugger_step;
184 r6 = [p4];
185 cc = r6 == 0;
186 if cc jump .Ldo_single_step;
187 r6 += -1;
188 cc = r6 < r7;
189 if cc jump _bfin_return_from_exception;
190.Ldo_single_step:
191#endif
192
161 /* If we were in user mode, do the single step normally. */ 193 /* If we were in user mode, do the single step normally. */
162 p5.l = lo(IPEND);
163 p5.h = hi(IPEND);
164 r6 = [p5]; 194 r6 = [p5];
165 r7 = 0xffe0 (z); 195 r7 = 0xffe0 (z);
166 r7 = r7 & r6; 196 r7 = r7 & r6;
167 cc = r7 == 0; 197 cc = r7 == 0;
168 if !cc jump 1f; 198 if cc jump 1f;
169
170 /* Single stepping only a single instruction, so clear the trace
171 * bit here. */
172 r7 = syscfg;
173 bitclr (r7, 0);
174 syscfg = R7;
175 jump _ex_trap_c;
176 199
1771:
178 /* 200 /*
179 * We were in an interrupt handler. By convention, all of them save 201 * We were in an interrupt handler. By convention, all of them save
180 * SYSCFG with their first instruction, so by checking whether our 202 * SYSCFG with their first instruction, so by checking whether our
@@ -202,11 +224,15 @@ ENTRY(_ex_single_step)
202 cc = R7 == R6; 224 cc = R7 == R6;
203 if !cc jump _bfin_return_from_exception; 225 if !cc jump _bfin_return_from_exception;
204 226
2271:
228 /* Single stepping only a single instruction, so clear the trace
229 * bit here. */
205 r7 = syscfg; 230 r7 = syscfg;
206 bitclr (r7, 0); 231 bitclr (r7, 0);
207 syscfg = R7; 232 syscfg = R7;
208 233
209 /* Fall through to _bfin_return_from_exception. */ 234 jump _ex_trap_c;
235
210ENDPROC(_ex_single_step) 236ENDPROC(_ex_single_step)
211 237
212ENTRY(_bfin_return_from_exception) 238ENTRY(_bfin_return_from_exception)