aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2008-07-29 13:29:25 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-30 13:49:27 -0400
commitc37b5efea43f9e500363f9973dd00e3d2cdcc685 (patch)
tree9ce635f1672099dafcd78e535b4ea18d80235d8f
parentbdd8caba5ed5bb7ee21c9f061597284ffeb280bf (diff)
x86, xsave: save/restore the extended state context in sigframe
On cpu's supporting xsave/xrstor, fpstate pointer in the sigcontext, will include the extended state information along with fpstate information. Presence of extended state information is indicated by the presence of FP_XSTATE_MAGIC1 at fpstate.sw_reserved.magic1 and FP_XSTATE_MAGIC2 at fpstate + (fpstate.sw_reserved.extended_size - FP_XSTATE_MAGIC2_SIZE). Extended feature bit mask that is saved in the memory layout is represented by the fpstate.sw_reserved.xstate_bv For RT signal frames, UC_FP_XSTATE in the uc_flags also indicate the presence of extended state information in the sigcontext's fpstate pointer. Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/ia32/ia32_signal.c5
-rw-r--r--arch/x86/kernel/i387.c82
-rw-r--r--arch/x86/kernel/signal_32.c5
-rw-r--r--arch/x86/kernel/signal_64.c7
-rw-r--r--arch/x86/kernel/xsave.c172
-rw-r--r--include/asm-x86/i387.h4
-rw-r--r--include/asm-x86/ucontext.h6
-rw-r--r--include/asm-x86/xsave.h5
8 files changed, 264 insertions, 22 deletions
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index c596eabbe98b..f25a10124005 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -544,7 +544,10 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
544 goto give_sigsegv; 544 goto give_sigsegv;
545 545
546 /* Create the ucontext. */ 546 /* Create the ucontext. */
547 err |= __put_user(0, &frame->uc.uc_flags); 547 if (cpu_has_xsave)
548 err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags);
549 else
550 err |= __put_user(0, &frame->uc.uc_flags);
548 err |= __put_user(0, &frame->uc.uc_link); 551 err |= __put_user(0, &frame->uc.uc_link);
549 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); 552 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
550 err |= __put_user(sas_ss_flags(regs->sp), 553 err |= __put_user(sas_ss_flags(regs->sp),
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index 7daf3a011dd9..cbb9dc474a21 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -26,6 +26,7 @@
26# define _fpstate_ia32 _fpstate 26# define _fpstate_ia32 _fpstate
27# define _xstate_ia32 _xstate 27# define _xstate_ia32 _xstate
28# define sig_xstate_ia32_size sig_xstate_size 28# define sig_xstate_ia32_size sig_xstate_size
29# define fx_sw_reserved_ia32 fx_sw_reserved
29# define user_i387_ia32_struct user_i387_struct 30# define user_i387_ia32_struct user_i387_struct
30# define user32_fxsr_struct user_fxsr_struct 31# define user32_fxsr_struct user_fxsr_struct
31#endif 32#endif
@@ -447,12 +448,30 @@ static int save_i387_fxsave(struct _fpstate_ia32 __user *buf)
447 if (err) 448 if (err)
448 return -1; 449 return -1;
449 450
450 if (__copy_to_user(&buf->_fxsr_env[0], fx, 451 if (__copy_to_user(&buf->_fxsr_env[0], fx, xstate_size))
451 sizeof(struct i387_fxsave_struct)))
452 return -1; 452 return -1;
453 return 1; 453 return 1;
454} 454}
455 455
456static int save_i387_xsave(void __user *buf)
457{
458 struct _fpstate_ia32 __user *fx = buf;
459 int err = 0;
460
461 if (save_i387_fxsave(fx) < 0)
462 return -1;
463
464 err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved_ia32,
465 sizeof(struct _fpx_sw_bytes));
466 err |= __put_user(FP_XSTATE_MAGIC2,
467 (__u32 __user *) (buf + sig_xstate_ia32_size
468 - FP_XSTATE_MAGIC2_SIZE));
469 if (err)
470 return -1;
471
472 return 1;
473}
474
456int save_i387_xstate_ia32(void __user *buf) 475int save_i387_xstate_ia32(void __user *buf)
457{ 476{
458 struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf; 477 struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf;
@@ -477,6 +496,8 @@ int save_i387_xstate_ia32(void __user *buf)
477 496
478 unlazy_fpu(tsk); 497 unlazy_fpu(tsk);
479 498
499 if (cpu_has_xsave)
500 return save_i387_xsave(fp);
480 if (cpu_has_fxsr) 501 if (cpu_has_fxsr)
481 return save_i387_fxsave(fp); 502 return save_i387_fxsave(fp);
482 else 503 else
@@ -491,14 +512,15 @@ static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf)
491 sizeof(struct i387_fsave_struct)); 512 sizeof(struct i387_fsave_struct));
492} 513}
493 514
494static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf) 515static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf,
516 unsigned int size)
495{ 517{
496 struct task_struct *tsk = current; 518 struct task_struct *tsk = current;
497 struct user_i387_ia32_struct env; 519 struct user_i387_ia32_struct env;
498 int err; 520 int err;
499 521
500 err = __copy_from_user(&tsk->thread.xstate->fxsave, &buf->_fxsr_env[0], 522 err = __copy_from_user(&tsk->thread.xstate->fxsave, &buf->_fxsr_env[0],
501 sizeof(struct i387_fxsave_struct)); 523 size);
502 /* mxcsr reserved bits must be masked to zero for security reasons */ 524 /* mxcsr reserved bits must be masked to zero for security reasons */
503 tsk->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask; 525 tsk->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask;
504 if (err || __copy_from_user(&env, buf, sizeof(env))) 526 if (err || __copy_from_user(&env, buf, sizeof(env)))
@@ -508,6 +530,51 @@ static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf)
508 return 0; 530 return 0;
509} 531}
510 532
533static int restore_i387_xsave(void __user *buf)
534{
535 struct _fpx_sw_bytes fx_sw_user;
536 struct _fpstate_ia32 __user *fx_user =
537 ((struct _fpstate_ia32 __user *) buf);
538 struct i387_fxsave_struct __user *fx =
539 (struct i387_fxsave_struct __user *) &fx_user->_fxsr_env[0];
540 struct xsave_hdr_struct *xsave_hdr =
541 &current->thread.xstate->xsave.xsave_hdr;
542 unsigned int lmask, hmask;
543 int err;
544
545 if (check_for_xstate(fx, buf, &fx_sw_user))
546 goto fx_only;
547
548 lmask = fx_sw_user.xstate_bv;
549 hmask = fx_sw_user.xstate_bv >> 32;
550
551 err = restore_i387_fxsave(buf, fx_sw_user.xstate_size);
552
553 xsave_hdr->xstate_bv &= (pcntxt_lmask | (((u64) pcntxt_hmask) << 32));
554 /*
555 * These bits must be zero.
556 */
557 xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0;
558
559 /*
560 * Init the state that is not present in the memory layout
561 * and enabled by the OS.
562 */
563 lmask = ~(pcntxt_lmask & ~lmask);
564 hmask = ~(pcntxt_hmask & ~hmask);
565 xsave_hdr->xstate_bv &= (lmask | (((u64) hmask) << 32));
566
567 return err;
568fx_only:
569 /*
570 * Couldn't find the extended state information in the memory
571 * layout. Restore the FP/SSE and init the other extended state
572 * enabled by the OS.
573 */
574 xsave_hdr->xstate_bv = XSTATE_FPSSE;
575 return restore_i387_fxsave(buf, sizeof(struct i387_fxsave_struct));
576}
577
511int restore_i387_xstate_ia32(void __user *buf) 578int restore_i387_xstate_ia32(void __user *buf)
512{ 579{
513 int err; 580 int err;
@@ -535,8 +602,11 @@ int restore_i387_xstate_ia32(void __user *buf)
535 } 602 }
536 603
537 if (HAVE_HWFP) { 604 if (HAVE_HWFP) {
538 if (cpu_has_fxsr) 605 if (cpu_has_xsave)
539 err = restore_i387_fxsave(fp); 606 err = restore_i387_xsave(buf);
607 else if (cpu_has_fxsr)
608 err = restore_i387_fxsave(fp, sizeof(struct
609 i387_fxsave_struct));
540 else 610 else
541 err = restore_i387_fsave(fp); 611 err = restore_i387_fsave(fp);
542 } else { 612 } else {
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c
index 690cc616ac07..0f98d69fbdb0 100644
--- a/arch/x86/kernel/signal_32.c
+++ b/arch/x86/kernel/signal_32.c
@@ -441,7 +441,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
441 goto give_sigsegv; 441 goto give_sigsegv;
442 442
443 /* Create the ucontext. */ 443 /* Create the ucontext. */
444 err |= __put_user(0, &frame->uc.uc_flags); 444 if (cpu_has_xsave)
445 err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags);
446 else
447 err |= __put_user(0, &frame->uc.uc_flags);
445 err |= __put_user(0, &frame->uc.uc_link); 448 err |= __put_user(0, &frame->uc.uc_link);
446 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); 449 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
447 err |= __put_user(sas_ss_flags(regs->sp), 450 err |= __put_user(sas_ss_flags(regs->sp),
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
index ddf6123a55c8..2621b98f5bf6 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -192,7 +192,7 @@ get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size)
192 sp = current->sas_ss_sp + current->sas_ss_size; 192 sp = current->sas_ss_sp + current->sas_ss_size;
193 } 193 }
194 194
195 return (void __user *)round_down(sp - size, 16); 195 return (void __user *)round_down(sp - size, 64);
196} 196}
197 197
198static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 198static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -226,7 +226,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
226 } 226 }
227 227
228 /* Create the ucontext. */ 228 /* Create the ucontext. */
229 err |= __put_user(0, &frame->uc.uc_flags); 229 if (cpu_has_xsave)
230 err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags);
231 else
232 err |= __put_user(0, &frame->uc.uc_flags);
230 err |= __put_user(0, &frame->uc.uc_link); 233 err |= __put_user(0, &frame->uc.uc_link);
231 err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); 234 err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
232 err |= __put_user(sas_ss_flags(regs->sp), 235 err |= __put_user(sas_ss_flags(regs->sp),
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index 608e72d7ca64..dd66d0714c18 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -6,12 +6,68 @@
6#include <linux/bootmem.h> 6#include <linux/bootmem.h>
7#include <linux/compat.h> 7#include <linux/compat.h>
8#include <asm/i387.h> 8#include <asm/i387.h>
9#ifdef CONFIG_IA32_EMULATION
10#include <asm/sigcontext32.h>
11#endif
9 12
10/* 13/*
11 * Supported feature mask by the CPU and the kernel. 14 * Supported feature mask by the CPU and the kernel.
12 */ 15 */
13unsigned int pcntxt_hmask, pcntxt_lmask; 16unsigned int pcntxt_hmask, pcntxt_lmask;
14 17
18struct _fpx_sw_bytes fx_sw_reserved;
19#ifdef CONFIG_IA32_EMULATION
20struct _fpx_sw_bytes fx_sw_reserved_ia32;
21#endif
22
23/*
24 * Check for the presence of extended state information in the
25 * user fpstate pointer in the sigcontext.
26 */
27int check_for_xstate(struct i387_fxsave_struct __user *buf,
28 void __user *fpstate,
29 struct _fpx_sw_bytes *fx_sw_user)
30{
31 int min_xstate_size = sizeof(struct i387_fxsave_struct) +
32 sizeof(struct xsave_hdr_struct);
33 unsigned int magic2;
34 int err;
35
36 err = __copy_from_user(fx_sw_user, &buf->sw_reserved[0],
37 sizeof(struct _fpx_sw_bytes));
38
39 if (err)
40 return err;
41
42 /*
43 * First Magic check failed.
44 */
45 if (fx_sw_user->magic1 != FP_XSTATE_MAGIC1)
46 return -1;
47
48 /*
49 * Check for error scenarios.
50 */
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)
54 return -1;
55
56 err = __get_user(magic2, (__u32 *) (((void *)fpstate) +
57 fx_sw_user->extended_size -
58 FP_XSTATE_MAGIC2_SIZE));
59 /*
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.
64 */
65 if (err || magic2 != FP_XSTATE_MAGIC2)
66 return -1;
67
68 return 0;
69}
70
15#ifdef CONFIG_X86_64 71#ifdef CONFIG_X86_64
16/* 72/*
17 * Signal frame handlers. 73 * Signal frame handlers.
@@ -28,15 +84,18 @@ int save_i387_xstate(void __user *buf)
28 BUILD_BUG_ON(sizeof(struct user_i387_struct) != 84 BUILD_BUG_ON(sizeof(struct user_i387_struct) !=
29 sizeof(tsk->thread.xstate->fxsave)); 85 sizeof(tsk->thread.xstate->fxsave));
30 86
31 if ((unsigned long)buf % 16) 87 if ((unsigned long)buf % 64)
32 printk("save_i387_xstate: bad fpstate %p\n", buf); 88 printk("save_i387_xstate: bad fpstate %p\n", buf);
33 89
34 if (!used_math()) 90 if (!used_math())
35 return 0; 91 return 0;
36 clear_used_math(); /* trigger finit */ 92 clear_used_math(); /* trigger finit */
37 if (task_thread_info(tsk)->status & TS_USEDFPU) { 93 if (task_thread_info(tsk)->status & TS_USEDFPU) {
38 err = save_i387_checking((struct i387_fxsave_struct __user *) 94 if (task_thread_info(tsk)->status & TS_XSAVE)
39 buf); 95 err = xsave_user(buf);
96 else
97 err = fxsave_user(buf);
98
40 if (err) 99 if (err)
41 return err; 100 return err;
42 task_thread_info(tsk)->status &= ~TS_USEDFPU; 101 task_thread_info(tsk)->status &= ~TS_USEDFPU;
@@ -46,23 +105,77 @@ int save_i387_xstate(void __user *buf)
46 xstate_size)) 105 xstate_size))
47 return -1; 106 return -1;
48 } 107 }
108
109 if (task_thread_info(tsk)->status & TS_XSAVE) {
110 struct _fpstate __user *fx = buf;
111
112 err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved,
113 sizeof(struct _fpx_sw_bytes));
114
115 err |= __put_user(FP_XSTATE_MAGIC2,
116 (__u32 __user *) (buf + sig_xstate_size
117 - FP_XSTATE_MAGIC2_SIZE));
118 }
119
49 return 1; 120 return 1;
50} 121}
51 122
52/* 123/*
124 * Restore the extended state if present. Otherwise, restore the FP/SSE
125 * state.
126 */
127int restore_user_xstate(void __user *buf)
128{
129 struct _fpx_sw_bytes fx_sw_user;
130 unsigned int lmask, hmask;
131 int err;
132
133 if (((unsigned long)buf % 64) ||
134 check_for_xstate(buf, buf, &fx_sw_user))
135 goto fx_only;
136
137 lmask = fx_sw_user.xstate_bv;
138 hmask = fx_sw_user.xstate_bv >> 32;
139
140 /*
141 * restore the state passed by the user.
142 */
143 err = xrestore_user(buf, lmask, hmask);
144 if (err)
145 return err;
146
147 /*
148 * init the state skipped by the user.
149 */
150 lmask = pcntxt_lmask & ~lmask;
151 hmask = pcntxt_hmask & ~hmask;
152
153 xrstor_state(init_xstate_buf, lmask, hmask);
154
155 return 0;
156
157fx_only:
158 /*
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.
162 */
163 xrstor_state(init_xstate_buf, pcntxt_lmask & ~XSTATE_FPSSE,
164 pcntxt_hmask);
165 return fxrstor_checking((__force struct i387_fxsave_struct *)buf);
166}
167
168/*
53 * This restores directly out of user space. Exceptions are handled. 169 * This restores directly out of user space. Exceptions are handled.
54 */ 170 */
55int restore_i387_xstate(void __user *buf) 171int restore_i387_xstate(void __user *buf)
56{ 172{
57 struct task_struct *tsk = current; 173 struct task_struct *tsk = current;
58 int err; 174 int err = 0;
59 175
60 if (!buf) { 176 if (!buf) {
61 if (used_math()) { 177 if (used_math())
62 clear_fpu(tsk); 178 goto clear;
63 clear_used_math();
64 }
65
66 return 0; 179 return 0;
67 } else 180 } else
68 if (!access_ok(VERIFY_READ, buf, sig_xstate_size)) 181 if (!access_ok(VERIFY_READ, buf, sig_xstate_size))
@@ -78,12 +191,17 @@ int restore_i387_xstate(void __user *buf)
78 clts(); 191 clts();
79 task_thread_info(current)->status |= TS_USEDFPU; 192 task_thread_info(current)->status |= TS_USEDFPU;
80 } 193 }
81 err = fxrstor_checking((__force struct i387_fxsave_struct *)buf); 194 if (task_thread_info(tsk)->status & TS_XSAVE)
195 err = restore_user_xstate(buf);
196 else
197 err = fxrstor_checking((__force struct i387_fxsave_struct *)
198 buf);
82 if (unlikely(err)) { 199 if (unlikely(err)) {
83 /* 200 /*
84 * Encountered an error while doing the restore from the 201 * Encountered an error while doing the restore from the
85 * user buffer, clear the fpu state. 202 * user buffer, clear the fpu state.
86 */ 203 */
204clear:
87 clear_fpu(tsk); 205 clear_fpu(tsk);
88 clear_used_math(); 206 clear_used_math();
89 } 207 }
@@ -92,6 +210,38 @@ int restore_i387_xstate(void __user *buf)
92#endif 210#endif
93 211
94/* 212/*
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.
218 */
219void prepare_fx_sw_frame(void)
220{
221 int size_extended = (xstate_size - sizeof(struct i387_fxsave_struct)) +
222 FP_XSTATE_MAGIC2_SIZE;
223
224 sig_xstate_size = sizeof(struct _fpstate) + size_extended;
225
226#ifdef CONFIG_IA32_EMULATION
227 sig_xstate_ia32_size = sizeof(struct _fpstate_ia32) + size_extended;
228#endif
229
230 memset(&fx_sw_reserved, 0, sizeof(fx_sw_reserved));
231
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;
241#endif
242}
243
244/*
95 * Represents init state for the supported extended state. 245 * Represents init state for the supported extended state.
96 */ 246 */
97struct xsave_struct *init_xstate_buf; 247struct xsave_struct *init_xstate_buf;
@@ -162,6 +312,8 @@ void __init xsave_cntxt_init(void)
162 312
163 xstate_size = ebx; 313 xstate_size = ebx;
164 314
315 prepare_fx_sw_frame();
316
165 setup_xstate_init(); 317 setup_xstate_init();
166 318
167 printk(KERN_INFO "xsave/xrstor: enabled xstate_bv 0x%Lx, " 319 printk(KERN_INFO "xsave/xrstor: enabled xstate_bv 0x%Lx, "
diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h
index dc3745e8040a..d3dda7161954 100644
--- a/include/asm-x86/i387.h
+++ b/include/asm-x86/i387.h
@@ -31,8 +31,10 @@ extern user_regset_active_fn fpregs_active, xfpregs_active;
31extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get; 31extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get;
32extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set; 32extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set;
33 33
34extern struct _fpx_sw_bytes fx_sw_reserved;
34#ifdef CONFIG_IA32_EMULATION 35#ifdef CONFIG_IA32_EMULATION
35extern unsigned int sig_xstate_ia32_size; 36extern unsigned int sig_xstate_ia32_size;
37extern struct _fpx_sw_bytes fx_sw_reserved_ia32;
36struct _fpstate_ia32; 38struct _fpstate_ia32;
37struct _xstate_ia32; 39struct _xstate_ia32;
38extern int save_i387_xstate_ia32(void __user *buf); 40extern int save_i387_xstate_ia32(void __user *buf);
@@ -104,7 +106,7 @@ static inline void clear_fpu_state(struct task_struct *tsk)
104 X86_FEATURE_FXSAVE_LEAK); 106 X86_FEATURE_FXSAVE_LEAK);
105} 107}
106 108
107static inline int save_i387_checking(struct i387_fxsave_struct __user *fx) 109static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
108{ 110{
109 int err; 111 int err;
110 112
diff --git a/include/asm-x86/ucontext.h b/include/asm-x86/ucontext.h
index 9948dd328084..89eaa5456a7e 100644
--- a/include/asm-x86/ucontext.h
+++ b/include/asm-x86/ucontext.h
@@ -1,6 +1,12 @@
1#ifndef ASM_X86__UCONTEXT_H 1#ifndef ASM_X86__UCONTEXT_H
2#define ASM_X86__UCONTEXT_H 2#define ASM_X86__UCONTEXT_H
3 3
4#define UC_FP_XSTATE 0x1 /* indicates the presence of extended state
5 * information in the memory layout pointed
6 * by the fpstate pointer in the ucontext's
7 * sigcontext struct (uc_mcontext).
8 */
9
4struct ucontext { 10struct ucontext {
5 unsigned long uc_flags; 11 unsigned long uc_flags;
6 struct ucontext *uc_link; 12 struct ucontext *uc_link;
diff --git a/include/asm-x86/xsave.h b/include/asm-x86/xsave.h
index b716511aede2..b7f64b9fcd94 100644
--- a/include/asm-x86/xsave.h
+++ b/include/asm-x86/xsave.h
@@ -29,6 +29,9 @@ extern struct xsave_struct *init_xstate_buf;
29extern void xsave_cntxt_init(void); 29extern void xsave_cntxt_init(void);
30extern void xsave_init(void); 30extern void xsave_init(void);
31extern int init_fpu(struct task_struct *child); 31extern int init_fpu(struct task_struct *child);
32extern int check_for_xstate(struct i387_fxsave_struct __user *buf,
33 void __user *fpstate,
34 struct _fpx_sw_bytes *sw);
32 35
33static inline int xrstor_checking(struct xsave_struct *fx) 36static inline int xrstor_checking(struct xsave_struct *fx)
34{ 37{
@@ -48,7 +51,7 @@ static inline int xrstor_checking(struct xsave_struct *fx)
48 return err; 51 return err;
49} 52}
50 53
51static inline int xsave_check(struct xsave_struct __user *buf) 54static inline int xsave_user(struct xsave_struct __user *buf)
52{ 55{
53 int err; 56 int err;
54 __asm__ __volatile__("1: .byte " REX_PREFIX "0x0f,0xae,0x27\n" 57 __asm__ __volatile__("1: .byte " REX_PREFIX "0x0f,0xae,0x27\n"