summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/0021-x86-fpu-Let-__fpu__restore_sig-restore-the-32bit-fxs.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/0021-x86-fpu-Let-__fpu__restore_sig-restore-the-32bit-fxs.patch')
-rw-r--r--debian/patches-rt/0021-x86-fpu-Let-__fpu__restore_sig-restore-the-32bit-fxs.patch196
1 files changed, 0 insertions, 196 deletions
diff --git a/debian/patches-rt/0021-x86-fpu-Let-__fpu__restore_sig-restore-the-32bit-fxs.patch b/debian/patches-rt/0021-x86-fpu-Let-__fpu__restore_sig-restore-the-32bit-fxs.patch
deleted file mode 100644
index 8f43994f5..000000000
--- a/debian/patches-rt/0021-x86-fpu-Let-__fpu__restore_sig-restore-the-32bit-fxs.patch
+++ /dev/null
@@ -1,196 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Tue, 27 Nov 2018 17:48:32 +0100
-Subject: [PATCH 21/27] x86/fpu: Let __fpu__restore_sig() restore the
- !32bit+fxsr frame from kernel memory
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/5.0/older/patches-5.0.10-rt7.tar.xz
-
-The !32bit+fxsr case loads the new state from user memory. In case we
-restore the FPU state on return to userland we can't do this. It would
-be required to disable preemption in order to avoid a context switch
-which would set TIF_NEED_FPU_LOAD. If this happens before the "restore"
-operation then the loaded registers would become volatile.
-
-Disabling preemption while accessing user memory requires to disable the
-pagefault handler. An error during XRSTOR would then mean that either a
-page fault occured (and we have to retry with enabled page fault
-handler) or a #GP occured because the xstate is bogus (after all the
-sig-handler can modify it).
-
-In order to avoid that mess, copy the FPU state from userland, validate
-it and then load it. The copy_users_…() helper are basically the old
-helper except that they operate on kernel memory and the fault handler
-just sets the error value and the caller handles it.
-
-copy_user_to_fpregs_zeroing() and its helpers remain and will be used
-later for a fastpath optimisation.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- arch/x86/include/asm/fpu/internal.h | 43 ++++++++++++++++++++++++
- arch/x86/kernel/fpu/signal.c | 62 ++++++++++++++++++++++++++++--------
- 2 files changed, 92 insertions(+), 13 deletions(-)
-
---- a/arch/x86/include/asm/fpu/internal.h
-+++ b/arch/x86/include/asm/fpu/internal.h
-@@ -121,6 +121,21 @@ extern void fpstate_sanitize_xstate(stru
- err; \
- })
-
-+#define kernel_insn_err(insn, output, input...) \
-+({ \
-+ int err; \
-+ asm volatile("1:" #insn "\n\t" \
-+ "2:\n" \
-+ ".section .fixup,\"ax\"\n" \
-+ "3: movl $-1,%[err]\n" \
-+ " jmp 2b\n" \
-+ ".previous\n" \
-+ _ASM_EXTABLE(1b, 3b) \
-+ : [err] "=r" (err), output \
-+ : "0"(0), input); \
-+ err; \
-+})
-+
- #define kernel_insn(insn, output, input...) \
- asm volatile("1:" #insn "\n\t" \
- "2:\n" \
-@@ -157,6 +172,14 @@ static inline void copy_kernel_to_fxregs
- }
- }
-
-+static inline int copy_kernel_to_fxregs_err(struct fxregs_state *fx)
-+{
-+ if (IS_ENABLED(CONFIG_X86_32))
-+ return kernel_insn_err(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
-+ else
-+ return kernel_insn_err(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
-+}
-+
- static inline int copy_user_to_fxregs(struct fxregs_state __user *fx)
- {
- if (IS_ENABLED(CONFIG_X86_32))
-@@ -174,6 +197,11 @@ static inline void copy_kernel_to_fregs(
- kernel_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
- }
-
-+static inline int copy_kernel_to_fregs_err(struct fregs_state *fx)
-+{
-+ return kernel_insn_err(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
-+}
-+
- static inline int copy_user_to_fregs(struct fregs_state __user *fx)
- {
- return user_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
-@@ -398,6 +426,21 @@ static inline int copy_user_to_xregs(str
-
- return err;
- }
-+
-+/*
-+ * Restore xstate from kernel space xsave area, return an error code instead an
-+ * exception.
-+ */
-+static inline int copy_kernel_to_xregs_err(struct xregs_state *xstate, u64 mask)
-+{
-+ u32 lmask = mask;
-+ u32 hmask = mask >> 32;
-+ int err;
-+
-+ XSTATE_OP(XRSTOR, xstate, lmask, hmask, err);
-+
-+ return err;
-+}
-
- /*
- * These must be called with preempt disabled. Returns
---- a/arch/x86/kernel/fpu/signal.c
-+++ b/arch/x86/kernel/fpu/signal.c
-@@ -234,7 +234,8 @@ sanitize_restored_xstate(union fpregs_st
- */
- xsave->i387.mxcsr &= mxcsr_feature_mask;
-
-- convert_to_fxsr(&state->fxsave, ia32_env);
-+ if (ia32_env)
-+ convert_to_fxsr(&state->fxsave, ia32_env);
- }
- }
-
-@@ -337,28 +338,63 @@ static int __fpu__restore_sig(void __use
- kfree(tmp);
- return err;
- } else {
-+ union fpregs_state *state;
-+ void *tmp;
- int ret;
-
-+ tmp = kzalloc(sizeof(*state) + fpu_kernel_xstate_size + 64, GFP_KERNEL);
-+ if (!tmp)
-+ return -ENOMEM;
-+ state = PTR_ALIGN(tmp, 64);
-+
- /*
- * For 64-bit frames and 32-bit fsave frames, restore the user
- * state to the registers directly (with exceptions handled).
- */
-- if (use_xsave()) {
-- if ((unsigned long)buf_fx % 64 || fx_only) {
-- u64 init_bv = xfeatures_mask & ~XFEATURE_MASK_FPSSE;
-- copy_kernel_to_xregs(&init_fpstate.xsave, init_bv);
-- ret = copy_user_to_fxregs(buf_fx);
-+ if ((unsigned long)buf_fx % 64)
-+ fx_only = 1;
-+
-+ if (use_xsave() && !fx_only) {
-+ u64 init_bv = xfeatures_mask & ~xfeatures;
-+
-+ if (using_compacted_format()) {
-+ ret = copy_user_to_xstate(&state->xsave, buf_fx);
- } else {
-- u64 init_bv = xfeatures_mask & ~xfeatures;
-- if (unlikely(init_bv))
-- copy_kernel_to_xregs(&init_fpstate.xsave, init_bv);
-- ret = copy_user_to_xregs(buf_fx, xfeatures);
-+ ret = __copy_from_user(&state->xsave, buf_fx, state_size);
-+
-+ if (!ret && state_size > offsetof(struct xregs_state, header))
-+ ret = validate_xstate_header(&state->xsave.header);
- }
-+ if (ret)
-+ goto err_out;
-+ sanitize_restored_xstate(state, NULL, xfeatures,
-+ fx_only);
-+
-+ if (unlikely(init_bv))
-+ copy_kernel_to_xregs(&init_fpstate.xsave, init_bv);
-+ ret = copy_kernel_to_xregs_err(&state->xsave, xfeatures);
-+
- } else if (use_fxsr()) {
-- ret = copy_user_to_fxregs(buf_fx);
-- } else
-- ret = copy_user_to_fregs(buf_fx);
-+ ret = __copy_from_user(&state->fxsave, buf_fx, state_size);
-+ if (ret)
-+ goto err_out;
-+
-+ if (use_xsave()) {
-+ u64 init_bv = xfeatures_mask & ~XFEATURE_MASK_FPSSE;
-+ copy_kernel_to_xregs(&init_fpstate.xsave, init_bv);
-+ }
-+ state->fxsave.mxcsr &= mxcsr_feature_mask;
-+
-+ ret = copy_kernel_to_fxregs_err(&state->fxsave);
-+ } else {
-+ ret = __copy_from_user(&state->fsave, buf_fx, state_size);
-+ if (ret)
-+ goto err_out;
-+ ret = copy_kernel_to_fregs_err(&state->fsave);
-+ }
-
-+err_out:
-+ kfree(tmp);
- if (ret) {
- fpu__clear(fpu);
- return -1;