#include <linux/smp.h>
#include <asm/semaphore.h>
#include <asm/processor.h>
+#include <asm/i387.h>
#include <asm/msr.h>
#include <asm/io.h>
#include <asm/mmu_context.h>
*/
current_thread_info()->status = 0;
current->used_math = 0;
- stts();
+ mxcsr_feature_mask_init();
}
#define HAVE_HWFP 1
#endif
+unsigned long mxcsr_feature_mask = 0xffffffff;
+
+void mxcsr_feature_mask_init(void)
+{
+ unsigned long mask = 0;
+ clts();
+ if (cpu_has_fxsr) {
+ memset(¤t->thread.i387.fxsave, 0, sizeof(struct i387_fxsave_struct));
+ asm volatile("fxsave %0" : : "m" (current->thread.i387.fxsave));
+ mask = current->thread.i387.fxsave.mxcsr_mask;
+ if (mask == 0) mask = 0x0000ffbf;
+ }
+ mxcsr_feature_mask &= mask;
+ stts();
+}
+
/*
* The _current_ task is using the FPU for the first time
* so initialize it and set the mxcsr to its default
}
}
-void set_fpu_mxcsr( struct task_struct *tsk, unsigned short mxcsr )
-{
- if ( cpu_has_xmm ) {
- tsk->thread.i387.fxsave.mxcsr = (mxcsr & 0xffbf);
- }
-}
-
/*
* FXSR floating point environment conversions.
*/
clear_fpu( tsk );
err = __copy_from_user( &tsk->thread.i387.fxsave, &buf->_fxsr_env[0],
sizeof(struct i387_fxsave_struct) );
- /* mxcsr bit 6 and 31-16 must be zero for security reasons */
- tsk->thread.i387.fxsave.mxcsr &= 0xffbf;
+ /* mxcsr reserved bits must be masked to zero for security reasons */
+ tsk->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
return err ? 1 : convert_fxsr_from_user( &tsk->thread.i387.fxsave, buf );
}
if (__copy_from_user( &tsk->thread.i387.fxsave, buf,
sizeof(struct user_fxsr_struct) ))
ret = -EFAULT;
- /* mxcsr bit 6 and 31-16 must be zero for security reasons */
- tsk->thread.i387.fxsave.mxcsr &= 0xffbf;
+ /* mxcsr reserved bits must be masked to zero for security reasons */
+ tsk->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
} else {
ret = -EIO;
}
/* restore FPU regs if necessary */
/* Do it out of line so that gcc does not move cr0 load to some stupid place */
kernel_fpu_end();
+ mxcsr_feature_mask_init();
}
void restore_processor_state(void)
&buf->_fxsr_env[0],
sizeof(struct i387_fxsave_struct)))
return -1;
- tsk->thread.i387.fxsave.mxcsr &= 0xffbf;
+ tsk->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
tsk->used_math = 1;
}
return convert_fxsr_from_user(&tsk->thread.i387.fxsave, buf);
/* no checking to be bug-to-bug compatible with i386 */
__copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u));
child->used_math = 1;
- child->thread.i387.fxsave.mxcsr &= 0xffbf;
+ child->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
ret = 0;
- break;
- }
+ break;
+ }
default:
ret = -EINVAL;
#include <asm/ptrace.h>
#include <asm/uaccess.h>
+unsigned int mxcsr_feature_mask = 0xffffffff;
+
+void mxcsr_feature_mask_init(void)
+{
+ unsigned int mask;
+ clts();
+ memset(¤t->thread.i387.fxsave, 0, sizeof(struct i387_fxsave_struct));
+ asm volatile("fxsave %0" : : "m" (current->thread.i387.fxsave));
+ mask = current->thread.i387.fxsave.mxcsr_mask;
+ if (mask == 0) mask = 0x0000ffbf;
+ mxcsr_feature_mask &= mask;
+ stts();
+}
+
/*
* Called at bootup to set up the initial FPU state that is later cloned
* into all processes.
write_cr0(oldcr0 & ~((1UL<<3)|(1UL<<2))); /* clear TS and EM */
+ mxcsr_feature_mask_init();
/* clean state in init */
- stts();
current_thread_info()->status = 0;
current->used_math = 0;
}
/* restore FPU regs if necessary */
/* Do it out of line so that gcc does not move cr0 load to some stupid place */
kernel_fpu_end();
+ mxcsr_feature_mask_init();
}
void restore_processor_state(void)
#define __ASM_I386_I387_H
#include <linux/sched.h>
+#include <linux/init.h>
#include <asm/processor.h>
#include <asm/sigcontext.h>
#include <asm/user.h>
+extern unsigned long mxcsr_feature_mask;
+extern void mxcsr_feature_mask_init(void);
extern void init_fpu(struct task_struct *);
/*
* FPU lazy state save handling...
extern void set_fpu_cwd( struct task_struct *tsk, unsigned short cwd );
extern void set_fpu_swd( struct task_struct *tsk, unsigned short swd );
extern void set_fpu_twd( struct task_struct *tsk, unsigned short twd );
-extern void set_fpu_mxcsr( struct task_struct *tsk, unsigned short mxcsr );
-
-#define load_mxcsr( val ) do { \
- unsigned long __mxcsr = ((unsigned long)(val) & 0xffbf); \
- asm volatile( "ldmxcsr %0" : : "m" (__mxcsr) ); \
-} while (0)
/*
* Signal frame handlers...
long foo;
long fos;
long mxcsr;
- long reserved;
+ long mxcsr_mask;
long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */
long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */
long padding[56];
#include <asm/uaccess.h>
extern void fpu_init(void);
+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 *buf);
} \
} while (0)
-#define load_mxcsr(val) do { \
- unsigned long __mxcsr = ((unsigned long)(val) & 0xffbf); \
- asm volatile("ldmxcsr %0" : : "m" (__mxcsr)); \
-} while (0)
-
/*
* ptrace request handers...
*/
#define set_fpu_cwd(t,val) ((t)->thread.i387.fxsave.cwd = (val))
#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 set_fpu_mxcsr(t,val) ((t)->thread.i387.fxsave.mxcsr = (val)&0xffbf)
static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
{