diff options
| -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 a9c15515bfd7..a1f9641a6425 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 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 | ||
| 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) |
