#include <linux/config.h>
#include <linux/sched.h>
+#include <linux/module.h>
#include <asm/processor.h>
#include <asm/i387.h>
#include <asm/math_emu.h>
#define HAVE_HWFP 1
#endif
-unsigned long mxcsr_feature_mask = 0xffffffff;
+static unsigned long mxcsr_feature_mask = 0xffffffff;
void mxcsr_feature_mask_init(void)
{
tsk->thread.i387.fsave.twd = 0xffffffffu;
tsk->thread.i387.fsave.fos = 0xffff0000u;
}
- tsk->used_math = 1;
+ /* only the device not available exception or ptrace can call init_fpu */
+ set_stopped_child_used_math(tsk);
}
/*
}
clts();
}
-
-void restore_fpu( struct task_struct *tsk )
-{
- if ( cpu_has_fxsr ) {
- asm volatile( "fxrstor %0"
- : : "m" (tsk->thread.i387.fxsave) );
- } else {
- asm volatile( "frstor %0"
- : : "m" (tsk->thread.i387.fsave) );
- }
-}
+EXPORT_SYMBOL_GPL(kernel_fpu_begin);
/*
* FPU tag word conversions.
static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave )
{
struct _fpxreg *st = NULL;
+ unsigned long tos = (fxsave->swd >> 11) & 7;
unsigned long twd = (unsigned long) fxsave->twd;
unsigned long tag;
unsigned long ret = 0xffff0000u;
int i;
-#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16);
+#define FPREG_ADDR(f, n) ((void *)&(f)->st_space + (n) * 16);
for ( i = 0 ; i < 8 ; i++ ) {
if ( twd & 0x1 ) {
- st = (struct _fpxreg *) FPREG_ADDR( fxsave, i );
+ st = FPREG_ADDR( fxsave, (i - tos) & 7 );
switch ( st->exponent & 0x7fff ) {
case 0x7fff:
}
}
+#if 0
unsigned short get_fpu_twd( struct task_struct *tsk )
{
if ( cpu_has_fxsr ) {
return (unsigned short)tsk->thread.i387.fsave.twd;
}
}
+#endif /* 0 */
unsigned short get_fpu_mxcsr( struct task_struct *tsk )
{
}
}
+#if 0
+
void set_fpu_cwd( struct task_struct *tsk, unsigned short cwd )
{
if ( cpu_has_fxsr ) {
}
}
+#endif /* 0 */
+
/*
* FXSR floating point environment conversions.
*/
to = &buf->_st[0];
from = (struct _fpxreg *) &fxsave->st_space[0];
for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
- unsigned long *t = (unsigned long *)to;
+ unsigned long __user *t = (unsigned long __user *)to;
unsigned long *f = (unsigned long *)from;
if (__put_user(*f, t) ||
from = &buf->_st[0];
for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
unsigned long *t = (unsigned long *)to;
- unsigned long *f = (unsigned long *)from;
+ unsigned long __user *f = (unsigned long __user *)from;
if (__get_user(*t, f) ||
__get_user(*(t + 1), f + 1) ||
int save_i387( struct _fpstate __user *buf )
{
- if ( !current->used_math )
+ if ( !used_math() )
return 0;
/* This will cause a "finit" to be triggered by the next
* attempted FPU operation by the 'current' process.
*/
- current->used_math = 0;
+ clear_used_math();
if ( HAVE_HWFP ) {
if ( cpu_has_fxsr ) {
} else {
err = restore_i387_soft( ¤t->thread.i387.soft, buf );
}
- current->used_math = 1;
+ set_used_math();
return err;
}
int fpvalid;
struct task_struct *tsk = current;
- fpvalid = tsk->used_math;
+ fpvalid = !!used_math();
if ( fpvalid ) {
unlazy_fpu( tsk );
if ( cpu_has_fxsr ) {
return fpvalid;
}
-
-int dump_extended_fpu( struct pt_regs *regs, struct user_fxsr_struct *fpu )
-{
- int fpvalid;
- struct task_struct *tsk = current;
-
- fpvalid = tsk->used_math && cpu_has_fxsr;
- if ( fpvalid ) {
- unlazy_fpu( tsk );
- memcpy( fpu, &tsk->thread.i387.fxsave,
- sizeof(struct user_fxsr_struct) );
- }
-
- return fpvalid;
-}
+EXPORT_SYMBOL(dump_fpu);
int dump_task_fpu(struct task_struct *tsk, struct user_i387_struct *fpu)
{
- int fpvalid = tsk->used_math;
+ int fpvalid = !!tsk_used_math(tsk);
if (fpvalid) {
if (tsk == current)
int dump_task_extended_fpu(struct task_struct *tsk, struct user_fxsr_struct *fpu)
{
- int fpvalid = tsk->used_math && cpu_has_fxsr;
+ int fpvalid = tsk_used_math(tsk) && cpu_has_fxsr;
if (fpvalid) {
if (tsk == current)