aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Wessel <jason.wessel@windriver.com>2010-05-20 22:04:29 -0400
committerJason Wessel <jason.wessel@windriver.com>2010-05-20 22:04:29 -0400
commit0b4b3827db386ec6034a5aba1261025b039440c2 (patch)
treea3469de6930fe3e850c8e4c49c26a2a3b53612dd
parent29c843912a0baa7fa63033fe28e1ca7e796686a5 (diff)
x86, kgdb, init: Add early and late debug states
The kernel debugger can operate well before mm_init(), but the x86 hardware breakpoint code which uses the perf api requires that the kernel allocators are initialized. This means the kernel debug core needs to provide an optional arch specific call back to allow the initialization functions to run after the kernel has been further initialized. The kdb shell already had a similar restriction with an early initialization and late initialization. The kdb_init() was moved into the debug core's version of the late init which is called dbg_late_init(); CC: kgdb-bugreport@lists.sourceforge.net Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
-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