1669ebabbSIngo Molnar #ifndef __ASM_X86_XSAVE_H 2669ebabbSIngo Molnar #define __ASM_X86_XSAVE_H 3669ebabbSIngo Molnar 4669ebabbSIngo Molnar #include <linux/types.h> 5669ebabbSIngo Molnar #include <asm/processor.h> 6*59a36d16SIngo Molnar #include <linux/uaccess.h> 7669ebabbSIngo Molnar 8669ebabbSIngo Molnar /* Bit 63 of XCR0 is reserved for future expansion */ 9669ebabbSIngo Molnar #define XSTATE_EXTEND_MASK (~(XSTATE_FPSSE | (1ULL << 63))) 10669ebabbSIngo Molnar 11677b98bdSIngo Molnar #define XSTATE_CPUID 0x0000000d 12677b98bdSIngo Molnar 13669ebabbSIngo Molnar #define FXSAVE_SIZE 512 14669ebabbSIngo Molnar 15669ebabbSIngo Molnar #define XSAVE_HDR_SIZE 64 16669ebabbSIngo Molnar #define XSAVE_HDR_OFFSET FXSAVE_SIZE 17669ebabbSIngo Molnar 18669ebabbSIngo Molnar #define XSAVE_YMM_SIZE 256 19669ebabbSIngo Molnar #define XSAVE_YMM_OFFSET (XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET) 20669ebabbSIngo Molnar 21669ebabbSIngo Molnar /* Supported features which support lazy state saving */ 22669ebabbSIngo Molnar #define XSTATE_LAZY (XSTATE_FP | XSTATE_SSE | XSTATE_YMM \ 23669ebabbSIngo Molnar | XSTATE_OPMASK | XSTATE_ZMM_Hi256 | XSTATE_Hi16_ZMM) 24669ebabbSIngo Molnar 25669ebabbSIngo Molnar /* Supported features which require eager state saving */ 26669ebabbSIngo Molnar #define XSTATE_EAGER (XSTATE_BNDREGS | XSTATE_BNDCSR) 27669ebabbSIngo Molnar 28669ebabbSIngo Molnar /* All currently supported features */ 29669ebabbSIngo Molnar #define XCNTXT_MASK (XSTATE_LAZY | XSTATE_EAGER) 30669ebabbSIngo Molnar 31669ebabbSIngo Molnar #ifdef CONFIG_X86_64 32669ebabbSIngo Molnar #define REX_PREFIX "0x48, " 33669ebabbSIngo Molnar #else 34669ebabbSIngo Molnar #define REX_PREFIX 35669ebabbSIngo Molnar #endif 36669ebabbSIngo Molnar 37669ebabbSIngo Molnar extern unsigned int xstate_size; 38669ebabbSIngo Molnar extern u64 xfeatures_mask; 39669ebabbSIngo Molnar extern u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS]; 40669ebabbSIngo Molnar extern struct xsave_struct init_xstate_ctx; 41669ebabbSIngo Molnar 42669ebabbSIngo Molnar extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask); 43669ebabbSIngo Molnar 44669ebabbSIngo Molnar /* These macros all use (%edi)/(%rdi) as the single memory argument. */ 45669ebabbSIngo Molnar #define XSAVE ".byte " REX_PREFIX "0x0f,0xae,0x27" 46669ebabbSIngo Molnar #define XSAVEOPT ".byte " REX_PREFIX "0x0f,0xae,0x37" 47669ebabbSIngo Molnar #define XSAVES ".byte " REX_PREFIX "0x0f,0xc7,0x2f" 48669ebabbSIngo Molnar #define XRSTOR ".byte " REX_PREFIX "0x0f,0xae,0x2f" 49669ebabbSIngo Molnar #define XRSTORS ".byte " REX_PREFIX "0x0f,0xc7,0x1f" 50669ebabbSIngo Molnar 51669ebabbSIngo Molnar #define xstate_fault ".section .fixup,\"ax\"\n" \ 52669ebabbSIngo Molnar "3: movl $-1,%[err]\n" \ 53669ebabbSIngo Molnar " jmp 2b\n" \ 54669ebabbSIngo Molnar ".previous\n" \ 55669ebabbSIngo Molnar _ASM_EXTABLE(1b, 3b) \ 56669ebabbSIngo Molnar : [err] "=r" (err) 57669ebabbSIngo Molnar 58669ebabbSIngo Molnar /* 59669ebabbSIngo Molnar * This function is called only during boot time when x86 caps are not set 60669ebabbSIngo Molnar * up and alternative can not be used yet. 61669ebabbSIngo Molnar */ 62669ebabbSIngo Molnar static inline int xsave_state_booting(struct xsave_struct *fx) 63669ebabbSIngo Molnar { 64669ebabbSIngo Molnar u64 mask = -1; 65669ebabbSIngo Molnar u32 lmask = mask; 66669ebabbSIngo Molnar u32 hmask = mask >> 32; 67669ebabbSIngo Molnar int err = 0; 68669ebabbSIngo Molnar 69669ebabbSIngo Molnar WARN_ON(system_state != SYSTEM_BOOTING); 70669ebabbSIngo Molnar 71669ebabbSIngo Molnar if (boot_cpu_has(X86_FEATURE_XSAVES)) 72669ebabbSIngo Molnar asm volatile("1:"XSAVES"\n\t" 73669ebabbSIngo Molnar "2:\n\t" 74669ebabbSIngo Molnar xstate_fault 75669ebabbSIngo Molnar : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask) 76669ebabbSIngo Molnar : "memory"); 77669ebabbSIngo Molnar else 78669ebabbSIngo Molnar asm volatile("1:"XSAVE"\n\t" 79669ebabbSIngo Molnar "2:\n\t" 80669ebabbSIngo Molnar xstate_fault 81669ebabbSIngo Molnar : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask) 82669ebabbSIngo Molnar : "memory"); 83669ebabbSIngo Molnar return err; 84669ebabbSIngo Molnar } 85669ebabbSIngo Molnar 86669ebabbSIngo Molnar /* 87669ebabbSIngo Molnar * This function is called only during boot time when x86 caps are not set 88669ebabbSIngo Molnar * up and alternative can not be used yet. 89669ebabbSIngo Molnar */ 90669ebabbSIngo Molnar static inline int xrstor_state_booting(struct xsave_struct *fx, u64 mask) 91669ebabbSIngo Molnar { 92669ebabbSIngo Molnar u32 lmask = mask; 93669ebabbSIngo Molnar u32 hmask = mask >> 32; 94669ebabbSIngo Molnar int err = 0; 95669ebabbSIngo Molnar 96669ebabbSIngo Molnar WARN_ON(system_state != SYSTEM_BOOTING); 97669ebabbSIngo Molnar 98669ebabbSIngo Molnar if (boot_cpu_has(X86_FEATURE_XSAVES)) 99669ebabbSIngo Molnar asm volatile("1:"XRSTORS"\n\t" 100669ebabbSIngo Molnar "2:\n\t" 101669ebabbSIngo Molnar xstate_fault 102669ebabbSIngo Molnar : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask) 103669ebabbSIngo Molnar : "memory"); 104669ebabbSIngo Molnar else 105669ebabbSIngo Molnar asm volatile("1:"XRSTOR"\n\t" 106669ebabbSIngo Molnar "2:\n\t" 107669ebabbSIngo Molnar xstate_fault 108669ebabbSIngo Molnar : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask) 109669ebabbSIngo Molnar : "memory"); 110669ebabbSIngo Molnar return err; 111669ebabbSIngo Molnar } 112669ebabbSIngo Molnar 113669ebabbSIngo Molnar /* 114669ebabbSIngo Molnar * Save processor xstate to xsave area. 115669ebabbSIngo Molnar */ 116669ebabbSIngo Molnar static inline int xsave_state(struct xsave_struct *fx) 117669ebabbSIngo Molnar { 118669ebabbSIngo Molnar u64 mask = -1; 119669ebabbSIngo Molnar u32 lmask = mask; 120669ebabbSIngo Molnar u32 hmask = mask >> 32; 121669ebabbSIngo Molnar int err = 0; 122669ebabbSIngo Molnar 1235e907bb0SIngo Molnar WARN_ON(!alternatives_patched); 124669ebabbSIngo Molnar 125669ebabbSIngo Molnar /* 126669ebabbSIngo Molnar * If xsaves is enabled, xsaves replaces xsaveopt because 127669ebabbSIngo Molnar * it supports compact format and supervisor states in addition to 128669ebabbSIngo Molnar * modified optimization in xsaveopt. 129669ebabbSIngo Molnar * 130669ebabbSIngo Molnar * Otherwise, if xsaveopt is enabled, xsaveopt replaces xsave 131669ebabbSIngo Molnar * because xsaveopt supports modified optimization which is not 132669ebabbSIngo Molnar * supported by xsave. 133669ebabbSIngo Molnar * 134669ebabbSIngo Molnar * If none of xsaves and xsaveopt is enabled, use xsave. 135669ebabbSIngo Molnar */ 136669ebabbSIngo Molnar alternative_input_2( 137669ebabbSIngo Molnar "1:"XSAVE, 138669ebabbSIngo Molnar XSAVEOPT, 139669ebabbSIngo Molnar X86_FEATURE_XSAVEOPT, 140669ebabbSIngo Molnar XSAVES, 141669ebabbSIngo Molnar X86_FEATURE_XSAVES, 142669ebabbSIngo Molnar [fx] "D" (fx), "a" (lmask), "d" (hmask) : 143669ebabbSIngo Molnar "memory"); 144669ebabbSIngo Molnar asm volatile("2:\n\t" 145669ebabbSIngo Molnar xstate_fault 146669ebabbSIngo Molnar : "0" (0) 147669ebabbSIngo Molnar : "memory"); 148669ebabbSIngo Molnar 149669ebabbSIngo Molnar return err; 150669ebabbSIngo Molnar } 151669ebabbSIngo Molnar 152669ebabbSIngo Molnar /* 153669ebabbSIngo Molnar * Restore processor xstate from xsave area. 154669ebabbSIngo Molnar */ 155669ebabbSIngo Molnar static inline int xrstor_state(struct xsave_struct *fx, u64 mask) 156669ebabbSIngo Molnar { 157669ebabbSIngo Molnar int err = 0; 158669ebabbSIngo Molnar u32 lmask = mask; 159669ebabbSIngo Molnar u32 hmask = mask >> 32; 160669ebabbSIngo Molnar 161669ebabbSIngo Molnar /* 162669ebabbSIngo Molnar * Use xrstors to restore context if it is enabled. xrstors supports 163669ebabbSIngo Molnar * compacted format of xsave area which is not supported by xrstor. 164669ebabbSIngo Molnar */ 165669ebabbSIngo Molnar alternative_input( 166669ebabbSIngo Molnar "1: " XRSTOR, 167669ebabbSIngo Molnar XRSTORS, 168669ebabbSIngo Molnar X86_FEATURE_XSAVES, 169669ebabbSIngo Molnar "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask) 170669ebabbSIngo Molnar : "memory"); 171669ebabbSIngo Molnar 172669ebabbSIngo Molnar asm volatile("2:\n" 173669ebabbSIngo Molnar xstate_fault 174669ebabbSIngo Molnar : "0" (0) 175669ebabbSIngo Molnar : "memory"); 176669ebabbSIngo Molnar 177669ebabbSIngo Molnar return err; 178669ebabbSIngo Molnar } 179669ebabbSIngo Molnar 180669ebabbSIngo Molnar /* 181669ebabbSIngo Molnar * Restore xstate context for new process during context switch. 182669ebabbSIngo Molnar */ 183669ebabbSIngo Molnar static inline int fpu_xrstor_checking(struct xsave_struct *fx) 184669ebabbSIngo Molnar { 185669ebabbSIngo Molnar return xrstor_state(fx, -1); 186669ebabbSIngo Molnar } 187669ebabbSIngo Molnar 188669ebabbSIngo Molnar /* 189669ebabbSIngo Molnar * Save xstate to user space xsave area. 190669ebabbSIngo Molnar * 191669ebabbSIngo Molnar * We don't use modified optimization because xrstor/xrstors might track 192669ebabbSIngo Molnar * a different application. 193669ebabbSIngo Molnar * 194669ebabbSIngo Molnar * We don't use compacted format xsave area for 195669ebabbSIngo Molnar * backward compatibility for old applications which don't understand 196669ebabbSIngo Molnar * compacted format of xsave area. 197669ebabbSIngo Molnar */ 198669ebabbSIngo Molnar static inline int xsave_user(struct xsave_struct __user *buf) 199669ebabbSIngo Molnar { 200669ebabbSIngo Molnar int err; 201669ebabbSIngo Molnar 202669ebabbSIngo Molnar /* 203669ebabbSIngo Molnar * Clear the xsave header first, so that reserved fields are 204669ebabbSIngo Molnar * initialized to zero. 205669ebabbSIngo Molnar */ 206669ebabbSIngo Molnar err = __clear_user(&buf->header, sizeof(buf->header)); 207669ebabbSIngo Molnar if (unlikely(err)) 208669ebabbSIngo Molnar return -EFAULT; 209669ebabbSIngo Molnar 210669ebabbSIngo Molnar __asm__ __volatile__(ASM_STAC "\n" 211669ebabbSIngo Molnar "1:"XSAVE"\n" 212669ebabbSIngo Molnar "2: " ASM_CLAC "\n" 213669ebabbSIngo Molnar xstate_fault 214669ebabbSIngo Molnar : "D" (buf), "a" (-1), "d" (-1), "0" (0) 215669ebabbSIngo Molnar : "memory"); 216669ebabbSIngo Molnar return err; 217669ebabbSIngo Molnar } 218669ebabbSIngo Molnar 219669ebabbSIngo Molnar /* 220669ebabbSIngo Molnar * Restore xstate from user space xsave area. 221669ebabbSIngo Molnar */ 222669ebabbSIngo Molnar static inline int xrestore_user(struct xsave_struct __user *buf, u64 mask) 223669ebabbSIngo Molnar { 224669ebabbSIngo Molnar int err = 0; 225669ebabbSIngo Molnar struct xsave_struct *xstate = ((__force struct xsave_struct *)buf); 226669ebabbSIngo Molnar u32 lmask = mask; 227669ebabbSIngo Molnar u32 hmask = mask >> 32; 228669ebabbSIngo Molnar 229669ebabbSIngo Molnar __asm__ __volatile__(ASM_STAC "\n" 230669ebabbSIngo Molnar "1:"XRSTOR"\n" 231669ebabbSIngo Molnar "2: " ASM_CLAC "\n" 232669ebabbSIngo Molnar xstate_fault 233669ebabbSIngo Molnar : "D" (xstate), "a" (lmask), "d" (hmask), "0" (0) 234669ebabbSIngo Molnar : "memory"); /* memory required? */ 235669ebabbSIngo Molnar return err; 236669ebabbSIngo Molnar } 237669ebabbSIngo Molnar 238669ebabbSIngo Molnar void *get_xsave_addr(struct xsave_struct *xsave, int xstate); 239669ebabbSIngo Molnar void setup_xstate_comp(void); 240669ebabbSIngo Molnar 241669ebabbSIngo Molnar #endif 242