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> 6669ebabbSIngo Molnar 7*677b98bdSIngo Molnar /* 8*677b98bdSIngo Molnar * List of XSAVE features Linux knows about: 9*677b98bdSIngo Molnar */ 10*677b98bdSIngo Molnar enum xfeature_bit { 11*677b98bdSIngo Molnar XSTATE_BIT_FP, 12*677b98bdSIngo Molnar XSTATE_BIT_SSE, 13*677b98bdSIngo Molnar XSTATE_BIT_YMM, 14*677b98bdSIngo Molnar XSTATE_BIT_BNDREGS, 15*677b98bdSIngo Molnar XSTATE_BIT_BNDCSR, 16*677b98bdSIngo Molnar XSTATE_BIT_OPMASK, 17*677b98bdSIngo Molnar XSTATE_BIT_ZMM_Hi256, 18*677b98bdSIngo Molnar XSTATE_BIT_Hi16_ZMM, 19669ebabbSIngo Molnar 20*677b98bdSIngo Molnar XFEATURES_NR_MAX, 21*677b98bdSIngo Molnar }; 22669ebabbSIngo Molnar 23*677b98bdSIngo Molnar #define XSTATE_FP (1 << XSTATE_BIT_FP) 24*677b98bdSIngo Molnar #define XSTATE_SSE (1 << XSTATE_BIT_SSE) 25*677b98bdSIngo Molnar #define XSTATE_YMM (1 << XSTATE_BIT_YMM) 26*677b98bdSIngo Molnar #define XSTATE_BNDREGS (1 << XSTATE_BIT_BNDREGS) 27*677b98bdSIngo Molnar #define XSTATE_BNDCSR (1 << XSTATE_BIT_BNDCSR) 28*677b98bdSIngo Molnar #define XSTATE_OPMASK (1 << XSTATE_BIT_OPMASK) 29*677b98bdSIngo Molnar #define XSTATE_ZMM_Hi256 (1 << XSTATE_BIT_ZMM_Hi256) 30*677b98bdSIngo Molnar #define XSTATE_Hi16_ZMM (1 << XSTATE_BIT_Hi16_ZMM) 31*677b98bdSIngo Molnar 32669ebabbSIngo Molnar 33669ebabbSIngo Molnar #define XSTATE_FPSSE (XSTATE_FP | XSTATE_SSE) 34669ebabbSIngo Molnar #define XSTATE_AVX512 (XSTATE_OPMASK | XSTATE_ZMM_Hi256 | XSTATE_Hi16_ZMM) 35669ebabbSIngo Molnar /* Bit 63 of XCR0 is reserved for future expansion */ 36669ebabbSIngo Molnar #define XSTATE_EXTEND_MASK (~(XSTATE_FPSSE | (1ULL << 63))) 37669ebabbSIngo Molnar 38*677b98bdSIngo Molnar #define XSTATE_CPUID 0x0000000d 39*677b98bdSIngo Molnar 40669ebabbSIngo Molnar #define FXSAVE_SIZE 512 41669ebabbSIngo Molnar 42669ebabbSIngo Molnar #define XSAVE_HDR_SIZE 64 43669ebabbSIngo Molnar #define XSAVE_HDR_OFFSET FXSAVE_SIZE 44669ebabbSIngo Molnar 45669ebabbSIngo Molnar #define XSAVE_YMM_SIZE 256 46669ebabbSIngo Molnar #define XSAVE_YMM_OFFSET (XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET) 47669ebabbSIngo Molnar 48669ebabbSIngo Molnar /* Supported features which support lazy state saving */ 49669ebabbSIngo Molnar #define XSTATE_LAZY (XSTATE_FP | XSTATE_SSE | XSTATE_YMM \ 50669ebabbSIngo Molnar | XSTATE_OPMASK | XSTATE_ZMM_Hi256 | XSTATE_Hi16_ZMM) 51669ebabbSIngo Molnar 52669ebabbSIngo Molnar /* Supported features which require eager state saving */ 53669ebabbSIngo Molnar #define XSTATE_EAGER (XSTATE_BNDREGS | XSTATE_BNDCSR) 54669ebabbSIngo Molnar 55669ebabbSIngo Molnar /* All currently supported features */ 56669ebabbSIngo Molnar #define XCNTXT_MASK (XSTATE_LAZY | XSTATE_EAGER) 57669ebabbSIngo Molnar 58669ebabbSIngo Molnar #ifdef CONFIG_X86_64 59669ebabbSIngo Molnar #define REX_PREFIX "0x48, " 60669ebabbSIngo Molnar #else 61669ebabbSIngo Molnar #define REX_PREFIX 62669ebabbSIngo Molnar #endif 63669ebabbSIngo Molnar 64669ebabbSIngo Molnar extern unsigned int xstate_size; 65669ebabbSIngo Molnar extern u64 xfeatures_mask; 66669ebabbSIngo Molnar extern u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS]; 67669ebabbSIngo Molnar extern struct xsave_struct init_xstate_ctx; 68669ebabbSIngo Molnar 69669ebabbSIngo Molnar extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask); 70669ebabbSIngo Molnar 71669ebabbSIngo Molnar /* These macros all use (%edi)/(%rdi) as the single memory argument. */ 72669ebabbSIngo Molnar #define XSAVE ".byte " REX_PREFIX "0x0f,0xae,0x27" 73669ebabbSIngo Molnar #define XSAVEOPT ".byte " REX_PREFIX "0x0f,0xae,0x37" 74669ebabbSIngo Molnar #define XSAVES ".byte " REX_PREFIX "0x0f,0xc7,0x2f" 75669ebabbSIngo Molnar #define XRSTOR ".byte " REX_PREFIX "0x0f,0xae,0x2f" 76669ebabbSIngo Molnar #define XRSTORS ".byte " REX_PREFIX "0x0f,0xc7,0x1f" 77669ebabbSIngo Molnar 78669ebabbSIngo Molnar #define xstate_fault ".section .fixup,\"ax\"\n" \ 79669ebabbSIngo Molnar "3: movl $-1,%[err]\n" \ 80669ebabbSIngo Molnar " jmp 2b\n" \ 81669ebabbSIngo Molnar ".previous\n" \ 82669ebabbSIngo Molnar _ASM_EXTABLE(1b, 3b) \ 83669ebabbSIngo Molnar : [err] "=r" (err) 84669ebabbSIngo Molnar 85669ebabbSIngo Molnar /* 86669ebabbSIngo Molnar * This function is called only during boot time when x86 caps are not set 87669ebabbSIngo Molnar * up and alternative can not be used yet. 88669ebabbSIngo Molnar */ 89669ebabbSIngo Molnar static inline int xsave_state_booting(struct xsave_struct *fx) 90669ebabbSIngo Molnar { 91669ebabbSIngo Molnar u64 mask = -1; 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:"XSAVES"\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:"XSAVE"\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 * This function is called only during boot time when x86 caps are not set 115669ebabbSIngo Molnar * up and alternative can not be used yet. 116669ebabbSIngo Molnar */ 117669ebabbSIngo Molnar static inline int xrstor_state_booting(struct xsave_struct *fx, u64 mask) 118669ebabbSIngo Molnar { 119669ebabbSIngo Molnar u32 lmask = mask; 120669ebabbSIngo Molnar u32 hmask = mask >> 32; 121669ebabbSIngo Molnar int err = 0; 122669ebabbSIngo Molnar 123669ebabbSIngo Molnar WARN_ON(system_state != SYSTEM_BOOTING); 124669ebabbSIngo Molnar 125669ebabbSIngo Molnar if (boot_cpu_has(X86_FEATURE_XSAVES)) 126669ebabbSIngo Molnar asm volatile("1:"XRSTORS"\n\t" 127669ebabbSIngo Molnar "2:\n\t" 128669ebabbSIngo Molnar xstate_fault 129669ebabbSIngo Molnar : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask) 130669ebabbSIngo Molnar : "memory"); 131669ebabbSIngo Molnar else 132669ebabbSIngo Molnar asm volatile("1:"XRSTOR"\n\t" 133669ebabbSIngo Molnar "2:\n\t" 134669ebabbSIngo Molnar xstate_fault 135669ebabbSIngo Molnar : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask) 136669ebabbSIngo Molnar : "memory"); 137669ebabbSIngo Molnar return err; 138669ebabbSIngo Molnar } 139669ebabbSIngo Molnar 140669ebabbSIngo Molnar /* 141669ebabbSIngo Molnar * Save processor xstate to xsave area. 142669ebabbSIngo Molnar */ 143669ebabbSIngo Molnar static inline int xsave_state(struct xsave_struct *fx) 144669ebabbSIngo Molnar { 145669ebabbSIngo Molnar u64 mask = -1; 146669ebabbSIngo Molnar u32 lmask = mask; 147669ebabbSIngo Molnar u32 hmask = mask >> 32; 148669ebabbSIngo Molnar int err = 0; 149669ebabbSIngo Molnar 150669ebabbSIngo Molnar WARN_ON(system_state == SYSTEM_BOOTING); 151669ebabbSIngo Molnar 152669ebabbSIngo Molnar /* 153669ebabbSIngo Molnar * If xsaves is enabled, xsaves replaces xsaveopt because 154669ebabbSIngo Molnar * it supports compact format and supervisor states in addition to 155669ebabbSIngo Molnar * modified optimization in xsaveopt. 156669ebabbSIngo Molnar * 157669ebabbSIngo Molnar * Otherwise, if xsaveopt is enabled, xsaveopt replaces xsave 158669ebabbSIngo Molnar * because xsaveopt supports modified optimization which is not 159669ebabbSIngo Molnar * supported by xsave. 160669ebabbSIngo Molnar * 161669ebabbSIngo Molnar * If none of xsaves and xsaveopt is enabled, use xsave. 162669ebabbSIngo Molnar */ 163669ebabbSIngo Molnar alternative_input_2( 164669ebabbSIngo Molnar "1:"XSAVE, 165669ebabbSIngo Molnar XSAVEOPT, 166669ebabbSIngo Molnar X86_FEATURE_XSAVEOPT, 167669ebabbSIngo Molnar XSAVES, 168669ebabbSIngo Molnar X86_FEATURE_XSAVES, 169669ebabbSIngo Molnar [fx] "D" (fx), "a" (lmask), "d" (hmask) : 170669ebabbSIngo Molnar "memory"); 171669ebabbSIngo Molnar asm volatile("2:\n\t" 172669ebabbSIngo Molnar xstate_fault 173669ebabbSIngo Molnar : "0" (0) 174669ebabbSIngo Molnar : "memory"); 175669ebabbSIngo Molnar 176669ebabbSIngo Molnar return err; 177669ebabbSIngo Molnar } 178669ebabbSIngo Molnar 179669ebabbSIngo Molnar /* 180669ebabbSIngo Molnar * Restore processor xstate from xsave area. 181669ebabbSIngo Molnar */ 182669ebabbSIngo Molnar static inline int xrstor_state(struct xsave_struct *fx, u64 mask) 183669ebabbSIngo Molnar { 184669ebabbSIngo Molnar int err = 0; 185669ebabbSIngo Molnar u32 lmask = mask; 186669ebabbSIngo Molnar u32 hmask = mask >> 32; 187669ebabbSIngo Molnar 188669ebabbSIngo Molnar /* 189669ebabbSIngo Molnar * Use xrstors to restore context if it is enabled. xrstors supports 190669ebabbSIngo Molnar * compacted format of xsave area which is not supported by xrstor. 191669ebabbSIngo Molnar */ 192669ebabbSIngo Molnar alternative_input( 193669ebabbSIngo Molnar "1: " XRSTOR, 194669ebabbSIngo Molnar XRSTORS, 195669ebabbSIngo Molnar X86_FEATURE_XSAVES, 196669ebabbSIngo Molnar "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask) 197669ebabbSIngo Molnar : "memory"); 198669ebabbSIngo Molnar 199669ebabbSIngo Molnar asm volatile("2:\n" 200669ebabbSIngo Molnar xstate_fault 201669ebabbSIngo Molnar : "0" (0) 202669ebabbSIngo Molnar : "memory"); 203669ebabbSIngo Molnar 204669ebabbSIngo Molnar return err; 205669ebabbSIngo Molnar } 206669ebabbSIngo Molnar 207669ebabbSIngo Molnar /* 208669ebabbSIngo Molnar * Restore xstate context for new process during context switch. 209669ebabbSIngo Molnar */ 210669ebabbSIngo Molnar static inline int fpu_xrstor_checking(struct xsave_struct *fx) 211669ebabbSIngo Molnar { 212669ebabbSIngo Molnar return xrstor_state(fx, -1); 213669ebabbSIngo Molnar } 214669ebabbSIngo Molnar 215669ebabbSIngo Molnar /* 216669ebabbSIngo Molnar * Save xstate to user space xsave area. 217669ebabbSIngo Molnar * 218669ebabbSIngo Molnar * We don't use modified optimization because xrstor/xrstors might track 219669ebabbSIngo Molnar * a different application. 220669ebabbSIngo Molnar * 221669ebabbSIngo Molnar * We don't use compacted format xsave area for 222669ebabbSIngo Molnar * backward compatibility for old applications which don't understand 223669ebabbSIngo Molnar * compacted format of xsave area. 224669ebabbSIngo Molnar */ 225669ebabbSIngo Molnar static inline int xsave_user(struct xsave_struct __user *buf) 226669ebabbSIngo Molnar { 227669ebabbSIngo Molnar int err; 228669ebabbSIngo Molnar 229669ebabbSIngo Molnar /* 230669ebabbSIngo Molnar * Clear the xsave header first, so that reserved fields are 231669ebabbSIngo Molnar * initialized to zero. 232669ebabbSIngo Molnar */ 233669ebabbSIngo Molnar err = __clear_user(&buf->header, sizeof(buf->header)); 234669ebabbSIngo Molnar if (unlikely(err)) 235669ebabbSIngo Molnar return -EFAULT; 236669ebabbSIngo Molnar 237669ebabbSIngo Molnar __asm__ __volatile__(ASM_STAC "\n" 238669ebabbSIngo Molnar "1:"XSAVE"\n" 239669ebabbSIngo Molnar "2: " ASM_CLAC "\n" 240669ebabbSIngo Molnar xstate_fault 241669ebabbSIngo Molnar : "D" (buf), "a" (-1), "d" (-1), "0" (0) 242669ebabbSIngo Molnar : "memory"); 243669ebabbSIngo Molnar return err; 244669ebabbSIngo Molnar } 245669ebabbSIngo Molnar 246669ebabbSIngo Molnar /* 247669ebabbSIngo Molnar * Restore xstate from user space xsave area. 248669ebabbSIngo Molnar */ 249669ebabbSIngo Molnar static inline int xrestore_user(struct xsave_struct __user *buf, u64 mask) 250669ebabbSIngo Molnar { 251669ebabbSIngo Molnar int err = 0; 252669ebabbSIngo Molnar struct xsave_struct *xstate = ((__force struct xsave_struct *)buf); 253669ebabbSIngo Molnar u32 lmask = mask; 254669ebabbSIngo Molnar u32 hmask = mask >> 32; 255669ebabbSIngo Molnar 256669ebabbSIngo Molnar __asm__ __volatile__(ASM_STAC "\n" 257669ebabbSIngo Molnar "1:"XRSTOR"\n" 258669ebabbSIngo Molnar "2: " ASM_CLAC "\n" 259669ebabbSIngo Molnar xstate_fault 260669ebabbSIngo Molnar : "D" (xstate), "a" (lmask), "d" (hmask), "0" (0) 261669ebabbSIngo Molnar : "memory"); /* memory required? */ 262669ebabbSIngo Molnar return err; 263669ebabbSIngo Molnar } 264669ebabbSIngo Molnar 265669ebabbSIngo Molnar void *get_xsave_addr(struct xsave_struct *xsave, int xstate); 266669ebabbSIngo Molnar void setup_xstate_comp(void); 267669ebabbSIngo Molnar 268669ebabbSIngo Molnar #endif 269