linux/kernel/debug/debug_core.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Kernel Debug Core
 *
 * Maintainer: Jason Wessel <[email protected]>
 *
 * Copyright (C) 2000-2001 VERITAS Software Corporation.
 * Copyright (C) 2002-2004 Timesys Corporation
 * Copyright (C) 2003-2004 Amit S. Kale <[email protected]>
 * Copyright (C) 2004 Pavel Machek <[email protected]>
 * Copyright (C) 2004-2006 Tom Rini <[email protected]>
 * 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 <[email protected]>
 *
 * Contributors at various stages not listed above:
 *  Jason Wessel ( [email protected] )
 *  George Anzinger <[email protected]>
 *  Anurekh Saxena ([email protected])
 *  Lake Stevens Instrument Division (Glenn Engel)
 *  Jim Kingdon, Cygnus Support.
 *
 * Original KGDB stub: David Grothe <[email protected]>,
 * Tigran Aivazian <[email protected]>
 */

#define pr_fmt(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();

/* 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 =;
/* Next cpu to become the master debug core */
int dbg_switch_cpu;

/* Use kdb or gdbserver mode */
int dbg_kdb_mode =;

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] =;

/*
 * The CPU# of the active CPU, or -1 if none:
 */
atomic_t			kgdb_active =;
EXPORT_SYMBOL_GPL();
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 =;

/*
 * 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 =;

static int __init opt_nokgdbroundup(char *str)
{}

early_param();

/*
 * 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)
{}
NOKPROBE_SYMBOL(kgdb_arch_set_breakpoint);

int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
{}
NOKPROBE_SYMBOL(kgdb_arch_remove_breakpoint);

int __weak kgdb_validate_break_address(unsigned long addr)
{}

unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs)
{}
NOKPROBE_SYMBOL(kgdb_arch_pc);

int __weak kgdb_arch_init(void)
{}

int __weak kgdb_skipexception(int exception, struct pt_regs *regs)
{}
NOKPROBE_SYMBOL(kgdb_skipexception);

#ifdef CONFIG_SMP

/*
 * Default (weak) implementation for kgdb_roundup_cpus
 */

void __weak kgdb_call_nmi_hook(void *ignored)
{}
NOKPROBE_SYMBOL(kgdb_call_nmi_hook);

static DEFINE_PER_CPU(call_single_data_t, kgdb_roundup_csd) =;

void __weak kgdb_roundup_cpus(void)
{}
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)
{}
NOKPROBE_SYMBOL(kgdb_flush_swbreak_addr);

/*
 * SW breakpoint management:
 */
int dbg_activate_sw_breakpoints(void)
{}
NOKPROBE_SYMBOL(dbg_activate_sw_breakpoints);

int dbg_set_sw_break(unsigned long addr)
{}

int dbg_deactivate_sw_breakpoints(void)
{}
NOKPROBE_SYMBOL(dbg_deactivate_sw_breakpoints);

int dbg_remove_sw_break(unsigned long addr)
{}

int kgdb_isremovedbreak(unsigned long addr)
{}

int kgdb_has_hit_break(unsigned long addr)
{}

int dbg_remove_all_break(void)
{}

void kgdb_free_init_mem(void)
{}

#ifdef CONFIG_KGDB_KDB
void kdb_dump_stack_on_cpu(int cpu)
{}
#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)
{}
NOKPROBE_SYMBOL(kgdb_io_ready);

static int kgdb_reenter_check(struct kgdb_state *ks)
{}
NOKPROBE_SYMBOL(kgdb_reenter_check);

static void dbg_touch_watchdogs(void)
{}
NOKPROBE_SYMBOL(dbg_touch_watchdogs);

static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs,
		int exception_state)
{}
NOKPROBE_SYMBOL(kgdb_cpu_enter);

/*
 * kgdb_handle_exception() - main entry point from a kernel exception
 *
 * Locking hierarchy:
 *	interface locks, if any (begin_session)
 *	kgdb lock (kgdb_active)
 */
int
kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
{}
NOKPROBE_SYMBOL(kgdb_handle_exception);

/*
 * GDB places a breakpoint at this function to know dynamically loaded objects.
 */
static int module_event(struct notifier_block *self, unsigned long val,
	void *data)
{}

static struct notifier_block dbg_module_load_nb =;

int kgdb_nmicallback(int cpu, void *regs)
{}
NOKPROBE_SYMBOL(kgdb_nmicallback);

int kgdb_nmicallin(int cpu, int trapnr, void *regs, int err_code,
							atomic_t *send_ready)
{}
NOKPROBE_SYMBOL(kgdb_nmicallin);

static void kgdb_console_write(struct console *co, const char *s,
   unsigned count)
{}

static struct console kgdbcons =;

static int __init opt_kgdb_con(char *str)
{}

early_param();

#ifdef CONFIG_MAGIC_SYSRQ
static void sysrq_handle_dbg(u8 key)
{}

static const struct sysrq_key_op sysrq_dbg_op =;
#endif

void kgdb_panic(const char *msg)
{}

static void kgdb_initial_breakpoint(void)
{}

void __weak kgdb_arch_late(void)
{}

void __init dbg_late_init(void)
{}

static int
dbg_notify_reboot(struct notifier_block *this, unsigned long code, void *x)
{}

static struct notifier_block dbg_reboot_notifier =;

static void kgdb_register_callbacks(void)
{}

static void kgdb_unregister_callbacks(void)
{}

/**
 *	kgdb_register_io_module - register KGDB IO module
 *	@new_dbg_io_ops: the io ops vector
 *
 *	Register it with the KGDB core.
 */
int kgdb_register_io_module(struct kgdb_io *new_dbg_io_ops)
{}
EXPORT_SYMBOL_GPL();

/**
 *	kgdb_unregister_io_module - unregister KGDB IO module
 *	@old_dbg_io_ops: the io ops vector
 *
 *	Unregister it with the KGDB core.
 */
void kgdb_unregister_io_module(struct kgdb_io *old_dbg_io_ops)
{}
EXPORT_SYMBOL_GPL();

int dbg_io_get_char(void)
{}

/**
 * kgdb_breakpoint - generate breakpoint exception
 *
 * This function will generate a breakpoint exception.  It is used at the
 * beginning of a program to sync up with a debugger and can be used
 * otherwise as a quick means to stop program execution and "break" into
 * the debugger.
 */
noinline void kgdb_breakpoint(void)
{}
EXPORT_SYMBOL_GPL();

static int __init opt_kgdb_wait(char *str)
{}

early_param();