]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - arch/x86/kernel/i387.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[net-next-2.6.git] / arch / x86 / kernel / i387.c
index f2f8540a7f3d0bd88a8ac7b27c9ba460581ba023..54c31c285488e4d0db84826dcd697878e20fc953 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/module.h>
 #include <linux/regset.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
 
 #include <asm/sigcontext.h>
 #include <asm/processor.h>
@@ -164,6 +165,11 @@ int init_fpu(struct task_struct *tsk)
        return 0;
 }
 
+/*
+ * The xstateregs_active() routine is the same as the fpregs_active() routine,
+ * as the "regset->n" for the xstate regset will be updated based on the feature
+ * capabilites supported by the xsave.
+ */
 int fpregs_active(struct task_struct *target, const struct user_regset *regset)
 {
        return tsk_used_math(target) ? regset->n : 0;
@@ -204,8 +210,6 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
        if (ret)
                return ret;
 
-       set_stopped_child_used_math(target);
-
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
                                 &target->thread.xstate->fxsave, 0, -1);
 
@@ -224,6 +228,68 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
        return ret;
 }
 
+int xstateregs_get(struct task_struct *target, const struct user_regset *regset,
+               unsigned int pos, unsigned int count,
+               void *kbuf, void __user *ubuf)
+{
+       int ret;
+
+       if (!cpu_has_xsave)
+               return -ENODEV;
+
+       ret = init_fpu(target);
+       if (ret)
+               return ret;
+
+       /*
+        * Copy the 48bytes defined by the software first into the xstate
+        * memory layout in the thread struct, so that we can copy the entire
+        * xstateregs to the user using one user_regset_copyout().
+        */
+       memcpy(&target->thread.xstate->fxsave.sw_reserved,
+              xstate_fx_sw_bytes, sizeof(xstate_fx_sw_bytes));
+
+       /*
+        * Copy the xstate memory layout.
+        */
+       ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+                                 &target->thread.xstate->xsave, 0, -1);
+       return ret;
+}
+
+int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
+                 unsigned int pos, unsigned int count,
+                 const void *kbuf, const void __user *ubuf)
+{
+       int ret;
+       struct xsave_hdr_struct *xsave_hdr;
+
+       if (!cpu_has_xsave)
+               return -ENODEV;
+
+       ret = init_fpu(target);
+       if (ret)
+               return ret;
+
+       ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+                                &target->thread.xstate->xsave, 0, -1);
+
+       /*
+        * mxcsr reserved bits must be masked to zero for security reasons.
+        */
+       target->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask;
+
+       xsave_hdr = &target->thread.xstate->xsave.xsave_hdr;
+
+       xsave_hdr->xstate_bv &= pcntxt_mask;
+       /*
+        * These bits must be zero.
+        */
+       xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0;
+
+       return ret;
+}
+
 #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
 
 /*
@@ -404,8 +470,6 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
        if (ret)
                return ret;
 
-       set_stopped_child_used_math(target);
-
        if (!HAVE_HWFP)
                return fpregs_soft_set(target, regset, pos, count, kbuf, ubuf);