 0570f90d28
			
		
	
	
		0570f90d28
		
	
	
	
	
		
			
			This allows us to fix the ZFS SIMD patch for 5.0 kernel way easier. Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
		
			
				
	
	
		
			104 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | |
| From: Thomas Lamprecht <t.lamprecht@proxmox.com>
 | |
| 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 <bigeasy@linutronix.de>
 | |
| 
 | |
| 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 <t.lamprecht@proxmox.com>
 | |
| ---
 | |
|  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
 |