*/
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
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);
}
}
}
- return ret;
}
/**
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.
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_ */
#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>
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 */
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;
.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