diff options
Diffstat (limited to 'arch/powerpc/kernel/kgdb.c')
| -rw-r--r-- | arch/powerpc/kernel/kgdb.c | 48 | 
1 files changed, 35 insertions, 13 deletions
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c index 7a9db64f3f0..8504657379f 100644 --- a/arch/powerpc/kernel/kgdb.c +++ b/arch/powerpc/kernel/kgdb.c @@ -15,7 +15,6 @@   */  #include <linux/kernel.h> -#include <linux/init.h>  #include <linux/kgdb.h>  #include <linux/smp.h>  #include <linux/signal.h> @@ -24,6 +23,8 @@  #include <asm/current.h>  #include <asm/processor.h>  #include <asm/machdep.h> +#include <asm/debug.h> +#include <linux/slab.h>  /*   * This table contains the mapping between PowerPC hardware trap types, and @@ -100,6 +101,21 @@ static int computeSignal(unsigned int tt)  	return SIGHUP;		/* default for things we don't know about */  } +/** + * + *	kgdb_skipexception - Bail out of KGDB when we've been triggered. + *	@exception: Exception vector number + *	@regs: Current &struct pt_regs. + * + *	On some architectures we need to skip a breakpoint exception when + *	it occurs after a breakpoint has been removed. + * + */ +int kgdb_skipexception(int exception, struct pt_regs *regs) +{ +	return kgdb_isremovedbreak(regs->nip); +} +  static int kgdb_call_nmi_hook(struct pt_regs *regs)  {  	kgdb_nmicallback(raw_smp_processor_id(), regs); @@ -109,7 +125,7 @@ static int kgdb_call_nmi_hook(struct pt_regs *regs)  #ifdef CONFIG_SMP  void kgdb_roundup_cpus(unsigned long flags)  { -	smp_send_debugger_break(MSG_ALL_BUT_SELF); +	smp_send_debugger_break();  }  #endif @@ -134,15 +150,18 @@ static int kgdb_handle_breakpoint(struct pt_regs *regs)  	return 1;  } +static DEFINE_PER_CPU(struct thread_info, kgdb_thread_info);  static int kgdb_singlestep(struct pt_regs *regs)  {  	struct thread_info *thread_info, *exception_thread_info; +	struct thread_info *backup_current_thread_info = +		&__get_cpu_var(kgdb_thread_info);  	if (user_mode(regs))  		return 0;  	/* -	 * On Book E and perhaps other processsors, singlestep is handled on +	 * On Book E and perhaps other processors, singlestep is handled on  	 * the critical exception stack.  This causes current_thread_info()  	 * to fail, since it it locates the thread_info by masking off  	 * the low bits of the current stack pointer.  We work around @@ -154,13 +173,17 @@ static int kgdb_singlestep(struct pt_regs *regs)  	thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));  	exception_thread_info = current_thread_info(); -	if (thread_info != exception_thread_info) +	if (thread_info != exception_thread_info) { +		/* Save the original current_thread_info. */ +		memcpy(backup_current_thread_info, exception_thread_info, sizeof *thread_info);  		memcpy(exception_thread_info, thread_info, sizeof *thread_info); +	}  	kgdb_handle_exception(0, SIGTRAP, 0, regs);  	if (thread_info != exception_thread_info) -		memcpy(thread_info, exception_thread_info, sizeof *thread_info); +		/* Restore current_thread_info lastly. */ +		memcpy(exception_thread_info, backup_current_thread_info, sizeof *thread_info);  	return 1;  } @@ -175,7 +198,7 @@ static int kgdb_iabr_match(struct pt_regs *regs)  	return 1;  } -static int kgdb_dabr_match(struct pt_regs *regs) +static int kgdb_break_match(struct pt_regs *regs)  {  	if (user_mode(regs))  		return 0; @@ -337,7 +360,7 @@ char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)  		/* FP registers 32 -> 63 */  #if defined(CONFIG_FSL_BOOKE) && defined(CONFIG_SPE)  		if (current) -			memcpy(mem, current->thread.evr[regno-32], +			memcpy(mem, ¤t->thread.evr[regno-32],  					dbg_reg_def[regno].size);  #else  		/* fp registers not used by kernel, leave zero */ @@ -362,7 +385,7 @@ int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)  	if (regno >= 32 && regno < 64) {  		/* FP registers 32 -> 63 */  #if defined(CONFIG_FSL_BOOKE) && defined(CONFIG_SPE) -		memcpy(current->thread.evr[regno-32], mem, +		memcpy(¤t->thread.evr[regno-32], mem,  				dbg_reg_def[regno].size);  #else  		/* fp registers not used by kernel, leave zero */ @@ -409,7 +432,6 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,  #else  			linux_regs->msr |= MSR_SE;  #endif -			kgdb_single_step = 1;  			atomic_set(&kgdb_cpu_doing_single_step,  				   raw_smp_processor_id());  		} @@ -436,7 +458,7 @@ static void *old__debugger;  static void *old__debugger_bpt;  static void *old__debugger_sstep;  static void *old__debugger_iabr_match; -static void *old__debugger_dabr_match; +static void *old__debugger_break_match;  static void *old__debugger_fault_handler;  int kgdb_arch_init(void) @@ -446,7 +468,7 @@ int kgdb_arch_init(void)  	old__debugger_bpt = __debugger_bpt;  	old__debugger_sstep = __debugger_sstep;  	old__debugger_iabr_match = __debugger_iabr_match; -	old__debugger_dabr_match = __debugger_dabr_match; +	old__debugger_break_match = __debugger_break_match;  	old__debugger_fault_handler = __debugger_fault_handler;  	__debugger_ipi = kgdb_call_nmi_hook; @@ -454,7 +476,7 @@ int kgdb_arch_init(void)  	__debugger_bpt = kgdb_handle_breakpoint;  	__debugger_sstep = kgdb_singlestep;  	__debugger_iabr_match = kgdb_iabr_match; -	__debugger_dabr_match = kgdb_dabr_match; +	__debugger_break_match = kgdb_break_match;  	__debugger_fault_handler = kgdb_not_implemented;  	return 0; @@ -467,6 +489,6 @@ void kgdb_arch_exit(void)  	__debugger_bpt = old__debugger_bpt;  	__debugger_sstep = old__debugger_sstep;  	__debugger_iabr_match = old__debugger_iabr_match; -	__debugger_dabr_match = old__debugger_dabr_match; +	__debugger_break_match = old__debugger_break_match;  	__debugger_fault_handler = old__debugger_fault_handler;  }  | 
