aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2010-05-06 04:45:45 -0400
committerH. Peter Anvin <hpa@zytor.com>2010-05-10 13:39:33 -0400
commitc9ad488289144ae5ef53b012e15895ef1f5e4bb6 (patch)
tree06c29cda09e204d3b0b5b3d9a2a97bda0b4e340d
parent250825008f1f94887bc039e9227a8adfb5ba366e (diff)
x86: Eliminate TS_XSAVE
The fpu code currently uses current->thread_info->status & TS_XSAVE as a way to distinguish between XSAVE capable processors and older processors. The decision is not really task specific; instead we use the task status to avoid a global memory reference - the value should be the same across all threads. Eliminate this tie-in into the task structure by using an alternative instruction keyed off the XSAVE cpu feature; this results in shorter and faster code, without introducing a global memory reference. [ hpa: in the future, this probably should use an asm jmp ] Signed-off-by: Avi Kivity <avi@redhat.com> Acked-by: Suresh Siddha <suresh.b.siddha@intel.com> LKML-Reference: <1273135546-29690-2-git-send-email-avi@redhat.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--arch/x86/include/asm/i387.h20
-rw-r--r--arch/x86/include/asm/thread_info.h1
-rw-r--r--arch/x86/kernel/cpu/common.c5
-rw-r--r--arch/x86/kernel/i387.c5
-rw-r--r--arch/x86/kernel/xsave.c6
5 files changed, 21 insertions, 16 deletions
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h
index da293092450..a301a6825c3 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
59static 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
165static inline void __save_init_fpu(struct task_struct *tsk) 177static 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 */
219static inline void __save_init_fpu(struct task_struct *tsk) 231static 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
267static inline int restore_fpu_checking(struct task_struct *tsk) 279static 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 e0d28901e96..e9e341505ab 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 4868e4a951e..c1c00d0b169 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 54c31c28548..14ca1dc7a70 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 782c3a362ec..c1b0a11033a 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 *)