diff options
Diffstat (limited to 'arch/mips/kernel/kgdb.c')
| -rw-r--r-- | arch/mips/kernel/kgdb.c | 33 | 
1 files changed, 29 insertions, 4 deletions
diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c index f4546e97c60..7afcc2f22c0 100644 --- a/arch/mips/kernel/kgdb.c +++ b/arch/mips/kernel/kgdb.c @@ -32,6 +32,7 @@  #include <asm/cacheflush.h>  #include <asm/processor.h>  #include <asm/sigcontext.h> +#include <asm/uaccess.h>  static struct hard_trap_info {  	unsigned char tt;	/* Trap type code for MIPS R3xxx and R4xxx */ @@ -40,7 +41,7 @@ static struct hard_trap_info {  	{ 6, SIGBUS },		/* instruction bus error */  	{ 7, SIGBUS },		/* data bus error */  	{ 9, SIGTRAP },		/* break */ -/*	{ 11, SIGILL },	*/	/* CPU unusable */ +/*	{ 11, SIGILL }, */	/* CPU unusable */  	{ 12, SIGFPE },		/* overflow */  	{ 13, SIGTRAP },	/* trap */  	{ 14, SIGSEGV },	/* virtual instruction cache coherency */ @@ -208,7 +209,14 @@ void arch_kgdb_breakpoint(void)  static void kgdb_call_nmi_hook(void *ignored)  { +	mm_segment_t old_fs; + +	old_fs = get_fs(); +	set_fs(get_ds()); +  	kgdb_nmicallback(raw_smp_processor_id(), NULL); + +	set_fs(old_fs);  }  void kgdb_roundup_cpus(unsigned long flags) @@ -282,16 +290,32 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,  	struct die_args *args = (struct die_args *)ptr;  	struct pt_regs *regs = args->regs;  	int trap = (regs->cp0_cause & 0x7c) >> 2; +	mm_segment_t old_fs; + +#ifdef CONFIG_KPROBES +	/* +	 * Return immediately if the kprobes fault notifier has set +	 * DIE_PAGE_FAULT. +	 */ +	if (cmd == DIE_PAGE_FAULT) +		return NOTIFY_DONE; +#endif /* CONFIG_KPROBES */  	/* Userspace events, ignore. */  	if (user_mode(regs))  		return NOTIFY_DONE; +	/* Kernel mode. Set correct address limit */ +	old_fs = get_fs(); +	set_fs(get_ds()); +  	if (atomic_read(&kgdb_active) != -1)  		kgdb_nmicallback(smp_processor_id(), regs); -	if (kgdb_handle_exception(trap, compute_signal(trap), cmd, regs)) +	if (kgdb_handle_exception(trap, compute_signal(trap), cmd, regs)) { +		set_fs(old_fs);  		return NOTIFY_DONE; +	}  	if (atomic_read(&kgdb_setting_breakpoint))  		if ((trap == 9) && (regs->cp0_epc == (unsigned long)breakinst)) @@ -301,6 +325,7 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,  	local_irq_enable();  	__flush_cache_all(); +	set_fs(old_fs);  	return NOTIFY_STOP;  } @@ -312,7 +337,7 @@ int kgdb_ll_trap(int cmd, const char *str,  		.regs	= regs,  		.str	= str,  		.err	= err, -		.trapnr	= trap, +		.trapnr = trap,  		.signr	= sig,  	}; @@ -362,7 +387,7 @@ int kgdb_arch_init(void)  	union mips_instruction insn = {  		.r_format = {  			.opcode = spec_op, -			.func   = break_op, +			.func	= break_op,  		}  	};  	memcpy(arch_kgdb_ops.gdb_bpt_instr, insn.byte, BREAK_INSTR_SIZE);  | 
