xref: /openbmc/linux/arch/x86/include/asm/fpu/xstate.h (revision 677b98bdd5b93d89ad58b8a4679db086dfbaa854)
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