diff options
Diffstat (limited to 'arch/blackfin')
-rw-r--r-- | arch/blackfin/kernel/kgdb.c | 16 | ||||
-rw-r--r-- | arch/blackfin/mach-common/entry.S | 50 |
2 files changed, 53 insertions, 13 deletions
diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c index a9c15515bfd..a1f9641a642 100644 --- a/arch/blackfin/kernel/kgdb.c +++ b/arch/blackfin/kernel/kgdb.c | |||
@@ -203,6 +203,8 @@ struct hw_breakpoint { | |||
203 | 203 | ||
204 | int kgdb_arch_init(void) | 204 | int 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 038f70e0be6..eceb484d90f 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 | ||
177 | 1: | ||
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 | ||
227 | 1: | ||
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 | |||
210 | ENDPROC(_ex_single_step) | 236 | ENDPROC(_ex_single_step) |
211 | 237 | ||
212 | ENTRY(_bfin_return_from_exception) | 238 | ENTRY(_bfin_return_from_exception) |