legacy.h (2882B)
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 7extern unsigned int mxcsr_feature_mask; 8 9static 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 50static 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 55static 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 64static 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 72static 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 80static 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 88static inline void frstor(struct fregs_state *fx) 89{ 90 kernel_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx)); 91} 92 93static inline int frstor_safe(struct fregs_state *fx) 94{ 95 return kernel_insn_err(frstor %[fx], "=m" (*fx), [fx] "m" (*fx)); 96} 97 98static 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 103static 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