1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __X86_KERNEL_FPU_LEGACY_H
3 #define __X86_KERNEL_FPU_LEGACY_H
4
5 #include <asm/fpu/types.h>
6
7 extern unsigned int mxcsr_feature_mask;
8
ldmxcsr(u32 mxcsr)9 static inline void ldmxcsr(u32 mxcsr)
10 {
11 asm volatile("ldmxcsr %0" :: "m" (mxcsr));
12 }
13
14 /*
15 * Returns 0 on success or the trap number when the operation raises an
16 * exception.
17 */
18 #define user_insn(insn, output, input...) \
19 ({ \
20 int err; \
21 \
22 might_fault(); \
23 \
24 asm volatile(ASM_STAC "\n" \
25 "1: " #insn "\n" \
26 "2: " ASM_CLAC "\n" \
27 _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_FAULT_MCE_SAFE) \
28 : [err] "=a" (err), output \
29 : "0"(0), input); \
30 err; \
31 })
32
33 #define kernel_insn_err(insn, output, input...) \
34 ({ \
35 int err; \
36 asm volatile("1:" #insn "\n\t" \
37 "2:\n" \
38 _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %[err]) \
39 : [err] "=r" (err), output \
40 : "0"(0), input); \
41 err; \
42 })
43
44 #define kernel_insn(insn, output, input...) \
45 asm volatile("1:" #insn "\n\t" \
46 "2:\n" \
47 _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_FPU_RESTORE) \
48 : output : input)
49
fnsave_to_user_sigframe(struct fregs_state __user * fx)50 static inline int fnsave_to_user_sigframe(struct fregs_state __user *fx)
51 {
52 return user_insn(fnsave %[fx]; fwait, [fx] "=m" (*fx), "m" (*fx));
53 }
54
fxsave_to_user_sigframe(struct fxregs_state __user * fx)55 static inline int fxsave_to_user_sigframe(struct fxregs_state __user *fx)
56 {
57 if (IS_ENABLED(CONFIG_X86_32))
58 return user_insn(fxsave %[fx], [fx] "=m" (*fx), "m" (*fx));
59 else
60 return user_insn(fxsaveq %[fx], [fx] "=m" (*fx), "m" (*fx));
61
62 }
63
fxrstor(struct fxregs_state * fx)64 static inline void fxrstor(struct fxregs_state *fx)
65 {
66 if (IS_ENABLED(CONFIG_X86_32))
67 kernel_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
68 else
69 kernel_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
70 }
71
fxrstor_safe(struct fxregs_state * fx)72 static inline int fxrstor_safe(struct fxregs_state *fx)
73 {
74 if (IS_ENABLED(CONFIG_X86_32))
75 return kernel_insn_err(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
76 else
77 return kernel_insn_err(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
78 }
79
fxrstor_from_user_sigframe(struct fxregs_state __user * fx)80 static inline int fxrstor_from_user_sigframe(struct fxregs_state __user *fx)
81 {
82 if (IS_ENABLED(CONFIG_X86_32))
83 return user_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
84 else
85 return user_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
86 }
87
frstor(struct fregs_state * fx)88 static inline void frstor(struct fregs_state *fx)
89 {
90 kernel_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
91 }
92
frstor_safe(struct fregs_state * fx)93 static inline int frstor_safe(struct fregs_state *fx)
94 {
95 return kernel_insn_err(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
96 }
97
frstor_from_user_sigframe(struct fregs_state __user * fx)98 static inline int frstor_from_user_sigframe(struct fregs_state __user *fx)
99 {
100 return user_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
101 }
102
fxsave(struct fxregs_state * fx)103 static inline void fxsave(struct fxregs_state *fx)
104 {
105 if (IS_ENABLED(CONFIG_X86_32))
106 asm volatile( "fxsave %[fx]" : [fx] "=m" (*fx));
107 else
108 asm volatile("fxsaveq %[fx]" : [fx] "=m" (*fx));
109 }
110
111 #endif
112