0001
0002 #ifndef __X86_KERNEL_FPU_LEGACY_H
0003 #define __X86_KERNEL_FPU_LEGACY_H
0004
0005 #include <asm/fpu/types.h>
0006
0007 extern unsigned int mxcsr_feature_mask;
0008
0009 static inline void ldmxcsr(u32 mxcsr)
0010 {
0011 asm volatile("ldmxcsr %0" :: "m" (mxcsr));
0012 }
0013
0014
0015
0016
0017
0018 #define user_insn(insn, output, input...) \
0019 ({ \
0020 int err; \
0021 \
0022 might_fault(); \
0023 \
0024 asm volatile(ASM_STAC "\n" \
0025 "1: " #insn "\n" \
0026 "2: " ASM_CLAC "\n" \
0027 _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_FAULT_MCE_SAFE) \
0028 : [err] "=a" (err), output \
0029 : "0"(0), input); \
0030 err; \
0031 })
0032
0033 #define kernel_insn_err(insn, output, input...) \
0034 ({ \
0035 int err; \
0036 asm volatile("1:" #insn "\n\t" \
0037 "2:\n" \
0038 _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %[err]) \
0039 : [err] "=r" (err), output \
0040 : "0"(0), input); \
0041 err; \
0042 })
0043
0044 #define kernel_insn(insn, output, input...) \
0045 asm volatile("1:" #insn "\n\t" \
0046 "2:\n" \
0047 _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_FPU_RESTORE) \
0048 : output : input)
0049
0050 static inline int fnsave_to_user_sigframe(struct fregs_state __user *fx)
0051 {
0052 return user_insn(fnsave %[fx]; fwait, [fx] "=m" (*fx), "m" (*fx));
0053 }
0054
0055 static inline int fxsave_to_user_sigframe(struct fxregs_state __user *fx)
0056 {
0057 if (IS_ENABLED(CONFIG_X86_32))
0058 return user_insn(fxsave %[fx], [fx] "=m" (*fx), "m" (*fx));
0059 else
0060 return user_insn(fxsaveq %[fx], [fx] "=m" (*fx), "m" (*fx));
0061
0062 }
0063
0064 static inline void fxrstor(struct fxregs_state *fx)
0065 {
0066 if (IS_ENABLED(CONFIG_X86_32))
0067 kernel_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
0068 else
0069 kernel_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
0070 }
0071
0072 static inline int fxrstor_safe(struct fxregs_state *fx)
0073 {
0074 if (IS_ENABLED(CONFIG_X86_32))
0075 return kernel_insn_err(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
0076 else
0077 return kernel_insn_err(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
0078 }
0079
0080 static inline int fxrstor_from_user_sigframe(struct fxregs_state __user *fx)
0081 {
0082 if (IS_ENABLED(CONFIG_X86_32))
0083 return user_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
0084 else
0085 return user_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
0086 }
0087
0088 static inline void frstor(struct fregs_state *fx)
0089 {
0090 kernel_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
0091 }
0092
0093 static inline int frstor_safe(struct fregs_state *fx)
0094 {
0095 return kernel_insn_err(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
0096 }
0097
0098 static inline int frstor_from_user_sigframe(struct fregs_state __user *fx)
0099 {
0100 return user_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
0101 }
0102
0103 static inline void fxsave(struct fxregs_state *fx)
0104 {
0105 if (IS_ENABLED(CONFIG_X86_32))
0106 asm volatile( "fxsave %[fx]" : [fx] "=m" (*fx));
0107 else
0108 asm volatile("fxsaveq %[fx]" : [fx] "=m" (*fx));
0109 }
0110
0111 #endif