Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Sonic Zhang and committed by
Bryan Wu
0d1cdd7a 3a2521fa

+53 -13
+15 -1
arch/blackfin/kernel/kgdb.c
··· 203 204 int kgdb_arch_init(void) 205 { 206 kgdb_remove_all_hw_break(); 207 return 0; 208 } ··· 370 char *ptr; 371 int newPC; 372 int wp_status; 373 374 switch (remcom_in_buffer[0]) { 375 case 'c': ··· 395 /* set the trace bit if we're stepping */ 396 if (remcom_in_buffer[0] == 's') { 397 linux_regs->syscfg |= 0x1; 398 - debugger_step = 1; 399 } 400 401 wp_status = bfin_read_WPSTAT();
··· 203 204 int kgdb_arch_init(void) 205 { 206 + debugger_step = 0; 207 + 208 kgdb_remove_all_hw_break(); 209 return 0; 210 } ··· 368 char *ptr; 369 int newPC; 370 int wp_status; 371 + int i; 372 373 switch (remcom_in_buffer[0]) { 374 case 'c': ··· 392 /* set the trace bit if we're stepping */ 393 if (remcom_in_buffer[0] == 's') { 394 linux_regs->syscfg |= 0x1; 395 + debugger_step = linux_regs->ipend; 396 + debugger_step >>= 6; 397 + for (i = 10; i > 0; i--, debugger_step >>= 1) 398 + if (debugger_step & 1) 399 + break; 400 + /* i indicate event priority of current stopped instruction 401 + * user space instruction is 0, IVG15 is 1, IVTMR is 10. 402 + * debugger_step > 0 means in single step mode 403 + */ 404 + debugger_step = i + 1; 405 + } else { 406 + debugger_step = 0; 407 } 408 409 wp_status = bfin_read_WPSTAT();
+38 -12
arch/blackfin/mach-common/entry.S
··· 158 cc = r7 == r6; 159 if cc jump _bfin_return_from_exception; 160 161 /* If we were in user mode, do the single step normally. */ 162 - p5.l = lo(IPEND); 163 - p5.h = hi(IPEND); 164 r6 = [p5]; 165 r7 = 0xffe0 (z); 166 r7 = r7 & r6; 167 cc = r7 == 0; 168 - 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 - 177 - 1: 178 /* 179 * We were in an interrupt handler. By convention, all of them save 180 * SYSCFG with their first instruction, so by checking whether our ··· 224 cc = R7 == R6; 225 if !cc jump _bfin_return_from_exception; 226 227 r7 = syscfg; 228 bitclr (r7, 0); 229 syscfg = R7; 230 231 - /* Fall through to _bfin_return_from_exception. */ 232 ENDPROC(_ex_single_step) 233 234 ENTRY(_bfin_return_from_exception)
··· 158 cc = r7 == r6; 159 if cc jump _bfin_return_from_exception; 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 + 193 /* If we were in user mode, do the single step normally. */ 194 r6 = [p5]; 195 r7 = 0xffe0 (z); 196 r7 = r7 & r6; 197 cc = r7 == 0; 198 + if cc jump 1f; 199 200 /* 201 * We were in an interrupt handler. By convention, all of them save 202 * SYSCFG with their first instruction, so by checking whether our ··· 202 cc = R7 == R6; 203 if !cc jump _bfin_return_from_exception; 204 205 + 1: 206 + /* Single stepping only a single instruction, so clear the trace 207 + * bit here. */ 208 r7 = syscfg; 209 bitclr (r7, 0); 210 syscfg = R7; 211 212 + jump _ex_trap_c; 213 + 214 ENDPROC(_ex_single_step) 215 216 ENTRY(_bfin_return_from_exception)