Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | /* * linux/kernel/panic.c * * Copyright (C) 1991, 1992 Linus Torvalds */ /* * This function is used through-out the kernel (including mm and fs) * to indicate a major problem. */ #include <linux/config.h> #include <linux/sched.h> #include <linux/delay.h> #include <linux/reboot.h> #include <linux/notifier.h> #include <linux/init.h> #include <linux/sysrq.h> #include <linux/interrupt.h> #include <linux/console.h> asmlinkage void sys_sync(void); /* it's really int */ int panic_timeout; struct notifier_block *panic_notifier_list; static int __init panic_setup(char *str) { panic_timeout = simple_strtoul(str, NULL, 0); return 1; } __setup("panic=", panic_setup); int machine_paniced; /** * 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). * * This function never returns. */ NORET_TYPE void panic(const char * fmt, ...) { static char buf[1024]; va_list args; #if defined(CONFIG_ARCH_S390) unsigned long caller = (unsigned long) __builtin_return_address(0); #endif #ifdef CONFIG_VT disable_console_blank(); #endif machine_paniced = 1; bust_spinlocks(1); va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); printk(KERN_EMERG "Kernel panic: %s\n",buf); 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); #ifdef CONFIG_SMP smp_send_stop(); #endif notifier_call_chain(&panic_notifier_list, 0, NULL); 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); mdelay(panic_timeout*1000); /* * Should we run the reboot notifier. For the moment Im * choosing not too. It might crash, be corrupt or do * more harm than good for other reasons. */ machine_restart(NULL); } #ifdef __sparc__ { extern int stop_a_enabled; /* Make sure the user can actually press L1-A */ stop_a_enabled = 1; printk("Press L1-A to return to the boot prom\n"); } #endif #if defined(CONFIG_ARCH_S390) disabled_wait(caller); #endif sti(); for(;;) { #if defined(CONFIG_X86) && defined(CONFIG_VT) extern void panic_blink(void); panic_blink(); #endif CHECK_EMERGENCY_SYNC } } /** * print_tainted - return a string to represent the kernel taint state. * * The string is overwritten by the next call to print_taint(). */ const char *print_tainted() { static char buf[20]; if (tainted) { snprintf(buf, sizeof(buf), "Tainted: %c%c", tainted & 1 ? 'P' : 'G', tainted & 2 ? 'F' : ' '); } else snprintf(buf, sizeof(buf), "Not tainted"); return(buf); } int tainted = 0; /* * A BUG() call in an inline function in a header should be avoided, * because it can seriously bloat the kernel. So here we have * helper functions. * We lose the BUG()-time file-and-line info this way, but it's * usually not very useful from an inline anyway. The backtrace * tells us what we want to know. */ void __out_of_line_bug(int line) { printk("kernel BUG in header file at line %d\n", line); BUG(); /* Satisfy __attribute__((noreturn)) */ for ( ; ; ) ; } |