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.



 Documentation/kernel-parameters.txt |    4 ++++
 init/main.c                         |   35 +++++++++++++++++++++++++++++++----
 2 files changed, 35 insertions(+), 4 deletions(-)

diff -puN init/main.c~initcall-debug init/main.c
--- 25/init/main.c~initcall-debug	2003-03-23 16:40:13.000000000 -0800
+++ 25-akpm/init/main.c	2003-03-23 20:38:18.000000000 -0800
@@ -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, __in
 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();
diff -puN Documentation/kernel-parameters.txt~initcall-debug Documentation/kernel-parameters.txt
--- 25/Documentation/kernel-parameters.txt~initcall-debug	2003-03-23 20:38:46.000000000 -0800
+++ 25-akpm/Documentation/kernel-parameters.txt	2003-03-23 20:42:25.000000000 -0800
@@ -390,6 +390,10 @@ running once the system is up.
 			Run specified binary instead of /sbin/init as init
 			process.
 
+	initcall_debug	[KNL] Trace initcalls as they are executed.  Useful
+			for working out where the kernel is dying during
+			startup.
+
 	initrd=		[BOOT] Specify the location of the initial ramdisk
 
 	inport_irq=	[HW] Inport (ATI XL and Microsoft) busmouse driver

_