diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-12-26 03:21:05 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-12-26 03:21:05 -0500 |
commit | c656d9ca48d3ef1a11449e892ce488ee0bb5a335 (patch) | |
tree | 0c5598659b3e7f12864d203967d42ac3feb1142c /arch/x86/kernel/traps.c | |
parent | 71ab6b245fda6e7597a667a67cce0d26c3c7a14b (diff) | |
parent | a73ad3331fdbf4191cf99b83ea9ac7082b6757ba (diff) |
Merge branch 'x86/fpu' into x86/cleanups
Diffstat (limited to 'arch/x86/kernel/traps.c')
-rw-r--r-- | arch/x86/kernel/traps.c | 35 |
1 files changed, 14 insertions, 21 deletions
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 04d242ab0161..f5a640ba04bc 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -664,7 +664,7 @@ void math_error(void __user *ip) | |||
664 | { | 664 | { |
665 | struct task_struct *task; | 665 | struct task_struct *task; |
666 | siginfo_t info; | 666 | siginfo_t info; |
667 | unsigned short cwd, swd; | 667 | unsigned short cwd, swd, err; |
668 | 668 | ||
669 | /* | 669 | /* |
670 | * Save the info for the exception handler and clear the error. | 670 | * Save the info for the exception handler and clear the error. |
@@ -675,7 +675,6 @@ void math_error(void __user *ip) | |||
675 | task->thread.error_code = 0; | 675 | task->thread.error_code = 0; |
676 | info.si_signo = SIGFPE; | 676 | info.si_signo = SIGFPE; |
677 | info.si_errno = 0; | 677 | info.si_errno = 0; |
678 | info.si_code = __SI_FAULT; | ||
679 | info.si_addr = ip; | 678 | info.si_addr = ip; |
680 | /* | 679 | /* |
681 | * (~cwd & swd) will mask out exceptions that are not set to unmasked | 680 | * (~cwd & swd) will mask out exceptions that are not set to unmasked |
@@ -689,34 +688,28 @@ void math_error(void __user *ip) | |||
689 | */ | 688 | */ |
690 | cwd = get_fpu_cwd(task); | 689 | cwd = get_fpu_cwd(task); |
691 | swd = get_fpu_swd(task); | 690 | swd = get_fpu_swd(task); |
692 | switch (swd & ~cwd & 0x3f) { | 691 | |
693 | case 0x000: /* No unmasked exception */ | 692 | err = swd & ~cwd; |
694 | #ifdef CONFIG_X86_32 | 693 | |
695 | return; | 694 | if (err & 0x001) { /* Invalid op */ |
696 | #endif | ||
697 | default: /* Multiple exceptions */ | ||
698 | break; | ||
699 | case 0x001: /* Invalid Op */ | ||
700 | /* | 695 | /* |
701 | * swd & 0x240 == 0x040: Stack Underflow | 696 | * swd & 0x240 == 0x040: Stack Underflow |
702 | * swd & 0x240 == 0x240: Stack Overflow | 697 | * swd & 0x240 == 0x240: Stack Overflow |
703 | * User must clear the SF bit (0x40) if set | 698 | * User must clear the SF bit (0x40) if set |
704 | */ | 699 | */ |
705 | info.si_code = FPE_FLTINV; | 700 | info.si_code = FPE_FLTINV; |
706 | break; | 701 | } else if (err & 0x004) { /* Divide by Zero */ |
707 | case 0x002: /* Denormalize */ | ||
708 | case 0x010: /* Underflow */ | ||
709 | info.si_code = FPE_FLTUND; | ||
710 | break; | ||
711 | case 0x004: /* Zero Divide */ | ||
712 | info.si_code = FPE_FLTDIV; | 702 | info.si_code = FPE_FLTDIV; |
713 | break; | 703 | } else if (err & 0x008) { /* Overflow */ |
714 | case 0x008: /* Overflow */ | ||
715 | info.si_code = FPE_FLTOVF; | 704 | info.si_code = FPE_FLTOVF; |
716 | break; | 705 | } else if (err & 0x012) { /* Denormal, Underflow */ |
717 | case 0x020: /* Precision */ | 706 | info.si_code = FPE_FLTUND; |
707 | } else if (err & 0x020) { /* Precision */ | ||
718 | info.si_code = FPE_FLTRES; | 708 | info.si_code = FPE_FLTRES; |
719 | break; | 709 | } else { |
710 | /* If we're using IRQ 13, or supposedly even some trap 16 | ||
711 | implementations, it's possible we get a spurious trap... */ | ||
712 | return; /* Spurious trap, no error */ | ||
720 | } | 713 | } |
721 | force_sig_info(SIGFPE, &info, task); | 714 | force_sig_info(SIGFPE, &info, task); |
722 | } | 715 | } |