Commit 9ee21723 authored by David Howells's avatar David Howells

MN10300: gdbstub: Restrict single-stepping to non-preemptable non-SMP configs

Restrict single-stepping through the kernel using gdbstub to non-preemptable
non-SMP configs as gdbstub has to do software single-stepping by means of
temporary breakpoints.  Hardware single-stepping is unavailable as Panasonic
have not sufficiently documented the interface to it.

Software single-stepping through preemptable or SMP kernels runs into problems
as it makes it much more likely that the wrong thread will hit the temporary
breakpoints.  It seems impractical to work around the problem for the most
part.  It could be possible to make a UP preemptable kernel switch temporary
breakpoints in and out in switch_to().
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent ddb7d1e9
...@@ -54,6 +54,14 @@ config GDBSTUB_IMMEDIATE ...@@ -54,6 +54,14 @@ config GDBSTUB_IMMEDIATE
possible, leaving the program counter at the beginning of possible, leaving the program counter at the beginning of
start_kernel() in init/main.c. start_kernel() in init/main.c.
config GDBSTUB_ALLOW_SINGLE_STEP
bool "Allow software single-stepping in GDB stub"
depends on GDBSTUB && !SMP && !PREEMPT
help
Allow GDB stub to perform software single-stepping through the
kernel. This doesn't work very well on SMP or preemptible kernels as
it uses temporary breakpoints to emulate single-stepping.
config GDB_CONSOLE config GDB_CONSOLE
bool "Console output to GDB" bool "Console output to GDB"
depends on GDBSTUB depends on GDBSTUB
......
...@@ -405,6 +405,7 @@ static int hexToInt(char **ptr, int *intValue) ...@@ -405,6 +405,7 @@ static int hexToInt(char **ptr, int *intValue)
return (numChars); return (numChars);
} }
#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP
/* /*
* We single-step by setting breakpoints. When an exception * We single-step by setting breakpoints. When an exception
* is handled, we need to restore the instructions hoisted * is handled, we need to restore the instructions hoisted
...@@ -729,6 +730,7 @@ static int gdbstub_single_step(struct pt_regs *regs) ...@@ -729,6 +730,7 @@ static int gdbstub_single_step(struct pt_regs *regs)
__gdbstub_restore_bp(); __gdbstub_restore_bp();
return -EFAULT; return -EFAULT;
} }
#endif /* CONFIG_GDBSTUB_ALLOW_SINGLE_STEP */
#ifdef CONFIG_GDBSTUB_CONSOLE #ifdef CONFIG_GDBSTUB_CONSOLE
...@@ -1208,11 +1210,13 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep) ...@@ -1208,11 +1210,13 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
/* if we were single stepping, restore the opcodes hoisted for the /* if we were single stepping, restore the opcodes hoisted for the
* breakpoint[s] */ * breakpoint[s] */
broke = 0; broke = 0;
#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP
if ((step_bp[0].addr && step_bp[0].addr == (u8 *) regs->pc) || if ((step_bp[0].addr && step_bp[0].addr == (u8 *) regs->pc) ||
(step_bp[1].addr && step_bp[1].addr == (u8 *) regs->pc)) (step_bp[1].addr && step_bp[1].addr == (u8 *) regs->pc))
broke = 1; broke = 1;
__gdbstub_restore_bp(); __gdbstub_restore_bp();
#endif
if (gdbstub_rx_unget) { if (gdbstub_rx_unget) {
sigval = SIGINT; sigval = SIGINT;
...@@ -1548,17 +1552,21 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep) ...@@ -1548,17 +1552,21 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
* Step to next instruction * Step to next instruction
*/ */
case 's': case 's':
/* /* Using the T flag doesn't seem to perform single
* using the T flag doesn't seem to perform single
* stepping (it seems to wind up being caught by the * stepping (it seems to wind up being caught by the
* JTAG unit), so we have to use breakpoints and * JTAG unit), so we have to use breakpoints and
* continue instead. * continue instead.
*/ */
#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP
if (gdbstub_single_step(regs) < 0) if (gdbstub_single_step(regs) < 0)
/* ignore any fault error for now */ /* ignore any fault error for now */
gdbstub_printk("unable to set single-step" gdbstub_printk("unable to set single-step"
" bp\n"); " bp\n");
goto done; goto done;
#else
gdbstub_strcpy(output_buffer, "E01");
break;
#endif
/* /*
* Set baud rate (bBB) * Set baud rate (bBB)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment