X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=kernel%2Fpanic.c;h=047cd09e029093d4617d661022822ac1b44caf95;hb=70e85d5472b5f8ef77ca1b1ff0546117f76e7ddd;hp=37f3e82def52e34a78ebde925277437563bbd7bd;hpb=1a70aa0b036ac86f9aa2395cfd0e75dc7010c490;p=linux-2.6.git diff --git a/kernel/panic.c b/kernel/panic.c index 37f3e82de..047cd09e0 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -16,20 +16,18 @@ #include #include #include -#include #include #include -#ifdef CONFIG_KEXEC #include -#endif +#include int panic_timeout = 900; int panic_on_oops = 1; int tainted; -void (*dump_function_ptr)(const char *, const struct pt_regs *) = 0; +unsigned int crashed; +int crash_dump_on; EXPORT_SYMBOL(panic_timeout); -EXPORT_SYMBOL(dump_function_ptr); struct notifier_block *panic_notifier_list; @@ -42,21 +40,27 @@ static int __init panic_setup(char *str) } __setup("panic=", panic_setup); -int netdump_mode = 0; -EXPORT_SYMBOL_GPL(netdump_mode); +static long no_blink(long time) +{ + return 0; +} + +/* Returns how long it waited in ms */ +long (*panic_blink)(long time); +EXPORT_SYMBOL(panic_blink); /** * panic - halt the system * @fmt: The text string to print * - * Display a message, then perform cleanups. Functions in the panic - * notifier list are called after the filesystem cache is flushed (when possible). + * Display a message, then perform cleanups. * * This function never returns. */ NORET_TYPE void panic(const char * fmt, ...) { + long i; static char buf[1024]; va_list args; #if defined(CONFIG_ARCH_S390) @@ -67,45 +71,36 @@ NORET_TYPE void panic(const char * fmt, ...) va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); - - printk(KERN_EMERG "Kernel panic: %s\n",buf); - if (netdump_func) + printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf); + dump_stack(); + if (crashdump_func()) BUG(); - if (in_interrupt()) - printk(KERN_EMERG "In interrupt handler - not syncing\n"); - else if (!current->pid) - printk(KERN_EMERG "In idle task - not syncing\n"); - else - sys_sync(); bust_spinlocks(0); - notifier_call_chain(&panic_notifier_list, 0, buf); - + /* If we have crashed, perform a kexec reboot, for dump write-out */ + crash_machine_kexec(); + #ifdef CONFIG_SMP smp_send_stop(); #endif - if (panic_timeout > 0) { - int i; + notifier_call_chain(&panic_notifier_list, 0, buf); + + if (!panic_blink) + panic_blink = no_blink; + + if (panic_timeout > 0) + { /* * Delay timeout seconds before rebooting the machine. * We can't use the "normal" timers since we just panicked.. */ printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout); -#ifdef CONFIG_KEXEC -{ - struct kimage *image; - image = xchg(&kexec_image, 0); - if (image) { - printk(KERN_EMERG "by starting a new kernel ..\n"); - mdelay(panic_timeout*1000); - machine_kexec(image); - } - } -#endif - for (i = 0; i < panic_timeout; i++) { + for (i = 0; i < panic_timeout*1000; ) { touch_nmi_watchdog(); - mdelay(1000); + i += panic_blink(i); + mdelay(1); + i++; } /* * Should we run the reboot notifier. For the moment Im @@ -117,17 +112,20 @@ NORET_TYPE void panic(const char * fmt, ...) #ifdef __sparc__ { extern int stop_a_enabled; - /* Make sure the user can actually press L1-A */ + /* Make sure the user can actually press Stop-A (L1-A) */ stop_a_enabled = 1; - printk(KERN_EMERG "Press L1-A to return to the boot prom\n"); + printk(KERN_EMERG "Press Stop-A (L1-A) to return to the boot prom\n"); } #endif #if defined(CONFIG_ARCH_S390) disabled_wait(caller); #endif local_irq_enable(); - for (;;) - ; + for (i = 0;;) { + i += panic_blink(i); + mdelay(1); + i++; + } } EXPORT_SYMBOL(panic); @@ -138,6 +136,9 @@ EXPORT_SYMBOL(panic); * 'P' - Proprietary module has been loaded. * 'F' - Module has been forcibly loaded. * 'S' - SMP with CPUs not designed for SMP. + * 'R' - User forced a module unload. + * 'M' - Machine had a machine check experience. + * 'B' - System has hit bad_page. * * The string is overwritten by the next call to print_taint(). */ @@ -146,12 +147,29 @@ const char *print_tainted(void) { static char buf[20]; if (tainted) { - snprintf(buf, sizeof(buf), "Tainted: %c%c%c", + snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c", tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G', tainted & TAINT_FORCED_MODULE ? 'F' : ' ', - tainted & TAINT_UNSAFE_SMP ? 'S' : ' '); + tainted & TAINT_UNSAFE_SMP ? 'S' : ' ', + tainted & TAINT_FORCED_RMMOD ? 'R' : ' ', + tainted & TAINT_MACHINE_CHECK ? 'M' : ' ', + tainted & TAINT_BAD_PAGE ? 'B' : ' '); } else snprintf(buf, sizeof(buf), "Not tainted"); return(buf); } +EXPORT_SYMBOL(print_tainted); + +void add_taint(unsigned flag) +{ + tainted |= flag; +} +EXPORT_SYMBOL(add_taint); + +int check_tainted(void) +{ + return tainted; +} +EXPORT_SYMBOL_GPL(check_tainted); +