1231 lines · 29.0 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* * 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> */ #define pr_fmt(fmt) "KGDB: " fmt #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/nmi.h>#include <linux/pid.h>#include <linux/smp.h>#include <linux/mm.h>#include <linux/rcupdate.h>#include <linux/irq.h>#include <linux/security.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 notifier, 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; 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;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 overridden by architectures when needed: */int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt){	int err; 	err = copy_from_kernel_nofault(bpt->saved_instr, (char *)bpt->bpt_addr,				BREAK_INSTR_SIZE);	if (err)		return err;	err = copy_to_kernel_nofault((char *)bpt->bpt_addr,				 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);	return err;}NOKPROBE_SYMBOL(kgdb_arch_set_breakpoint); int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt){	return copy_to_kernel_nofault((char *)bpt->bpt_addr,				  (char *)bpt->saved_instr, BREAK_INSTR_SIZE);}NOKPROBE_SYMBOL(kgdb_arch_remove_breakpoint); int __weak kgdb_validate_break_address(unsigned long addr){	struct kgdb_bkpt tmp;	int err; 	if (kgdb_within_blocklist(addr))		return -EINVAL; 	/* 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)		pr_err("Critical breakpoint error, kernel memory destroyed at: %lx\n",		       addr);	return err;} unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs){	return instruction_pointer(regs);}NOKPROBE_SYMBOL(kgdb_arch_pc); int __weak kgdb_arch_init(void){	return 0;} int __weak kgdb_skipexception(int exception, struct pt_regs *regs){	return 0;}NOKPROBE_SYMBOL(kgdb_skipexception); #ifdef CONFIG_SMP /* * Default (weak) implementation for kgdb_roundup_cpus */ void __weak kgdb_call_nmi_hook(void *ignored){	/*	 * NOTE: get_irq_regs() is supposed to get the registers from	 * before the IPI interrupt happened and so is supposed to	 * show where the processor was.  In some situations it's	 * possible we might be called without an IPI, so it might be	 * safer to figure out how to make kgdb_breakpoint() work	 * properly here.	 */	kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());}NOKPROBE_SYMBOL(kgdb_call_nmi_hook); static DEFINE_PER_CPU(call_single_data_t, kgdb_roundup_csd) =	CSD_INIT(kgdb_call_nmi_hook, NULL); void __weak kgdb_roundup_cpus(void){	call_single_data_t *csd;	int this_cpu = raw_smp_processor_id();	int cpu;	int ret; 	for_each_online_cpu(cpu) {		/* No need to roundup ourselves */		if (cpu == this_cpu)			continue; 		csd = &per_cpu(kgdb_roundup_csd, cpu); 		/*		 * If it didn't round up last time, don't try again		 * since smp_call_function_single_async() will block.		 *		 * If rounding_up is false then we know that the		 * previous call must have at least started and that		 * means smp_call_function_single_async() won't block.		 */		if (kgdb_info[cpu].rounding_up)			continue;		kgdb_info[cpu].rounding_up = true; 		ret = smp_call_function_single_async(cpu, csd);		if (ret)			kgdb_info[cpu].rounding_up = false;	}}NOKPROBE_SYMBOL(kgdb_roundup_cpus); #endif /* * 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; 	/* Force flush instruction cache if it was outside the mm */	flush_icache_range(addr, addr + BREAK_INSTR_SIZE);}NOKPROBE_SYMBOL(kgdb_flush_swbreak_addr); /* * 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;			pr_info("BP install failed: %lx\n",				kgdb_break[i].bpt_addr);			continue;		} 		kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);		kgdb_break[i].state = BP_ACTIVE;	}	return ret;}NOKPROBE_SYMBOL(dbg_activate_sw_breakpoints); 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) {			pr_info("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;}NOKPROBE_SYMBOL(dbg_deactivate_sw_breakpoints); 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 kgdb_has_hit_break(unsigned long addr){	int i; 	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {		if (kgdb_break[i].state == BP_ACTIVE &&		    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)			pr_err("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;} void kgdb_free_init_mem(void){	int i; 	/* Clear init memory breakpoints. */	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {		if (init_section_contains((void *)kgdb_break[i].bpt_addr, 0))			kgdb_break[i].state = BP_UNDEFINED;	}} #ifdef CONFIG_KGDB_KDBvoid kdb_dump_stack_on_cpu(int cpu){	if (cpu == raw_smp_processor_id() || !IS_ENABLED(CONFIG_SMP)) {		dump_stack();		return;	} 	if (!(kgdb_info[cpu].exception_state & DCPU_IS_SLAVE)) {		kdb_printf("ERROR: Task on cpu %d didn't stop in the debugger\n",			   cpu);		return;	} 	/*	 * In general, architectures don't support dumping the stack of a	 * "running" process that's not the current one.  From the point of	 * view of the Linux, kernel processes that are looping in the kgdb	 * slave loop are still "running".  There's also no API (that actually	 * works across all architectures) that can do a stack crawl based	 * on registers passed as a parameter.	 *	 * Solve this conundrum by asking slave CPUs to do the backtrace	 * themselves.	 */	kgdb_info[cpu].exception_state |= DCPU_WANT_BT;	while (kgdb_info[cpu].exception_state & DCPU_WANT_BT)		cpu_relax();}#endif /* * 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;

Lines 1–500 of 1231.