diff options
| -rw-r--r-- | arch/x86/include/asm/i387.h | 20 | ||||
| -rw-r--r-- | arch/x86/include/asm/thread_info.h | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/common.c | 5 | ||||
| -rw-r--r-- | arch/x86/kernel/i387.c | 5 | ||||
| -rw-r--r-- | arch/x86/kernel/xsave.c | 6 |
5 files changed, 21 insertions, 16 deletions
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index da2930924501..a301a6825c3a 100644 --- a/arch/x86/include/asm/i387.h +++ b/arch/x86/include/asm/i387.h | |||
| @@ -56,6 +56,18 @@ extern int restore_i387_xstate_ia32(void __user *buf); | |||
| 56 | 56 | ||
| 57 | #define X87_FSW_ES (1 << 7) /* Exception Summary */ | 57 | #define X87_FSW_ES (1 << 7) /* Exception Summary */ |
| 58 | 58 | ||
| 59 | static inline bool use_xsave(void) | ||
| 60 | { | ||
| 61 | u8 has_xsave; | ||
| 62 | |||
| 63 | alternative_io("mov $0, %0", | ||
| 64 | "mov $1, %0", | ||
| 65 | X86_FEATURE_XSAVE, | ||
| 66 | "=g"(has_xsave)); | ||
| 67 | |||
| 68 | return has_xsave; | ||
| 69 | } | ||
| 70 | |||
| 59 | #ifdef CONFIG_X86_64 | 71 | #ifdef CONFIG_X86_64 |
| 60 | 72 | ||
| 61 | /* Ignore delayed exceptions from user space */ | 73 | /* Ignore delayed exceptions from user space */ |
| @@ -99,7 +111,7 @@ static inline void clear_fpu_state(struct task_struct *tsk) | |||
| 99 | /* | 111 | /* |
| 100 | * xsave header may indicate the init state of the FP. | 112 | * xsave header may indicate the init state of the FP. |
| 101 | */ | 113 | */ |
| 102 | if ((task_thread_info(tsk)->status & TS_XSAVE) && | 114 | if (use_xsave() && |
| 103 | !(xstate->xsave_hdr.xstate_bv & XSTATE_FP)) | 115 | !(xstate->xsave_hdr.xstate_bv & XSTATE_FP)) |
| 104 | return; | 116 | return; |
| 105 | 117 | ||
| @@ -164,7 +176,7 @@ static inline void fxsave(struct task_struct *tsk) | |||
| 164 | 176 | ||
| 165 | static inline void __save_init_fpu(struct task_struct *tsk) | 177 | static inline void __save_init_fpu(struct task_struct *tsk) |
| 166 | { | 178 | { |
| 167 | if (task_thread_info(tsk)->status & TS_XSAVE) | 179 | if (use_xsave()) |
| 168 | xsave(tsk); | 180 | xsave(tsk); |
| 169 | else | 181 | else |
| 170 | fxsave(tsk); | 182 | fxsave(tsk); |
| @@ -218,7 +230,7 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx) | |||
| 218 | */ | 230 | */ |
| 219 | static inline void __save_init_fpu(struct task_struct *tsk) | 231 | static inline void __save_init_fpu(struct task_struct *tsk) |
| 220 | { | 232 | { |
| 221 | if (task_thread_info(tsk)->status & TS_XSAVE) { | 233 | if (use_xsave()) { |
| 222 | struct xsave_struct *xstate = &tsk->thread.xstate->xsave; | 234 | struct xsave_struct *xstate = &tsk->thread.xstate->xsave; |
| 223 | struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave; | 235 | struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave; |
| 224 | 236 | ||
| @@ -266,7 +278,7 @@ end: | |||
| 266 | 278 | ||
| 267 | static inline int restore_fpu_checking(struct task_struct *tsk) | 279 | static inline int restore_fpu_checking(struct task_struct *tsk) |
| 268 | { | 280 | { |
| 269 | if (task_thread_info(tsk)->status & TS_XSAVE) | 281 | if (use_xsave()) |
| 270 | return xrstor_checking(&tsk->thread.xstate->xsave); | 282 | return xrstor_checking(&tsk->thread.xstate->xsave); |
| 271 | else | 283 | else |
| 272 | return fxrstor_checking(&tsk->thread.xstate->fxsave); | 284 | return fxrstor_checking(&tsk->thread.xstate->fxsave); |
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index e0d28901e969..e9e341505ab3 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h | |||
| @@ -244,7 +244,6 @@ static inline struct thread_info *current_thread_info(void) | |||
| 244 | #define TS_POLLING 0x0004 /* true if in idle loop | 244 | #define TS_POLLING 0x0004 /* true if in idle loop |
| 245 | and not sleeping */ | 245 | and not sleeping */ |
| 246 | #define TS_RESTORE_SIGMASK 0x0008 /* restore signal mask in do_signal() */ | 246 | #define TS_RESTORE_SIGMASK 0x0008 /* restore signal mask in do_signal() */ |
| 247 | #define TS_XSAVE 0x0010 /* Use xsave/xrstor */ | ||
| 248 | 247 | ||
| 249 | #define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING) | 248 | #define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING) |
| 250 | 249 | ||
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 4868e4a951ee..c1c00d0b1692 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
| @@ -1243,10 +1243,7 @@ void __cpuinit cpu_init(void) | |||
| 1243 | /* | 1243 | /* |
| 1244 | * Force FPU initialization: | 1244 | * Force FPU initialization: |
| 1245 | */ | 1245 | */ |
| 1246 | if (cpu_has_xsave) | 1246 | current_thread_info()->status = 0; |
| 1247 | current_thread_info()->status = TS_XSAVE; | ||
| 1248 | else | ||
| 1249 | current_thread_info()->status = 0; | ||
| 1250 | clear_used_math(); | 1247 | clear_used_math(); |
| 1251 | mxcsr_feature_mask_init(); | 1248 | mxcsr_feature_mask_init(); |
| 1252 | 1249 | ||
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 54c31c285488..14ca1dc7a703 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c | |||
| @@ -102,10 +102,7 @@ void __cpuinit fpu_init(void) | |||
| 102 | 102 | ||
| 103 | mxcsr_feature_mask_init(); | 103 | mxcsr_feature_mask_init(); |
| 104 | /* clean state in init */ | 104 | /* clean state in init */ |
| 105 | if (cpu_has_xsave) | 105 | current_thread_info()->status = 0; |
| 106 | current_thread_info()->status = TS_XSAVE; | ||
| 107 | else | ||
| 108 | current_thread_info()->status = 0; | ||
| 109 | clear_used_math(); | 106 | clear_used_math(); |
| 110 | } | 107 | } |
| 111 | #endif /* CONFIG_X86_64 */ | 108 | #endif /* CONFIG_X86_64 */ |
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 782c3a362ec6..c1b0a11033a2 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c | |||
| @@ -99,7 +99,7 @@ int save_i387_xstate(void __user *buf) | |||
| 99 | if (err) | 99 | if (err) |
| 100 | return err; | 100 | return err; |
| 101 | 101 | ||
| 102 | if (task_thread_info(tsk)->status & TS_XSAVE) | 102 | if (use_xsave()) |
| 103 | err = xsave_user(buf); | 103 | err = xsave_user(buf); |
| 104 | else | 104 | else |
| 105 | err = fxsave_user(buf); | 105 | err = fxsave_user(buf); |
| @@ -116,7 +116,7 @@ int save_i387_xstate(void __user *buf) | |||
| 116 | 116 | ||
| 117 | clear_used_math(); /* trigger finit */ | 117 | clear_used_math(); /* trigger finit */ |
| 118 | 118 | ||
| 119 | if (task_thread_info(tsk)->status & TS_XSAVE) { | 119 | if (use_xsave()) { |
| 120 | struct _fpstate __user *fx = buf; | 120 | struct _fpstate __user *fx = buf; |
| 121 | struct _xstate __user *x = buf; | 121 | struct _xstate __user *x = buf; |
| 122 | u64 xstate_bv; | 122 | u64 xstate_bv; |
| @@ -225,7 +225,7 @@ int restore_i387_xstate(void __user *buf) | |||
| 225 | clts(); | 225 | clts(); |
| 226 | task_thread_info(current)->status |= TS_USEDFPU; | 226 | task_thread_info(current)->status |= TS_USEDFPU; |
| 227 | } | 227 | } |
| 228 | if (task_thread_info(tsk)->status & TS_XSAVE) | 228 | if (use_xsave()) |
| 229 | err = restore_user_xstate(buf); | 229 | err = restore_user_xstate(buf); |
| 230 | else | 230 | else |
| 231 | err = fxrstor_checking((__force struct i387_fxsave_struct *) | 231 | err = fxrstor_checking((__force struct i387_fxsave_struct *) |
