blob: 2737366ea5830df0f3b54b69be488c41768dc799 [file] [log] [blame]
Linus Torvalds1361b832012-02-21 13:19:22 -08001/*
2 * Copyright (C) 1994 Linus Torvalds
3 *
4 * Pentium III FXSR, SSE support
5 * General FPU state handling cleanups
6 * Gareth Hughes <gareth@valinux.com>, May 2000
7 * x86-64 work by Andi Kleen 2002
8 */
9
Ingo Molnar78f7f1e2015-04-24 02:54:44 +020010#ifndef _ASM_X86_FPU_INTERNAL_H
11#define _ASM_X86_FPU_INTERNAL_H
Linus Torvalds1361b832012-02-21 13:19:22 -080012
Suresh Siddha050902c2012-07-24 16:05:27 -070013#include <linux/compat.h>
Ingo Molnar952f07e2015-04-26 16:56:05 +020014#include <linux/sched.h>
Linus Torvalds1361b832012-02-21 13:19:22 -080015#include <linux/slab.h>
Ingo Molnarf89e32e2015-04-22 10:58:10 +020016
Linus Torvalds1361b832012-02-21 13:19:22 -080017#include <asm/user.h>
Ingo Molnardf6b35f2015-04-24 02:46:00 +020018#include <asm/fpu/api.h>
Ingo Molnar669ebab2015-04-28 08:41:33 +020019#include <asm/fpu/xstate.h>
Borislav Petkovcd4d09e2016-01-26 22:12:04 +010020#include <asm/cpufeature.h>
Dave Hansend1898b72016-06-01 10:42:20 -070021#include <asm/trace/fpu.h>
Linus Torvalds1361b832012-02-21 13:19:22 -080022
Ingo Molnar6ffc1522015-04-29 20:24:14 +020023/*
24 * High level FPU state handling functions:
25 */
Ingo Molnar0c306bc2015-04-30 12:59:30 +020026extern void fpu__activate_curr(struct fpu *fpu);
Ingo Molnar056028122015-05-27 12:22:29 +020027extern void fpu__activate_fpstate_read(struct fpu *fpu);
Ingo Molnar6a81d7e2015-05-27 12:22:29 +020028extern void fpu__activate_fpstate_write(struct fpu *fpu);
Dave Hansenb8b9b6b2016-02-12 13:02:35 -080029extern void fpu__current_fpstate_write_begin(void);
30extern void fpu__current_fpstate_write_end(void);
Ingo Molnar6ffc1522015-04-29 20:24:14 +020031extern void fpu__save(struct fpu *fpu);
Ingo Molnare1884d62015-05-04 11:49:58 +020032extern void fpu__restore(struct fpu *fpu);
Ingo Molnar82c0e452015-04-29 21:09:18 +020033extern int fpu__restore_sig(void __user *buf, int ia32_frame);
Ingo Molnar6ffc1522015-04-29 20:24:14 +020034extern void fpu__drop(struct fpu *fpu);
35extern int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu);
Ingo Molnar04c8e012015-04-29 20:35:33 +020036extern void fpu__clear(struct fpu *fpu);
Ingo Molnarb1b64dc2015-05-05 15:56:33 +020037extern int fpu__exception_code(struct fpu *fpu, int trap_nr);
38extern int dump_fpu(struct pt_regs *ptregs, struct user_i387_struct *fpstate);
Ingo Molnar6ffc1522015-04-29 20:24:14 +020039
Ingo Molnarb1b64dc2015-05-05 15:56:33 +020040/*
41 * Boot time FPU initialization functions:
42 */
43extern void fpu__init_cpu(void);
44extern void fpu__init_system_xstate(void);
45extern void fpu__init_cpu_xstate(void);
46extern void fpu__init_system(struct cpuinfo_x86 *c);
Ingo Molnar952f07e2015-04-26 16:56:05 +020047extern void fpu__init_check_bugs(void);
48extern void fpu__resume_cpu(void);
yu-cheng yua5fe93a2016-01-06 14:24:53 -080049extern u64 fpu__get_supported_xfeatures_mask(void);
Ingo Molnar952f07e2015-04-26 16:56:05 +020050
Ingo Molnare97131a2015-05-05 11:34:49 +020051/*
52 * Debugging facility:
53 */
54#ifdef CONFIG_X86_DEBUG_FPU
55# define WARN_ON_FPU(x) WARN_ON_ONCE(x)
56#else
Ingo Molnar83242c52015-05-27 12:22:29 +020057# define WARN_ON_FPU(x) ({ (void)(x); 0; })
Ingo Molnare97131a2015-05-05 11:34:49 +020058#endif
59
Rik van Riel1c927ee2015-02-06 15:02:01 -050060/*
Ingo Molnarb1b64dc2015-05-05 15:56:33 +020061 * FPU related CPU feature flag helper routines:
Rik van Riel1c927ee2015-02-06 15:02:01 -050062 */
Suresh Siddha5d2bd702012-09-06 14:58:52 -070063static __always_inline __pure bool use_eager_fpu(void)
64{
Borislav Petkovbc696ca2016-01-26 22:12:05 +010065 return static_cpu_has(X86_FEATURE_EAGER_FPU);
Suresh Siddha5d2bd702012-09-06 14:58:52 -070066}
67
Linus Torvalds1361b832012-02-21 13:19:22 -080068static __always_inline __pure bool use_xsaveopt(void)
69{
Borislav Petkovbc696ca2016-01-26 22:12:05 +010070 return static_cpu_has(X86_FEATURE_XSAVEOPT);
Linus Torvalds1361b832012-02-21 13:19:22 -080071}
72
73static __always_inline __pure bool use_xsave(void)
74{
Borislav Petkovbc696ca2016-01-26 22:12:05 +010075 return static_cpu_has(X86_FEATURE_XSAVE);
Linus Torvalds1361b832012-02-21 13:19:22 -080076}
77
78static __always_inline __pure bool use_fxsr(void)
79{
Borislav Petkovbc696ca2016-01-26 22:12:05 +010080 return static_cpu_has(X86_FEATURE_FXSR);
Linus Torvalds1361b832012-02-21 13:19:22 -080081}
82
Ingo Molnarb1b64dc2015-05-05 15:56:33 +020083/*
84 * fpstate handling functions:
85 */
86
87extern union fpregs_state init_fpstate;
88
89extern void fpstate_init(union fpregs_state *state);
90#ifdef CONFIG_MATH_EMULATION
91extern void fpstate_init_soft(struct swregs_state *soft);
92#else
93static inline void fpstate_init_soft(struct swregs_state *soft) {}
94#endif
95static inline void fpstate_init_fxstate(struct fxregs_state *fx)
96{
97 fx->cwd = 0x37f;
98 fx->mxcsr = MXCSR_DEFAULT;
99}
Ingo Molnar36e49e7f2015-04-28 11:25:02 +0200100extern void fpstate_sanitize_xstate(struct fpu *fpu);
Linus Torvalds1361b832012-02-21 13:19:22 -0800101
H. Peter Anvin49b8c692012-09-21 17:18:44 -0700102#define user_insn(insn, output, input...) \
103({ \
104 int err; \
105 asm volatile(ASM_STAC "\n" \
106 "1:" #insn "\n\t" \
107 "2: " ASM_CLAC "\n" \
108 ".section .fixup,\"ax\"\n" \
109 "3: movl $-1,%[err]\n" \
110 " jmp 2b\n" \
111 ".previous\n" \
112 _ASM_EXTABLE(1b, 3b) \
113 : [err] "=r" (err), output \
114 : "0"(0), input); \
115 err; \
116})
Linus Torvalds1361b832012-02-21 13:19:22 -0800117
Suresh Siddha0ca5bd02012-07-24 16:05:28 -0700118#define check_insn(insn, output, input...) \
119({ \
120 int err; \
121 asm volatile("1:" #insn "\n\t" \
122 "2:\n" \
123 ".section .fixup,\"ax\"\n" \
124 "3: movl $-1,%[err]\n" \
125 " jmp 2b\n" \
126 ".previous\n" \
127 _ASM_EXTABLE(1b, 3b) \
128 : [err] "=r" (err), output \
129 : "0"(0), input); \
130 err; \
131})
Linus Torvalds1361b832012-02-21 13:19:22 -0800132
Ingo Molnarc47ada32015-04-30 17:15:32 +0200133static inline int copy_fregs_to_user(struct fregs_state __user *fx)
Suresh Siddha0ca5bd02012-07-24 16:05:28 -0700134{
H. Peter Anvin49b8c692012-09-21 17:18:44 -0700135 return user_insn(fnsave %[fx]; fwait, [fx] "=m" (*fx), "m" (*fx));
Linus Torvalds1361b832012-02-21 13:19:22 -0800136}
137
Ingo Molnarc47ada32015-04-30 17:15:32 +0200138static inline int copy_fxregs_to_user(struct fxregs_state __user *fx)
Linus Torvalds1361b832012-02-21 13:19:22 -0800139{
Masahiro Yamada97f26452016-08-03 13:45:50 -0700140 if (IS_ENABLED(CONFIG_X86_32))
H. Peter Anvin49b8c692012-09-21 17:18:44 -0700141 return user_insn(fxsave %[fx], [fx] "=m" (*fx), "m" (*fx));
Masahiro Yamada97f26452016-08-03 13:45:50 -0700142 else if (IS_ENABLED(CONFIG_AS_FXSAVEQ))
H. Peter Anvin49b8c692012-09-21 17:18:44 -0700143 return user_insn(fxsaveq %[fx], [fx] "=m" (*fx), "m" (*fx));
Linus Torvalds1361b832012-02-21 13:19:22 -0800144
Ingo Molnarc6813142015-04-30 11:34:09 +0200145 /* See comment in copy_fxregs_to_kernel() below. */
H. Peter Anvin49b8c692012-09-21 17:18:44 -0700146 return user_insn(rex64/fxsave (%[fx]), "=m" (*fx), [fx] "R" (fx));
Linus Torvalds1361b832012-02-21 13:19:22 -0800147}
148
Ingo Molnar9ccc27a2015-05-25 11:27:46 +0200149static inline void copy_kernel_to_fxregs(struct fxregs_state *fx)
Linus Torvalds1361b832012-02-21 13:19:22 -0800150{
Ingo Molnar43b287b2015-05-25 10:59:31 +0200151 int err;
Linus Torvalds1361b832012-02-21 13:19:22 -0800152
Masahiro Yamada97f26452016-08-03 13:45:50 -0700153 if (IS_ENABLED(CONFIG_X86_32)) {
Ingo Molnar43b287b2015-05-25 10:59:31 +0200154 err = check_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
155 } else {
Masahiro Yamada97f26452016-08-03 13:45:50 -0700156 if (IS_ENABLED(CONFIG_AS_FXSAVEQ)) {
Ingo Molnar43b287b2015-05-25 10:59:31 +0200157 err = check_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
158 } else {
159 /* See comment in copy_fxregs_to_kernel() below. */
160 err = check_insn(rex64/fxrstor (%[fx]), "=m" (*fx), [fx] "R" (fx), "m" (*fx));
161 }
162 }
163 /* Copying from a kernel buffer to FPU registers should never fail: */
164 WARN_ON_FPU(err);
Suresh Siddha0ca5bd02012-07-24 16:05:28 -0700165}
166
Ingo Molnarc47ada32015-04-30 17:15:32 +0200167static inline int copy_user_to_fxregs(struct fxregs_state __user *fx)
H. Peter Anvine139e952012-09-25 15:42:18 -0700168{
Masahiro Yamada97f26452016-08-03 13:45:50 -0700169 if (IS_ENABLED(CONFIG_X86_32))
H. Peter Anvine139e952012-09-25 15:42:18 -0700170 return user_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
Masahiro Yamada97f26452016-08-03 13:45:50 -0700171 else if (IS_ENABLED(CONFIG_AS_FXSAVEQ))
H. Peter Anvine139e952012-09-25 15:42:18 -0700172 return user_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
173
Ingo Molnarc6813142015-04-30 11:34:09 +0200174 /* See comment in copy_fxregs_to_kernel() below. */
H. Peter Anvine139e952012-09-25 15:42:18 -0700175 return user_insn(rex64/fxrstor (%[fx]), "=m" (*fx), [fx] "R" (fx),
176 "m" (*fx));
177}
178
Ingo Molnar9ccc27a2015-05-25 11:27:46 +0200179static inline void copy_kernel_to_fregs(struct fregs_state *fx)
Suresh Siddha0ca5bd02012-07-24 16:05:28 -0700180{
Ingo Molnar43b287b2015-05-25 10:59:31 +0200181 int err = check_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
182
183 WARN_ON_FPU(err);
Linus Torvalds1361b832012-02-21 13:19:22 -0800184}
185
Ingo Molnarc47ada32015-04-30 17:15:32 +0200186static inline int copy_user_to_fregs(struct fregs_state __user *fx)
H. Peter Anvine139e952012-09-25 15:42:18 -0700187{
188 return user_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
189}
190
Ingo Molnarc6813142015-04-30 11:34:09 +0200191static inline void copy_fxregs_to_kernel(struct fpu *fpu)
Linus Torvalds1361b832012-02-21 13:19:22 -0800192{
Masahiro Yamada97f26452016-08-03 13:45:50 -0700193 if (IS_ENABLED(CONFIG_X86_32))
Ingo Molnar7366ed72015-04-27 04:19:39 +0200194 asm volatile( "fxsave %[fx]" : [fx] "=m" (fpu->state.fxsave));
Masahiro Yamada97f26452016-08-03 13:45:50 -0700195 else if (IS_ENABLED(CONFIG_AS_FXSAVEQ))
Ingo Molnar7366ed72015-04-27 04:19:39 +0200196 asm volatile("fxsaveq %[fx]" : [fx] "=m" (fpu->state.fxsave));
Suresh Siddha0ca5bd02012-07-24 16:05:28 -0700197 else {
198 /* Using "rex64; fxsave %0" is broken because, if the memory
199 * operand uses any extended registers for addressing, a second
200 * REX prefix will be generated (to the assembler, rex64
201 * followed by semicolon is a separate instruction), and hence
202 * the 64-bitness is lost.
203 *
204 * Using "fxsaveq %0" would be the ideal choice, but is only
205 * supported starting with gas 2.16.
206 *
207 * Using, as a workaround, the properly prefixed form below
208 * isn't accepted by any binutils version so far released,
209 * complaining that the same type of prefix is used twice if
210 * an extended register is needed for addressing (fix submitted
211 * to mainline 2005-11-21).
212 *
Ingo Molnar7366ed72015-04-27 04:19:39 +0200213 * asm volatile("rex64/fxsave %0" : "=m" (fpu->state.fxsave));
Suresh Siddha0ca5bd02012-07-24 16:05:28 -0700214 *
215 * This, however, we can work around by forcing the compiler to
216 * select an addressing mode that doesn't require extended
217 * registers.
218 */
219 asm volatile( "rex64/fxsave (%[fx])"
Ingo Molnar7366ed72015-04-27 04:19:39 +0200220 : "=m" (fpu->state.fxsave)
221 : [fx] "R" (&fpu->state.fxsave));
Suresh Siddha0ca5bd02012-07-24 16:05:28 -0700222 }
Linus Torvalds1361b832012-02-21 13:19:22 -0800223}
224
Ingo Molnarfd169b02015-05-25 09:55:39 +0200225/* These macros all use (%edi)/(%rdi) as the single memory argument. */
226#define XSAVE ".byte " REX_PREFIX "0x0f,0xae,0x27"
227#define XSAVEOPT ".byte " REX_PREFIX "0x0f,0xae,0x37"
228#define XSAVES ".byte " REX_PREFIX "0x0f,0xc7,0x2f"
229#define XRSTOR ".byte " REX_PREFIX "0x0f,0xae,0x2f"
230#define XRSTORS ".byte " REX_PREFIX "0x0f,0xc7,0x1f"
231
Borislav Petkovb74a0cf2015-11-19 12:25:25 +0100232#define XSTATE_OP(op, st, lmask, hmask, err) \
233 asm volatile("1:" op "\n\t" \
234 "xor %[err], %[err]\n" \
235 "2:\n\t" \
236 ".pushsection .fixup,\"ax\"\n\t" \
237 "3: movl $-2,%[err]\n\t" \
238 "jmp 2b\n\t" \
239 ".popsection\n\t" \
240 _ASM_EXTABLE(1b, 3b) \
241 : [err] "=r" (err) \
242 : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \
243 : "memory")
244
Borislav Petkovb7106fa2015-11-19 12:25:26 +0100245/*
246 * If XSAVES is enabled, it replaces XSAVEOPT because it supports a compact
247 * format and supervisor states in addition to modified optimization in
248 * XSAVEOPT.
249 *
250 * Otherwise, if XSAVEOPT is enabled, XSAVEOPT replaces XSAVE because XSAVEOPT
251 * supports modified optimization which is not supported by XSAVE.
252 *
253 * We use XSAVE as a fallback.
254 *
255 * The 661 label is defined in the ALTERNATIVE* macros as the address of the
256 * original instruction which gets replaced. We need to use it here as the
257 * address of the instruction where we might get an exception at.
258 */
259#define XSTATE_XSAVE(st, lmask, hmask, err) \
260 asm volatile(ALTERNATIVE_2(XSAVE, \
261 XSAVEOPT, X86_FEATURE_XSAVEOPT, \
262 XSAVES, X86_FEATURE_XSAVES) \
263 "\n" \
264 "xor %[err], %[err]\n" \
265 "3:\n" \
266 ".pushsection .fixup,\"ax\"\n" \
267 "4: movl $-2, %[err]\n" \
268 "jmp 3b\n" \
269 ".popsection\n" \
270 _ASM_EXTABLE(661b, 4b) \
271 : [err] "=r" (err) \
272 : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \
273 : "memory")
274
275/*
276 * Use XRSTORS to restore context if it is enabled. XRSTORS supports compact
277 * XSAVE area format.
278 */
279#define XSTATE_XRESTORE(st, lmask, hmask, err) \
280 asm volatile(ALTERNATIVE(XRSTOR, \
281 XRSTORS, X86_FEATURE_XSAVES) \
282 "\n" \
283 "xor %[err], %[err]\n" \
284 "3:\n" \
285 ".pushsection .fixup,\"ax\"\n" \
286 "4: movl $-2, %[err]\n" \
287 "jmp 3b\n" \
288 ".popsection\n" \
289 _ASM_EXTABLE(661b, 4b) \
290 : [err] "=r" (err) \
291 : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \
292 : "memory")
Borislav Petkovb74a0cf2015-11-19 12:25:25 +0100293
Ingo Molnarfd169b02015-05-25 09:55:39 +0200294/*
295 * This function is called only during boot time when x86 caps are not set
296 * up and alternative can not be used yet.
297 */
Ingo Molnar8c05f052015-05-24 09:23:25 +0200298static inline void copy_xregs_to_kernel_booting(struct xregs_state *xstate)
Ingo Molnarfd169b02015-05-25 09:55:39 +0200299{
300 u64 mask = -1;
301 u32 lmask = mask;
302 u32 hmask = mask >> 32;
Borislav Petkovb74a0cf2015-11-19 12:25:25 +0100303 int err;
Ingo Molnarfd169b02015-05-25 09:55:39 +0200304
305 WARN_ON(system_state != SYSTEM_BOOTING);
306
Borislav Petkovbc696ca2016-01-26 22:12:05 +0100307 if (static_cpu_has(X86_FEATURE_XSAVES))
Borislav Petkovb74a0cf2015-11-19 12:25:25 +0100308 XSTATE_OP(XSAVES, xstate, lmask, hmask, err);
Ingo Molnarfd169b02015-05-25 09:55:39 +0200309 else
Borislav Petkovb74a0cf2015-11-19 12:25:25 +0100310 XSTATE_OP(XSAVE, xstate, lmask, hmask, err);
Ingo Molnar8c05f052015-05-24 09:23:25 +0200311
312 /* We should never fault when copying to a kernel buffer: */
313 WARN_ON_FPU(err);
Ingo Molnarfd169b02015-05-25 09:55:39 +0200314}
315
316/*
317 * This function is called only during boot time when x86 caps are not set
318 * up and alternative can not be used yet.
319 */
Ingo Molnard65fcd62015-05-27 14:04:44 +0200320static inline void copy_kernel_to_xregs_booting(struct xregs_state *xstate)
Ingo Molnarfd169b02015-05-25 09:55:39 +0200321{
Ingo Molnard65fcd62015-05-27 14:04:44 +0200322 u64 mask = -1;
Ingo Molnarfd169b02015-05-25 09:55:39 +0200323 u32 lmask = mask;
324 u32 hmask = mask >> 32;
Borislav Petkovb74a0cf2015-11-19 12:25:25 +0100325 int err;
Ingo Molnarfd169b02015-05-25 09:55:39 +0200326
327 WARN_ON(system_state != SYSTEM_BOOTING);
328
Borislav Petkovbc696ca2016-01-26 22:12:05 +0100329 if (static_cpu_has(X86_FEATURE_XSAVES))
Borislav Petkovb74a0cf2015-11-19 12:25:25 +0100330 XSTATE_OP(XRSTORS, xstate, lmask, hmask, err);
Ingo Molnarfd169b02015-05-25 09:55:39 +0200331 else
Borislav Petkovb74a0cf2015-11-19 12:25:25 +0100332 XSTATE_OP(XRSTOR, xstate, lmask, hmask, err);
Ingo Molnar8c05f052015-05-24 09:23:25 +0200333
334 /* We should never fault when copying from a kernel buffer: */
335 WARN_ON_FPU(err);
Ingo Molnarfd169b02015-05-25 09:55:39 +0200336}
337
338/*
339 * Save processor xstate to xsave area.
340 */
Ingo Molnar8c05f052015-05-24 09:23:25 +0200341static inline void copy_xregs_to_kernel(struct xregs_state *xstate)
Ingo Molnarfd169b02015-05-25 09:55:39 +0200342{
343 u64 mask = -1;
344 u32 lmask = mask;
345 u32 hmask = mask >> 32;
Borislav Petkovb7106fa2015-11-19 12:25:26 +0100346 int err;
Ingo Molnarfd169b02015-05-25 09:55:39 +0200347
348 WARN_ON(!alternatives_patched);
349
Borislav Petkovb7106fa2015-11-19 12:25:26 +0100350 XSTATE_XSAVE(xstate, lmask, hmask, err);
Ingo Molnarfd169b02015-05-25 09:55:39 +0200351
Ingo Molnar8c05f052015-05-24 09:23:25 +0200352 /* We should never fault when copying to a kernel buffer: */
353 WARN_ON_FPU(err);
Ingo Molnarfd169b02015-05-25 09:55:39 +0200354}
355
356/*
357 * Restore processor xstate from xsave area.
358 */
Ingo Molnar8c05f052015-05-24 09:23:25 +0200359static inline void copy_kernel_to_xregs(struct xregs_state *xstate, u64 mask)
Ingo Molnarfd169b02015-05-25 09:55:39 +0200360{
Ingo Molnarfd169b02015-05-25 09:55:39 +0200361 u32 lmask = mask;
362 u32 hmask = mask >> 32;
Borislav Petkovb7106fa2015-11-19 12:25:26 +0100363 int err;
Ingo Molnarfd169b02015-05-25 09:55:39 +0200364
Borislav Petkovb7106fa2015-11-19 12:25:26 +0100365 XSTATE_XRESTORE(xstate, lmask, hmask, err);
Ingo Molnarfd169b02015-05-25 09:55:39 +0200366
Ingo Molnar8c05f052015-05-24 09:23:25 +0200367 /* We should never fault when copying from a kernel buffer: */
368 WARN_ON_FPU(err);
Ingo Molnarfd169b02015-05-25 09:55:39 +0200369}
370
371/*
372 * Save xstate to user space xsave area.
373 *
374 * We don't use modified optimization because xrstor/xrstors might track
375 * a different application.
376 *
377 * We don't use compacted format xsave area for
378 * backward compatibility for old applications which don't understand
379 * compacted format of xsave area.
380 */
381static inline int copy_xregs_to_user(struct xregs_state __user *buf)
382{
383 int err;
384
385 /*
386 * Clear the xsave header first, so that reserved fields are
387 * initialized to zero.
388 */
389 err = __clear_user(&buf->header, sizeof(buf->header));
390 if (unlikely(err))
391 return -EFAULT;
392
Borislav Petkovb74a0cf2015-11-19 12:25:25 +0100393 stac();
394 XSTATE_OP(XSAVE, buf, -1, -1, err);
395 clac();
396
Ingo Molnarfd169b02015-05-25 09:55:39 +0200397 return err;
398}
399
400/*
401 * Restore xstate from user space xsave area.
402 */
403static inline int copy_user_to_xregs(struct xregs_state __user *buf, u64 mask)
404{
Ingo Molnarfd169b02015-05-25 09:55:39 +0200405 struct xregs_state *xstate = ((__force struct xregs_state *)buf);
406 u32 lmask = mask;
407 u32 hmask = mask >> 32;
Borislav Petkovb74a0cf2015-11-19 12:25:25 +0100408 int err;
Ingo Molnarfd169b02015-05-25 09:55:39 +0200409
Borislav Petkovb74a0cf2015-11-19 12:25:25 +0100410 stac();
411 XSTATE_OP(XRSTOR, xstate, lmask, hmask, err);
412 clac();
413
Ingo Molnarfd169b02015-05-25 09:55:39 +0200414 return err;
415}
416
Linus Torvalds1361b832012-02-21 13:19:22 -0800417/*
418 * These must be called with preempt disabled. Returns
Ingo Molnar4f836342015-04-27 02:53:16 +0200419 * 'true' if the FPU state is still intact and we can
420 * keep registers active.
421 *
422 * The legacy FNSAVE instruction cleared all FPU state
423 * unconditionally, so registers are essentially destroyed.
424 * Modern FPU state can be kept in registers, if there are
Ingo Molnar1bc6b052015-04-27 03:32:18 +0200425 * no pending FP exceptions.
Linus Torvalds1361b832012-02-21 13:19:22 -0800426 */
Ingo Molnar4f836342015-04-27 02:53:16 +0200427static inline int copy_fpregs_to_fpstate(struct fpu *fpu)
Linus Torvalds1361b832012-02-21 13:19:22 -0800428{
Ingo Molnar1bc6b052015-04-27 03:32:18 +0200429 if (likely(use_xsave())) {
Ingo Molnarc6813142015-04-30 11:34:09 +0200430 copy_xregs_to_kernel(&fpu->state.xsave);
Ingo Molnar1bc6b052015-04-27 03:32:18 +0200431 return 1;
432 }
Linus Torvalds1361b832012-02-21 13:19:22 -0800433
Ingo Molnar1bc6b052015-04-27 03:32:18 +0200434 if (likely(use_fxsr())) {
Ingo Molnarc6813142015-04-30 11:34:09 +0200435 copy_fxregs_to_kernel(fpu);
Ingo Molnar1bc6b052015-04-27 03:32:18 +0200436 return 1;
Linus Torvalds1361b832012-02-21 13:19:22 -0800437 }
438
439 /*
Ingo Molnar1bc6b052015-04-27 03:32:18 +0200440 * Legacy FPU register saving, FNSAVE always clears FPU registers,
441 * so we have to mark them inactive:
Linus Torvalds1361b832012-02-21 13:19:22 -0800442 */
Ingo Molnar87dafd42015-05-25 10:57:06 +0200443 asm volatile("fnsave %[fp]; fwait" : [fp] "=m" (fpu->state.fsave));
Ingo Molnar4f836342015-04-27 02:53:16 +0200444
Ingo Molnar4f836342015-04-27 02:53:16 +0200445 return 0;
Linus Torvalds1361b832012-02-21 13:19:22 -0800446}
447
Ingo Molnar003e2e82015-05-25 11:59:35 +0200448static inline void __copy_kernel_to_fpregs(union fpregs_state *fpstate)
Linus Torvalds1361b832012-02-21 13:19:22 -0800449{
Ingo Molnar8c05f052015-05-24 09:23:25 +0200450 if (use_xsave()) {
Ingo Molnar003e2e82015-05-25 11:59:35 +0200451 copy_kernel_to_xregs(&fpstate->xsave, -1);
Ingo Molnar8c05f052015-05-24 09:23:25 +0200452 } else {
453 if (use_fxsr())
Ingo Molnar003e2e82015-05-25 11:59:35 +0200454 copy_kernel_to_fxregs(&fpstate->fxsave);
Ingo Molnar8c05f052015-05-24 09:23:25 +0200455 else
Ingo Molnar003e2e82015-05-25 11:59:35 +0200456 copy_kernel_to_fregs(&fpstate->fsave);
Ingo Molnar8c05f052015-05-24 09:23:25 +0200457 }
Linus Torvalds1361b832012-02-21 13:19:22 -0800458}
459
Ingo Molnar003e2e82015-05-25 11:59:35 +0200460static inline void copy_kernel_to_fpregs(union fpregs_state *fpstate)
Linus Torvalds1361b832012-02-21 13:19:22 -0800461{
Borislav Petkov6ca7a8a2014-12-21 15:02:23 +0100462 /*
463 * AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception is
464 * pending. Clear the x87 state here by setting it to fixed values.
465 * "m" is a random variable that should be in L1.
466 */
Borislav Petkovbc696ca2016-01-26 22:12:05 +0100467 if (unlikely(static_cpu_has_bug(X86_BUG_FXSAVE_LEAK))) {
Linus Torvalds26bef132014-01-11 19:15:52 -0800468 asm volatile(
469 "fnclex\n\t"
470 "emms\n\t"
471 "fildl %P[addr]" /* set F?P to defined value */
Ingo Molnar003e2e82015-05-25 11:59:35 +0200472 : : [addr] "m" (fpstate));
Linus Torvalds26bef132014-01-11 19:15:52 -0800473 }
Linus Torvalds1361b832012-02-21 13:19:22 -0800474
Ingo Molnar003e2e82015-05-25 11:59:35 +0200475 __copy_kernel_to_fpregs(fpstate);
Linus Torvalds1361b832012-02-21 13:19:22 -0800476}
477
Ingo Molnar87dafd42015-05-25 10:57:06 +0200478extern int copy_fpstate_to_sigframe(void __user *buf, void __user *fp, int size);
Ingo Molnarb1b64dc2015-05-05 15:56:33 +0200479
480/*
481 * FPU context switch related helper methods:
482 */
483
484DECLARE_PER_CPU(struct fpu *, fpu_fpregs_owner_ctx);
485
486/*
487 * Must be run with preemption disabled: this clears the fpu_fpregs_owner_ctx,
488 * on this CPU.
489 *
490 * This will disable any lazy FPU state restore of the current FPU state,
491 * but if the current thread owns the FPU, it will still be saved by.
492 */
493static inline void __cpu_disable_lazy_restore(unsigned int cpu)
494{
495 per_cpu(fpu_fpregs_owner_ctx, cpu) = NULL;
496}
497
498static inline int fpu_want_lazy_restore(struct fpu *fpu, unsigned int cpu)
499{
500 return fpu == this_cpu_read_stable(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu;
501}
502
503
Ingo Molnar32b49b32015-04-27 08:58:45 +0200504/*
505 * Wrap lazy FPU TS handling in a 'hw fpregs activation/deactivation'
506 * idiom, which is then paired with the sw-flag (fpregs_active) later on:
507 */
508
509static inline void __fpregs_activate_hw(void)
510{
511 if (!use_eager_fpu())
512 clts();
513}
514
515static inline void __fpregs_deactivate_hw(void)
516{
517 if (!use_eager_fpu())
518 stts();
519}
520
521/* Must be paired with an 'stts' (fpregs_deactivate_hw()) after! */
Ingo Molnar723c58e2015-04-24 14:28:01 +0200522static inline void __fpregs_deactivate(struct fpu *fpu)
Linus Torvalds1361b832012-02-21 13:19:22 -0800523{
Ingo Molnare97131a2015-05-05 11:34:49 +0200524 WARN_ON_FPU(!fpu->fpregs_active);
525
Ingo Molnard5cea9b2015-04-24 14:19:26 +0200526 fpu->fpregs_active = 0;
Ingo Molnar36b544d2015-04-23 12:18:28 +0200527 this_cpu_write(fpu_fpregs_owner_ctx, NULL);
Dave Hansend1898b72016-06-01 10:42:20 -0700528 trace_x86_fpu_regs_deactivated(fpu);
Linus Torvalds1361b832012-02-21 13:19:22 -0800529}
530
Ingo Molnar32b49b32015-04-27 08:58:45 +0200531/* Must be paired with a 'clts' (fpregs_activate_hw()) before! */
Ingo Molnardfaea4e2015-04-24 14:26:47 +0200532static inline void __fpregs_activate(struct fpu *fpu)
Linus Torvalds1361b832012-02-21 13:19:22 -0800533{
Ingo Molnare97131a2015-05-05 11:34:49 +0200534 WARN_ON_FPU(fpu->fpregs_active);
535
Ingo Molnard5cea9b2015-04-24 14:19:26 +0200536 fpu->fpregs_active = 1;
Ingo Molnarc0311f62015-04-23 12:24:59 +0200537 this_cpu_write(fpu_fpregs_owner_ctx, fpu);
Dave Hansend1898b72016-06-01 10:42:20 -0700538 trace_x86_fpu_regs_activated(fpu);
Linus Torvalds1361b832012-02-21 13:19:22 -0800539}
540
541/*
Ingo Molnar952f07e2015-04-26 16:56:05 +0200542 * The question "does this thread have fpu access?"
543 * is slightly racy, since preemption could come in
544 * and revoke it immediately after the test.
545 *
546 * However, even in that very unlikely scenario,
547 * we can just assume we have FPU access - typically
548 * to save the FP state - we'll just take a #NM
549 * fault and get the FPU access back.
550 */
Ingo Molnar3c6dffa2015-04-28 12:28:08 +0200551static inline int fpregs_active(void)
Ingo Molnar952f07e2015-04-26 16:56:05 +0200552{
553 return current->thread.fpu.fpregs_active;
554}
555
556/*
Linus Torvalds1361b832012-02-21 13:19:22 -0800557 * Encapsulate the CR0.TS handling together with the
558 * software flag.
559 *
560 * These generally need preemption protection to work,
561 * do try to avoid using these on their own.
562 */
Ingo Molnar232f62c2015-04-24 14:30:38 +0200563static inline void fpregs_activate(struct fpu *fpu)
Linus Torvalds1361b832012-02-21 13:19:22 -0800564{
Ingo Molnar32b49b32015-04-27 08:58:45 +0200565 __fpregs_activate_hw();
Ingo Molnardfaea4e2015-04-24 14:26:47 +0200566 __fpregs_activate(fpu);
Linus Torvalds1361b832012-02-21 13:19:22 -0800567}
568
Ingo Molnar66af8e22015-04-24 14:31:27 +0200569static inline void fpregs_deactivate(struct fpu *fpu)
570{
571 __fpregs_deactivate(fpu);
Ingo Molnar32b49b32015-04-27 08:58:45 +0200572 __fpregs_deactivate_hw();
Ingo Molnar66af8e22015-04-24 14:31:27 +0200573}
574
Borislav Petkovb85e67d2015-03-16 10:21:55 +0100575/*
Linus Torvalds1361b832012-02-21 13:19:22 -0800576 * FPU state switching for scheduling.
577 *
578 * This is a two-stage process:
579 *
580 * - switch_fpu_prepare() saves the old state and
581 * sets the new state of the CR0.TS bit. This is
582 * done within the context of the old process.
583 *
584 * - switch_fpu_finish() restores the new state as
585 * necessary.
586 */
587typedef struct { int preload; } fpu_switch_t;
588
Ingo Molnarcb8818b2015-04-23 17:39:04 +0200589static inline fpu_switch_t
590switch_fpu_prepare(struct fpu *old_fpu, struct fpu *new_fpu, int cpu)
Linus Torvalds1361b832012-02-21 13:19:22 -0800591{
592 fpu_switch_t fpu;
593
Suresh Siddha304bced2012-08-24 14:13:02 -0700594 /*
595 * If the task has used the math, pre-load the FPU on xsave processors
596 * or if the past 5 consecutive context-switches used math.
597 */
Andy Lutomirski4ecd16e2016-01-24 14:38:06 -0800598 fpu.preload = static_cpu_has(X86_FEATURE_FPU) &&
599 new_fpu->fpstate_active &&
Ingo Molnarcb8818b2015-04-23 17:39:04 +0200600 (use_eager_fpu() || new_fpu->counter > 5);
Rik van Riel1361ef22015-02-06 15:02:03 -0500601
Ingo Molnard5cea9b2015-04-24 14:19:26 +0200602 if (old_fpu->fpregs_active) {
Ingo Molnar4f836342015-04-27 02:53:16 +0200603 if (!copy_fpregs_to_fpstate(old_fpu))
Ingo Molnarcb8818b2015-04-23 17:39:04 +0200604 old_fpu->last_cpu = -1;
Rik van Riel1361ef22015-02-06 15:02:03 -0500605 else
Ingo Molnarcb8818b2015-04-23 17:39:04 +0200606 old_fpu->last_cpu = cpu;
Rik van Riel1361ef22015-02-06 15:02:03 -0500607
Ingo Molnar36b544d2015-04-23 12:18:28 +0200608 /* But leave fpu_fpregs_owner_ctx! */
Ingo Molnard5cea9b2015-04-24 14:19:26 +0200609 old_fpu->fpregs_active = 0;
Dave Hansend1898b72016-06-01 10:42:20 -0700610 trace_x86_fpu_regs_deactivated(old_fpu);
Linus Torvalds1361b832012-02-21 13:19:22 -0800611
612 /* Don't change CR0.TS if we just switch! */
613 if (fpu.preload) {
Ingo Molnarcb8818b2015-04-23 17:39:04 +0200614 new_fpu->counter++;
Ingo Molnardfaea4e2015-04-24 14:26:47 +0200615 __fpregs_activate(new_fpu);
Dave Hansend1898b72016-06-01 10:42:20 -0700616 trace_x86_fpu_regs_activated(new_fpu);
Ingo Molnar7366ed72015-04-27 04:19:39 +0200617 prefetch(&new_fpu->state);
Ingo Molnar32b49b32015-04-27 08:58:45 +0200618 } else {
619 __fpregs_deactivate_hw();
620 }
Linus Torvalds1361b832012-02-21 13:19:22 -0800621 } else {
Ingo Molnarcb8818b2015-04-23 17:39:04 +0200622 old_fpu->counter = 0;
623 old_fpu->last_cpu = -1;
Linus Torvalds1361b832012-02-21 13:19:22 -0800624 if (fpu.preload) {
Ingo Molnarcb8818b2015-04-23 17:39:04 +0200625 new_fpu->counter++;
Ingo Molnar66ddc2c2015-04-23 17:25:44 +0200626 if (fpu_want_lazy_restore(new_fpu, cpu))
Linus Torvalds1361b832012-02-21 13:19:22 -0800627 fpu.preload = 0;
628 else
Ingo Molnar7366ed72015-04-27 04:19:39 +0200629 prefetch(&new_fpu->state);
Ingo Molnar232f62c2015-04-24 14:30:38 +0200630 fpregs_activate(new_fpu);
Linus Torvalds1361b832012-02-21 13:19:22 -0800631 }
632 }
633 return fpu;
634}
635
636/*
Ingo Molnarb1b64dc2015-05-05 15:56:33 +0200637 * Misc helper functions:
638 */
639
640/*
Linus Torvalds1361b832012-02-21 13:19:22 -0800641 * By the time this gets called, we've already cleared CR0.TS and
642 * given the process the FPU if we are going to preload the FPU
643 * state - all we need to do is to conditionally restore the register
644 * state itself.
645 */
Ingo Molnar384a23f2015-04-23 17:43:27 +0200646static inline void switch_fpu_finish(struct fpu *new_fpu, fpu_switch_t fpu_switch)
Linus Torvalds1361b832012-02-21 13:19:22 -0800647{
Ingo Molnar9ccc27a2015-05-25 11:27:46 +0200648 if (fpu_switch.preload)
Ingo Molnar003e2e82015-05-25 11:59:35 +0200649 copy_kernel_to_fpregs(&new_fpu->state);
Linus Torvalds1361b832012-02-21 13:19:22 -0800650}
651
652/*
Oleg Nesterovfb14b4e2015-03-11 18:34:09 +0100653 * Needs to be preemption-safe.
Linus Torvalds1361b832012-02-21 13:19:22 -0800654 *
Suresh Siddha377ffbc2012-08-24 14:12:58 -0700655 * NOTE! user_fpu_begin() must be used only immediately before restoring
Oleg Nesterovfb14b4e2015-03-11 18:34:09 +0100656 * the save state. It does not do any saving/restoring on its own. In
657 * lazy FPU mode, it is just an optimization to avoid a #NM exception,
658 * the task can lose the FPU right after preempt_enable().
Linus Torvalds1361b832012-02-21 13:19:22 -0800659 */
Linus Torvalds1361b832012-02-21 13:19:22 -0800660static inline void user_fpu_begin(void)
661{
Ingo Molnar4540d3f2015-04-23 12:31:17 +0200662 struct fpu *fpu = &current->thread.fpu;
663
Linus Torvalds1361b832012-02-21 13:19:22 -0800664 preempt_disable();
Ingo Molnar3c6dffa2015-04-28 12:28:08 +0200665 if (!fpregs_active())
Ingo Molnar232f62c2015-04-24 14:30:38 +0200666 fpregs_activate(fpu);
Linus Torvalds1361b832012-02-21 13:19:22 -0800667 preempt_enable();
668}
669
Ingo Molnarb1b64dc2015-05-05 15:56:33 +0200670/*
671 * MXCSR and XCR definitions:
672 */
673
674extern unsigned int mxcsr_feature_mask;
675
676#define XCR_XFEATURE_ENABLED_MASK 0x00000000
677
678static inline u64 xgetbv(u32 index)
679{
680 u32 eax, edx;
681
682 asm volatile(".byte 0x0f,0x01,0xd0" /* xgetbv */
683 : "=a" (eax), "=d" (edx)
684 : "c" (index));
685 return eax + ((u64)edx << 32);
686}
687
688static inline void xsetbv(u32 index, u64 value)
689{
690 u32 eax = value;
691 u32 edx = value >> 32;
692
693 asm volatile(".byte 0x0f,0x01,0xd1" /* xsetbv */
694 : : "a" (eax), "d" (edx), "c" (index));
695}
696
Ingo Molnar78f7f1e2015-04-24 02:54:44 +0200697#endif /* _ASM_X86_FPU_INTERNAL_H */