internal.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. /*
  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. #ifndef _ASM_X86_FPU_INTERNAL_H
  10. #define _ASM_X86_FPU_INTERNAL_H
  11. #include <linux/compat.h>
  12. #include <linux/sched.h>
  13. #include <linux/slab.h>
  14. #include <asm/user.h>
  15. #include <asm/fpu/api.h>
  16. #include <asm/fpu/xstate.h>
  17. #include <asm/cpufeature.h>
  18. /*
  19. * High level FPU state handling functions:
  20. */
  21. extern void fpu__activate_curr(struct fpu *fpu);
  22. extern void fpu__activate_fpstate_read(struct fpu *fpu);
  23. extern void fpu__activate_fpstate_write(struct fpu *fpu);
  24. extern void fpu__save(struct fpu *fpu);
  25. extern void fpu__restore(struct fpu *fpu);
  26. extern int fpu__restore_sig(void __user *buf, int ia32_frame);
  27. extern void fpu__drop(struct fpu *fpu);
  28. extern int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu);
  29. extern void fpu__clear(struct fpu *fpu);
  30. extern int fpu__exception_code(struct fpu *fpu, int trap_nr);
  31. extern int dump_fpu(struct pt_regs *ptregs, struct user_i387_struct *fpstate);
  32. /*
  33. * Boot time FPU initialization functions:
  34. */
  35. extern void fpu__init_cpu(void);
  36. extern void fpu__init_system_xstate(void);
  37. extern void fpu__init_cpu_xstate(void);
  38. extern void fpu__init_system(struct cpuinfo_x86 *c);
  39. extern void fpu__init_check_bugs(void);
  40. extern void fpu__resume_cpu(void);
  41. extern u64 fpu__get_supported_xfeatures_mask(void);
  42. /*
  43. * Debugging facility:
  44. */
  45. #ifdef CONFIG_X86_DEBUG_FPU
  46. # define WARN_ON_FPU(x) WARN_ON_ONCE(x)
  47. #else
  48. # define WARN_ON_FPU(x) ({ (void)(x); 0; })
  49. #endif
  50. /*
  51. * FPU related CPU feature flag helper routines:
  52. */
  53. static __always_inline __pure bool use_eager_fpu(void)
  54. {
  55. return static_cpu_has(X86_FEATURE_EAGER_FPU);
  56. }
  57. static __always_inline __pure bool use_xsaveopt(void)
  58. {
  59. return static_cpu_has(X86_FEATURE_XSAVEOPT);
  60. }
  61. static __always_inline __pure bool use_xsave(void)
  62. {
  63. return static_cpu_has(X86_FEATURE_XSAVE);
  64. }
  65. static __always_inline __pure bool use_fxsr(void)
  66. {
  67. return static_cpu_has(X86_FEATURE_FXSR);
  68. }
  69. /*
  70. * fpstate handling functions:
  71. */
  72. extern union fpregs_state init_fpstate;
  73. extern void fpstate_init(union fpregs_state *state);
  74. #ifdef CONFIG_MATH_EMULATION
  75. extern void fpstate_init_soft(struct swregs_state *soft);
  76. #else
  77. static inline void fpstate_init_soft(struct swregs_state *soft) {}
  78. #endif
  79. static inline void fpstate_init_fxstate(struct fxregs_state *fx)
  80. {
  81. fx->cwd = 0x37f;
  82. fx->mxcsr = MXCSR_DEFAULT;
  83. }
  84. extern void fpstate_sanitize_xstate(struct fpu *fpu);
  85. #define user_insn(insn, output, input...) \
  86. ({ \
  87. int err; \
  88. asm volatile(ASM_STAC "\n" \
  89. "1:" #insn "\n\t" \
  90. "2: " ASM_CLAC "\n" \
  91. ".section .fixup,\"ax\"\n" \
  92. "3: movl $-1,%[err]\n" \
  93. " jmp 2b\n" \
  94. ".previous\n" \
  95. _ASM_EXTABLE(1b, 3b) \
  96. : [err] "=r" (err), output \
  97. : "0"(0), input); \
  98. err; \
  99. })
  100. #define check_insn(insn, output, input...) \
  101. ({ \
  102. int err; \
  103. asm volatile("1:" #insn "\n\t" \
  104. "2:\n" \
  105. ".section .fixup,\"ax\"\n" \
  106. "3: movl $-1,%[err]\n" \
  107. " jmp 2b\n" \
  108. ".previous\n" \
  109. _ASM_EXTABLE(1b, 3b) \
  110. : [err] "=r" (err), output \
  111. : "0"(0), input); \
  112. err; \
  113. })
  114. static inline int copy_fregs_to_user(struct fregs_state __user *fx)
  115. {
  116. return user_insn(fnsave %[fx]; fwait, [fx] "=m" (*fx), "m" (*fx));
  117. }
  118. static inline int copy_fxregs_to_user(struct fxregs_state __user *fx)
  119. {
  120. if (config_enabled(CONFIG_X86_32))
  121. return user_insn(fxsave %[fx], [fx] "=m" (*fx), "m" (*fx));
  122. else if (config_enabled(CONFIG_AS_FXSAVEQ))
  123. return user_insn(fxsaveq %[fx], [fx] "=m" (*fx), "m" (*fx));
  124. /* See comment in copy_fxregs_to_kernel() below. */
  125. return user_insn(rex64/fxsave (%[fx]), "=m" (*fx), [fx] "R" (fx));
  126. }
  127. static inline void copy_kernel_to_fxregs(struct fxregs_state *fx)
  128. {
  129. int err;
  130. if (config_enabled(CONFIG_X86_32)) {
  131. err = check_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
  132. } else {
  133. if (config_enabled(CONFIG_AS_FXSAVEQ)) {
  134. err = check_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
  135. } else {
  136. /* See comment in copy_fxregs_to_kernel() below. */
  137. err = check_insn(rex64/fxrstor (%[fx]), "=m" (*fx), [fx] "R" (fx), "m" (*fx));
  138. }
  139. }
  140. /* Copying from a kernel buffer to FPU registers should never fail: */
  141. WARN_ON_FPU(err);
  142. }
  143. static inline int copy_user_to_fxregs(struct fxregs_state __user *fx)
  144. {
  145. if (config_enabled(CONFIG_X86_32))
  146. return user_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
  147. else if (config_enabled(CONFIG_AS_FXSAVEQ))
  148. return user_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
  149. /* See comment in copy_fxregs_to_kernel() below. */
  150. return user_insn(rex64/fxrstor (%[fx]), "=m" (*fx), [fx] "R" (fx),
  151. "m" (*fx));
  152. }
  153. static inline void copy_kernel_to_fregs(struct fregs_state *fx)
  154. {
  155. int err = check_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
  156. WARN_ON_FPU(err);
  157. }
  158. static inline int copy_user_to_fregs(struct fregs_state __user *fx)
  159. {
  160. return user_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
  161. }
  162. static inline void copy_fxregs_to_kernel(struct fpu *fpu)
  163. {
  164. if (config_enabled(CONFIG_X86_32))
  165. asm volatile( "fxsave %[fx]" : [fx] "=m" (fpu->state.fxsave));
  166. else if (config_enabled(CONFIG_AS_FXSAVEQ))
  167. asm volatile("fxsaveq %[fx]" : [fx] "=m" (fpu->state.fxsave));
  168. else {
  169. /* Using "rex64; fxsave %0" is broken because, if the memory
  170. * operand uses any extended registers for addressing, a second
  171. * REX prefix will be generated (to the assembler, rex64
  172. * followed by semicolon is a separate instruction), and hence
  173. * the 64-bitness is lost.
  174. *
  175. * Using "fxsaveq %0" would be the ideal choice, but is only
  176. * supported starting with gas 2.16.
  177. *
  178. * Using, as a workaround, the properly prefixed form below
  179. * isn't accepted by any binutils version so far released,
  180. * complaining that the same type of prefix is used twice if
  181. * an extended register is needed for addressing (fix submitted
  182. * to mainline 2005-11-21).
  183. *
  184. * asm volatile("rex64/fxsave %0" : "=m" (fpu->state.fxsave));
  185. *
  186. * This, however, we can work around by forcing the compiler to
  187. * select an addressing mode that doesn't require extended
  188. * registers.
  189. */
  190. asm volatile( "rex64/fxsave (%[fx])"
  191. : "=m" (fpu->state.fxsave)
  192. : [fx] "R" (&fpu->state.fxsave));
  193. }
  194. }
  195. /* These macros all use (%edi)/(%rdi) as the single memory argument. */
  196. #define XSAVE ".byte " REX_PREFIX "0x0f,0xae,0x27"
  197. #define XSAVEOPT ".byte " REX_PREFIX "0x0f,0xae,0x37"
  198. #define XSAVES ".byte " REX_PREFIX "0x0f,0xc7,0x2f"
  199. #define XRSTOR ".byte " REX_PREFIX "0x0f,0xae,0x2f"
  200. #define XRSTORS ".byte " REX_PREFIX "0x0f,0xc7,0x1f"
  201. #define XSTATE_OP(op, st, lmask, hmask, err) \
  202. asm volatile("1:" op "\n\t" \
  203. "xor %[err], %[err]\n" \
  204. "2:\n\t" \
  205. ".pushsection .fixup,\"ax\"\n\t" \
  206. "3: movl $-2,%[err]\n\t" \
  207. "jmp 2b\n\t" \
  208. ".popsection\n\t" \
  209. _ASM_EXTABLE(1b, 3b) \
  210. : [err] "=r" (err) \
  211. : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \
  212. : "memory")
  213. /*
  214. * If XSAVES is enabled, it replaces XSAVEOPT because it supports a compact
  215. * format and supervisor states in addition to modified optimization in
  216. * XSAVEOPT.
  217. *
  218. * Otherwise, if XSAVEOPT is enabled, XSAVEOPT replaces XSAVE because XSAVEOPT
  219. * supports modified optimization which is not supported by XSAVE.
  220. *
  221. * We use XSAVE as a fallback.
  222. *
  223. * The 661 label is defined in the ALTERNATIVE* macros as the address of the
  224. * original instruction which gets replaced. We need to use it here as the
  225. * address of the instruction where we might get an exception at.
  226. */
  227. #define XSTATE_XSAVE(st, lmask, hmask, err) \
  228. asm volatile(ALTERNATIVE_2(XSAVE, \
  229. XSAVEOPT, X86_FEATURE_XSAVEOPT, \
  230. XSAVES, X86_FEATURE_XSAVES) \
  231. "\n" \
  232. "xor %[err], %[err]\n" \
  233. "3:\n" \
  234. ".pushsection .fixup,\"ax\"\n" \
  235. "4: movl $-2, %[err]\n" \
  236. "jmp 3b\n" \
  237. ".popsection\n" \
  238. _ASM_EXTABLE(661b, 4b) \
  239. : [err] "=r" (err) \
  240. : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \
  241. : "memory")
  242. /*
  243. * Use XRSTORS to restore context if it is enabled. XRSTORS supports compact
  244. * XSAVE area format.
  245. */
  246. #define XSTATE_XRESTORE(st, lmask, hmask, err) \
  247. asm volatile(ALTERNATIVE(XRSTOR, \
  248. XRSTORS, X86_FEATURE_XSAVES) \
  249. "\n" \
  250. "xor %[err], %[err]\n" \
  251. "3:\n" \
  252. ".pushsection .fixup,\"ax\"\n" \
  253. "4: movl $-2, %[err]\n" \
  254. "jmp 3b\n" \
  255. ".popsection\n" \
  256. _ASM_EXTABLE(661b, 4b) \
  257. : [err] "=r" (err) \
  258. : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \
  259. : "memory")
  260. /*
  261. * This function is called only during boot time when x86 caps are not set
  262. * up and alternative can not be used yet.
  263. */
  264. static inline void copy_xregs_to_kernel_booting(struct xregs_state *xstate)
  265. {
  266. u64 mask = -1;
  267. u32 lmask = mask;
  268. u32 hmask = mask >> 32;
  269. int err;
  270. WARN_ON(system_state != SYSTEM_BOOTING);
  271. if (static_cpu_has(X86_FEATURE_XSAVES))
  272. XSTATE_OP(XSAVES, xstate, lmask, hmask, err);
  273. else
  274. XSTATE_OP(XSAVE, xstate, lmask, hmask, err);
  275. /* We should never fault when copying to a kernel buffer: */
  276. WARN_ON_FPU(err);
  277. }
  278. /*
  279. * This function is called only during boot time when x86 caps are not set
  280. * up and alternative can not be used yet.
  281. */
  282. static inline void copy_kernel_to_xregs_booting(struct xregs_state *xstate)
  283. {
  284. u64 mask = -1;
  285. u32 lmask = mask;
  286. u32 hmask = mask >> 32;
  287. int err;
  288. WARN_ON(system_state != SYSTEM_BOOTING);
  289. if (static_cpu_has(X86_FEATURE_XSAVES))
  290. XSTATE_OP(XRSTORS, xstate, lmask, hmask, err);
  291. else
  292. XSTATE_OP(XRSTOR, xstate, lmask, hmask, err);
  293. /* We should never fault when copying from a kernel buffer: */
  294. WARN_ON_FPU(err);
  295. }
  296. /*
  297. * Save processor xstate to xsave area.
  298. */
  299. static inline void copy_xregs_to_kernel(struct xregs_state *xstate)
  300. {
  301. u64 mask = -1;
  302. u32 lmask = mask;
  303. u32 hmask = mask >> 32;
  304. int err;
  305. WARN_ON(!alternatives_patched);
  306. XSTATE_XSAVE(xstate, lmask, hmask, err);
  307. /* We should never fault when copying to a kernel buffer: */
  308. WARN_ON_FPU(err);
  309. }
  310. /*
  311. * Restore processor xstate from xsave area.
  312. */
  313. static inline void copy_kernel_to_xregs(struct xregs_state *xstate, u64 mask)
  314. {
  315. u32 lmask = mask;
  316. u32 hmask = mask >> 32;
  317. int err;
  318. XSTATE_XRESTORE(xstate, lmask, hmask, err);
  319. /* We should never fault when copying from a kernel buffer: */
  320. WARN_ON_FPU(err);
  321. }
  322. /*
  323. * Save xstate to user space xsave area.
  324. *
  325. * We don't use modified optimization because xrstor/xrstors might track
  326. * a different application.
  327. *
  328. * We don't use compacted format xsave area for
  329. * backward compatibility for old applications which don't understand
  330. * compacted format of xsave area.
  331. */
  332. static inline int copy_xregs_to_user(struct xregs_state __user *buf)
  333. {
  334. int err;
  335. /*
  336. * Clear the xsave header first, so that reserved fields are
  337. * initialized to zero.
  338. */
  339. err = __clear_user(&buf->header, sizeof(buf->header));
  340. if (unlikely(err))
  341. return -EFAULT;
  342. stac();
  343. XSTATE_OP(XSAVE, buf, -1, -1, err);
  344. clac();
  345. return err;
  346. }
  347. /*
  348. * Restore xstate from user space xsave area.
  349. */
  350. static inline int copy_user_to_xregs(struct xregs_state __user *buf, u64 mask)
  351. {
  352. struct xregs_state *xstate = ((__force struct xregs_state *)buf);
  353. u32 lmask = mask;
  354. u32 hmask = mask >> 32;
  355. int err;
  356. stac();
  357. XSTATE_OP(XRSTOR, xstate, lmask, hmask, err);
  358. clac();
  359. return err;
  360. }
  361. /*
  362. * These must be called with preempt disabled. Returns
  363. * 'true' if the FPU state is still intact and we can
  364. * keep registers active.
  365. *
  366. * The legacy FNSAVE instruction cleared all FPU state
  367. * unconditionally, so registers are essentially destroyed.
  368. * Modern FPU state can be kept in registers, if there are
  369. * no pending FP exceptions.
  370. */
  371. static inline int copy_fpregs_to_fpstate(struct fpu *fpu)
  372. {
  373. if (likely(use_xsave())) {
  374. copy_xregs_to_kernel(&fpu->state.xsave);
  375. return 1;
  376. }
  377. if (likely(use_fxsr())) {
  378. copy_fxregs_to_kernel(fpu);
  379. return 1;
  380. }
  381. /*
  382. * Legacy FPU register saving, FNSAVE always clears FPU registers,
  383. * so we have to mark them inactive:
  384. */
  385. asm volatile("fnsave %[fp]; fwait" : [fp] "=m" (fpu->state.fsave));
  386. return 0;
  387. }
  388. static inline void __copy_kernel_to_fpregs(union fpregs_state *fpstate)
  389. {
  390. if (use_xsave()) {
  391. copy_kernel_to_xregs(&fpstate->xsave, -1);
  392. } else {
  393. if (use_fxsr())
  394. copy_kernel_to_fxregs(&fpstate->fxsave);
  395. else
  396. copy_kernel_to_fregs(&fpstate->fsave);
  397. }
  398. }
  399. static inline void copy_kernel_to_fpregs(union fpregs_state *fpstate)
  400. {
  401. /*
  402. * AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception is
  403. * pending. Clear the x87 state here by setting it to fixed values.
  404. * "m" is a random variable that should be in L1.
  405. */
  406. if (unlikely(static_cpu_has_bug(X86_BUG_FXSAVE_LEAK))) {
  407. asm volatile(
  408. "fnclex\n\t"
  409. "emms\n\t"
  410. "fildl %P[addr]" /* set F?P to defined value */
  411. : : [addr] "m" (fpstate));
  412. }
  413. __copy_kernel_to_fpregs(fpstate);
  414. }
  415. extern int copy_fpstate_to_sigframe(void __user *buf, void __user *fp, int size);
  416. /*
  417. * FPU context switch related helper methods:
  418. */
  419. DECLARE_PER_CPU(struct fpu *, fpu_fpregs_owner_ctx);
  420. /*
  421. * Must be run with preemption disabled: this clears the fpu_fpregs_owner_ctx,
  422. * on this CPU.
  423. *
  424. * This will disable any lazy FPU state restore of the current FPU state,
  425. * but if the current thread owns the FPU, it will still be saved by.
  426. */
  427. static inline void __cpu_disable_lazy_restore(unsigned int cpu)
  428. {
  429. per_cpu(fpu_fpregs_owner_ctx, cpu) = NULL;
  430. }
  431. static inline int fpu_want_lazy_restore(struct fpu *fpu, unsigned int cpu)
  432. {
  433. return fpu == this_cpu_read_stable(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu;
  434. }
  435. /*
  436. * Wrap lazy FPU TS handling in a 'hw fpregs activation/deactivation'
  437. * idiom, which is then paired with the sw-flag (fpregs_active) later on:
  438. */
  439. static inline void __fpregs_activate_hw(void)
  440. {
  441. if (!use_eager_fpu())
  442. clts();
  443. }
  444. static inline void __fpregs_deactivate_hw(void)
  445. {
  446. if (!use_eager_fpu())
  447. stts();
  448. }
  449. /* Must be paired with an 'stts' (fpregs_deactivate_hw()) after! */
  450. static inline void __fpregs_deactivate(struct fpu *fpu)
  451. {
  452. WARN_ON_FPU(!fpu->fpregs_active);
  453. fpu->fpregs_active = 0;
  454. this_cpu_write(fpu_fpregs_owner_ctx, NULL);
  455. }
  456. /* Must be paired with a 'clts' (fpregs_activate_hw()) before! */
  457. static inline void __fpregs_activate(struct fpu *fpu)
  458. {
  459. WARN_ON_FPU(fpu->fpregs_active);
  460. fpu->fpregs_active = 1;
  461. this_cpu_write(fpu_fpregs_owner_ctx, fpu);
  462. }
  463. /*
  464. * The question "does this thread have fpu access?"
  465. * is slightly racy, since preemption could come in
  466. * and revoke it immediately after the test.
  467. *
  468. * However, even in that very unlikely scenario,
  469. * we can just assume we have FPU access - typically
  470. * to save the FP state - we'll just take a #NM
  471. * fault and get the FPU access back.
  472. */
  473. static inline int fpregs_active(void)
  474. {
  475. return current->thread.fpu.fpregs_active;
  476. }
  477. /*
  478. * Encapsulate the CR0.TS handling together with the
  479. * software flag.
  480. *
  481. * These generally need preemption protection to work,
  482. * do try to avoid using these on their own.
  483. */
  484. static inline void fpregs_activate(struct fpu *fpu)
  485. {
  486. __fpregs_activate_hw();
  487. __fpregs_activate(fpu);
  488. }
  489. static inline void fpregs_deactivate(struct fpu *fpu)
  490. {
  491. __fpregs_deactivate(fpu);
  492. __fpregs_deactivate_hw();
  493. }
  494. /*
  495. * FPU state switching for scheduling.
  496. *
  497. * This is a two-stage process:
  498. *
  499. * - switch_fpu_prepare() saves the old state and
  500. * sets the new state of the CR0.TS bit. This is
  501. * done within the context of the old process.
  502. *
  503. * - switch_fpu_finish() restores the new state as
  504. * necessary.
  505. */
  506. typedef struct { int preload; } fpu_switch_t;
  507. static inline fpu_switch_t
  508. switch_fpu_prepare(struct fpu *old_fpu, struct fpu *new_fpu, int cpu)
  509. {
  510. fpu_switch_t fpu;
  511. /*
  512. * If the task has used the math, pre-load the FPU on xsave processors
  513. * or if the past 5 consecutive context-switches used math.
  514. */
  515. fpu.preload = new_fpu->fpstate_active &&
  516. (use_eager_fpu() || new_fpu->counter > 5);
  517. if (old_fpu->fpregs_active) {
  518. if (!copy_fpregs_to_fpstate(old_fpu))
  519. old_fpu->last_cpu = -1;
  520. else
  521. old_fpu->last_cpu = cpu;
  522. /* But leave fpu_fpregs_owner_ctx! */
  523. old_fpu->fpregs_active = 0;
  524. /* Don't change CR0.TS if we just switch! */
  525. if (fpu.preload) {
  526. new_fpu->counter++;
  527. __fpregs_activate(new_fpu);
  528. prefetch(&new_fpu->state);
  529. } else {
  530. __fpregs_deactivate_hw();
  531. }
  532. } else {
  533. old_fpu->counter = 0;
  534. old_fpu->last_cpu = -1;
  535. if (fpu.preload) {
  536. new_fpu->counter++;
  537. if (fpu_want_lazy_restore(new_fpu, cpu))
  538. fpu.preload = 0;
  539. else
  540. prefetch(&new_fpu->state);
  541. fpregs_activate(new_fpu);
  542. }
  543. }
  544. return fpu;
  545. }
  546. /*
  547. * Misc helper functions:
  548. */
  549. /*
  550. * By the time this gets called, we've already cleared CR0.TS and
  551. * given the process the FPU if we are going to preload the FPU
  552. * state - all we need to do is to conditionally restore the register
  553. * state itself.
  554. */
  555. static inline void switch_fpu_finish(struct fpu *new_fpu, fpu_switch_t fpu_switch)
  556. {
  557. if (fpu_switch.preload)
  558. copy_kernel_to_fpregs(&new_fpu->state);
  559. }
  560. /*
  561. * Needs to be preemption-safe.
  562. *
  563. * NOTE! user_fpu_begin() must be used only immediately before restoring
  564. * the save state. It does not do any saving/restoring on its own. In
  565. * lazy FPU mode, it is just an optimization to avoid a #NM exception,
  566. * the task can lose the FPU right after preempt_enable().
  567. */
  568. static inline void user_fpu_begin(void)
  569. {
  570. struct fpu *fpu = &current->thread.fpu;
  571. preempt_disable();
  572. if (!fpregs_active())
  573. fpregs_activate(fpu);
  574. preempt_enable();
  575. }
  576. /*
  577. * MXCSR and XCR definitions:
  578. */
  579. extern unsigned int mxcsr_feature_mask;
  580. #define XCR_XFEATURE_ENABLED_MASK 0x00000000
  581. static inline u64 xgetbv(u32 index)
  582. {
  583. u32 eax, edx;
  584. asm volatile(".byte 0x0f,0x01,0xd0" /* xgetbv */
  585. : "=a" (eax), "=d" (edx)
  586. : "c" (index));
  587. return eax + ((u64)edx << 32);
  588. }
  589. static inline void xsetbv(u32 index, u64 value)
  590. {
  591. u32 eax = value;
  592. u32 edx = value >> 32;
  593. asm volatile(".byte 0x0f,0x01,0xd1" /* xsetbv */
  594. : : "a" (eax), "d" (edx), "c" (index));
  595. }
  596. #endif /* _ASM_X86_FPU_INTERNAL_H */