]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] mxcsr patch for i386 & x86-64
authorNitin A. Kamble <nitin.a.kamble@intel.com>
Thu, 6 May 2004 23:26:06 +0000 (16:26 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Thu, 6 May 2004 23:26:06 +0000 (16:26 -0700)
This enables proper mxcsr register masking: the magic mask "0xffbf"
is not necessarily correct for all CPU's, and there is an architected
way to discover the proper MXCSR feature bits by examining the fxsave
results.

Please refer to IA32 Software Developer's Manual, Volume 1, Section
11.6.6 for more details.

arch/i386/kernel/cpu/common.c
arch/i386/kernel/i387.c
arch/i386/power/cpu.c
arch/x86_64/ia32/fpu32.c
arch/x86_64/ia32/ptrace32.c
arch/x86_64/kernel/i387.c
arch/x86_64/kernel/suspend.c
include/asm-i386/i387.h
include/asm-i386/processor.h
include/asm-x86_64/i387.h

index 6dac129171bad19951effc4ac237bcd26412b9d5..85fdfdcf250a56e7f656c7c20de908b25eb24d96 100644 (file)
@@ -4,6 +4,7 @@
 #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>
@@ -536,5 +537,5 @@ void __init cpu_init (void)
         */
        current_thread_info()->status = 0;
        current->used_math = 0;
-       stts();
+       mxcsr_feature_mask_init();
 }
index 6556f63d2b90a167c391b1c65db7b74c33977f6e..0d35516ca293596bf199a79ecb75577d7417ce5c 100644 (file)
 #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(&current->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
@@ -204,13 +220,6 @@ void set_fpu_twd( struct task_struct *tsk, unsigned short twd )
        }
 }
 
-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.
  */
@@ -355,8 +364,8 @@ static int restore_i387_fxsave( struct _fpstate __user *buf )
        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 );
 }
 
@@ -457,8 +466,8 @@ int set_fpxregs( struct task_struct *tsk, struct user_fxsr_struct __user *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;
        }
index b71175ff75594947e4d27f6d454adc7af25e240e..98bea6d85b037b8d544bd3abe88981d0e0682898 100644 (file)
@@ -72,6 +72,7 @@ do_fpu_end(void)
         /* 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)
index 2094e76b9093b7ffdd4fe0e356064a062e592861..c6d0b02a1013b2940684701afd63e5bb998c798f 100644 (file)
@@ -155,7 +155,7 @@ int restore_i387_ia32(struct task_struct *tsk, struct _fpstate_ia32 *buf, int fs
                                     &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);
index bf57e0eeb9f490e08305608fc891b88b112d01e2..f115f64a7a08b20b11b233175a1f8a1f42d50ba7 100644 (file)
@@ -357,10 +357,10 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
                /* 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;
index 120bf87e7945b432e13cc9017132005f69a339c6..1aa4deb43de17f2fe75951bcd6f8263fb9e7f0f9 100644 (file)
 #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(&current->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.
@@ -40,8 +54,8 @@ void __init fpu_init(void)
 
        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;
 }
index f4e65f7f67c3bd2b7fba0289f309bf08328cf3a2..d8cdbe131c73b7963548404eed9c1e684f31c6d9 100644 (file)
@@ -77,6 +77,7 @@ do_fpu_end(void)
         /* 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)
index 6a4e35ac7d124dcf731b715d37a299abc6fe96ab..db663695d003e9b4140f6798717f3077a5dd81e7 100644 (file)
 #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...
@@ -89,12 +92,6 @@ extern unsigned short get_fpu_mxcsr( struct task_struct *tsk );
 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...
index 0ebe1aa1afb02c8c4393c0a6e5da29b2d178585c..e114f9fe9cbe2a9cef983e6058c75d755afbada0 100644 (file)
@@ -332,7 +332,7 @@ struct i387_fxsave_struct {
        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];
index b9ecf53519a2ef76b165a6e3d1e8d2ffe865369a..bb5edc3cd348e1ebd6d4bffdb0e4efa058523f25 100644 (file)
@@ -20,6 +20,8 @@
 #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);
 
@@ -52,11 +54,6 @@ static inline int need_signal_i387(struct task_struct *me)
        }                                                       \
 } 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...
  */
@@ -75,7 +72,6 @@ extern int set_fpregs(struct task_struct *tsk,
 #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) 
 {