2 * xsave/xrstor support.
4 * Author: Suresh Siddha <suresh.b.siddha@intel.com>
6 #include <linux/bootmem.h>
7 #include <linux/compat.h>
9 #ifdef CONFIG_IA32_EMULATION
10 #include <asm/sigcontext32.h>
14 * Supported feature mask by the CPU and the kernel.
16 unsigned int pcntxt_hmask, pcntxt_lmask;
18 struct _fpx_sw_bytes fx_sw_reserved;
19 #ifdef CONFIG_IA32_EMULATION
20 struct _fpx_sw_bytes fx_sw_reserved_ia32;
24 * Check for the presence of extended state information in the
25 * user fpstate pointer in the sigcontext.
27 int check_for_xstate(struct i387_fxsave_struct __user *buf,
29 struct _fpx_sw_bytes *fx_sw_user)
31 int min_xstate_size = sizeof(struct i387_fxsave_struct) +
32 sizeof(struct xsave_hdr_struct);
36 err = __copy_from_user(fx_sw_user, &buf->sw_reserved[0],
37 sizeof(struct _fpx_sw_bytes));
43 * First Magic check failed.
45 if (fx_sw_user->magic1 != FP_XSTATE_MAGIC1)
49 * Check for error scenarios.
51 if (fx_sw_user->xstate_size < min_xstate_size ||
52 fx_sw_user->xstate_size > xstate_size ||
53 fx_sw_user->xstate_size > fx_sw_user->extended_size)
56 err = __get_user(magic2, (__u32 *) (((void *)fpstate) +
57 fx_sw_user->extended_size -
58 FP_XSTATE_MAGIC2_SIZE));
60 * Check for the presence of second magic word at the end of memory
61 * layout. This detects the case where the user just copied the legacy
62 * fpstate layout with out copying the extended state information
63 * in the memory layout.
65 if (err || magic2 != FP_XSTATE_MAGIC2)
73 * Signal frame handlers.
76 int save_i387_xstate(void __user *buf)
78 struct task_struct *tsk = current;
81 if (!access_ok(VERIFY_WRITE, buf, sig_xstate_size))
84 BUILD_BUG_ON(sizeof(struct user_i387_struct) !=
85 sizeof(tsk->thread.xstate->fxsave));
87 if ((unsigned long)buf % 64)
88 printk("save_i387_xstate: bad fpstate %p\n", buf);
92 clear_used_math(); /* trigger finit */
93 if (task_thread_info(tsk)->status & TS_USEDFPU) {
94 if (task_thread_info(tsk)->status & TS_XSAVE)
95 err = xsave_user(buf);
97 err = fxsave_user(buf);
101 task_thread_info(tsk)->status &= ~TS_USEDFPU;
104 if (__copy_to_user(buf, &tsk->thread.xstate->fxsave,
109 if (task_thread_info(tsk)->status & TS_XSAVE) {
110 struct _fpstate __user *fx = buf;
112 err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved,
113 sizeof(struct _fpx_sw_bytes));
115 err |= __put_user(FP_XSTATE_MAGIC2,
116 (__u32 __user *) (buf + sig_xstate_size
117 - FP_XSTATE_MAGIC2_SIZE));
124 * Restore the extended state if present. Otherwise, restore the FP/SSE
127 int restore_user_xstate(void __user *buf)
129 struct _fpx_sw_bytes fx_sw_user;
130 unsigned int lmask, hmask;
133 if (((unsigned long)buf % 64) ||
134 check_for_xstate(buf, buf, &fx_sw_user))
137 lmask = fx_sw_user.xstate_bv;
138 hmask = fx_sw_user.xstate_bv >> 32;
141 * restore the state passed by the user.
143 err = xrestore_user(buf, lmask, hmask);
148 * init the state skipped by the user.
150 lmask = pcntxt_lmask & ~lmask;
151 hmask = pcntxt_hmask & ~hmask;
153 xrstor_state(init_xstate_buf, lmask, hmask);
159 * couldn't find the extended state information in the
160 * memory layout. Restore just the FP/SSE and init all
161 * the other extended state.
163 xrstor_state(init_xstate_buf, pcntxt_lmask & ~XSTATE_FPSSE,
165 return fxrstor_checking((__force struct i387_fxsave_struct *)buf);
169 * This restores directly out of user space. Exceptions are handled.
171 int restore_i387_xstate(void __user *buf)
173 struct task_struct *tsk = current;
181 if (!access_ok(VERIFY_READ, buf, sig_xstate_size))
190 if (!(task_thread_info(current)->status & TS_USEDFPU)) {
192 task_thread_info(current)->status |= TS_USEDFPU;
194 if (task_thread_info(tsk)->status & TS_XSAVE)
195 err = restore_user_xstate(buf);
197 err = fxrstor_checking((__force struct i387_fxsave_struct *)
201 * Encountered an error while doing the restore from the
202 * user buffer, clear the fpu state.
213 * Prepare the SW reserved portion of the fxsave memory layout, indicating
214 * the presence of the extended state information in the memory layout
215 * pointed by the fpstate pointer in the sigcontext.
216 * This will be saved when ever the FP and extended state context is
217 * saved on the user stack during the signal handler delivery to the user.
219 void prepare_fx_sw_frame(void)
221 int size_extended = (xstate_size - sizeof(struct i387_fxsave_struct)) +
222 FP_XSTATE_MAGIC2_SIZE;
224 sig_xstate_size = sizeof(struct _fpstate) + size_extended;
226 #ifdef CONFIG_IA32_EMULATION
227 sig_xstate_ia32_size = sizeof(struct _fpstate_ia32) + size_extended;
230 memset(&fx_sw_reserved, 0, sizeof(fx_sw_reserved));
232 fx_sw_reserved.magic1 = FP_XSTATE_MAGIC1;
233 fx_sw_reserved.extended_size = sig_xstate_size;
234 fx_sw_reserved.xstate_bv = pcntxt_lmask |
235 (((u64) (pcntxt_hmask)) << 32);
236 fx_sw_reserved.xstate_size = xstate_size;
237 #ifdef CONFIG_IA32_EMULATION
238 memcpy(&fx_sw_reserved_ia32, &fx_sw_reserved,
239 sizeof(struct _fpx_sw_bytes));
240 fx_sw_reserved_ia32.extended_size = sig_xstate_ia32_size;
245 * Represents init state for the supported extended state.
247 struct xsave_struct *init_xstate_buf;
250 unsigned int sig_xstate_size = sizeof(struct _fpstate);
254 * Enable the extended processor state save/restore feature
256 void __cpuinit xsave_init(void)
261 set_in_cr4(X86_CR4_OSXSAVE);
264 * Enable all the features that the HW is capable of
265 * and the Linux kernel is aware of.
269 asm volatile(".byte 0x0f,0x01,0xd1" : : "c" (0),
270 "a" (pcntxt_lmask), "d" (pcntxt_hmask));
274 * setup the xstate image representing the init state
276 void setup_xstate_init(void)
278 init_xstate_buf = alloc_bootmem(xstate_size);
279 init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT;
283 * Enable and initialize the xsave feature.
285 void __init xsave_cntxt_init(void)
287 unsigned int eax, ebx, ecx, edx;
289 cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx);
294 if ((pcntxt_lmask & XSTATE_FPSSE) != XSTATE_FPSSE) {
295 printk(KERN_ERR "FP/SSE not shown under xsave features %x\n",
301 * for now OS knows only about FP/SSE
303 pcntxt_lmask = pcntxt_lmask & XCNTXT_LMASK;
304 pcntxt_hmask = pcntxt_hmask & XCNTXT_HMASK;
309 * Recompute the context size for enabled features
311 cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx);
315 prepare_fx_sw_frame();
319 printk(KERN_INFO "xsave/xrstor: enabled xstate_bv 0x%Lx, "
321 (pcntxt_lmask | ((u64) pcntxt_hmask << 32)), xstate_size);