From 9ee21723ccc30070f47c411826d4ed013cd050c2 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:29 +0000 Subject: 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: David Howells --- arch/mn10300/Kconfig.debug | 8 ++++++++ arch/mn10300/kernel/gdb-stub.c | 12 ++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'arch/mn10300') diff --git a/arch/mn10300/Kconfig.debug b/arch/mn10300/Kconfig.debug index ce83c74b3fd7..a1b8620f65ae 100644 --- a/arch/mn10300/Kconfig.debug +++ b/arch/mn10300/Kconfig.debug @@ -54,6 +54,14 @@ config GDBSTUB_IMMEDIATE possible, leaving the program counter at the beginning of 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 bool "Console output to GDB" depends on GDBSTUB diff --git a/arch/mn10300/kernel/gdb-stub.c b/arch/mn10300/kernel/gdb-stub.c index b169d99d9f20..a9c1e916687f 100644 --- a/arch/mn10300/kernel/gdb-stub.c +++ b/arch/mn10300/kernel/gdb-stub.c @@ -405,6 +405,7 @@ static int hexToInt(char **ptr, int *intValue) return (numChars); } +#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP /* * We single-step by setting breakpoints. When an exception * is handled, we need to restore the instructions hoisted @@ -729,6 +730,7 @@ static int gdbstub_single_step(struct pt_regs *regs) __gdbstub_restore_bp(); return -EFAULT; } +#endif /* CONFIG_GDBSTUB_ALLOW_SINGLE_STEP */ #ifdef CONFIG_GDBSTUB_CONSOLE @@ -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 * breakpoint[s] */ broke = 0; +#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP if ((step_bp[0].addr && step_bp[0].addr == (u8 *) regs->pc) || (step_bp[1].addr && step_bp[1].addr == (u8 *) regs->pc)) broke = 1; __gdbstub_restore_bp(); +#endif if (gdbstub_rx_unget) { sigval = SIGINT; @@ -1548,17 +1552,21 @@ packet_waiting: * Step to next instruction */ 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 * JTAG unit), so we have to use breakpoints and * continue instead. */ +#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP if (gdbstub_single_step(regs) < 0) /* ignore any fault error for now */ gdbstub_printk("unable to set single-step" " bp\n"); goto done; +#else + gdbstub_strcpy(output_buffer, "E01"); + break; +#endif /* * Set baud rate (bBB) -- cgit v1.2.3