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 ".section .fixup,\"ax\"\n" \
39 "3: movl $-1,%[err]\n" \
40 " jmp 2b\n" \
41 ".previous\n" \
42 _ASM_EXTABLE(1b, 3b) \
43 : [err] "=r" (err), output \
44 : "0"(0), input); \
45 err; \
46 })
47
48 #define kernel_insn(insn, output, input...) \
49 asm volatile("1:" #insn "\n\t" \
50 "2:\n" \
51 _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_FPU_RESTORE) \
52 : output : input)
53
fnsave_to_user_sigframe(struct fregs_state __user * fx)54 static inline int fnsave_to_user_sigframe(struct fregs_state __user *fx)
55 {
56 return user_insn(fnsave %[fx]; fwait, [fx] "=m" (*fx), "m" (*fx));
57 }
58
fxsave_to_user_sigframe(struct fxregs_state __user * fx)59 static inline int fxsave_to_user_sigframe(struct fxregs_state __user *fx)
60 {
61 if (IS_ENABLED(CONFIG_X86_32))
62 return user_insn(fxsave %[fx], [fx] "=m" (*fx), "m" (*fx));
63 else
64 return user_insn(fxsaveq %[fx], [fx] "=m" (*fx), "m" (*fx));
65
66 }
67
fxrstor(struct fxregs_state * fx)68 static inline void fxrstor(struct fxregs_state *fx)
69 {
70 if (IS_ENABLED(CONFIG_X86_32))
71 kernel_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
72 else
73 kernel_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
74 }
75
fxrstor_safe(struct fxregs_state * fx)76 static inline int fxrstor_safe(struct fxregs_state *fx)
77 {
78 if (IS_ENABLED(CONFIG_X86_32))
79 return kernel_insn_err(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
80 else
81 return kernel_insn_err(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
82 }
83
fxrstor_from_user_sigframe(struct fxregs_state __user * fx)84 static inline int fxrstor_from_user_sigframe(struct fxregs_state __user *fx)
85 {
86 if (IS_ENABLED(CONFIG_X86_32))
87 return user_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
88 else
89 return user_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
90 }
91
frstor(struct fregs_state * fx)92 static inline void frstor(struct fregs_state *fx)
93 {
94 kernel_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
95 }
96
frstor_safe(struct fregs_state * fx)97 static inline int frstor_safe(struct fregs_state *fx)
98 {
99 return kernel_insn_err(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
100 }
101
frstor_from_user_sigframe(struct fregs_state __user * fx)102 static inline int frstor_from_user_sigframe(struct fregs_state __user *fx)
103 {
104 return user_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
105 }
106
fxsave(struct fxregs_state * fx)107 static inline void fxsave(struct fxregs_state *fx)
108 {
109 if (IS_ENABLED(CONFIG_X86_32))
110 asm volatile( "fxsave %[fx]" : [fx] "=m" (*fx));
111 else
112 asm volatile("fxsaveq %[fx]" : [fx] "=m" (*fx));
113 }
114
115 #endif
116