Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b7106fa0 authored by Borislav Petkov's avatar Borislav Petkov Committed by Ingo Molnar
Browse files

x86/fpu: Get rid of xstate_fault()



Add macros for the alternative XSAVE*/XRSTOR* operations which
contain the fault handling and use them. Kill xstate_fault().

Also, copy_xregs_to_kernel() didn't have the extended state as
memory reference in the asm.

Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.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: Quentin Casasnovas <quentin.casasnovas@oracle.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1447932326-4371-3-git-send-email-bp@alien8.de


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent b74a0cf1
Loading
Loading
Loading
Loading
+52 −53
Original line number Original line Diff line number Diff line
@@ -224,19 +224,6 @@ static inline void copy_fxregs_to_kernel(struct fpu *fpu)
#define XRSTOR		".byte " REX_PREFIX "0x0f,0xae,0x2f"
#define XRSTOR		".byte " REX_PREFIX "0x0f,0xae,0x2f"
#define XRSTORS		".byte " REX_PREFIX "0x0f,0xc7,0x1f"
#define XRSTORS		".byte " REX_PREFIX "0x0f,0xc7,0x1f"


/* xstate instruction fault handler: */
#define xstate_fault(__err)		\
					\
	".section .fixup,\"ax\"\n"	\
					\
	"3:  movl $-2,%[_err]\n"	\
	"    jmp  2b\n"			\
					\
	".previous\n"			\
					\
	_ASM_EXTABLE(1b, 3b)		\
	: [_err] "=r" (__err)

#define XSTATE_OP(op, st, lmask, hmask, err)				\
#define XSTATE_OP(op, st, lmask, hmask, err)				\
	asm volatile("1:" op "\n\t"					\
	asm volatile("1:" op "\n\t"					\
		     "xor %[err], %[err]\n"				\
		     "xor %[err], %[err]\n"				\
@@ -250,6 +237,54 @@ static inline void copy_fxregs_to_kernel(struct fpu *fpu)
		     : "D" (st), "m" (*st), "a" (lmask), "d" (hmask)	\
		     : "D" (st), "m" (*st), "a" (lmask), "d" (hmask)	\
		     : "memory")
		     : "memory")


/*
 * If XSAVES is enabled, it replaces XSAVEOPT because it supports a compact
 * format and supervisor states in addition to modified optimization in
 * XSAVEOPT.
 *
 * Otherwise, if XSAVEOPT is enabled, XSAVEOPT replaces XSAVE because XSAVEOPT
 * supports modified optimization which is not supported by XSAVE.
 *
 * We use XSAVE as a fallback.
 *
 * The 661 label is defined in the ALTERNATIVE* macros as the address of the
 * original instruction which gets replaced. We need to use it here as the
 * address of the instruction where we might get an exception at.
 */
#define XSTATE_XSAVE(st, lmask, hmask, err)				\
	asm volatile(ALTERNATIVE_2(XSAVE,				\
				   XSAVEOPT, X86_FEATURE_XSAVEOPT,	\
				   XSAVES,   X86_FEATURE_XSAVES)	\
		     "\n"						\
		     "xor %[err], %[err]\n"				\
		     "3:\n"						\
		     ".pushsection .fixup,\"ax\"\n"			\
		     "4: movl $-2, %[err]\n"				\
		     "jmp 3b\n"						\
		     ".popsection\n"					\
		     _ASM_EXTABLE(661b, 4b)				\
		     : [err] "=r" (err)					\
		     : "D" (st), "m" (*st), "a" (lmask), "d" (hmask)	\
		     : "memory")

/*
 * Use XRSTORS to restore context if it is enabled. XRSTORS supports compact
 * XSAVE area format.
 */
#define XSTATE_XRESTORE(st, lmask, hmask, err)				\
	asm volatile(ALTERNATIVE(XRSTOR,				\
				 XRSTORS, X86_FEATURE_XSAVES)		\
		     "\n"						\
		     "xor %[err], %[err]\n"				\
		     "3:\n"						\
		     ".pushsection .fixup,\"ax\"\n"			\
		     "4: movl $-2, %[err]\n"				\
		     "jmp 3b\n"						\
		     ".popsection\n"					\
		     _ASM_EXTABLE(661b, 4b)				\
		     : [err] "=r" (err)					\
		     : "D" (st), "m" (*st), "a" (lmask), "d" (hmask)	\
		     : "memory")


/*
/*
 * This function is called only during boot time when x86 caps are not set
 * This function is called only during boot time when x86 caps are not set
@@ -303,33 +338,11 @@ static inline void copy_xregs_to_kernel(struct xregs_state *xstate)
	u64 mask = -1;
	u64 mask = -1;
	u32 lmask = mask;
	u32 lmask = mask;
	u32 hmask = mask >> 32;
	u32 hmask = mask >> 32;
	int err = 0;
	int err;


	WARN_ON(!alternatives_patched);
	WARN_ON(!alternatives_patched);


	/*
	XSTATE_XSAVE(xstate, lmask, hmask, err);
	 * If xsaves is enabled, xsaves replaces xsaveopt because
	 * it supports compact format and supervisor states in addition to
	 * modified optimization in xsaveopt.
	 *
	 * Otherwise, if xsaveopt is enabled, xsaveopt replaces xsave
	 * because xsaveopt supports modified optimization which is not
	 * supported by xsave.
	 *
	 * If none of xsaves and xsaveopt is enabled, use xsave.
	 */
	alternative_input_2(
		"1:"XSAVE,
		XSAVEOPT,
		X86_FEATURE_XSAVEOPT,
		XSAVES,
		X86_FEATURE_XSAVES,
		[xstate] "D" (xstate), "a" (lmask), "d" (hmask) :
		"memory");
	asm volatile("2:\n\t"
		     xstate_fault(err)
		     : "0" (err)
		     : "memory");


	/* We should never fault when copying to a kernel buffer: */
	/* We should never fault when copying to a kernel buffer: */
	WARN_ON_FPU(err);
	WARN_ON_FPU(err);
@@ -342,23 +355,9 @@ static inline void copy_kernel_to_xregs(struct xregs_state *xstate, u64 mask)
{
{
	u32 lmask = mask;
	u32 lmask = mask;
	u32 hmask = mask >> 32;
	u32 hmask = mask >> 32;
	int err = 0;
	int err;


	/*
	XSTATE_XRESTORE(xstate, lmask, hmask, err);
	 * Use xrstors to restore context if it is enabled. xrstors supports
	 * compacted format of xsave area which is not supported by xrstor.
	 */
	alternative_input(
		"1: " XRSTOR,
		XRSTORS,
		X86_FEATURE_XSAVES,
		"D" (xstate), "m" (*xstate), "a" (lmask), "d" (hmask)
		: "memory");

	asm volatile("2:\n"
		     xstate_fault(err)
		     : "0" (err)
		     : "memory");


	/* We should never fault when copying from a kernel buffer: */
	/* We should never fault when copying from a kernel buffer: */
	WARN_ON_FPU(err);
	WARN_ON_FPU(err);