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 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 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 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 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 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 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 92 static inline void frstor(struct fregs_state *fx) 93 { 94 kernel_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx)); 95 } 96 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 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 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