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