diff options
-rw-r--r-- | arch/x86/kernel/kgdb.c | 17 | ||||
-rw-r--r-- | include/linux/kgdb.h | 14 | ||||
-rw-r--r-- | init/main.c | 4 | ||||
-rw-r--r-- | kernel/debug/debug_core.c | 16 |
4 files changed, 42 insertions, 9 deletions
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 95b89d4cb8f..2b71ec41869 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -596,14 +596,15 @@ static struct notifier_block kgdb_notifier = { */ int kgdb_arch_init(void) { + return register_die_notifier(&kgdb_notifier); +} + +void kgdb_arch_late(void) +{ int i, cpu; - int ret; struct perf_event_attr attr; struct perf_event **pevent; - ret = register_die_notifier(&kgdb_notifier); - if (ret != 0) - return ret; /* * Pre-allocate the hw breakpoint structions in the non-atomic * portion of kgdb because this operation requires mutexs to @@ -615,12 +616,15 @@ int kgdb_arch_init(void) attr.bp_type = HW_BREAKPOINT_W; attr.disabled = 1; for (i = 0; i < 4; i++) { + if (breakinfo[i].pev) + continue; breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL); if (IS_ERR(breakinfo[i].pev)) { - printk(KERN_ERR "kgdb: Could not allocate hw breakpoints\n"); + printk(KERN_ERR "kgdb: Could not allocate hw" + "breakpoints\nDisabling the kernel debugger\n"); breakinfo[i].pev = NULL; kgdb_arch_exit(); - return -1; + return; } for_each_online_cpu(cpu) { pevent = per_cpu_ptr(breakinfo[i].pev, cpu); @@ -631,7 +635,6 @@ int kgdb_arch_init(void) } } } - return ret; } /** diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index 6c784ab6856..9340f34d1bb 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -208,6 +208,17 @@ extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr); extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle); /** + * kgdb_arch_late - Perform any architecture specific initalization. + * + * This function will handle the late initalization of any + * architecture specific callbacks. This is an optional function for + * handling things like late initialization of hw breakpoints. The + * default implementation does nothing. + */ +extern void kgdb_arch_late(void); + + +/** * struct kgdb_arch - Describe architecture specific values. * @gdb_bpt_instr: The instruction to trigger a breakpoint. * @flags: Flags for the breakpoint, currently just %KGDB_HW_BREAKPOINT. @@ -285,7 +296,10 @@ extern int kgdb_single_step; extern atomic_t kgdb_active; #define in_dbg_master() \ (raw_smp_processor_id() == atomic_read(&kgdb_active)) +extern bool dbg_is_early; +extern void __init dbg_late_init(void); #else /* ! CONFIG_KGDB */ #define in_dbg_master() (0) +#define dbg_late_init() #endif /* ! CONFIG_KGDB */ #endif /* _KGDB_H_ */ diff --git a/init/main.c b/init/main.c index 372771333d9..22881b5e95e 100644 --- a/init/main.c +++ b/init/main.c @@ -62,7 +62,7 @@ #include <linux/sched.h> #include <linux/signal.h> #include <linux/idr.h> -#include <linux/kdb.h> +#include <linux/kgdb.h> #include <linux/ftrace.h> #include <linux/async.h> #include <linux/kmemcheck.h> @@ -676,7 +676,7 @@ asmlinkage void __init start_kernel(void) buffer_init(); key_init(); security_init(); - kdb_init(KDB_INIT_FULL); + dbg_late_init(); vfs_caches_init(totalram_pages); signals_init(); /* rootfs populating might need page-writeback */ diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 64b5588c963..5cb7cd1de10 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c @@ -78,6 +78,8 @@ static DEFINE_SPINLOCK(kgdb_registration_lock); 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; @@ -777,11 +779,25 @@ static struct notifier_block kgdb_panic_event_nb = { .priority = INT_MAX, }; +void __weak kgdb_arch_late(void) +{ +} + +void __init dbg_late_init(void) +{ + dbg_is_early = false; + if (kgdb_io_module_registered) + kgdb_arch_late(); + kdb_init(KDB_INIT_FULL); +} + static void kgdb_register_callbacks(void) { if (!kgdb_io_module_registered) { kgdb_io_module_registered = 1; kgdb_arch_init(); + if (!dbg_is_early) + kgdb_arch_late(); atomic_notifier_chain_register(&panic_notifier_list, &kgdb_panic_event_nb); #ifdef CONFIG_MAGIC_SYSRQ |