diff options
Diffstat (limited to 'arch/x86/kernel/traps.c')
| -rw-r--r-- | arch/x86/kernel/traps.c | 38 |
1 files changed, 15 insertions, 23 deletions
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 04d242ab0161..141907ab6e22 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
| @@ -481,11 +481,7 @@ do_nmi(struct pt_regs *regs, long error_code) | |||
| 481 | { | 481 | { |
| 482 | nmi_enter(); | 482 | nmi_enter(); |
| 483 | 483 | ||
| 484 | #ifdef CONFIG_X86_32 | 484 | inc_irq_stat(__nmi_count); |
| 485 | { int cpu; cpu = smp_processor_id(); ++nmi_count(cpu); } | ||
| 486 | #else | ||
| 487 | add_pda(__nmi_count, 1); | ||
| 488 | #endif | ||
| 489 | 485 | ||
| 490 | if (!ignore_nmis) | 486 | if (!ignore_nmis) |
| 491 | default_do_nmi(regs); | 487 | default_do_nmi(regs); |
| @@ -664,7 +660,7 @@ void math_error(void __user *ip) | |||
| 664 | { | 660 | { |
| 665 | struct task_struct *task; | 661 | struct task_struct *task; |
| 666 | siginfo_t info; | 662 | siginfo_t info; |
| 667 | unsigned short cwd, swd; | 663 | unsigned short cwd, swd, err; |
| 668 | 664 | ||
| 669 | /* | 665 | /* |
| 670 | * Save the info for the exception handler and clear the error. | 666 | * Save the info for the exception handler and clear the error. |
| @@ -675,7 +671,6 @@ void math_error(void __user *ip) | |||
| 675 | task->thread.error_code = 0; | 671 | task->thread.error_code = 0; |
| 676 | info.si_signo = SIGFPE; | 672 | info.si_signo = SIGFPE; |
| 677 | info.si_errno = 0; | 673 | info.si_errno = 0; |
| 678 | info.si_code = __SI_FAULT; | ||
| 679 | info.si_addr = ip; | 674 | info.si_addr = ip; |
| 680 | /* | 675 | /* |
| 681 | * (~cwd & swd) will mask out exceptions that are not set to unmasked | 676 | * (~cwd & swd) will mask out exceptions that are not set to unmasked |
| @@ -689,34 +684,31 @@ void math_error(void __user *ip) | |||
| 689 | */ | 684 | */ |
| 690 | cwd = get_fpu_cwd(task); | 685 | cwd = get_fpu_cwd(task); |
| 691 | swd = get_fpu_swd(task); | 686 | swd = get_fpu_swd(task); |
| 692 | switch (swd & ~cwd & 0x3f) { | 687 | |
| 693 | case 0x000: /* No unmasked exception */ | 688 | err = swd & ~cwd & 0x3f; |
| 689 | |||
| 694 | #ifdef CONFIG_X86_32 | 690 | #ifdef CONFIG_X86_32 |
| 691 | if (!err) | ||
| 695 | return; | 692 | return; |
| 696 | #endif | 693 | #endif |
| 697 | default: /* Multiple exceptions */ | 694 | |
| 698 | break; | 695 | if (err & 0x001) { /* Invalid op */ |
| 699 | case 0x001: /* Invalid Op */ | ||
| 700 | /* | 696 | /* |
| 701 | * swd & 0x240 == 0x040: Stack Underflow | 697 | * swd & 0x240 == 0x040: Stack Underflow |
| 702 | * swd & 0x240 == 0x240: Stack Overflow | 698 | * swd & 0x240 == 0x240: Stack Overflow |
| 703 | * User must clear the SF bit (0x40) if set | 699 | * User must clear the SF bit (0x40) if set |
| 704 | */ | 700 | */ |
| 705 | info.si_code = FPE_FLTINV; | 701 | info.si_code = FPE_FLTINV; |
| 706 | break; | 702 | } 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; | 703 | info.si_code = FPE_FLTDIV; |
| 713 | break; | 704 | } else if (err & 0x008) { /* Overflow */ |
| 714 | case 0x008: /* Overflow */ | ||
| 715 | info.si_code = FPE_FLTOVF; | 705 | info.si_code = FPE_FLTOVF; |
| 716 | break; | 706 | } else if (err & 0x012) { /* Denormal, Underflow */ |
| 717 | case 0x020: /* Precision */ | 707 | info.si_code = FPE_FLTUND; |
| 708 | } else if (err & 0x020) { /* Precision */ | ||
| 718 | info.si_code = FPE_FLTRES; | 709 | info.si_code = FPE_FLTRES; |
| 719 | break; | 710 | } else { |
| 711 | info.si_code = __SI_FAULT|SI_KERNEL; /* WTF? */ | ||
| 720 | } | 712 | } |
| 721 | force_sig_info(SIGFPE, &info, task); | 713 | force_sig_info(SIGFPE, &info, task); |
| 722 | } | 714 | } |
