X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=include%2Fasm-x86_64%2Fi387.h;h=0217b74cc9fc0cd30456d40929e6196229680178;hb=43a145a3440c5c5f24ff2888801e40e2242187e6;hp=57f7e14338492df5c8c1b37f54658d6f61894afd;hpb=7180d4fb83085fef9d24b353f5bd79cf6fd98447;p=powerpc.git diff --git a/include/asm-x86_64/i387.h b/include/asm-x86_64/i387.h index 57f7e14338..0217b74cc9 100644 --- a/include/asm-x86_64/i387.h +++ b/include/asm-x86_64/i387.h @@ -24,14 +24,17 @@ extern unsigned int mxcsr_feature_mask; extern void mxcsr_feature_mask_init(void); extern void init_fpu(struct task_struct *child); extern int save_i387(struct _fpstate __user *buf); +extern asmlinkage void math_state_restore(void); /* * FPU lazy state save handling... */ #define unlazy_fpu(tsk) do { \ - if ((tsk)->thread_info->status & TS_USEDFPU) \ - save_init_fpu(tsk); \ + if (task_thread_info(tsk)->status & TS_USEDFPU) \ + save_init_fpu(tsk); \ + else \ + tsk->fpu_counter = 0; \ } while (0) /* Ignore delayed exceptions from user space */ @@ -46,9 +49,9 @@ static inline void tolerant_fwait(void) } #define clear_fpu(tsk) do { \ - if ((tsk)->thread_info->status & TS_USEDFPU) { \ + if (task_thread_info(tsk)->status & TS_USEDFPU) { \ tolerant_fwait(); \ - (tsk)->thread_info->status &= ~TS_USEDFPU; \ + task_thread_info(tsk)->status &= ~TS_USEDFPU; \ stts(); \ } \ } while (0) @@ -72,6 +75,23 @@ extern int set_fpregs(struct task_struct *tsk, #define set_fpu_swd(t,val) ((t)->thread.i387.fxsave.swd = (val)) #define set_fpu_fxsr_twd(t,val) ((t)->thread.i387.fxsave.twd = (val)) +#define X87_FSW_ES (1 << 7) /* Exception Summary */ + +/* AMD CPUs don't save/restore FDP/FIP/FOP unless an exception + is pending. Clear the x87 state here by setting it to fixed + values. The kernel data segment can be sometimes 0 and sometimes + new user value. Both should be ok. + Use the PDA as safe address because it should be already in L1. */ +static inline void clear_fpu_state(struct i387_fxsave_struct *fx) +{ + if (unlikely(fx->swd & X87_FSW_ES)) + asm volatile("fnclex"); + alternative_input(ASM_NOP8 ASM_NOP2, + " emms\n" /* clear stack tags */ + " fildl %%gs:0", /* load to clear state */ + X86_FEATURE_FXSAVE_LEAK); +} + static inline int restore_fpu_checking(struct i387_fxsave_struct *fx) { int err; @@ -117,8 +137,9 @@ static inline int save_i387_checking(struct i387_fxsave_struct __user *fx) #else : [fx] "cdaSDb" (fx), "0" (0)); #endif - if (unlikely(err)) - __clear_user(fx, sizeof(struct i387_fxsave_struct)); + if (unlikely(err) && __clear_user(fx, sizeof(struct i387_fxsave_struct))) + err = -EFAULT; + /* No need to clear here because the caller clears USED_MATH */ return err; } @@ -149,7 +170,7 @@ static inline void __fxsave_clear(struct task_struct *tsk) "i" (offsetof(__typeof__(*tsk), thread.i387.fxsave))); #endif - __asm__ __volatile__("fnclex"); + clear_fpu_state(&tsk->thread.i387.fxsave); } static inline void kernel_fpu_begin(void) @@ -170,10 +191,10 @@ static inline void kernel_fpu_end(void) preempt_enable(); } -static inline void save_init_fpu( struct task_struct *tsk ) +static inline void save_init_fpu(struct task_struct *tsk) { __fxsave_clear(tsk); - tsk->thread_info->status &= ~TS_USEDFPU; + task_thread_info(tsk)->status &= ~TS_USEDFPU; stts(); }