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