internal.h 18 KB

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