diff options
author | Andrew Morton <akpm@digeo.com> | 2003-03-28 03:18:04 -0800 |
---|---|---|
committer | Dave Jones <davej@tetrachloride.(none)> | 2003-03-28 03:18:04 -0800 |
commit | a3fa4e811e89f670cd21ef8f67ad3ccffce14333 (patch) | |
tree | 5c39340eb6b80cc9fab1424ccc6c4d6cda712de5 /init | |
parent | edad54dce95e2ebc3ff0be0d8a99334789a6bf5a (diff) | |
download | history-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.c | 35 |
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(); |