xref: /openbmc/linux/arch/x86/include/asm/fpu/xstate.h (revision 669ebabb79906302ba6e6922a683893788a134e8)
1*669ebabbSIngo Molnar #ifndef __ASM_X86_XSAVE_H
2*669ebabbSIngo Molnar #define __ASM_X86_XSAVE_H
3*669ebabbSIngo Molnar 
4*669ebabbSIngo Molnar #include <linux/types.h>
5*669ebabbSIngo Molnar #include <asm/processor.h>
6*669ebabbSIngo Molnar 
7*669ebabbSIngo Molnar #define XSTATE_CPUID		0x0000000d
8*669ebabbSIngo Molnar 
9*669ebabbSIngo Molnar #define XSTATE_FP		0x1
10*669ebabbSIngo Molnar #define XSTATE_SSE		0x2
11*669ebabbSIngo Molnar #define XSTATE_YMM		0x4
12*669ebabbSIngo Molnar #define XSTATE_BNDREGS		0x8
13*669ebabbSIngo Molnar #define XSTATE_BNDCSR		0x10
14*669ebabbSIngo Molnar #define XSTATE_OPMASK		0x20
15*669ebabbSIngo Molnar #define XSTATE_ZMM_Hi256	0x40
16*669ebabbSIngo Molnar #define XSTATE_Hi16_ZMM		0x80
17*669ebabbSIngo Molnar 
18*669ebabbSIngo Molnar /* The highest xstate bit above (of XSTATE_Hi16_ZMM): */
19*669ebabbSIngo Molnar #define XFEATURES_NR_MAX	8
20*669ebabbSIngo Molnar 
21*669ebabbSIngo Molnar #define XSTATE_FPSSE	(XSTATE_FP | XSTATE_SSE)
22*669ebabbSIngo Molnar #define XSTATE_AVX512	(XSTATE_OPMASK | XSTATE_ZMM_Hi256 | XSTATE_Hi16_ZMM)
23*669ebabbSIngo Molnar /* Bit 63 of XCR0 is reserved for future expansion */
24*669ebabbSIngo Molnar #define XSTATE_EXTEND_MASK	(~(XSTATE_FPSSE | (1ULL << 63)))
25*669ebabbSIngo Molnar 
26*669ebabbSIngo Molnar #define FXSAVE_SIZE	512
27*669ebabbSIngo Molnar 
28*669ebabbSIngo Molnar #define XSAVE_HDR_SIZE	    64
29*669ebabbSIngo Molnar #define XSAVE_HDR_OFFSET    FXSAVE_SIZE
30*669ebabbSIngo Molnar 
31*669ebabbSIngo Molnar #define XSAVE_YMM_SIZE	    256
32*669ebabbSIngo Molnar #define XSAVE_YMM_OFFSET    (XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET)
33*669ebabbSIngo Molnar 
34*669ebabbSIngo Molnar /* Supported features which support lazy state saving */
35*669ebabbSIngo Molnar #define XSTATE_LAZY	(XSTATE_FP | XSTATE_SSE | XSTATE_YMM		      \
36*669ebabbSIngo Molnar 			| XSTATE_OPMASK | XSTATE_ZMM_Hi256 | XSTATE_Hi16_ZMM)
37*669ebabbSIngo Molnar 
38*669ebabbSIngo Molnar /* Supported features which require eager state saving */
39*669ebabbSIngo Molnar #define XSTATE_EAGER	(XSTATE_BNDREGS | XSTATE_BNDCSR)
40*669ebabbSIngo Molnar 
41*669ebabbSIngo Molnar /* All currently supported features */
42*669ebabbSIngo Molnar #define XCNTXT_MASK	(XSTATE_LAZY | XSTATE_EAGER)
43*669ebabbSIngo Molnar 
44*669ebabbSIngo Molnar #ifdef CONFIG_X86_64
45*669ebabbSIngo Molnar #define REX_PREFIX	"0x48, "
46*669ebabbSIngo Molnar #else
47*669ebabbSIngo Molnar #define REX_PREFIX
48*669ebabbSIngo Molnar #endif
49*669ebabbSIngo Molnar 
50*669ebabbSIngo Molnar extern unsigned int xstate_size;
51*669ebabbSIngo Molnar extern u64 xfeatures_mask;
52*669ebabbSIngo Molnar extern u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS];
53*669ebabbSIngo Molnar extern struct xsave_struct init_xstate_ctx;
54*669ebabbSIngo Molnar 
55*669ebabbSIngo Molnar extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask);
56*669ebabbSIngo Molnar 
57*669ebabbSIngo Molnar /* These macros all use (%edi)/(%rdi) as the single memory argument. */
58*669ebabbSIngo Molnar #define XSAVE		".byte " REX_PREFIX "0x0f,0xae,0x27"
59*669ebabbSIngo Molnar #define XSAVEOPT	".byte " REX_PREFIX "0x0f,0xae,0x37"
60*669ebabbSIngo Molnar #define XSAVES		".byte " REX_PREFIX "0x0f,0xc7,0x2f"
61*669ebabbSIngo Molnar #define XRSTOR		".byte " REX_PREFIX "0x0f,0xae,0x2f"
62*669ebabbSIngo Molnar #define XRSTORS		".byte " REX_PREFIX "0x0f,0xc7,0x1f"
63*669ebabbSIngo Molnar 
64*669ebabbSIngo Molnar #define xstate_fault	".section .fixup,\"ax\"\n"	\
65*669ebabbSIngo Molnar 			"3:  movl $-1,%[err]\n"		\
66*669ebabbSIngo Molnar 			"    jmp  2b\n"			\
67*669ebabbSIngo Molnar 			".previous\n"			\
68*669ebabbSIngo Molnar 			_ASM_EXTABLE(1b, 3b)		\
69*669ebabbSIngo Molnar 			: [err] "=r" (err)
70*669ebabbSIngo Molnar 
71*669ebabbSIngo Molnar /*
72*669ebabbSIngo Molnar  * This function is called only during boot time when x86 caps are not set
73*669ebabbSIngo Molnar  * up and alternative can not be used yet.
74*669ebabbSIngo Molnar  */
75*669ebabbSIngo Molnar static inline int xsave_state_booting(struct xsave_struct *fx)
76*669ebabbSIngo Molnar {
77*669ebabbSIngo Molnar 	u64 mask = -1;
78*669ebabbSIngo Molnar 	u32 lmask = mask;
79*669ebabbSIngo Molnar 	u32 hmask = mask >> 32;
80*669ebabbSIngo Molnar 	int err = 0;
81*669ebabbSIngo Molnar 
82*669ebabbSIngo Molnar 	WARN_ON(system_state != SYSTEM_BOOTING);
83*669ebabbSIngo Molnar 
84*669ebabbSIngo Molnar 	if (boot_cpu_has(X86_FEATURE_XSAVES))
85*669ebabbSIngo Molnar 		asm volatile("1:"XSAVES"\n\t"
86*669ebabbSIngo Molnar 			"2:\n\t"
87*669ebabbSIngo Molnar 			     xstate_fault
88*669ebabbSIngo Molnar 			: "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
89*669ebabbSIngo Molnar 			:   "memory");
90*669ebabbSIngo Molnar 	else
91*669ebabbSIngo Molnar 		asm volatile("1:"XSAVE"\n\t"
92*669ebabbSIngo Molnar 			"2:\n\t"
93*669ebabbSIngo Molnar 			     xstate_fault
94*669ebabbSIngo Molnar 			: "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
95*669ebabbSIngo Molnar 			:   "memory");
96*669ebabbSIngo Molnar 	return err;
97*669ebabbSIngo Molnar }
98*669ebabbSIngo Molnar 
99*669ebabbSIngo Molnar /*
100*669ebabbSIngo Molnar  * This function is called only during boot time when x86 caps are not set
101*669ebabbSIngo Molnar  * up and alternative can not be used yet.
102*669ebabbSIngo Molnar  */
103*669ebabbSIngo Molnar static inline int xrstor_state_booting(struct xsave_struct *fx, u64 mask)
104*669ebabbSIngo Molnar {
105*669ebabbSIngo Molnar 	u32 lmask = mask;
106*669ebabbSIngo Molnar 	u32 hmask = mask >> 32;
107*669ebabbSIngo Molnar 	int err = 0;
108*669ebabbSIngo Molnar 
109*669ebabbSIngo Molnar 	WARN_ON(system_state != SYSTEM_BOOTING);
110*669ebabbSIngo Molnar 
111*669ebabbSIngo Molnar 	if (boot_cpu_has(X86_FEATURE_XSAVES))
112*669ebabbSIngo Molnar 		asm volatile("1:"XRSTORS"\n\t"
113*669ebabbSIngo Molnar 			"2:\n\t"
114*669ebabbSIngo Molnar 			     xstate_fault
115*669ebabbSIngo Molnar 			: "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
116*669ebabbSIngo Molnar 			:   "memory");
117*669ebabbSIngo Molnar 	else
118*669ebabbSIngo Molnar 		asm volatile("1:"XRSTOR"\n\t"
119*669ebabbSIngo Molnar 			"2:\n\t"
120*669ebabbSIngo Molnar 			     xstate_fault
121*669ebabbSIngo Molnar 			: "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
122*669ebabbSIngo Molnar 			:   "memory");
123*669ebabbSIngo Molnar 	return err;
124*669ebabbSIngo Molnar }
125*669ebabbSIngo Molnar 
126*669ebabbSIngo Molnar /*
127*669ebabbSIngo Molnar  * Save processor xstate to xsave area.
128*669ebabbSIngo Molnar  */
129*669ebabbSIngo Molnar static inline int xsave_state(struct xsave_struct *fx)
130*669ebabbSIngo Molnar {
131*669ebabbSIngo Molnar 	u64 mask = -1;
132*669ebabbSIngo Molnar 	u32 lmask = mask;
133*669ebabbSIngo Molnar 	u32 hmask = mask >> 32;
134*669ebabbSIngo Molnar 	int err = 0;
135*669ebabbSIngo Molnar 
136*669ebabbSIngo Molnar 	WARN_ON(system_state == SYSTEM_BOOTING);
137*669ebabbSIngo Molnar 
138*669ebabbSIngo Molnar 	/*
139*669ebabbSIngo Molnar 	 * If xsaves is enabled, xsaves replaces xsaveopt because
140*669ebabbSIngo Molnar 	 * it supports compact format and supervisor states in addition to
141*669ebabbSIngo Molnar 	 * modified optimization in xsaveopt.
142*669ebabbSIngo Molnar 	 *
143*669ebabbSIngo Molnar 	 * Otherwise, if xsaveopt is enabled, xsaveopt replaces xsave
144*669ebabbSIngo Molnar 	 * because xsaveopt supports modified optimization which is not
145*669ebabbSIngo Molnar 	 * supported by xsave.
146*669ebabbSIngo Molnar 	 *
147*669ebabbSIngo Molnar 	 * If none of xsaves and xsaveopt is enabled, use xsave.
148*669ebabbSIngo Molnar 	 */
149*669ebabbSIngo Molnar 	alternative_input_2(
150*669ebabbSIngo Molnar 		"1:"XSAVE,
151*669ebabbSIngo Molnar 		XSAVEOPT,
152*669ebabbSIngo Molnar 		X86_FEATURE_XSAVEOPT,
153*669ebabbSIngo Molnar 		XSAVES,
154*669ebabbSIngo Molnar 		X86_FEATURE_XSAVES,
155*669ebabbSIngo Molnar 		[fx] "D" (fx), "a" (lmask), "d" (hmask) :
156*669ebabbSIngo Molnar 		"memory");
157*669ebabbSIngo Molnar 	asm volatile("2:\n\t"
158*669ebabbSIngo Molnar 		     xstate_fault
159*669ebabbSIngo Molnar 		     : "0" (0)
160*669ebabbSIngo Molnar 		     : "memory");
161*669ebabbSIngo Molnar 
162*669ebabbSIngo Molnar 	return err;
163*669ebabbSIngo Molnar }
164*669ebabbSIngo Molnar 
165*669ebabbSIngo Molnar /*
166*669ebabbSIngo Molnar  * Restore processor xstate from xsave area.
167*669ebabbSIngo Molnar  */
168*669ebabbSIngo Molnar static inline int xrstor_state(struct xsave_struct *fx, u64 mask)
169*669ebabbSIngo Molnar {
170*669ebabbSIngo Molnar 	int err = 0;
171*669ebabbSIngo Molnar 	u32 lmask = mask;
172*669ebabbSIngo Molnar 	u32 hmask = mask >> 32;
173*669ebabbSIngo Molnar 
174*669ebabbSIngo Molnar 	/*
175*669ebabbSIngo Molnar 	 * Use xrstors to restore context if it is enabled. xrstors supports
176*669ebabbSIngo Molnar 	 * compacted format of xsave area which is not supported by xrstor.
177*669ebabbSIngo Molnar 	 */
178*669ebabbSIngo Molnar 	alternative_input(
179*669ebabbSIngo Molnar 		"1: " XRSTOR,
180*669ebabbSIngo Molnar 		XRSTORS,
181*669ebabbSIngo Molnar 		X86_FEATURE_XSAVES,
182*669ebabbSIngo Molnar 		"D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
183*669ebabbSIngo Molnar 		: "memory");
184*669ebabbSIngo Molnar 
185*669ebabbSIngo Molnar 	asm volatile("2:\n"
186*669ebabbSIngo Molnar 		     xstate_fault
187*669ebabbSIngo Molnar 		     : "0" (0)
188*669ebabbSIngo Molnar 		     : "memory");
189*669ebabbSIngo Molnar 
190*669ebabbSIngo Molnar 	return err;
191*669ebabbSIngo Molnar }
192*669ebabbSIngo Molnar 
193*669ebabbSIngo Molnar /*
194*669ebabbSIngo Molnar  * Restore xstate context for new process during context switch.
195*669ebabbSIngo Molnar  */
196*669ebabbSIngo Molnar static inline int fpu_xrstor_checking(struct xsave_struct *fx)
197*669ebabbSIngo Molnar {
198*669ebabbSIngo Molnar 	return xrstor_state(fx, -1);
199*669ebabbSIngo Molnar }
200*669ebabbSIngo Molnar 
201*669ebabbSIngo Molnar /*
202*669ebabbSIngo Molnar  * Save xstate to user space xsave area.
203*669ebabbSIngo Molnar  *
204*669ebabbSIngo Molnar  * We don't use modified optimization because xrstor/xrstors might track
205*669ebabbSIngo Molnar  * a different application.
206*669ebabbSIngo Molnar  *
207*669ebabbSIngo Molnar  * We don't use compacted format xsave area for
208*669ebabbSIngo Molnar  * backward compatibility for old applications which don't understand
209*669ebabbSIngo Molnar  * compacted format of xsave area.
210*669ebabbSIngo Molnar  */
211*669ebabbSIngo Molnar static inline int xsave_user(struct xsave_struct __user *buf)
212*669ebabbSIngo Molnar {
213*669ebabbSIngo Molnar 	int err;
214*669ebabbSIngo Molnar 
215*669ebabbSIngo Molnar 	/*
216*669ebabbSIngo Molnar 	 * Clear the xsave header first, so that reserved fields are
217*669ebabbSIngo Molnar 	 * initialized to zero.
218*669ebabbSIngo Molnar 	 */
219*669ebabbSIngo Molnar 	err = __clear_user(&buf->header, sizeof(buf->header));
220*669ebabbSIngo Molnar 	if (unlikely(err))
221*669ebabbSIngo Molnar 		return -EFAULT;
222*669ebabbSIngo Molnar 
223*669ebabbSIngo Molnar 	__asm__ __volatile__(ASM_STAC "\n"
224*669ebabbSIngo Molnar 			     "1:"XSAVE"\n"
225*669ebabbSIngo Molnar 			     "2: " ASM_CLAC "\n"
226*669ebabbSIngo Molnar 			     xstate_fault
227*669ebabbSIngo Molnar 			     : "D" (buf), "a" (-1), "d" (-1), "0" (0)
228*669ebabbSIngo Molnar 			     : "memory");
229*669ebabbSIngo Molnar 	return err;
230*669ebabbSIngo Molnar }
231*669ebabbSIngo Molnar 
232*669ebabbSIngo Molnar /*
233*669ebabbSIngo Molnar  * Restore xstate from user space xsave area.
234*669ebabbSIngo Molnar  */
235*669ebabbSIngo Molnar static inline int xrestore_user(struct xsave_struct __user *buf, u64 mask)
236*669ebabbSIngo Molnar {
237*669ebabbSIngo Molnar 	int err = 0;
238*669ebabbSIngo Molnar 	struct xsave_struct *xstate = ((__force struct xsave_struct *)buf);
239*669ebabbSIngo Molnar 	u32 lmask = mask;
240*669ebabbSIngo Molnar 	u32 hmask = mask >> 32;
241*669ebabbSIngo Molnar 
242*669ebabbSIngo Molnar 	__asm__ __volatile__(ASM_STAC "\n"
243*669ebabbSIngo Molnar 			     "1:"XRSTOR"\n"
244*669ebabbSIngo Molnar 			     "2: " ASM_CLAC "\n"
245*669ebabbSIngo Molnar 			     xstate_fault
246*669ebabbSIngo Molnar 			     : "D" (xstate), "a" (lmask), "d" (hmask), "0" (0)
247*669ebabbSIngo Molnar 			     : "memory");	/* memory required? */
248*669ebabbSIngo Molnar 	return err;
249*669ebabbSIngo Molnar }
250*669ebabbSIngo Molnar 
251*669ebabbSIngo Molnar void *get_xsave_addr(struct xsave_struct *xsave, int xstate);
252*669ebabbSIngo Molnar void setup_xstate_comp(void);
253*669ebabbSIngo Molnar 
254*669ebabbSIngo Molnar #endif
255