1067 lines · 24.8 KB · C
RawDownload
/* * Kernel Debug Core * * Maintainer: Jason Wessel <jason.wessel@windriver.com> * * Copyright (C) 2000-2001 VERITAS Software Corporation. * Copyright (C) 2002-2004 Timesys Corporation * Copyright (C) 2003-2004 Amit S. Kale <amitkale@linsyssoft.com> * Copyright (C) 2004 Pavel Machek <pavel@ucw.cz> * Copyright (C) 2004-2006 Tom Rini <trini@kernel.crashing.org> * Copyright (C) 2004-2006 LinSysSoft Technologies Pvt. Ltd. * Copyright (C) 2005-2009 Wind River Systems, Inc. * Copyright (C) 2007 MontaVista Software, Inc. * Copyright (C) 2008 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> * * Contributors at various stages not listed above: *  Jason Wessel ( jason.wessel@windriver.com ) *  George Anzinger <george@mvista.com> *  Anurekh Saxena (anurekh.saxena@timesys.com) *  Lake Stevens Instrument Division (Glenn Engel) *  Jim Kingdon, Cygnus Support. * * Original KGDB stub: David Grothe <dave@gcom.com>, * Tigran Aivazian <tigran@sco.com> * * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of any * kind, whether express or implied. */#include <linux/pid_namespace.h>#include <linux/clocksource.h>#include <linux/serial_core.h>#include <linux/interrupt.h>#include <linux/spinlock.h>#include <linux/console.h>#include <linux/threads.h>#include <linux/uaccess.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/ptrace.h>#include <linux/string.h>#include <linux/delay.h>#include <linux/sched.h>#include <linux/sysrq.h>#include <linux/reboot.h>#include <linux/init.h>#include <linux/kgdb.h>#include <linux/kdb.h>#include <linux/pid.h>#include <linux/smp.h>#include <linux/mm.h>#include <linux/vmacache.h>#include <linux/rcupdate.h> #include <asm/cacheflush.h>#include <asm/byteorder.h>#include <linux/atomic.h> #include "debug_core.h" static int kgdb_break_asap; struct debuggerinfo_struct kgdb_info[NR_CPUS]; /** * kgdb_connected - Is a host GDB connected to us? */int				kgdb_connected;EXPORT_SYMBOL_GPL(kgdb_connected); /* All the KGDB handlers are installed */int			kgdb_io_module_registered; /* Guard for recursive entry */static int			exception_level; struct kgdb_io		*dbg_io_ops;static DEFINE_SPINLOCK(kgdb_registration_lock); /* Action for the reboot notifiter, a global allow kdb to change it */static int kgdbreboot;/* kgdb console driver is loaded */static int kgdb_con_registered;/* determine if kgdb console output should be used */static int kgdb_use_con;/* Flag for alternate operations for early debugging */bool dbg_is_early = true;/* Next cpu to become the master debug core */int dbg_switch_cpu; /* Use kdb or gdbserver mode */int dbg_kdb_mode = 1; static int __init opt_kgdb_con(char *str){	kgdb_use_con = 1;	return 0;} early_param("kgdbcon", opt_kgdb_con); module_param(kgdb_use_con, int, 0644);module_param(kgdbreboot, int, 0644); /* * Holds information about breakpoints in a kernel. These breakpoints are * added and removed by gdb. */static struct kgdb_bkpt		kgdb_break[KGDB_MAX_BREAKPOINTS] = {	[0 ... KGDB_MAX_BREAKPOINTS-1] = { .state = BP_UNDEFINED }}; /* * The CPU# of the active CPU, or -1 if none: */atomic_t			kgdb_active = ATOMIC_INIT(-1);EXPORT_SYMBOL_GPL(kgdb_active);static DEFINE_RAW_SPINLOCK(dbg_master_lock);static DEFINE_RAW_SPINLOCK(dbg_slave_lock); /* * We use NR_CPUs not PERCPU, in case kgdb is used to debug early * bootup code (which might not have percpu set up yet): */static atomic_t			masters_in_kgdb;static atomic_t			slaves_in_kgdb;static atomic_t			kgdb_break_tasklet_var;atomic_t			kgdb_setting_breakpoint; struct task_struct		*kgdb_usethread;struct task_struct		*kgdb_contthread; int				kgdb_single_step;static pid_t			kgdb_sstep_pid; /* to keep track of the CPU which is doing the single stepping*/atomic_t			kgdb_cpu_doing_single_step = ATOMIC_INIT(-1); /* * If you are debugging a problem where roundup (the collection of * all other CPUs) is a problem [this should be extremely rare], * then use the nokgdbroundup option to avoid roundup. In that case * the other CPUs might interfere with your debugging context, so * use this with care: */static int kgdb_do_roundup = 1; static int __init opt_nokgdbroundup(char *str){	kgdb_do_roundup = 0; 	return 0;} early_param("nokgdbroundup", opt_nokgdbroundup); /* * Finally, some KGDB code :-) */ /* * Weak aliases for breakpoint management, * can be overriden by architectures when needed: */int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt){	int err; 	err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,				BREAK_INSTR_SIZE);	if (err)		return err;	err = probe_kernel_write((char *)bpt->bpt_addr,				 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);	return err;} int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt){	return probe_kernel_write((char *)bpt->bpt_addr,				  (char *)bpt->saved_instr, BREAK_INSTR_SIZE);} int __weak kgdb_validate_break_address(unsigned long addr){	struct kgdb_bkpt tmp;	int err;	/* Validate setting the breakpoint and then removing it.  If the	 * remove fails, the kernel needs to emit a bad message because we	 * are deep trouble not being able to put things back the way we	 * found them.	 */	tmp.bpt_addr = addr;	err = kgdb_arch_set_breakpoint(&tmp);	if (err)		return err;	err = kgdb_arch_remove_breakpoint(&tmp);	if (err)		printk(KERN_ERR "KGDB: Critical breakpoint error, kernel "		   "memory destroyed at: %lx", addr);	return err;} unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs){	return instruction_pointer(regs);} int __weak kgdb_arch_init(void){	return 0;} int __weak kgdb_skipexception(int exception, struct pt_regs *regs){	return 0;} /* * Some architectures need cache flushes when we set/clear a * breakpoint: */static void kgdb_flush_swbreak_addr(unsigned long addr){	if (!CACHE_FLUSH_IS_SAFE)		return; 	if (current->mm) {		int i; 		for (i = 0; i < VMACACHE_SIZE; i++) {			if (!current->vmacache[i])				continue;			flush_cache_range(current->vmacache[i],					  addr, addr + BREAK_INSTR_SIZE);		}	} 	/* Force flush instruction cache if it was outside the mm */	flush_icache_range(addr, addr + BREAK_INSTR_SIZE);} /* * SW breakpoint management: */int dbg_activate_sw_breakpoints(void){	int error;	int ret = 0;	int i; 	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {		if (kgdb_break[i].state != BP_SET)			continue; 		error = kgdb_arch_set_breakpoint(&kgdb_break[i]);		if (error) {			ret = error;			printk(KERN_INFO "KGDB: BP install failed: %lx",			       kgdb_break[i].bpt_addr);			continue;		} 		kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);		kgdb_break[i].state = BP_ACTIVE;	}	return ret;} int dbg_set_sw_break(unsigned long addr){	int err = kgdb_validate_break_address(addr);	int breakno = -1;	int i; 	if (err)		return err; 	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {		if ((kgdb_break[i].state == BP_SET) &&					(kgdb_break[i].bpt_addr == addr))			return -EEXIST;	}	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {		if (kgdb_break[i].state == BP_REMOVED &&					kgdb_break[i].bpt_addr == addr) {			breakno = i;			break;		}	} 	if (breakno == -1) {		for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {			if (kgdb_break[i].state == BP_UNDEFINED) {				breakno = i;				break;			}		}	} 	if (breakno == -1)		return -E2BIG; 	kgdb_break[breakno].state = BP_SET;	kgdb_break[breakno].type = BP_BREAKPOINT;	kgdb_break[breakno].bpt_addr = addr; 	return 0;} int dbg_deactivate_sw_breakpoints(void){	int error;	int ret = 0;	int i; 	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {		if (kgdb_break[i].state != BP_ACTIVE)			continue;		error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);		if (error) {			printk(KERN_INFO "KGDB: BP remove failed: %lx\n",			       kgdb_break[i].bpt_addr);			ret = error;		} 		kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);		kgdb_break[i].state = BP_SET;	}	return ret;} int dbg_remove_sw_break(unsigned long addr){	int i; 	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {		if ((kgdb_break[i].state == BP_SET) &&				(kgdb_break[i].bpt_addr == addr)) {			kgdb_break[i].state = BP_REMOVED;			return 0;		}	}	return -ENOENT;} int kgdb_isremovedbreak(unsigned long addr){	int i; 	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {		if ((kgdb_break[i].state == BP_REMOVED) &&					(kgdb_break[i].bpt_addr == addr))			return 1;	}	return 0;} int dbg_remove_all_break(void){	int error;	int i; 	/* Clear memory breakpoints. */	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {		if (kgdb_break[i].state != BP_ACTIVE)			goto setundefined;		error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);		if (error)			printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n",			       kgdb_break[i].bpt_addr);setundefined:		kgdb_break[i].state = BP_UNDEFINED;	} 	/* Clear hardware breakpoints. */	if (arch_kgdb_ops.remove_all_hw_break)		arch_kgdb_ops.remove_all_hw_break(); 	return 0;} /* * Return true if there is a valid kgdb I/O module.  Also if no * debugger is attached a message can be printed to the console about * waiting for the debugger to attach. * * The print_wait argument is only to be true when called from inside * the core kgdb_handle_exception, because it will wait for the * debugger to attach. */static int kgdb_io_ready(int print_wait){	if (!dbg_io_ops)		return 0;	if (kgdb_connected)		return 1;	if (atomic_read(&kgdb_setting_breakpoint))		return 1;	if (print_wait) {#ifdef CONFIG_KGDB_KDB		if (!dbg_kdb_mode)			printk(KERN_CRIT "KGDB: waiting... or $3#33 for KDB\n");#else		printk(KERN_CRIT "KGDB: Waiting for remote debugger\n");#endif	}	return 1;} static int kgdb_reenter_check(struct kgdb_state *ks){	unsigned long addr; 	if (atomic_read(&kgdb_active) != raw_smp_processor_id())		return 0; 	/* Panic on recursive debugger calls: */	exception_level++;	addr = kgdb_arch_pc(ks->ex_vector, ks->linux_regs);	dbg_deactivate_sw_breakpoints(); 	/*	 * If the break point removed ok at the place exception	 * occurred, try to recover and print a warning to the end	 * user because the user planted a breakpoint in a place that	 * KGDB needs in order to function.	 */	if (dbg_remove_sw_break(addr) == 0) {		exception_level = 0;		kgdb_skipexception(ks->ex_vector, ks->linux_regs);		dbg_activate_sw_breakpoints();		printk(KERN_CRIT "KGDB: re-enter error: breakpoint removed %lx\n",			addr);		WARN_ON_ONCE(1); 		return 1;	}	dbg_remove_all_break();	kgdb_skipexception(ks->ex_vector, ks->linux_regs); 	if (exception_level > 1) {		dump_stack();		panic("Recursive entry to debugger");	} 	printk(KERN_CRIT "KGDB: re-enter exception: ALL breakpoints killed\n");#ifdef CONFIG_KGDB_KDB	/* Allow kdb to debug itself one level */	return 0;#endif	dump_stack();	panic("Recursive entry to debugger"); 	return 1;} static void dbg_touch_watchdogs(void){	touch_softlockup_watchdog_sync();	clocksource_touch_watchdog();	rcu_cpu_stall_reset();} static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs,		int exception_state){	unsigned long flags;	int sstep_tries = 100;	int error;	int cpu;	int trace_on = 0;	int online_cpus = num_online_cpus(); 	kgdb_info[ks->cpu].enter_kgdb++;	kgdb_info[ks->cpu].exception_state |= exception_state; 	if (exception_state == DCPU_WANT_MASTER)		atomic_inc(&masters_in_kgdb);	else		atomic_inc(&slaves_in_kgdb); 	if (arch_kgdb_ops.disable_hw_break)		arch_kgdb_ops.disable_hw_break(regs); acquirelock:	/*	 * Interrupts will be restored by the 'trap return' code, except when	 * single stepping.	 */	local_irq_save(flags); 	cpu = ks->cpu;	kgdb_info[cpu].debuggerinfo = regs;	kgdb_info[cpu].task = current;	kgdb_info[cpu].ret_state = 0;	kgdb_info[cpu].irq_depth = hardirq_count() >> HARDIRQ_SHIFT; 	/* Make sure the above info reaches the primary CPU */	smp_mb();

Lines 1–500 of 1067.