Commit a3fa4e81 authored by Andrew Morton's avatar Andrew Morton Committed by Dave Jones

[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.
parent edad54dc
...@@ -390,6 +390,10 @@ running once the system is up. ...@@ -390,6 +390,10 @@ running once the system is up.
Run specified binary instead of /sbin/init as init Run specified binary instead of /sbin/init as init
process. 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 initrd= [BOOT] Specify the location of the initial ramdisk
inport_irq= [HW] Inport (ATI XL and Microsoft) busmouse driver inport_irq= [HW] Inport (ATI XL and Microsoft) busmouse driver
......
...@@ -463,6 +463,15 @@ asmlinkage void __init start_kernel(void) ...@@ -463,6 +463,15 @@ asmlinkage void __init start_kernel(void)
rest_init(); 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; struct task_struct *child_reaper = &init_task;
extern initcall_t __initcall_start, __initcall_end; extern initcall_t __initcall_start, __initcall_end;
...@@ -470,12 +479,30 @@ extern initcall_t __initcall_start, __initcall_end; ...@@ -470,12 +479,30 @@ extern initcall_t __initcall_start, __initcall_end;
static void __init do_initcalls(void) static void __init do_initcalls(void)
{ {
initcall_t *call; 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)();
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 */ /* Make sure there is no pending stuff from the initcall sequence */
flush_scheduled_work(); flush_scheduled_work();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment