diff options
| -rw-r--r-- | arch/x86/include/asm/i387.h | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/traps.c | 33 |
2 files changed, 24 insertions, 10 deletions
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index 175adf58dd4f..2e7529295f55 100644 --- a/arch/x86/include/asm/i387.h +++ b/arch/x86/include/asm/i387.h | |||
| @@ -26,6 +26,7 @@ extern void fpu_init(void); | |||
| 26 | extern void mxcsr_feature_mask_init(void); | 26 | extern void mxcsr_feature_mask_init(void); |
| 27 | extern int init_fpu(struct task_struct *child); | 27 | extern int init_fpu(struct task_struct *child); |
| 28 | extern asmlinkage void math_state_restore(void); | 28 | extern asmlinkage void math_state_restore(void); |
| 29 | extern void __math_state_restore(void); | ||
| 29 | extern void init_thread_xstate(void); | 30 | extern void init_thread_xstate(void); |
| 30 | extern int dump_fpu(struct pt_regs *, struct user_i387_struct *); | 31 | extern int dump_fpu(struct pt_regs *, struct user_i387_struct *); |
| 31 | 32 | ||
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 5f935f0d5861..71b91669ad19 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
| @@ -814,6 +814,28 @@ asmlinkage void __attribute__((weak)) smp_threshold_interrupt(void) | |||
| 814 | } | 814 | } |
| 815 | 815 | ||
| 816 | /* | 816 | /* |
| 817 | * __math_state_restore assumes that cr0.TS is already clear and the | ||
| 818 | * fpu state is all ready for use. Used during context switch. | ||
| 819 | */ | ||
| 820 | void __math_state_restore(void) | ||
| 821 | { | ||
| 822 | struct thread_info *thread = current_thread_info(); | ||
| 823 | struct task_struct *tsk = thread->task; | ||
| 824 | |||
| 825 | /* | ||
| 826 | * Paranoid restore. send a SIGSEGV if we fail to restore the state. | ||
| 827 | */ | ||
| 828 | if (unlikely(restore_fpu_checking(tsk))) { | ||
| 829 | stts(); | ||
| 830 | force_sig(SIGSEGV, tsk); | ||
| 831 | return; | ||
| 832 | } | ||
| 833 | |||
| 834 | thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ | ||
| 835 | tsk->fpu_counter++; | ||
| 836 | } | ||
| 837 | |||
| 838 | /* | ||
| 817 | * 'math_state_restore()' saves the current math information in the | 839 | * 'math_state_restore()' saves the current math information in the |
| 818 | * old math state array, and gets the new ones from the current task | 840 | * old math state array, and gets the new ones from the current task |
| 819 | * | 841 | * |
| @@ -844,17 +866,8 @@ asmlinkage void math_state_restore(void) | |||
| 844 | } | 866 | } |
| 845 | 867 | ||
| 846 | clts(); /* Allow maths ops (or we recurse) */ | 868 | clts(); /* Allow maths ops (or we recurse) */ |
| 847 | /* | ||
| 848 | * Paranoid restore. send a SIGSEGV if we fail to restore the state. | ||
| 849 | */ | ||
| 850 | if (unlikely(restore_fpu_checking(tsk))) { | ||
| 851 | stts(); | ||
| 852 | force_sig(SIGSEGV, tsk); | ||
| 853 | return; | ||
| 854 | } | ||
| 855 | 869 | ||
| 856 | thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ | 870 | __math_state_restore(); |
| 857 | tsk->fpu_counter++; | ||
| 858 | } | 871 | } |
| 859 | EXPORT_SYMBOL_GPL(math_state_restore); | 872 | EXPORT_SYMBOL_GPL(math_state_restore); |
| 860 | 873 | ||
