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/kernel/gdb-stub.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'arch/mn10300/kernel/gdb-stub.c') 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 From 7f386ac3272e057fbf51e5b5712fad1a80e77125 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:30 +0000 Subject: MN10300: Create general kernel debugger cache flushing Create general kernel debugger cache flushing for MN10300 and get rid of the old stuff that gdbstub was using. Signed-off-by: David Howells --- arch/mn10300/kernel/gdb-stub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/mn10300/kernel/gdb-stub.c') diff --git a/arch/mn10300/kernel/gdb-stub.c b/arch/mn10300/kernel/gdb-stub.c index a9c1e916687f..1e8f24f00637 100644 --- a/arch/mn10300/kernel/gdb-stub.c +++ b/arch/mn10300/kernel/gdb-stub.c @@ -133,7 +133,7 @@ #include #include #include -#include +#include #include #include #include @@ -1665,7 +1665,7 @@ done: * NB: We flush both caches, just to be sure... */ if (gdbstub_flush_caches) - gdbstub_purge_cache(); + debugger_local_cache_flushinv(); gdbstub_load_fpu(); mn10300_set_gdbleds(0); -- cgit From 67ddb4052daac9d449caf2643ac365d42a04219a Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Mar 2011 16:54:30 +0000 Subject: MN10300: Create generic kernel debugger hooks Create generic kernel debugger hooks in the MN10300 arch and make gdbstub use them. This is a preparation for KGDB support. Signed-off-by: David Howells --- arch/mn10300/kernel/gdb-stub.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'arch/mn10300/kernel/gdb-stub.c') diff --git a/arch/mn10300/kernel/gdb-stub.c b/arch/mn10300/kernel/gdb-stub.c index 1e8f24f00637..538266b2c9bc 100644 --- a/arch/mn10300/kernel/gdb-stub.c +++ b/arch/mn10300/kernel/gdb-stub.c @@ -1173,7 +1173,7 @@ int gdbstub_clear_breakpoint(u8 *addr, int len) /* * This function does all command processing for interfacing to gdb - * - returns 1 if the exception should be skipped, 0 otherwise. + * - returns 0 if the exception should be skipped, -ERROR otherwise. */ static int gdbstub(struct pt_regs *regs, enum exception_code excep) { @@ -1188,7 +1188,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep) int loop; if (excep == EXCEP_FPU_DISABLED) - return 0; + return -ENOTSUPP; gdbstub_flush_caches = 0; @@ -1197,7 +1197,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep) asm volatile("mov mdr,%0" : "=d"(mdr)); local_save_flags(epsw); arch_local_change_intr_mask_level( - NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1)); + NUM2EPSW_IM(CONFIG_DEBUGGER_IRQ_LEVEL + 1)); gdbstub_store_fpu(); @@ -1675,14 +1675,23 @@ done: touch_softlockup_watchdog(); local_irq_restore(epsw); - return 1; + return 0; +} + +/* + * Determine if we hit a debugger special breakpoint that needs skipping over + * automatically. + */ +int at_debugger_breakpoint(struct pt_regs *regs) +{ + return 0; } /* * handle event interception */ -asmlinkage int gdbstub_intercept(struct pt_regs *regs, - enum exception_code excep) +asmlinkage int debugger_intercept(enum exception_code excep, + int signo, int si_code, struct pt_regs *regs) { static u8 notfirst = 1; int ret; @@ -1696,7 +1705,7 @@ asmlinkage int gdbstub_intercept(struct pt_regs *regs, asm("mov mdr,%0" : "=d"(mdr)); gdbstub_entry( - "--> gdbstub_intercept(%p,%04x) [MDR=%lx PC=%lx]\n", + "--> debugger_intercept(%p,%04x) [MDR=%lx PC=%lx]\n", regs, excep, mdr, regs->pc); gdbstub_entry( @@ -1730,7 +1739,7 @@ asmlinkage int gdbstub_intercept(struct pt_regs *regs, ret = gdbstub(regs, excep); - gdbstub_entry("<-- gdbstub_intercept()\n"); + gdbstub_entry("<-- debugger_intercept()\n"); gdbstub_busy = 0; return ret; } -- cgit