aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/kgdb.c17
-rw-r--r--include/linux/kgdb.h14
-rw-r--r--init/main.c4
-rw-r--r--kernel/debug/debug_core.c16
4 files changed, 42 insertions, 9 deletions
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 95b89d4cb8f1..2b71ec41869f 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -596,14 +596,15 @@ static struct notifier_block kgdb_notifier = {
596 */ 596 */
597int kgdb_arch_init(void) 597int kgdb_arch_init(void)
598{ 598{
599 return register_die_notifier(&kgdb_notifier);
600}
601
602void kgdb_arch_late(void)
603{
599 int i, cpu; 604 int i, cpu;
600 int ret;
601 struct perf_event_attr attr; 605 struct perf_event_attr attr;
602 struct perf_event **pevent; 606 struct perf_event **pevent;
603 607
604 ret = register_die_notifier(&kgdb_notifier);
605 if (ret != 0)
606 return ret;
607 /* 608 /*
608 * Pre-allocate the hw breakpoint structions in the non-atomic 609 * Pre-allocate the hw breakpoint structions in the non-atomic
609 * portion of kgdb because this operation requires mutexs to 610 * portion of kgdb because this operation requires mutexs to
@@ -615,12 +616,15 @@ int kgdb_arch_init(void)
615 attr.bp_type = HW_BREAKPOINT_W; 616 attr.bp_type = HW_BREAKPOINT_W;
616 attr.disabled = 1; 617 attr.disabled = 1;
617 for (i = 0; i < 4; i++) { 618 for (i = 0; i < 4; i++) {
619 if (breakinfo[i].pev)
620 continue;
618 breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL); 621 breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL);
619 if (IS_ERR(breakinfo[i].pev)) { 622 if (IS_ERR(breakinfo[i].pev)) {
620 printk(KERN_ERR "kgdb: Could not allocate hw breakpoints\n"); 623 printk(KERN_ERR "kgdb: Could not allocate hw"
624 "breakpoints\nDisabling the kernel debugger\n");
621 breakinfo[i].pev = NULL; 625 breakinfo[i].pev = NULL;
622 kgdb_arch_exit(); 626 kgdb_arch_exit();
623 return -1; 627 return;
624 } 628 }
625 for_each_online_cpu(cpu) { 629 for_each_online_cpu(cpu) {
626 pevent = per_cpu_ptr(breakinfo[i].pev, cpu); 630 pevent = per_cpu_ptr(breakinfo[i].pev, cpu);
@@ -631,7 +635,6 @@ int kgdb_arch_init(void)
631 } 635 }
632 } 636 }
633 } 637 }
634 return ret;
635} 638}
636 639
637/** 640/**
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
index 6c784ab6856a..9340f34d1bb5 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);
208extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle); 208extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle);
209 209
210/** 210/**
211 * kgdb_arch_late - Perform any architecture specific initalization.
212 *
213 * This function will handle the late initalization of any
214 * architecture specific callbacks. This is an optional function for
215 * handling things like late initialization of hw breakpoints. The
216 * default implementation does nothing.
217 */
218extern void kgdb_arch_late(void);
219
220
221/**
211 * struct kgdb_arch - Describe architecture specific values. 222 * struct kgdb_arch - Describe architecture specific values.
212 * @gdb_bpt_instr: The instruction to trigger a breakpoint. 223 * @gdb_bpt_instr: The instruction to trigger a breakpoint.
213 * @flags: Flags for the breakpoint, currently just %KGDB_HW_BREAKPOINT. 224 * @flags: Flags for the breakpoint, currently just %KGDB_HW_BREAKPOINT.
@@ -285,7 +296,10 @@ extern int kgdb_single_step;
285extern atomic_t kgdb_active; 296extern atomic_t kgdb_active;
286#define in_dbg_master() \ 297#define in_dbg_master() \
287 (raw_smp_processor_id() == atomic_read(&kgdb_active)) 298 (raw_smp_processor_id() == atomic_read(&kgdb_active))
299extern bool dbg_is_early;
300extern void __init dbg_late_init(void);
288#else /* ! CONFIG_KGDB */ 301#else /* ! CONFIG_KGDB */
289#define in_dbg_master() (0) 302#define in_dbg_master() (0)
303#define dbg_late_init()
290#endif /* ! CONFIG_KGDB */ 304#endif /* ! CONFIG_KGDB */
291#endif /* _KGDB_H_ */ 305#endif /* _KGDB_H_ */
diff --git a/init/main.c b/init/main.c
index 372771333d98..22881b5e95e3 100644
--- a/init/main.c
+++ b/init/main.c
@@ -62,7 +62,7 @@
62#include <linux/sched.h> 62#include <linux/sched.h>
63#include <linux/signal.h> 63#include <linux/signal.h>
64#include <linux/idr.h> 64#include <linux/idr.h>
65#include <linux/kdb.h> 65#include <linux/kgdb.h>
66#include <linux/ftrace.h> 66#include <linux/ftrace.h>
67#include <linux/async.h> 67#include <linux/async.h>
68#include <linux/kmemcheck.h> 68#include <linux/kmemcheck.h>
@@ -676,7 +676,7 @@ asmlinkage void __init start_kernel(void)
676 buffer_init(); 676 buffer_init();
677 key_init(); 677 key_init();
678 security_init(); 678 security_init();
679 kdb_init(KDB_INIT_FULL); 679 dbg_late_init();
680 vfs_caches_init(totalram_pages); 680 vfs_caches_init(totalram_pages);
681 signals_init(); 681 signals_init();
682 /* rootfs populating might need page-writeback */ 682 /* rootfs populating might need page-writeback */
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index 64b5588c9638..5cb7cd1de10c 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -78,6 +78,8 @@ static DEFINE_SPINLOCK(kgdb_registration_lock);
78static int kgdb_con_registered; 78static int kgdb_con_registered;
79/* determine if kgdb console output should be used */ 79/* determine if kgdb console output should be used */
80static int kgdb_use_con; 80static int kgdb_use_con;
81/* Flag for alternate operations for early debugging */
82bool dbg_is_early = true;
81/* Next cpu to become the master debug core */ 83/* Next cpu to become the master debug core */
82int dbg_switch_cpu; 84int dbg_switch_cpu;
83 85
@@ -777,11 +779,25 @@ static struct notifier_block kgdb_panic_event_nb = {
777 .priority = INT_MAX, 779 .priority = INT_MAX,
778}; 780};
779 781
782void __weak kgdb_arch_late(void)
783{
784}
785
786void __init dbg_late_init(void)
787{
788 dbg_is_early = false;
789 if (kgdb_io_module_registered)
790 kgdb_arch_late();
791 kdb_init(KDB_INIT_FULL);
792}
793
780static void kgdb_register_callbacks(void) 794static void kgdb_register_callbacks(void)
781{ 795{
782 if (!kgdb_io_module_registered) { 796 if (!kgdb_io_module_registered) {
783 kgdb_io_module_registered = 1; 797 kgdb_io_module_registered = 1;
784 kgdb_arch_init(); 798 kgdb_arch_init();
799 if (!dbg_is_early)
800 kgdb_arch_late();
785 atomic_notifier_chain_register(&panic_notifier_list, 801 atomic_notifier_chain_register(&panic_notifier_list,
786 &kgdb_panic_event_nb); 802 &kgdb_panic_event_nb);
787#ifdef CONFIG_MAGIC_SYSRQ 803#ifdef CONFIG_MAGIC_SYSRQ