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 *) |