Commit 90b9a32d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'kdb-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb

* 'kdb-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb: (25 commits)
  kdb,debug_core: Allow the debug core to receive a panic notification
  MAINTAINERS: update kgdb, kdb, and debug_core info
  debug_core,kdb: Allow the debug core to process a recursive debug entry
  printk,kdb: capture printk() when in kdb shell
  kgdboc,kdb: Allow kdb to work on a non open console port
  kgdb: Add the ability to schedule a breakpoint via a tasklet
  mips,kgdb: kdb low level trap catch and stack trace
  powerpc,kgdb: Introduce low level trap catching
  x86,kgdb: Add low level debug hook
  kgdb: remove post_primary_code references
  kgdb,docs: Update the kgdb docs to include kdb
  kgdboc,keyboard: Keyboard driver for kdb with kgdb
  kgdb: gdb "monitor" -> kdb passthrough
  sparc,sunzilog: Add console polling support for sunzilog serial driver
  sh,sh-sci: Use NO_POLL_CHAR in the SCIF polled console code
  kgdb,8250,pl011: Return immediately from console poll
  kgdb: core changes to support kdb
  kdb: core for kgdb back end (2 of 2)
  kdb: core for kgdb back end (1 of 2)
  kgdb,blackfin: Add in kgdb_arch_set_pc for blackfin
  ...
parents 8b108c60 4402c153
This diff is collapsed.
......@@ -58,6 +58,7 @@ parameter is applicable:
ISAPNP ISA PnP code is enabled.
ISDN Appropriate ISDN support is enabled.
JOY Appropriate joystick support is enabled.
KGDB Kernel debugger support is enabled.
KVM Kernel Virtual Machine support is enabled.
LIBATA Libata driver is enabled
LP Printer support is enabled.
......@@ -1120,10 +1121,15 @@ and is between 256 and 4096 characters. It is defined in the file
use the HighMem zone if it exists, and the Normal
zone if it does not.
kgdboc= [HW] kgdb over consoles.
Requires a tty driver that supports console polling.
(only serial supported for now)
Format: <serial_device>[,baud]
kgdboc= [KGDB,HW] kgdb over consoles.
Requires a tty driver that supports console polling,
or a supported polling keyboard driver (non-usb).
Serial only format: <serial_device>[,baud]
keyboard only format: kbd
keyboard and serial format: kbd,<serial_device>[,baud]
kgdbwait [KGDB] Stop kernel execution and enter the
kernel debugger at the earliest opportunity.
kmac= [MIPS] korina ethernet MAC address.
Configure the RouterBoard 532 series on-chip
......
......@@ -3319,15 +3319,17 @@ F: include/linux/key-type.h
F: include/keys/
F: security/keys/
KGDB
KGDB / KDB /debug_core
M: Jason Wessel <jason.wessel@windriver.com>
W: http://kgdb.wiki.kernel.org/
L: kgdb-bugreport@lists.sourceforge.net
S: Maintained
F: Documentation/DocBook/kgdb.tmpl
F: drivers/misc/kgdbts.c
F: drivers/serial/kgdboc.c
F: include/linux/kdb.h
F: include/linux/kgdb.h
F: kernel/kgdb.c
F: kernel/debug/
KMEMCHECK
M: Vegard Nossum <vegardno@ifi.uio.no>
......
......@@ -20,6 +20,7 @@ enum km_type {
KM_SOFTIRQ1,
KM_L1_CACHE,
KM_L2_CACHE,
KM_KDB,
KM_TYPE_NR
};
......
......@@ -98,6 +98,11 @@ sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
gdb_regs[_CPSR] = thread_regs->ARM_cpsr;
}
void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
{
regs->ARM_pc = pc;
}
static int compiled_break;
int kgdb_arch_handle_exception(int exception_vector, int signo,
......
......@@ -439,6 +439,11 @@ int kgdb_validate_break_address(unsigned long addr)
return -EFAULT;
}
void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
{
regs->retx = ip;
}
int kgdb_arch_init(void)
{
kgdb_single_step = 0;
......
......@@ -38,6 +38,8 @@ extern int kgdb_early_setup;
extern void *saved_vectors[32];
extern void handle_exception(struct pt_regs *regs);
extern void breakinst(void);
extern int kgdb_ll_trap(int cmd, const char *str,
struct pt_regs *regs, long err, int trap, int sig);
#endif /* __KERNEL__ */
......
......@@ -180,6 +180,11 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
*(ptr++) = regs->cp0_epc;
}
void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
{
regs->cp0_epc = pc;
}
/*
* Calls linux_debug_hook before the kernel dies. If KGDB is enabled,
* then try to fall into the debugger
......@@ -198,7 +203,7 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
if (atomic_read(&kgdb_active) != -1)
kgdb_nmicallback(smp_processor_id(), regs);
if (kgdb_handle_exception(trap, compute_signal(trap), 0, regs))
if (kgdb_handle_exception(trap, compute_signal(trap), cmd, regs))
return NOTIFY_DONE;
if (atomic_read(&kgdb_setting_breakpoint))
......@@ -212,6 +217,26 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
return NOTIFY_STOP;
}
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
int kgdb_ll_trap(int cmd, const char *str,
struct pt_regs *regs, long err, int trap, int sig)
{
struct die_args args = {
.regs = regs,
.str = str,
.err = err,
.trapnr = trap,
.signr = sig,
};
if (!kgdb_io_module_registered)
return NOTIFY_DONE;
return kgdb_mips_notify(NULL, cmd, &args);
}
#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
static struct notifier_block kgdb_notifier = {
.notifier_call = kgdb_mips_notify,
};
......
......@@ -26,6 +26,7 @@
#include <linux/kgdb.h>
#include <linux/kdebug.h>
#include <linux/notifier.h>
#include <linux/kdb.h>
#include <asm/bootinfo.h>
#include <asm/branch.h>
......@@ -185,6 +186,11 @@ void show_stack(struct task_struct *task, unsigned long *sp)
regs.regs[29] = task->thread.reg29;
regs.regs[31] = 0;
regs.cp0_epc = task->thread.reg31;
#ifdef CONFIG_KGDB_KDB
} else if (atomic_read(&kgdb_active) != -1 &&
kdb_current_regs) {
memcpy(&regs, kdb_current_regs, sizeof(regs));
#endif /* CONFIG_KGDB_KDB */
} else {
prepare_frametrace(&regs);
}
......@@ -360,6 +366,8 @@ void __noreturn die(const char * str, struct pt_regs * regs)
unsigned long dvpret = dvpe();
#endif /* CONFIG_MIPS_MT_SMTC */
notify_die(DIE_OOPS, str, (struct pt_regs *)regs, SIGSEGV, 0, 0);
console_verbose();
spin_lock_irq(&die_lock);
bust_spinlocks(1);
......@@ -704,6 +712,11 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
siginfo_t info;
char b[40];
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
if (kgdb_ll_trap(DIE_TRAP, str, regs, code, 0, 0) == NOTIFY_STOP)
return;
#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
if (notify_die(DIE_TRAP, str, regs, code, 0, 0) == NOTIFY_STOP)
return;
......
......@@ -26,6 +26,7 @@ enum km_type {
KM_SOFTIRQ1,
KM_PPC_SYNC_PAGE,
KM_PPC_SYNC_ICACHE,
KM_KDB,
KM_TYPE_NR
};
......
......@@ -20,6 +20,7 @@
#include <linux/smp.h>
#include <linux/signal.h>
#include <linux/ptrace.h>
#include <linux/kdebug.h>
#include <asm/current.h>
#include <asm/processor.h>
#include <asm/machdep.h>
......@@ -115,7 +116,8 @@ void kgdb_roundup_cpus(unsigned long flags)
/* KGDB functions to use existing PowerPC64 hooks. */
static int kgdb_debugger(struct pt_regs *regs)
{
return kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
return !kgdb_handle_exception(1, computeSignal(TRAP(regs)),
DIE_OOPS, regs);
}
static int kgdb_handle_breakpoint(struct pt_regs *regs)
......@@ -123,7 +125,7 @@ static int kgdb_handle_breakpoint(struct pt_regs *regs)
if (user_mode(regs))
return 0;
if (kgdb_handle_exception(0, SIGTRAP, 0, regs) != 0)
if (kgdb_handle_exception(1, SIGTRAP, 0, regs) != 0)
return 0;
if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
......@@ -309,6 +311,11 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
(unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
}
void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
{
regs->nip = pc;
}
/*
* This function does PowerPC specific procesing for interfacing to gdb.
*/
......
......@@ -815,12 +815,15 @@ void __kprobes program_check_exception(struct pt_regs *regs)
return;
}
if (reason & REASON_TRAP) {
/* Debugger is first in line to stop recursive faults in
* rcu_lock, notify_die, or atomic_notifier_call_chain */
if (debugger_bpt(regs))
return;
/* trap exception */
if (notify_die(DIE_BPT, "breakpoint", regs, 5, 5, SIGTRAP)
== NOTIFY_STOP)
return;
if (debugger_bpt(regs))
return;
if (!(regs->msr & MSR_PR) && /* not user-mode */
report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) {
......
......@@ -237,6 +237,18 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
return -1;
}
unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
{
if (exception == 60)
return instruction_pointer(regs) - 2;
return instruction_pointer(regs);
}
void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
{
regs->pc = ip;
}
/*
* The primary entry points for the kgdb debug trap table entries.
*/
......@@ -247,7 +259,7 @@ BUILD_TRAP_HANDLER(singlestep)
local_irq_save(flags);
regs->pc -= instruction_size(__raw_readw(regs->pc - 4));
kgdb_handle_exception(vec >> 2, SIGTRAP, 0, regs);
kgdb_handle_exception(0, SIGTRAP, 0, regs);
local_irq_restore(flags);
}
......
......@@ -158,6 +158,12 @@ void kgdb_arch_exit(void)
{
}
void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
{
regs->pc = ip;
regs->npc = regs->pc + 4;
}
struct kgdb_arch arch_kgdb_ops = {
/* Breakpoint instruction: ta 0x7d */
.gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x7d },
......
......@@ -181,6 +181,12 @@ void kgdb_arch_exit(void)
{
}
void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
{
regs->tpc = ip;
regs->tnpc = regs->tpc + 4;
}
struct kgdb_arch arch_kgdb_ops = {
/* Breakpoint instruction: ta 0x72 */
.gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x72 },
......
......@@ -76,4 +76,7 @@ static inline void arch_kgdb_breakpoint(void)
#define BREAK_INSTR_SIZE 1
#define CACHE_FLUSH_IS_SAFE 1
extern int kgdb_ll_trap(int cmd, const char *str,
struct pt_regs *regs, long err, int trap, int sig);
#endif /* _ASM_X86_KGDB_H */
......@@ -47,20 +47,8 @@
#include <asm/debugreg.h>
#include <asm/apicdef.h>
#include <asm/system.h>
#include <asm/apic.h>
/*
* Put the error code here just in case the user cares:
*/
static int gdb_x86errcode;
/*
* Likewise, the vector number here (since GDB only gets the signal
* number through the usual means, and that's not very specific):
*/
static int gdb_x86vector = -1;
/**
* pt_regs_to_gdb_regs - Convert ptrace regs to GDB regs
* @gdb_regs: A pointer to hold the registers in the order GDB wants.
......@@ -399,23 +387,6 @@ void kgdb_disable_hw_debug(struct pt_regs *regs)
}
}
/**
* kgdb_post_primary_code - Save error vector/code numbers.
* @regs: Original pt_regs.
* @e_vector: Original error vector.
* @err_code: Original error code.
*
* This is needed on architectures which support SMP and KGDB.
* This function is called after all the slave cpus have been put
* to a know spin state and the primary CPU has control over KGDB.
*/
void kgdb_post_primary_code(struct pt_regs *regs, int e_vector, int err_code)
{
/* primary processor is completely in the debugger */
gdb_x86vector = e_vector;
gdb_x86errcode = err_code;
}
#ifdef CONFIG_SMP
/**
* kgdb_roundup_cpus - Get other CPUs into a holding pattern
......@@ -567,7 +538,7 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
return NOTIFY_DONE;
}
if (kgdb_handle_exception(args->trapnr, args->signr, args->err, regs))
if (kgdb_handle_exception(args->trapnr, args->signr, cmd, regs))
return NOTIFY_DONE;
/* Must touch watchdog before return to normal operation */
......@@ -575,6 +546,26 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
return NOTIFY_STOP;
}
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
int kgdb_ll_trap(int cmd, const char *str,
struct pt_regs *regs, long err, int trap, int sig)
{
struct die_args args = {
.regs = regs,
.str = str,
.err = err,
.trapnr = trap,
.signr = sig,
};
if (!kgdb_io_module_registered)
return NOTIFY_DONE;
return __kgdb_notify(&args, cmd);
}
#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
static int
kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
{
......@@ -690,6 +681,11 @@ unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
return instruction_pointer(regs);
}
void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
{
regs->ip = ip;
}
struct kgdb_arch arch_kgdb_ops = {
/* Breakpoint instruction: */
.gdb_bpt_instr = { 0xcc },
......
......@@ -15,6 +15,7 @@
#include <linux/kprobes.h>
#include <linux/uaccess.h>
#include <linux/kdebug.h>
#include <linux/kgdb.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/ptrace.h>
......@@ -451,6 +452,11 @@ void restart_nmi(void)
/* May run on IST stack. */
dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)
{
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
== NOTIFY_STOP)
return;
#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
#ifdef CONFIG_KPROBES
if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
== NOTIFY_STOP)
......
......@@ -1891,8 +1891,8 @@ static int serial8250_get_poll_char(struct uart_port *port)
struct uart_8250_port *up = (struct uart_8250_port *)port;
unsigned char lsr = serial_inp(up, UART_LSR);
while (!(lsr & UART_LSR_DR))
lsr = serial_inp(up, UART_LSR);
if (!(lsr & UART_LSR_DR))
return NO_POLL_CHAR;
return serial_inp(up, UART_RX);
}
......
......@@ -342,9 +342,9 @@ static int pl010_get_poll_char(struct uart_port *port)
struct uart_amba_port *uap = (struct uart_amba_port *)port;
unsigned int status;
do {
status = readw(uap->port.membase + UART01x_FR);
} while (status & UART01x_FR_RXFE);
status = readw(uap->port.membase + UART01x_FR);
if (status & UART01x_FR_RXFE)
return NO_POLL_CHAR;
return readw(uap->port.membase + UART01x_DR);
}
......
......@@ -14,7 +14,9 @@
#include <linux/kernel.h>
#include <linux/ctype.h>
#include <linux/kgdb.h>
#include <linux/kdb.h>
#include <linux/tty.h>
#include <linux/console.h>
#define MAX_CONFIG_LEN 40
......@@ -32,6 +34,40 @@ static struct kparam_string kps = {
static struct tty_driver *kgdb_tty_driver;
static int kgdb_tty_line;
#ifdef CONFIG_KDB_KEYBOARD
static int kgdboc_register_kbd(char **cptr)
{
if (strncmp(*cptr, "kbd", 3) == 0) {
if (kdb_poll_idx < KDB_POLL_FUNC_MAX) {
kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char;
kdb_poll_idx++;
if (cptr[0][3] == ',')
*cptr += 4;
else
return 1;
}
}
return 0;
}
static void kgdboc_unregister_kbd(void)
{
int i;
for (i = 0; i < kdb_poll_idx; i++) {
if (kdb_poll_funcs[i] == kdb_get_kbd_char) {
kdb_poll_idx--;
kdb_poll_funcs[i] = kdb_poll_funcs[kdb_poll_idx];
kdb_poll_funcs[kdb_poll_idx] = NULL;
i--;
}
}
}
#else /* ! CONFIG_KDB_KEYBOARD */
#define kgdboc_register_kbd(x) 0
#define kgdboc_unregister_kbd()
#endif /* ! CONFIG_KDB_KEYBOARD */
static int kgdboc_option_setup(char *opt)
{
if (strlen(opt) > MAX_CONFIG_LEN) {
......@@ -45,25 +81,51 @@ static int kgdboc_option_setup(char *opt)
__setup("kgdboc=", kgdboc_option_setup);
static void cleanup_kgdboc(void)
{
kgdboc_unregister_kbd();
if (configured == 1)
kgdb_unregister_io_module(&kgdboc_io_ops);
}
static int configure_kgdboc(void)
{
struct tty_driver *p;
int tty_line = 0;
int err;
char *cptr = config;
struct console *cons;
err = kgdboc_option_setup(config);
if (err || !strlen(config) || isspace(config[0]))
goto noconfig;
err = -ENODEV;
kgdboc_io_ops.is_console = 0;
kgdb_tty_driver = NULL;
p = tty_find_polling_driver(config, &tty_line);
if (kgdboc_register_kbd(&cptr))
goto do_register;
p = tty_find_polling_driver(cptr, &tty_line);
if (!p)
goto noconfig;
cons = console_drivers;
while (cons) {
int idx;
if (cons->device && cons->device(cons, &idx) == p &&
idx == tty_line) {
kgdboc_io_ops.is_console = 1;
break;
}
cons = cons->next;
}
kgdb_tty_driver = p;
kgdb_tty_line = tty_line;
do_register:
err = kgdb_register_io_module(&kgdboc_io_ops);
if (err)
goto noconfig;
......@@ -75,6 +137,7 @@ static int configure_kgdboc(void)
noconfig:
config[0] = 0;
configured = 0;
cleanup_kgdboc();
return err;
}
......@@ -88,20 +151,18 @@ static int __init init_kgdboc(void)
return configure_kgdboc();
}
static void cleanup_kgdboc(void)
{
if (configured == 1)
kgdb_unregister_io_module(&kgdboc_io_ops);
}
static int kgdboc_get_char(void)
{
if (!kgdb_tty_driver)
return -1;
return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver,
kgdb_tty_line);
}
static void kgdboc_put_char(u8 chr)
{
if (!kgdb_tty_driver)
return;
kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver,
kgdb_tty_line, chr);
}
......
......@@ -151,7 +151,11 @@ static int sci_poll_get_char(struct uart_port *port)
handle_error(port);
continue;
}
} while (!(status & SCxSR_RDxF(port)));
break;
} while (1);
if (!(status & SCxSR_RDxF(port)))
return NO_POLL_CHAR;
c = sci_in(port, SCxRDR);
......
......@@ -102,6 +102,8 @@ struct uart_sunzilog_port {
#endif
};
static void sunzilog_putchar(struct uart_port *port, int ch);
#define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel __iomem *)((PORT)->membase))
#define UART_ZILOG(PORT) ((struct uart_sunzilog_port *)(PORT))
......@@ -996,6 +998,50 @@ static int sunzilog_verify_port(struct uart_port *port, struct serial_struct *se
return -EINVAL;
}
#ifdef CONFIG_CONSOLE_POLL
static int sunzilog_get_poll_char(struct uart_port *port)
{
unsigned char ch, r1;
struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
struct zilog_channel __iomem *channel
= ZILOG_CHANNEL_FROM_PORT(&up->port);
r1 = read_zsreg(channel, R1);
if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
writeb(ERR_RES, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
}
ch = readb(&channel->control);
ZSDELAY();
/* This funny hack depends upon BRK_ABRT not interfering
* with the other bits we care about in R1.
*/
if (ch & BRK_ABRT)
r1 |= BRK_ABRT;
if (!(ch & Rx_CH_AV))
return NO_POLL_CHAR;
ch = readb(&channel->data);
ZSDELAY();
ch &= up->parity_mask;
return ch;
}
static void sunzilog_put_poll_char(struct uart_port *port,
unsigned char ch)
{
struct uart_sunzilog_port *up = (struct uart_sunzilog_port *)port;
sunzilog_putchar(&up->port, ch);
}
#endif /* CONFIG_CONSOLE_POLL */
static struct uart_ops sunzilog_pops = {
.tx_empty = sunzilog_tx_empty,
.set_mctrl = sunzilog_set_mctrl,
......@@ -1013,6 +1059,10 @@ static struct uart_ops sunzilog_pops = {
.request_port = sunzilog_request_port,
.config_port = sunzilog_config_port,
.verify_port = sunzilog_verify_port,
#ifdef CONFIG_CONSOLE_POLL
.poll_get_char = sunzilog_get_poll_char,
.poll_put_char = sunzilog_put_poll_char,
#endif
};
static int uart_chip_count;
......
......@@ -28,7 +28,8 @@ KMAP_D(15) KM_UML_USERCOPY,
KMAP_D(16) KM_IRQ_PTE,
KMAP_D(17) KM_NMI,
KMAP_D(18) KM_NMI_PTE,
KMAP_D(19) KM_TYPE_NR
KMAP_D(19) KM_KDB,
KMAP_D(20) KM_TYPE_NR
};
#undef KMAP_D
......
#ifndef _KDB_H
#define _KDB_H
/*
* Kernel Debugger Architecture Independent Global Headers
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (c) 2000-2007 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
* Copyright (C) 2009 Jason Wessel <jason.wessel@windriver.com>
*/
#ifdef CONFIG_KGDB_KDB
#include <linux/init.h>
#include <linux/sched.h>
#include <asm/atomic.h>
#define KDB_POLL_FUNC_MAX 5
extern int kdb_poll_idx;
/*
* kdb_initial_cpu is initialized to -1, and is set to the cpu
* number whenever the kernel debugger is entered.
*/
extern int kdb_initial_cpu;
extern atomic_t kdb_event;
/*
* kdb_diemsg
*
* Contains a pointer to the last string supplied to the
* kernel 'die' panic function.
*/
extern const char *kdb_diemsg;
#define KDB_FLAG_EARLYKDB (1 << 0) /* set from boot parameter kdb=early */
#define KDB_FLAG_CATASTROPHIC (1 << 1) /* A catastrophic event has occurred */
#define KDB_FLAG_CMD_INTERRUPT (1 << 2) /* Previous command was interrupted */
#define KDB_FLAG_NOIPI (1 << 3) /* Do not send IPIs */
#define KDB_FLAG_ONLY_DO_DUMP (1 << 4) /* Only do a dump, used when
* kdb is off */
#define KDB_FLAG_NO_CONSOLE (1 << 5) /* No console is available,
* kdb is disabled */
#define KDB_FLAG_NO_VT_CONSOLE (1 << 6) /* No VT console is available, do
* not use keyboard */
#define KDB_FLAG_NO_I8042 (1 << 7) /* No i8042 chip is available, do
* not use keyboard */