From 0570f90d28b7a84538324abcd4c94aaf2c294993 Mon Sep 17 00:00:00 2001 From: Thomas Lamprecht Date: Fri, 27 Sep 2019 11:27:56 +0200 Subject: [PATCH] backport new FPU register copy helpers This allows us to fix the ZFS SIMD patch for 5.0 kernel way easier. Signed-off-by: Thomas Lamprecht --- ...kport-copy_kernel_to_XYZ_err-helpers.patch | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 patches/kernel/0007-x86-fpu-backport-copy_kernel_to_XYZ_err-helpers.patch diff --git a/patches/kernel/0007-x86-fpu-backport-copy_kernel_to_XYZ_err-helpers.patch b/patches/kernel/0007-x86-fpu-backport-copy_kernel_to_XYZ_err-helpers.patch new file mode 100644 index 0000000..35c1140 --- /dev/null +++ b/patches/kernel/0007-x86-fpu-backport-copy_kernel_to_XYZ_err-helpers.patch @@ -0,0 +1,103 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thomas Lamprecht +Date: Wed, 3 Apr 2019 18:41:50 +0200 +Subject: [PATCH] x86/fpu: backport copy_kernel_to_XYZ_err helpers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +partial cherry-pick from upstream 5.2 "86/fpu: Restore from kernel +memory on the 64-bit path too" +commit 926b21f37b072ae4c117052de45a975c6d468fec +Author: Sebastian Andrzej Siewior + +Namely, only backport the added helpers, none of the semantic changes. + +relevant parts of the original commit message: +> In order to avoid that mess, copy the FPU state from userland, validate +> it and then load it. The copy_kernel_…() helpers are basically just +> like the old helpers except that they operate on kernel memory and the +> fault handler just sets the error value and the caller handles it. + +Link: https://lkml.kernel.org/r/20190403164156.19645-22-bigeasy@linutronix.de +(partial cherry picked from commit 926b21f37b072ae4c117052de45a975c6d468fec) +Signed-off-by: Thomas Lamprecht +--- + arch/x86/include/asm/fpu/internal.h | 43 +++++++++++++++++++++++++++++ + 1 file changed, 43 insertions(+) + +diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h +index fa2c93cb42a2..f3193ab0a2fb 100644 +--- a/arch/x86/include/asm/fpu/internal.h ++++ b/arch/x86/include/asm/fpu/internal.h +@@ -122,6 +122,21 @@ extern void fpstate_sanitize_xstate(struct fpu *fpu); + 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" \ +@@ -158,6 +173,14 @@ static inline void copy_kernel_to_fxregs(struct fxregs_state *fx) + } + } + ++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)) +@@ -175,6 +198,11 @@ static inline void copy_kernel_to_fregs(struct fregs_state *fx) + 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)); +@@ -400,6 +428,21 @@ static inline int copy_user_to_xregs(struct xregs_state __user *buf, u64 mask) + return err; + } + ++/* ++ * Restore xstate from kernel space xsave area, return an error code instead of ++ * 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 + * 'true' if the FPU state is still intact and we can