x86/fpu: Factor out fpu/signal.c
authorIngo Molnar <mingo@kernel.org>
Thu, 30 Apr 2015 10:45:38 +0000 (12:45 +0200)
committerIngo Molnar <mingo@kernel.org>
Tue, 19 May 2015 13:48:08 +0000 (15:48 +0200)
fpu/xstate.c has a lot of generic FPU signal frame handling routines,
move them into a separate file: fpu/signal.c.

Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/include/asm/fpu/signal.h
arch/x86/kernel/fpu/Makefile
arch/x86/kernel/fpu/signal.c [new file with mode: 0644]
arch/x86/kernel/fpu/xstate.c

index 0803dc2aba80b0e4b06293eb5e5eca0dae16d0a2..7358e9d61f1e70ebb069048d5120e5a377895ba4 100644 (file)
@@ -28,4 +28,6 @@ unsigned long
 fpu__alloc_mathframe(unsigned long sp, int ia32_frame,
                     unsigned long *buf_fx, unsigned long *size);
 
+extern void fpu__init_prepare_fx_sw_frame(void);
+
 #endif /* _ASM_X86_FPU_SIGNAL_H */
index 6ae59bccdd2f2fabacfec2db9ffb0be5006c74d5..5c697ded57f208f8e334ce99b83ccf5dfddefed9 100644 (file)
@@ -2,4 +2,4 @@
 # Build rules for the FPU support code:
 #
 
-obj-y                          += init.o bugs.o core.o xstate.o
+obj-y                          += init.o bugs.o core.o signal.o xstate.o
diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
new file mode 100644 (file)
index 0000000..8d0c26a
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * FPU signal frame handling routines.
+ */
+
+#include <linux/compat.h>
+#include <linux/cpu.h>
+
+#include <asm/fpu/internal.h>
+#include <asm/fpu/signal.h>
+#include <asm/fpu/regset.h>
+
+#include <asm/sigframe.h>
+
+static struct _fpx_sw_bytes fx_sw_reserved, fx_sw_reserved_ia32;
+
+/*
+ * Check for the presence of extended state information in the
+ * user fpstate pointer in the sigcontext.
+ */
+static inline int check_for_xstate(struct i387_fxsave_struct __user *buf,
+                                  void __user *fpstate,
+                                  struct _fpx_sw_bytes *fx_sw)
+{
+       int min_xstate_size = sizeof(struct i387_fxsave_struct) +
+                             sizeof(struct xstate_header);
+       unsigned int magic2;
+
+       if (__copy_from_user(fx_sw, &buf->sw_reserved[0], sizeof(*fx_sw)))
+               return -1;
+
+       /* Check for the first magic field and other error scenarios. */
+       if (fx_sw->magic1 != FP_XSTATE_MAGIC1 ||
+           fx_sw->xstate_size < min_xstate_size ||
+           fx_sw->xstate_size > xstate_size ||
+           fx_sw->xstate_size > fx_sw->extended_size)
+               return -1;
+
+       /*
+        * Check for the presence of second magic word at the end of memory
+        * layout. This detects the case where the user just copied the legacy
+        * fpstate layout with out copying the extended state information
+        * in the memory layout.
+        */
+       if (__get_user(magic2, (__u32 __user *)(fpstate + fx_sw->xstate_size))
+           || magic2 != FP_XSTATE_MAGIC2)
+               return -1;
+
+       return 0;
+}
+
+/*
+ * Signal frame handlers.
+ */
+static inline int save_fsave_header(struct task_struct *tsk, void __user *buf)
+{
+       if (use_fxsr()) {
+               struct xsave_struct *xsave = &tsk->thread.fpu.state.xsave;
+               struct user_i387_ia32_struct env;
+               struct _fpstate_ia32 __user *fp = buf;
+
+               convert_from_fxsr(&env, tsk);
+
+               if (__copy_to_user(buf, &env, sizeof(env)) ||
+                   __put_user(xsave->i387.swd, &fp->status) ||
+                   __put_user(X86_FXSR_MAGIC, &fp->magic))
+                       return -1;
+       } else {
+               struct i387_fsave_struct __user *fp = buf;
+               u32 swd;
+               if (__get_user(swd, &fp->swd) || __put_user(swd, &fp->status))
+                       return -1;
+       }
+
+       return 0;
+}
+
+static inline int save_xstate_epilog(void __user *buf, int ia32_frame)
+{
+       struct xsave_struct __user *x = buf;
+       struct _fpx_sw_bytes *sw_bytes;
+       u32 xfeatures;
+       int err;
+
+       /* Setup the bytes not touched by the [f]xsave and reserved for SW. */
+       sw_bytes = ia32_frame ? &fx_sw_reserved_ia32 : &fx_sw_reserved;
+       err = __copy_to_user(&x->i387.sw_reserved, sw_bytes, sizeof(*sw_bytes));
+
+       if (!use_xsave())
+               return err;
+
+       err |= __put_user(FP_XSTATE_MAGIC2, (__u32 *)(buf + xstate_size));
+
+       /*
+        * Read the xfeatures which we copied (directly from the cpu or
+        * from the state in task struct) to the user buffers.
+        */
+       err |= __get_user(xfeatures, (__u32 *)&x->header.xfeatures);
+
+       /*
+        * For legacy compatible, we always set FP/SSE bits in the bit
+        * vector while saving the state to the user context. This will
+        * enable us capturing any changes(during sigreturn) to
+        * the FP/SSE bits by the legacy applications which don't touch
+        * xfeatures in the xsave header.
+        *
+        * xsave aware apps can change the xfeatures in the xsave
+        * header as well as change any contents in the memory layout.
+        * xrestore as part of sigreturn will capture all the changes.
+        */
+       xfeatures |= XSTATE_FPSSE;
+
+       err |= __put_user(xfeatures, (__u32 *)&x->header.xfeatures);
+
+       return err;
+}
+
+static inline int copy_fpregs_to_sigframe(struct xsave_struct __user *buf)
+{
+       int err;
+
+       if (use_xsave())
+               err = copy_xregs_to_user(buf);
+       else if (use_fxsr())
+               err = copy_fxregs_to_user((struct i387_fxsave_struct __user *) buf);
+       else
+               err = copy_fregs_to_user((struct i387_fsave_struct __user *) buf);
+
+       if (unlikely(err) && __clear_user(buf, xstate_size))
+               err = -EFAULT;
+       return err;
+}
+
+/*
+ * Save the fpu, extended register state to the user signal frame.
+ *
+ * 'buf_fx' is the 64-byte aligned pointer at which the [f|fx|x]save
+ *  state is copied.
+ *  'buf' points to the 'buf_fx' or to the fsave header followed by 'buf_fx'.
+ *
+ *     buf == buf_fx for 64-bit frames and 32-bit fsave frame.
+ *     buf != buf_fx for 32-bit frames with fxstate.
+ *
+ * If the fpu, extended register state is live, save the state directly
+ * to the user frame pointed by the aligned pointer 'buf_fx'. Otherwise,
+ * copy the thread's fpu state to the user frame starting at 'buf_fx'.
+ *
+ * If this is a 32-bit frame with fxstate, put a fsave header before
+ * the aligned state at 'buf_fx'.
+ *
+ * For [f]xsave state, update the SW reserved fields in the [f]xsave frame
+ * indicating the absence/presence of the extended state to the user.
+ */
+int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
+{
+       struct xsave_struct *xsave = &current->thread.fpu.state.xsave;
+       struct task_struct *tsk = current;
+       int ia32_fxstate = (buf != buf_fx);
+
+       ia32_fxstate &= (config_enabled(CONFIG_X86_32) ||
+                        config_enabled(CONFIG_IA32_EMULATION));
+
+       if (!access_ok(VERIFY_WRITE, buf, size))
+               return -EACCES;
+
+       if (!static_cpu_has(X86_FEATURE_FPU))
+               return fpregs_soft_get(current, NULL, 0,
+                       sizeof(struct user_i387_ia32_struct), NULL,
+                       (struct _fpstate_ia32 __user *) buf) ? -1 : 1;
+
+       if (fpregs_active()) {
+               /* Save the live register state to the user directly. */
+               if (copy_fpregs_to_sigframe(buf_fx))
+                       return -1;
+               /* Update the thread's fxstate to save the fsave header. */
+               if (ia32_fxstate)
+                       copy_fxregs_to_kernel(&tsk->thread.fpu);
+       } else {
+               fpstate_sanitize_xstate(&tsk->thread.fpu);
+               if (__copy_to_user(buf_fx, xsave, xstate_size))
+                       return -1;
+       }
+
+       /* Save the fsave header for the 32-bit frames. */
+       if ((ia32_fxstate || !use_fxsr()) && save_fsave_header(tsk, buf))
+               return -1;
+
+       if (use_fxsr() && save_xstate_epilog(buf_fx, ia32_fxstate))
+               return -1;
+
+       return 0;
+}
+
+static inline void
+sanitize_restored_xstate(struct task_struct *tsk,
+                        struct user_i387_ia32_struct *ia32_env,
+                        u64 xfeatures, int fx_only)
+{
+       struct xsave_struct *xsave = &tsk->thread.fpu.state.xsave;
+       struct xstate_header *header = &xsave->header;
+
+       if (use_xsave()) {
+               /* These bits must be zero. */
+               memset(header->reserved, 0, 48);
+
+               /*
+                * Init the state that is not present in the memory
+                * layout and not enabled by the OS.
+                */
+               if (fx_only)
+                       header->xfeatures = XSTATE_FPSSE;
+               else
+                       header->xfeatures &= (xfeatures_mask & xfeatures);
+       }
+
+       if (use_fxsr()) {
+               /*
+                * mscsr reserved bits must be masked to zero for security
+                * reasons.
+                */
+               xsave->i387.mxcsr &= mxcsr_feature_mask;
+
+               convert_to_fxsr(tsk, ia32_env);
+       }
+}
+
+/*
+ * Restore the extended state if present. Otherwise, restore the FP/SSE state.
+ */
+static inline int copy_user_to_fpregs_zeroing(void __user *buf, u64 xbv, int fx_only)
+{
+       if (use_xsave()) {
+               if ((unsigned long)buf % 64 || fx_only) {
+                       u64 init_bv = xfeatures_mask & ~XSTATE_FPSSE;
+                       copy_kernel_to_xregs(&init_fpstate.xsave, init_bv);
+                       return copy_user_to_fxregs(buf);
+               } else {
+                       u64 init_bv = xfeatures_mask & ~xbv;
+                       if (unlikely(init_bv))
+                               copy_kernel_to_xregs(&init_fpstate.xsave, init_bv);
+                       return copy_user_to_xregs(buf, xbv);
+               }
+       } else if (use_fxsr()) {
+               return copy_user_to_fxregs(buf);
+       } else
+               return copy_user_to_fregs(buf);
+}
+
+static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
+{
+       int ia32_fxstate = (buf != buf_fx);
+       struct task_struct *tsk = current;
+       struct fpu *fpu = &tsk->thread.fpu;
+       int state_size = xstate_size;
+       u64 xfeatures = 0;
+       int fx_only = 0;
+
+       ia32_fxstate &= (config_enabled(CONFIG_X86_32) ||
+                        config_enabled(CONFIG_IA32_EMULATION));
+
+       if (!buf) {
+               fpu__clear(fpu);
+               return 0;
+       }
+
+       if (!access_ok(VERIFY_READ, buf, size))
+               return -EACCES;
+
+       fpu__activate_curr(fpu);
+
+       if (!static_cpu_has(X86_FEATURE_FPU))
+               return fpregs_soft_set(current, NULL,
+                                      0, sizeof(struct user_i387_ia32_struct),
+                                      NULL, buf) != 0;
+
+       if (use_xsave()) {
+               struct _fpx_sw_bytes fx_sw_user;
+               if (unlikely(check_for_xstate(buf_fx, buf_fx, &fx_sw_user))) {
+                       /*
+                        * Couldn't find the extended state information in the
+                        * memory layout. Restore just the FP/SSE and init all
+                        * the other extended state.
+                        */
+                       state_size = sizeof(struct i387_fxsave_struct);
+                       fx_only = 1;
+               } else {
+                       state_size = fx_sw_user.xstate_size;
+                       xfeatures = fx_sw_user.xfeatures;
+               }
+       }
+
+       if (ia32_fxstate) {
+               /*
+                * For 32-bit frames with fxstate, copy the user state to the
+                * thread's fpu state, reconstruct fxstate from the fsave
+                * header. Sanitize the copied state etc.
+                */
+               struct fpu *fpu = &tsk->thread.fpu;
+               struct user_i387_ia32_struct env;
+               int err = 0;
+
+               /*
+                * Drop the current fpu which clears fpu->fpstate_active. This ensures
+                * that any context-switch during the copy of the new state,
+                * avoids the intermediate state from getting restored/saved.
+                * Thus avoiding the new restored state from getting corrupted.
+                * We will be ready to restore/save the state only after
+                * fpu->fpstate_active is again set.
+                */
+               fpu__drop(fpu);
+
+               if (__copy_from_user(&fpu->state.xsave, buf_fx, state_size) ||
+                   __copy_from_user(&env, buf, sizeof(env))) {
+                       fpstate_init(&fpu->state);
+                       err = -1;
+               } else {
+                       sanitize_restored_xstate(tsk, &env, xfeatures, fx_only);
+               }
+
+               fpu->fpstate_active = 1;
+               if (use_eager_fpu()) {
+                       preempt_disable();
+                       fpu__restore();
+                       preempt_enable();
+               }
+
+               return err;
+       } else {
+               /*
+                * For 64-bit frames and 32-bit fsave frames, restore the user
+                * state to the registers directly (with exceptions handled).
+                */
+               user_fpu_begin();
+               if (copy_user_to_fpregs_zeroing(buf_fx, xfeatures, fx_only)) {
+                       fpu__clear(fpu);
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+static inline int xstate_sigframe_size(void)
+{
+       return use_xsave() ? xstate_size + FP_XSTATE_MAGIC2_SIZE : xstate_size;
+}
+
+/*
+ * Restore FPU state from a sigframe:
+ */
+int fpu__restore_sig(void __user *buf, int ia32_frame)
+{
+       void __user *buf_fx = buf;
+       int size = xstate_sigframe_size();
+
+       if (ia32_frame && use_fxsr()) {
+               buf_fx = buf + sizeof(struct i387_fsave_struct);
+               size += sizeof(struct i387_fsave_struct);
+       }
+
+       return __fpu__restore_sig(buf, buf_fx, size);
+}
+
+unsigned long
+fpu__alloc_mathframe(unsigned long sp, int ia32_frame,
+                    unsigned long *buf_fx, unsigned long *size)
+{
+       unsigned long frame_size = xstate_sigframe_size();
+
+       *buf_fx = sp = round_down(sp - frame_size, 64);
+       if (ia32_frame && use_fxsr()) {
+               frame_size += sizeof(struct i387_fsave_struct);
+               sp -= sizeof(struct i387_fsave_struct);
+       }
+
+       *size = frame_size;
+
+       return sp;
+}
+/*
+ * Prepare the SW reserved portion of the fxsave memory layout, indicating
+ * the presence of the extended state information in the memory layout
+ * pointed by the fpstate pointer in the sigcontext.
+ * This will be saved when ever the FP and extended state context is
+ * saved on the user stack during the signal handler delivery to the user.
+ */
+void fpu__init_prepare_fx_sw_frame(void)
+{
+       int fsave_header_size = sizeof(struct i387_fsave_struct);
+       int size = xstate_size + FP_XSTATE_MAGIC2_SIZE;
+
+       if (config_enabled(CONFIG_X86_32))
+               size += fsave_header_size;
+
+       fx_sw_reserved.magic1 = FP_XSTATE_MAGIC1;
+       fx_sw_reserved.extended_size = size;
+       fx_sw_reserved.xfeatures = xfeatures_mask;
+       fx_sw_reserved.xstate_size = xstate_size;
+
+       if (config_enabled(CONFIG_IA32_EMULATION)) {
+               fx_sw_reserved_ia32 = fx_sw_reserved;
+               fx_sw_reserved_ia32.extended_size += fsave_header_size;
+       }
+}
+
index 336b3dae59cadbdb28250bddc2243b9b84313ab4..3629e2ef3c944f3072f2bf2fde237269fba03224 100644 (file)
@@ -10,7 +10,7 @@
 #include <asm/fpu/internal.h>
 #include <asm/fpu/signal.h>
 #include <asm/fpu/regset.h>
-#include <asm/sigframe.h>
+
 #include <asm/tlbflush.h>
 
 static const char *xfeature_names[] =
@@ -31,7 +31,6 @@ static const char *xfeature_names[] =
  */
 u64 xfeatures_mask __read_mostly;
 
-static struct _fpx_sw_bytes fx_sw_reserved, fx_sw_reserved_ia32;
 static unsigned int xstate_offsets[XFEATURES_NR_MAX], xstate_sizes[XFEATURES_NR_MAX];
 static unsigned int xstate_comp_offsets[sizeof(xfeatures_mask)*8];
 
@@ -154,395 +153,6 @@ void fpstate_sanitize_xstate(struct fpu *fpu)
        }
 }
 
-/*
- * Check for the presence of extended state information in the
- * user fpstate pointer in the sigcontext.
- */
-static inline int check_for_xstate(struct i387_fxsave_struct __user *buf,
-                                  void __user *fpstate,
-                                  struct _fpx_sw_bytes *fx_sw)
-{
-       int min_xstate_size = sizeof(struct i387_fxsave_struct) +
-                             sizeof(struct xstate_header);
-       unsigned int magic2;
-
-       if (__copy_from_user(fx_sw, &buf->sw_reserved[0], sizeof(*fx_sw)))
-               return -1;
-
-       /* Check for the first magic field and other error scenarios. */
-       if (fx_sw->magic1 != FP_XSTATE_MAGIC1 ||
-           fx_sw->xstate_size < min_xstate_size ||
-           fx_sw->xstate_size > xstate_size ||
-           fx_sw->xstate_size > fx_sw->extended_size)
-               return -1;
-
-       /*
-        * Check for the presence of second magic word at the end of memory
-        * layout. This detects the case where the user just copied the legacy
-        * fpstate layout with out copying the extended state information
-        * in the memory layout.
-        */
-       if (__get_user(magic2, (__u32 __user *)(fpstate + fx_sw->xstate_size))
-           || magic2 != FP_XSTATE_MAGIC2)
-               return -1;
-
-       return 0;
-}
-
-/*
- * Signal frame handlers.
- */
-static inline int save_fsave_header(struct task_struct *tsk, void __user *buf)
-{
-       if (use_fxsr()) {
-               struct xsave_struct *xsave = &tsk->thread.fpu.state.xsave;
-               struct user_i387_ia32_struct env;
-               struct _fpstate_ia32 __user *fp = buf;
-
-               convert_from_fxsr(&env, tsk);
-
-               if (__copy_to_user(buf, &env, sizeof(env)) ||
-                   __put_user(xsave->i387.swd, &fp->status) ||
-                   __put_user(X86_FXSR_MAGIC, &fp->magic))
-                       return -1;
-       } else {
-               struct i387_fsave_struct __user *fp = buf;
-               u32 swd;
-               if (__get_user(swd, &fp->swd) || __put_user(swd, &fp->status))
-                       return -1;
-       }
-
-       return 0;
-}
-
-static inline int save_xstate_epilog(void __user *buf, int ia32_frame)
-{
-       struct xsave_struct __user *x = buf;
-       struct _fpx_sw_bytes *sw_bytes;
-       u32 xfeatures;
-       int err;
-
-       /* Setup the bytes not touched by the [f]xsave and reserved for SW. */
-       sw_bytes = ia32_frame ? &fx_sw_reserved_ia32 : &fx_sw_reserved;
-       err = __copy_to_user(&x->i387.sw_reserved, sw_bytes, sizeof(*sw_bytes));
-
-       if (!use_xsave())
-               return err;
-
-       err |= __put_user(FP_XSTATE_MAGIC2, (__u32 *)(buf + xstate_size));
-
-       /*
-        * Read the xfeatures which we copied (directly from the cpu or
-        * from the state in task struct) to the user buffers.
-        */
-       err |= __get_user(xfeatures, (__u32 *)&x->header.xfeatures);
-
-       /*
-        * For legacy compatible, we always set FP/SSE bits in the bit
-        * vector while saving the state to the user context. This will
-        * enable us capturing any changes(during sigreturn) to
-        * the FP/SSE bits by the legacy applications which don't touch
-        * xfeatures in the xsave header.
-        *
-        * xsave aware apps can change the xfeatures in the xsave
-        * header as well as change any contents in the memory layout.
-        * xrestore as part of sigreturn will capture all the changes.
-        */
-       xfeatures |= XSTATE_FPSSE;
-
-       err |= __put_user(xfeatures, (__u32 *)&x->header.xfeatures);
-
-       return err;
-}
-
-static inline int copy_fpregs_to_sigframe(struct xsave_struct __user *buf)
-{
-       int err;
-
-       if (use_xsave())
-               err = copy_xregs_to_user(buf);
-       else if (use_fxsr())
-               err = copy_fxregs_to_user((struct i387_fxsave_struct __user *) buf);
-       else
-               err = copy_fregs_to_user((struct i387_fsave_struct __user *) buf);
-
-       if (unlikely(err) && __clear_user(buf, xstate_size))
-               err = -EFAULT;
-       return err;
-}
-
-/*
- * Save the fpu, extended register state to the user signal frame.
- *
- * 'buf_fx' is the 64-byte aligned pointer at which the [f|fx|x]save
- *  state is copied.
- *  'buf' points to the 'buf_fx' or to the fsave header followed by 'buf_fx'.
- *
- *     buf == buf_fx for 64-bit frames and 32-bit fsave frame.
- *     buf != buf_fx for 32-bit frames with fxstate.
- *
- * If the fpu, extended register state is live, save the state directly
- * to the user frame pointed by the aligned pointer 'buf_fx'. Otherwise,
- * copy the thread's fpu state to the user frame starting at 'buf_fx'.
- *
- * If this is a 32-bit frame with fxstate, put a fsave header before
- * the aligned state at 'buf_fx'.
- *
- * For [f]xsave state, update the SW reserved fields in the [f]xsave frame
- * indicating the absence/presence of the extended state to the user.
- */
-int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
-{
-       struct xsave_struct *xsave = &current->thread.fpu.state.xsave;
-       struct task_struct *tsk = current;
-       int ia32_fxstate = (buf != buf_fx);
-
-       ia32_fxstate &= (config_enabled(CONFIG_X86_32) ||
-                        config_enabled(CONFIG_IA32_EMULATION));
-
-       if (!access_ok(VERIFY_WRITE, buf, size))
-               return -EACCES;
-
-       if (!static_cpu_has(X86_FEATURE_FPU))
-               return fpregs_soft_get(current, NULL, 0,
-                       sizeof(struct user_i387_ia32_struct), NULL,
-                       (struct _fpstate_ia32 __user *) buf) ? -1 : 1;
-
-       if (fpregs_active()) {
-               /* Save the live register state to the user directly. */
-               if (copy_fpregs_to_sigframe(buf_fx))
-                       return -1;
-               /* Update the thread's fxstate to save the fsave header. */
-               if (ia32_fxstate)
-                       copy_fxregs_to_kernel(&tsk->thread.fpu);
-       } else {
-               fpstate_sanitize_xstate(&tsk->thread.fpu);
-               if (__copy_to_user(buf_fx, xsave, xstate_size))
-                       return -1;
-       }
-
-       /* Save the fsave header for the 32-bit frames. */
-       if ((ia32_fxstate || !use_fxsr()) && save_fsave_header(tsk, buf))
-               return -1;
-
-       if (use_fxsr() && save_xstate_epilog(buf_fx, ia32_fxstate))
-               return -1;
-
-       return 0;
-}
-
-static inline void
-sanitize_restored_xstate(struct task_struct *tsk,
-                        struct user_i387_ia32_struct *ia32_env,
-                        u64 xfeatures, int fx_only)
-{
-       struct xsave_struct *xsave = &tsk->thread.fpu.state.xsave;
-       struct xstate_header *header = &xsave->header;
-
-       if (use_xsave()) {
-               /* These bits must be zero. */
-               memset(header->reserved, 0, 48);
-
-               /*
-                * Init the state that is not present in the memory
-                * layout and not enabled by the OS.
-                */
-               if (fx_only)
-                       header->xfeatures = XSTATE_FPSSE;
-               else
-                       header->xfeatures &= (xfeatures_mask & xfeatures);
-       }
-
-       if (use_fxsr()) {
-               /*
-                * mscsr reserved bits must be masked to zero for security
-                * reasons.
-                */
-               xsave->i387.mxcsr &= mxcsr_feature_mask;
-
-               convert_to_fxsr(tsk, ia32_env);
-       }
-}
-
-/*
- * Restore the extended state if present. Otherwise, restore the FP/SSE state.
- */
-static inline int copy_user_to_fpregs_zeroing(void __user *buf, u64 xbv, int fx_only)
-{
-       if (use_xsave()) {
-               if ((unsigned long)buf % 64 || fx_only) {
-                       u64 init_bv = xfeatures_mask & ~XSTATE_FPSSE;
-                       copy_kernel_to_xregs(&init_fpstate.xsave, init_bv);
-                       return copy_user_to_fxregs(buf);
-               } else {
-                       u64 init_bv = xfeatures_mask & ~xbv;
-                       if (unlikely(init_bv))
-                               copy_kernel_to_xregs(&init_fpstate.xsave, init_bv);
-                       return copy_user_to_xregs(buf, xbv);
-               }
-       } else if (use_fxsr()) {
-               return copy_user_to_fxregs(buf);
-       } else
-               return copy_user_to_fregs(buf);
-}
-
-static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
-{
-       int ia32_fxstate = (buf != buf_fx);
-       struct task_struct *tsk = current;
-       struct fpu *fpu = &tsk->thread.fpu;
-       int state_size = xstate_size;
-       u64 xfeatures = 0;
-       int fx_only = 0;
-
-       ia32_fxstate &= (config_enabled(CONFIG_X86_32) ||
-                        config_enabled(CONFIG_IA32_EMULATION));
-
-       if (!buf) {
-               fpu__clear(fpu);
-               return 0;
-       }
-
-       if (!access_ok(VERIFY_READ, buf, size))
-               return -EACCES;
-
-       fpu__activate_curr(fpu);
-
-       if (!static_cpu_has(X86_FEATURE_FPU))
-               return fpregs_soft_set(current, NULL,
-                                      0, sizeof(struct user_i387_ia32_struct),
-                                      NULL, buf) != 0;
-
-       if (use_xsave()) {
-               struct _fpx_sw_bytes fx_sw_user;
-               if (unlikely(check_for_xstate(buf_fx, buf_fx, &fx_sw_user))) {
-                       /*
-                        * Couldn't find the extended state information in the
-                        * memory layout. Restore just the FP/SSE and init all
-                        * the other extended state.
-                        */
-                       state_size = sizeof(struct i387_fxsave_struct);
-                       fx_only = 1;
-               } else {
-                       state_size = fx_sw_user.xstate_size;
-                       xfeatures = fx_sw_user.xfeatures;
-               }
-       }
-
-       if (ia32_fxstate) {
-               /*
-                * For 32-bit frames with fxstate, copy the user state to the
-                * thread's fpu state, reconstruct fxstate from the fsave
-                * header. Sanitize the copied state etc.
-                */
-               struct fpu *fpu = &tsk->thread.fpu;
-               struct user_i387_ia32_struct env;
-               int err = 0;
-
-               /*
-                * Drop the current fpu which clears fpu->fpstate_active. This ensures
-                * that any context-switch during the copy of the new state,
-                * avoids the intermediate state from getting restored/saved.
-                * Thus avoiding the new restored state from getting corrupted.
-                * We will be ready to restore/save the state only after
-                * fpu->fpstate_active is again set.
-                */
-               fpu__drop(fpu);
-
-               if (__copy_from_user(&fpu->state.xsave, buf_fx, state_size) ||
-                   __copy_from_user(&env, buf, sizeof(env))) {
-                       fpstate_init(&fpu->state);
-                       err = -1;
-               } else {
-                       sanitize_restored_xstate(tsk, &env, xfeatures, fx_only);
-               }
-
-               fpu->fpstate_active = 1;
-               if (use_eager_fpu()) {
-                       preempt_disable();
-                       fpu__restore();
-                       preempt_enable();
-               }
-
-               return err;
-       } else {
-               /*
-                * For 64-bit frames and 32-bit fsave frames, restore the user
-                * state to the registers directly (with exceptions handled).
-                */
-               user_fpu_begin();
-               if (copy_user_to_fpregs_zeroing(buf_fx, xfeatures, fx_only)) {
-                       fpu__clear(fpu);
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-static inline int xstate_sigframe_size(void)
-{
-       return use_xsave() ? xstate_size + FP_XSTATE_MAGIC2_SIZE : xstate_size;
-}
-
-/*
- * Restore FPU state from a sigframe:
- */
-int fpu__restore_sig(void __user *buf, int ia32_frame)
-{
-       void __user *buf_fx = buf;
-       int size = xstate_sigframe_size();
-
-       if (ia32_frame && use_fxsr()) {
-               buf_fx = buf + sizeof(struct i387_fsave_struct);
-               size += sizeof(struct i387_fsave_struct);
-       }
-
-       return __fpu__restore_sig(buf, buf_fx, size);
-}
-
-unsigned long
-fpu__alloc_mathframe(unsigned long sp, int ia32_frame,
-                    unsigned long *buf_fx, unsigned long *size)
-{
-       unsigned long frame_size = xstate_sigframe_size();
-
-       *buf_fx = sp = round_down(sp - frame_size, 64);
-       if (ia32_frame && use_fxsr()) {
-               frame_size += sizeof(struct i387_fsave_struct);
-               sp -= sizeof(struct i387_fsave_struct);
-       }
-
-       *size = frame_size;
-
-       return sp;
-}
-/*
- * Prepare the SW reserved portion of the fxsave memory layout, indicating
- * the presence of the extended state information in the memory layout
- * pointed by the fpstate pointer in the sigcontext.
- * This will be saved when ever the FP and extended state context is
- * saved on the user stack during the signal handler delivery to the user.
- */
-static void prepare_fx_sw_frame(void)
-{
-       int fsave_header_size = sizeof(struct i387_fsave_struct);
-       int size = xstate_size + FP_XSTATE_MAGIC2_SIZE;
-
-       if (config_enabled(CONFIG_X86_32))
-               size += fsave_header_size;
-
-       fx_sw_reserved.magic1 = FP_XSTATE_MAGIC1;
-       fx_sw_reserved.extended_size = size;
-       fx_sw_reserved.xfeatures = xfeatures_mask;
-       fx_sw_reserved.xstate_size = xstate_size;
-
-       if (config_enabled(CONFIG_IA32_EMULATION)) {
-               fx_sw_reserved_ia32 = fx_sw_reserved;
-               fx_sw_reserved_ia32.extended_size += fsave_header_size;
-       }
-}
-
 /*
  * Enable the extended processor state save/restore feature.
  * Called once per CPU onlining.
@@ -741,7 +351,7 @@ void fpu__init_system_xstate(void)
        init_xstate_size();
 
        update_regset_xstate_info(xstate_size, xfeatures_mask);
-       prepare_fx_sw_frame();
+       fpu__init_prepare_fx_sw_frame();
        setup_init_fpu_buf();
 
        pr_info("x86/fpu: Enabled xstate features 0x%llx, context size is 0x%x bytes, using '%s' format.\n",