Skip to content

Commit

Permalink
Merge branch 'kdb-merge' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
  ...
  • Loading branch information
Linus Torvalds committed May 21, 2010
2 parents 8b108c6 + 4402c15 commit 90b9a32
Show file tree
Hide file tree
Showing 51 changed files with 9,240 additions and 2,016 deletions.
692 changes: 516 additions & 176 deletions Documentation/DocBook/kgdb.tmpl

Large diffs are not rendered by default.

14 changes: 10 additions & 4 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
1 change: 1 addition & 0 deletions arch/arm/include/asm/kmap_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ enum km_type {
KM_SOFTIRQ1,
KM_L1_CACHE,
KM_L2_CACHE,
KM_KDB,
KM_TYPE_NR
};

Expand Down
5 changes: 5 additions & 0 deletions arch/arm/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions arch/blackfin/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions arch/mips/include/asm/kgdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__ */

Expand Down
27 changes: 26 additions & 1 deletion arch/mips/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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))
Expand All @@ -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,
};
Expand Down
13 changes: 13 additions & 0 deletions arch/mips/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/include/asm/kmap_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ enum km_type {
KM_SOFTIRQ1,
KM_PPC_SYNC_PAGE,
KM_PPC_SYNC_ICACHE,
KM_KDB,
KM_TYPE_NR
};

Expand Down
11 changes: 9 additions & 2 deletions arch/powerpc/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -115,15 +116,16 @@ 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)
{
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))
Expand Down Expand Up @@ -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.
*/
Expand Down
7 changes: 5 additions & 2 deletions arch/powerpc/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
14 changes: 13 additions & 1 deletion arch/sh/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -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);
}

Expand Down
6 changes: 6 additions & 0 deletions arch/sparc/kernel/kgdb_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down
6 changes: 6 additions & 0 deletions arch/sparc/kernel/kgdb_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down
3 changes: 3 additions & 0 deletions arch/x86/include/asm/kgdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
56 changes: 26 additions & 30 deletions arch/x86/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -567,14 +538,34 @@ 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 */
touch_nmi_watchdog();
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)
{
Expand Down Expand Up @@ -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 },
Expand Down
Loading

0 comments on commit 90b9a32

Please sign in to comment.