aboutsummaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
authorAndrew Morton <akpm@digeo.com>2003-03-28 03:18:04 -0800
committerDave Jones <davej@tetrachloride.(none)>2003-03-28 03:18:04 -0800
commita3fa4e811e89f670cd21ef8f67ad3ccffce14333 (patch)
tree5c39340eb6b80cc9fab1424ccc6c4d6cda712de5 /init
parentedad54dce95e2ebc3ff0be0d8a99334789a6bf5a (diff)
downloadhistory-a3fa4e811e89f670cd21ef8f67ad3ccffce14333.tar.gz
[PATCH] initcall debug code
The patch is designed to help locate where the kernel is dying during the startup sequence. - Boot parameter "initcall_debug" causes the kernel to print out the address of each initcall before calling it. The kallsyms tables do not cover __init sections, so printing the symbolic version of these symbols doesn't work. They need to be looked up in System.map. - Detect whether an initcall returns with interrupts disabled or with a locking imbalance. If it does, complain and then try to fix it up.
Diffstat (limited to 'init')
-rw-r--r--init/main.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/init/main.c b/init/main.c
index c6367147fe2935..6fdeca1aca670c 100644
--- a/init/main.c
+++ b/init/main.c
@@ -463,6 +463,15 @@ asmlinkage void __init start_kernel(void)
rest_init();
}
+int __initdata initcall_debug;
+
+static int __init initcall_debug_setup(char *str)
+{
+ initcall_debug = 1;
+ return 1;
+}
+__setup("initcall_debug", initcall_debug_setup);
+
struct task_struct *child_reaper = &init_task;
extern initcall_t __initcall_start, __initcall_end;
@@ -470,12 +479,30 @@ extern initcall_t __initcall_start, __initcall_end;
static void __init do_initcalls(void)
{
initcall_t *call;
+ int count = preempt_count();
+
+ for (call = &__initcall_start; call < &__initcall_end; call++) {
+ char *msg;
+
+ if (initcall_debug)
+ printk("calling initcall 0x%p\n", *call);
- call = &__initcall_start;
- do {
(*call)();
- call++;
- } while (call < &__initcall_end);
+
+ msg = NULL;
+ if (preempt_count() != count) {
+ msg = "preemption imbalance";
+ preempt_count() = count;
+ }
+ if (irqs_disabled()) {
+ msg = "disabled interrupts";
+ local_irq_enable();
+ }
+ if (msg) {
+ printk("error in initcall at 0x%p: "
+ "returned with %s\n", *call, msg);
+ }
+ }
/* Make sure there is no pending stuff from the initcall sequence */
flush_scheduled_work();