diff options
author | Avi Kivity <avi@redhat.com> | 2010-05-06 04:45:45 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2010-05-10 13:39:33 -0400 |
commit | c9ad488289144ae5ef53b012e15895ef1f5e4bb6 (patch) | |
tree | 06c29cda09e204d3b0b5b3d9a2a97bda0b4e340d /arch/x86/include | |
parent | 250825008f1f94887bc039e9227a8adfb5ba366e (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>
Diffstat (limited to 'arch/x86/include')
-rw-r--r-- | arch/x86/include/asm/i387.h | 20 | ||||
-rw-r--r-- | arch/x86/include/asm/thread_info.h | 1 |
2 files changed, 16 insertions, 5 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 | ||