aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/traps.c')
-rw-r--r--arch/i386/kernel/traps.c51
1 files changed, 40 insertions, 11 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index e4d4e2162c7a..a61f33d06ea3 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -27,6 +27,7 @@
27#include <linux/ptrace.h> 27#include <linux/ptrace.h>
28#include <linux/utsname.h> 28#include <linux/utsname.h>
29#include <linux/kprobes.h> 29#include <linux/kprobes.h>
30#include <linux/kexec.h>
30 31
31#ifdef CONFIG_EISA 32#ifdef CONFIG_EISA
32#include <linux/ioport.h> 33#include <linux/ioport.h>
@@ -234,22 +235,22 @@ void show_registers(struct pt_regs *regs)
234 * time of the fault.. 235 * time of the fault..
235 */ 236 */
236 if (in_kernel) { 237 if (in_kernel) {
237 u8 *eip; 238 u8 __user *eip;
238 239
239 printk("\nStack: "); 240 printk("\nStack: ");
240 show_stack(NULL, (unsigned long*)esp); 241 show_stack(NULL, (unsigned long*)esp);
241 242
242 printk("Code: "); 243 printk("Code: ");
243 244
244 eip = (u8 *)regs->eip - 43; 245 eip = (u8 __user *)regs->eip - 43;
245 for (i = 0; i < 64; i++, eip++) { 246 for (i = 0; i < 64; i++, eip++) {
246 unsigned char c; 247 unsigned char c;
247 248
248 if (eip < (u8 *)PAGE_OFFSET || __get_user(c, eip)) { 249 if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) {
249 printk(" Bad EIP value."); 250 printk(" Bad EIP value.");
250 break; 251 break;
251 } 252 }
252 if (eip == (u8 *)regs->eip) 253 if (eip == (u8 __user *)regs->eip)
253 printk("<%02x> ", c); 254 printk("<%02x> ", c);
254 else 255 else
255 printk("%02x ", c); 256 printk("%02x ", c);
@@ -273,13 +274,13 @@ static void handle_BUG(struct pt_regs *regs)
273 274
274 if (eip < PAGE_OFFSET) 275 if (eip < PAGE_OFFSET)
275 goto no_bug; 276 goto no_bug;
276 if (__get_user(ud2, (unsigned short *)eip)) 277 if (__get_user(ud2, (unsigned short __user *)eip))
277 goto no_bug; 278 goto no_bug;
278 if (ud2 != 0x0b0f) 279 if (ud2 != 0x0b0f)
279 goto no_bug; 280 goto no_bug;
280 if (__get_user(line, (unsigned short *)(eip + 2))) 281 if (__get_user(line, (unsigned short __user *)(eip + 2)))
281 goto bug; 282 goto bug;
282 if (__get_user(file, (char **)(eip + 4)) || 283 if (__get_user(file, (char * __user *)(eip + 4)) ||
283 (unsigned long)file < PAGE_OFFSET || __get_user(c, file)) 284 (unsigned long)file < PAGE_OFFSET || __get_user(c, file))
284 file = "<bad filename>"; 285 file = "<bad filename>";
285 286
@@ -294,6 +295,9 @@ bug:
294 printk("Kernel BUG\n"); 295 printk("Kernel BUG\n");
295} 296}
296 297
298/* This is gone through when something in the kernel
299 * has done something bad and is about to be terminated.
300*/
297void die(const char * str, struct pt_regs * regs, long err) 301void die(const char * str, struct pt_regs * regs, long err)
298{ 302{
299 static struct { 303 static struct {
@@ -341,6 +345,10 @@ void die(const char * str, struct pt_regs * regs, long err)
341 bust_spinlocks(0); 345 bust_spinlocks(0);
342 die.lock_owner = -1; 346 die.lock_owner = -1;
343 spin_unlock_irq(&die.lock); 347 spin_unlock_irq(&die.lock);
348
349 if (kexec_should_crash(current))
350 crash_kexec(regs);
351
344 if (in_interrupt()) 352 if (in_interrupt())
345 panic("Fatal exception in interrupt"); 353 panic("Fatal exception in interrupt");
346 354
@@ -361,6 +369,10 @@ static inline void die_if_kernel(const char * str, struct pt_regs * regs, long e
361static void do_trap(int trapnr, int signr, char *str, int vm86, 369static void do_trap(int trapnr, int signr, char *str, int vm86,
362 struct pt_regs * regs, long error_code, siginfo_t *info) 370 struct pt_regs * regs, long error_code, siginfo_t *info)
363{ 371{
372 struct task_struct *tsk = current;
373 tsk->thread.error_code = error_code;
374 tsk->thread.trap_no = trapnr;
375
364 if (regs->eflags & VM_MASK) { 376 if (regs->eflags & VM_MASK) {
365 if (vm86) 377 if (vm86)
366 goto vm86_trap; 378 goto vm86_trap;
@@ -371,9 +383,6 @@ static void do_trap(int trapnr, int signr, char *str, int vm86,
371 goto kernel_trap; 383 goto kernel_trap;
372 384
373 trap_signal: { 385 trap_signal: {
374 struct task_struct *tsk = current;
375 tsk->thread.error_code = error_code;
376 tsk->thread.trap_no = trapnr;
377 if (info) 386 if (info)
378 force_sig_info(signr, info, tsk); 387 force_sig_info(signr, info, tsk);
379 else 388 else
@@ -486,6 +495,9 @@ fastcall void do_general_protection(struct pt_regs * regs, long error_code)
486 } 495 }
487 put_cpu(); 496 put_cpu();
488 497
498 current->thread.error_code = error_code;
499 current->thread.trap_no = 13;
500
489 if (regs->eflags & VM_MASK) 501 if (regs->eflags & VM_MASK)
490 goto gp_in_vm86; 502 goto gp_in_vm86;
491 503
@@ -570,6 +582,15 @@ void die_nmi (struct pt_regs *regs, const char *msg)
570 console_silent(); 582 console_silent();
571 spin_unlock(&nmi_print_lock); 583 spin_unlock(&nmi_print_lock);
572 bust_spinlocks(0); 584 bust_spinlocks(0);
585
586 /* If we are in kernel we are probably nested up pretty bad
587 * and might aswell get out now while we still can.
588 */
589 if (!user_mode(regs)) {
590 current->thread.trap_no = 2;
591 crash_kexec(regs);
592 }
593
573 do_exit(SIGSEGV); 594 do_exit(SIGSEGV);
574} 595}
575 596
@@ -625,6 +646,14 @@ fastcall void do_nmi(struct pt_regs * regs, long error_code)
625 nmi_enter(); 646 nmi_enter();
626 647
627 cpu = smp_processor_id(); 648 cpu = smp_processor_id();
649
650#ifdef CONFIG_HOTPLUG_CPU
651 if (!cpu_online(cpu)) {
652 nmi_exit();
653 return;
654 }
655#endif
656
628 ++nmi_count(cpu); 657 ++nmi_count(cpu);
629 658
630 if (!nmi_callback(regs, cpu)) 659 if (!nmi_callback(regs, cpu))
@@ -872,9 +901,9 @@ fastcall void do_simd_coprocessor_error(struct pt_regs * regs,
872 error_code); 901 error_code);
873 return; 902 return;
874 } 903 }
875 die_if_kernel("cache flush denied", regs, error_code);
876 current->thread.trap_no = 19; 904 current->thread.trap_no = 19;
877 current->thread.error_code = error_code; 905 current->thread.error_code = error_code;
906 die_if_kernel("cache flush denied", regs, error_code);
878 force_sig(SIGSEGV, current); 907 force_sig(SIGSEGV, current);
879 } 908 }
880} 909}