diff options
Diffstat (limited to 'arch/i386/kernel/traps.c')
-rw-r--r-- | arch/i386/kernel/traps.c | 150 |
1 files changed, 98 insertions, 52 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index c34d1bfc5161..0aaebf3e1cfa 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c | |||
@@ -112,33 +112,38 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) | |||
112 | p < (void *)tinfo + THREAD_SIZE - 3; | 112 | p < (void *)tinfo + THREAD_SIZE - 3; |
113 | } | 113 | } |
114 | 114 | ||
115 | static void print_addr_and_symbol(unsigned long addr, char *log_lvl) | ||
116 | { | ||
117 | printk(log_lvl); | ||
118 | printk(" [<%08lx>] ", addr); | ||
119 | print_symbol("%s", addr); | ||
120 | printk("\n"); | ||
121 | } | ||
122 | |||
115 | static inline unsigned long print_context_stack(struct thread_info *tinfo, | 123 | static inline unsigned long print_context_stack(struct thread_info *tinfo, |
116 | unsigned long *stack, unsigned long ebp) | 124 | unsigned long *stack, unsigned long ebp, |
125 | char *log_lvl) | ||
117 | { | 126 | { |
118 | unsigned long addr; | 127 | unsigned long addr; |
119 | 128 | ||
120 | #ifdef CONFIG_FRAME_POINTER | 129 | #ifdef CONFIG_FRAME_POINTER |
121 | while (valid_stack_ptr(tinfo, (void *)ebp)) { | 130 | while (valid_stack_ptr(tinfo, (void *)ebp)) { |
122 | addr = *(unsigned long *)(ebp + 4); | 131 | addr = *(unsigned long *)(ebp + 4); |
123 | printk(" [<%08lx>] ", addr); | 132 | print_addr_and_symbol(addr, log_lvl); |
124 | print_symbol("%s", addr); | ||
125 | printk("\n"); | ||
126 | ebp = *(unsigned long *)ebp; | 133 | ebp = *(unsigned long *)ebp; |
127 | } | 134 | } |
128 | #else | 135 | #else |
129 | while (valid_stack_ptr(tinfo, stack)) { | 136 | while (valid_stack_ptr(tinfo, stack)) { |
130 | addr = *stack++; | 137 | addr = *stack++; |
131 | if (__kernel_text_address(addr)) { | 138 | if (__kernel_text_address(addr)) |
132 | printk(" [<%08lx>]", addr); | 139 | print_addr_and_symbol(addr, log_lvl); |
133 | print_symbol(" %s", addr); | ||
134 | printk("\n"); | ||
135 | } | ||
136 | } | 140 | } |
137 | #endif | 141 | #endif |
138 | return ebp; | 142 | return ebp; |
139 | } | 143 | } |
140 | 144 | ||
141 | void show_trace(struct task_struct *task, unsigned long * stack) | 145 | static void show_trace_log_lvl(struct task_struct *task, |
146 | unsigned long *stack, char *log_lvl) | ||
142 | { | 147 | { |
143 | unsigned long ebp; | 148 | unsigned long ebp; |
144 | 149 | ||
@@ -157,15 +162,21 @@ void show_trace(struct task_struct *task, unsigned long * stack) | |||
157 | struct thread_info *context; | 162 | struct thread_info *context; |
158 | context = (struct thread_info *) | 163 | context = (struct thread_info *) |
159 | ((unsigned long)stack & (~(THREAD_SIZE - 1))); | 164 | ((unsigned long)stack & (~(THREAD_SIZE - 1))); |
160 | ebp = print_context_stack(context, stack, ebp); | 165 | ebp = print_context_stack(context, stack, ebp, log_lvl); |
161 | stack = (unsigned long*)context->previous_esp; | 166 | stack = (unsigned long*)context->previous_esp; |
162 | if (!stack) | 167 | if (!stack) |
163 | break; | 168 | break; |
164 | printk(" =======================\n"); | 169 | printk(KERN_EMERG " =======================\n"); |
165 | } | 170 | } |
166 | } | 171 | } |
167 | 172 | ||
168 | void show_stack(struct task_struct *task, unsigned long *esp) | 173 | void show_trace(struct task_struct *task, unsigned long * stack) |
174 | { | ||
175 | show_trace_log_lvl(task, stack, ""); | ||
176 | } | ||
177 | |||
178 | static void show_stack_log_lvl(struct task_struct *task, unsigned long *esp, | ||
179 | char *log_lvl) | ||
169 | { | 180 | { |
170 | unsigned long *stack; | 181 | unsigned long *stack; |
171 | int i; | 182 | int i; |
@@ -178,15 +189,26 @@ void show_stack(struct task_struct *task, unsigned long *esp) | |||
178 | } | 189 | } |
179 | 190 | ||
180 | stack = esp; | 191 | stack = esp; |
192 | printk(log_lvl); | ||
181 | for(i = 0; i < kstack_depth_to_print; i++) { | 193 | for(i = 0; i < kstack_depth_to_print; i++) { |
182 | if (kstack_end(stack)) | 194 | if (kstack_end(stack)) |
183 | break; | 195 | break; |
184 | if (i && ((i % 8) == 0)) | 196 | if (i && ((i % 8) == 0)) { |
185 | printk("\n "); | 197 | printk("\n"); |
198 | printk(log_lvl); | ||
199 | printk(" "); | ||
200 | } | ||
186 | printk("%08lx ", *stack++); | 201 | printk("%08lx ", *stack++); |
187 | } | 202 | } |
188 | printk("\nCall Trace:\n"); | 203 | printk("\n"); |
189 | show_trace(task, esp); | 204 | printk(log_lvl); |
205 | printk("Call Trace:\n"); | ||
206 | show_trace_log_lvl(task, esp, log_lvl); | ||
207 | } | ||
208 | |||
209 | void show_stack(struct task_struct *task, unsigned long *esp) | ||
210 | { | ||
211 | show_stack_log_lvl(task, esp, ""); | ||
190 | } | 212 | } |
191 | 213 | ||
192 | /* | 214 | /* |
@@ -216,18 +238,18 @@ void show_registers(struct pt_regs *regs) | |||
216 | ss = regs->xss & 0xffff; | 238 | ss = regs->xss & 0xffff; |
217 | } | 239 | } |
218 | print_modules(); | 240 | print_modules(); |
219 | printk("CPU: %d\nEIP: %04x:[<%08lx>] %s VLI\nEFLAGS: %08lx" | 241 | printk(KERN_EMERG "CPU: %d\nEIP: %04x:[<%08lx>] %s VLI\n" |
220 | " (%s) \n", | 242 | "EFLAGS: %08lx (%s) \n", |
221 | smp_processor_id(), 0xffff & regs->xcs, regs->eip, | 243 | smp_processor_id(), 0xffff & regs->xcs, regs->eip, |
222 | print_tainted(), regs->eflags, system_utsname.release); | 244 | print_tainted(), regs->eflags, system_utsname.release); |
223 | print_symbol("EIP is at %s\n", regs->eip); | 245 | print_symbol(KERN_EMERG "EIP is at %s\n", regs->eip); |
224 | printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", | 246 | printk(KERN_EMERG "eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", |
225 | regs->eax, regs->ebx, regs->ecx, regs->edx); | 247 | regs->eax, regs->ebx, regs->ecx, regs->edx); |
226 | printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", | 248 | printk(KERN_EMERG "esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", |
227 | regs->esi, regs->edi, regs->ebp, esp); | 249 | regs->esi, regs->edi, regs->ebp, esp); |
228 | printk("ds: %04x es: %04x ss: %04x\n", | 250 | printk(KERN_EMERG "ds: %04x es: %04x ss: %04x\n", |
229 | regs->xds & 0xffff, regs->xes & 0xffff, ss); | 251 | regs->xds & 0xffff, regs->xes & 0xffff, ss); |
230 | printk("Process %s (pid: %d, threadinfo=%p task=%p)", | 252 | printk(KERN_EMERG "Process %s (pid: %d, threadinfo=%p task=%p)", |
231 | current->comm, current->pid, current_thread_info(), current); | 253 | current->comm, current->pid, current_thread_info(), current); |
232 | /* | 254 | /* |
233 | * When in-kernel, we also print out the stack and code at the | 255 | * When in-kernel, we also print out the stack and code at the |
@@ -236,10 +258,10 @@ void show_registers(struct pt_regs *regs) | |||
236 | if (in_kernel) { | 258 | if (in_kernel) { |
237 | u8 __user *eip; | 259 | u8 __user *eip; |
238 | 260 | ||
239 | printk("\nStack: "); | 261 | printk("\n" KERN_EMERG "Stack: "); |
240 | show_stack(NULL, (unsigned long*)esp); | 262 | show_stack_log_lvl(NULL, (unsigned long *)esp, KERN_EMERG); |
241 | 263 | ||
242 | printk("Code: "); | 264 | printk(KERN_EMERG "Code: "); |
243 | 265 | ||
244 | eip = (u8 __user *)regs->eip - 43; | 266 | eip = (u8 __user *)regs->eip - 43; |
245 | for (i = 0; i < 64; i++, eip++) { | 267 | for (i = 0; i < 64; i++, eip++) { |
@@ -280,15 +302,15 @@ static void handle_BUG(struct pt_regs *regs) | |||
280 | (unsigned long)file < PAGE_OFFSET || __get_user(c, file)) | 302 | (unsigned long)file < PAGE_OFFSET || __get_user(c, file)) |
281 | file = "<bad filename>"; | 303 | file = "<bad filename>"; |
282 | 304 | ||
283 | printk("------------[ cut here ]------------\n"); | 305 | printk(KERN_EMERG "------------[ cut here ]------------\n"); |
284 | printk(KERN_ALERT "kernel BUG at %s:%d!\n", file, line); | 306 | printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line); |
285 | 307 | ||
286 | no_bug: | 308 | no_bug: |
287 | return; | 309 | return; |
288 | 310 | ||
289 | /* Here we know it was a BUG but file-n-line is unavailable */ | 311 | /* Here we know it was a BUG but file-n-line is unavailable */ |
290 | bug: | 312 | bug: |
291 | printk("Kernel BUG\n"); | 313 | printk(KERN_EMERG "Kernel BUG\n"); |
292 | } | 314 | } |
293 | 315 | ||
294 | /* This is gone through when something in the kernel | 316 | /* This is gone through when something in the kernel |
@@ -306,28 +328,35 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
306 | .lock_owner_depth = 0 | 328 | .lock_owner_depth = 0 |
307 | }; | 329 | }; |
308 | static int die_counter; | 330 | static int die_counter; |
331 | unsigned long flags; | ||
309 | 332 | ||
310 | if (die.lock_owner != raw_smp_processor_id()) { | 333 | if (die.lock_owner != raw_smp_processor_id()) { |
311 | console_verbose(); | 334 | console_verbose(); |
312 | spin_lock_irq(&die.lock); | 335 | spin_lock_irqsave(&die.lock, flags); |
313 | die.lock_owner = smp_processor_id(); | 336 | die.lock_owner = smp_processor_id(); |
314 | die.lock_owner_depth = 0; | 337 | die.lock_owner_depth = 0; |
315 | bust_spinlocks(1); | 338 | bust_spinlocks(1); |
316 | } | 339 | } |
340 | else | ||
341 | local_save_flags(flags); | ||
317 | 342 | ||
318 | if (++die.lock_owner_depth < 3) { | 343 | if (++die.lock_owner_depth < 3) { |
319 | int nl = 0; | 344 | int nl = 0; |
320 | handle_BUG(regs); | 345 | handle_BUG(regs); |
321 | printk(KERN_ALERT "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); | 346 | printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); |
322 | #ifdef CONFIG_PREEMPT | 347 | #ifdef CONFIG_PREEMPT |
323 | printk("PREEMPT "); | 348 | printk(KERN_EMERG "PREEMPT "); |
324 | nl = 1; | 349 | nl = 1; |
325 | #endif | 350 | #endif |
326 | #ifdef CONFIG_SMP | 351 | #ifdef CONFIG_SMP |
352 | if (!nl) | ||
353 | printk(KERN_EMERG); | ||
327 | printk("SMP "); | 354 | printk("SMP "); |
328 | nl = 1; | 355 | nl = 1; |
329 | #endif | 356 | #endif |
330 | #ifdef CONFIG_DEBUG_PAGEALLOC | 357 | #ifdef CONFIG_DEBUG_PAGEALLOC |
358 | if (!nl) | ||
359 | printk(KERN_EMERG); | ||
331 | printk("DEBUG_PAGEALLOC"); | 360 | printk("DEBUG_PAGEALLOC"); |
332 | nl = 1; | 361 | nl = 1; |
333 | #endif | 362 | #endif |
@@ -336,11 +365,11 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
336 | notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); | 365 | notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); |
337 | show_registers(regs); | 366 | show_registers(regs); |
338 | } else | 367 | } else |
339 | printk(KERN_ERR "Recursive die() failure, output suppressed\n"); | 368 | printk(KERN_EMERG "Recursive die() failure, output suppressed\n"); |
340 | 369 | ||
341 | bust_spinlocks(0); | 370 | bust_spinlocks(0); |
342 | die.lock_owner = -1; | 371 | die.lock_owner = -1; |
343 | spin_unlock_irq(&die.lock); | 372 | spin_unlock_irqrestore(&die.lock, flags); |
344 | 373 | ||
345 | if (kexec_should_crash(current)) | 374 | if (kexec_should_crash(current)) |
346 | crash_kexec(regs); | 375 | crash_kexec(regs); |
@@ -452,7 +481,7 @@ DO_VM86_ERROR( 3, SIGTRAP, "int3", int3) | |||
452 | #endif | 481 | #endif |
453 | DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) | 482 | DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) |
454 | DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) | 483 | DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) |
455 | DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip) | 484 | DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip) |
456 | DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) | 485 | DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) |
457 | DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) | 486 | DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) |
458 | DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) | 487 | DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) |
@@ -524,8 +553,10 @@ gp_in_kernel: | |||
524 | 553 | ||
525 | static void mem_parity_error(unsigned char reason, struct pt_regs * regs) | 554 | static void mem_parity_error(unsigned char reason, struct pt_regs * regs) |
526 | { | 555 | { |
527 | printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n"); | 556 | printk(KERN_EMERG "Uhhuh. NMI received. Dazed and confused, but trying " |
528 | printk("You probably have a hardware problem with your RAM chips\n"); | 557 | "to continue\n"); |
558 | printk(KERN_EMERG "You probably have a hardware problem with your RAM " | ||
559 | "chips\n"); | ||
529 | 560 | ||
530 | /* Clear and disable the memory parity error line. */ | 561 | /* Clear and disable the memory parity error line. */ |
531 | clear_mem_error(reason); | 562 | clear_mem_error(reason); |
@@ -535,7 +566,7 @@ static void io_check_error(unsigned char reason, struct pt_regs * regs) | |||
535 | { | 566 | { |
536 | unsigned long i; | 567 | unsigned long i; |
537 | 568 | ||
538 | printk("NMI: IOCK error (debug interrupt?)\n"); | 569 | printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n"); |
539 | show_registers(regs); | 570 | show_registers(regs); |
540 | 571 | ||
541 | /* Re-enable the IOCK line, wait for a few seconds */ | 572 | /* Re-enable the IOCK line, wait for a few seconds */ |
@@ -577,11 +608,11 @@ void die_nmi (struct pt_regs *regs, const char *msg) | |||
577 | * to get a message out. | 608 | * to get a message out. |
578 | */ | 609 | */ |
579 | bust_spinlocks(1); | 610 | bust_spinlocks(1); |
580 | printk(msg); | 611 | printk(KERN_EMERG "%s", msg); |
581 | printk(" on CPU%d, eip %08lx, registers:\n", | 612 | printk(" on CPU%d, eip %08lx, registers:\n", |
582 | smp_processor_id(), regs->eip); | 613 | smp_processor_id(), regs->eip); |
583 | show_registers(regs); | 614 | show_registers(regs); |
584 | printk("console shuts up ...\n"); | 615 | printk(KERN_EMERG "console shuts up ...\n"); |
585 | console_silent(); | 616 | console_silent(); |
586 | spin_unlock(&nmi_print_lock); | 617 | spin_unlock(&nmi_print_lock); |
587 | bust_spinlocks(0); | 618 | bust_spinlocks(0); |
@@ -650,13 +681,6 @@ fastcall void do_nmi(struct pt_regs * regs, long error_code) | |||
650 | 681 | ||
651 | cpu = smp_processor_id(); | 682 | cpu = smp_processor_id(); |
652 | 683 | ||
653 | #ifdef CONFIG_HOTPLUG_CPU | ||
654 | if (!cpu_online(cpu)) { | ||
655 | nmi_exit(); | ||
656 | return; | ||
657 | } | ||
658 | #endif | ||
659 | |||
660 | ++nmi_count(cpu); | 684 | ++nmi_count(cpu); |
661 | 685 | ||
662 | if (!rcu_dereference(nmi_callback)(regs, cpu)) | 686 | if (!rcu_dereference(nmi_callback)(regs, cpu)) |
@@ -994,8 +1018,8 @@ asmlinkage void math_state_restore(struct pt_regs regs) | |||
994 | 1018 | ||
995 | asmlinkage void math_emulate(long arg) | 1019 | asmlinkage void math_emulate(long arg) |
996 | { | 1020 | { |
997 | printk("math-emulation not enabled and no coprocessor found.\n"); | 1021 | printk(KERN_EMERG "math-emulation not enabled and no coprocessor found.\n"); |
998 | printk("killing %s.\n",current->comm); | 1022 | printk(KERN_EMERG "killing %s.\n",current->comm); |
999 | force_sig(SIGFPE,current); | 1023 | force_sig(SIGFPE,current); |
1000 | schedule(); | 1024 | schedule(); |
1001 | } | 1025 | } |
@@ -1082,9 +1106,9 @@ void __init trap_init(void) | |||
1082 | set_trap_gate(0,÷_error); | 1106 | set_trap_gate(0,÷_error); |
1083 | set_intr_gate(1,&debug); | 1107 | set_intr_gate(1,&debug); |
1084 | set_intr_gate(2,&nmi); | 1108 | set_intr_gate(2,&nmi); |
1085 | set_system_intr_gate(3, &int3); /* int3-5 can be called from all */ | 1109 | set_system_intr_gate(3, &int3); /* int3/4 can be called from all */ |
1086 | set_system_gate(4,&overflow); | 1110 | set_system_gate(4,&overflow); |
1087 | set_system_gate(5,&bounds); | 1111 | set_trap_gate(5,&bounds); |
1088 | set_trap_gate(6,&invalid_op); | 1112 | set_trap_gate(6,&invalid_op); |
1089 | set_trap_gate(7,&device_not_available); | 1113 | set_trap_gate(7,&device_not_available); |
1090 | set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS); | 1114 | set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS); |
@@ -1102,6 +1126,28 @@ void __init trap_init(void) | |||
1102 | #endif | 1126 | #endif |
1103 | set_trap_gate(19,&simd_coprocessor_error); | 1127 | set_trap_gate(19,&simd_coprocessor_error); |
1104 | 1128 | ||
1129 | if (cpu_has_fxsr) { | ||
1130 | /* | ||
1131 | * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned. | ||
1132 | * Generates a compile-time "error: zero width for bit-field" if | ||
1133 | * the alignment is wrong. | ||
1134 | */ | ||
1135 | struct fxsrAlignAssert { | ||
1136 | int _:!(offsetof(struct task_struct, | ||
1137 | thread.i387.fxsave) & 15); | ||
1138 | }; | ||
1139 | |||
1140 | printk(KERN_INFO "Enabling fast FPU save and restore... "); | ||
1141 | set_in_cr4(X86_CR4_OSFXSR); | ||
1142 | printk("done.\n"); | ||
1143 | } | ||
1144 | if (cpu_has_xmm) { | ||
1145 | printk(KERN_INFO "Enabling unmasked SIMD FPU exception " | ||
1146 | "support... "); | ||
1147 | set_in_cr4(X86_CR4_OSXMMEXCPT); | ||
1148 | printk("done.\n"); | ||
1149 | } | ||
1150 | |||
1105 | set_system_gate(SYSCALL_VECTOR,&system_call); | 1151 | set_system_gate(SYSCALL_VECTOR,&system_call); |
1106 | 1152 | ||
1107 | /* | 1153 | /* |