f617e61
Bugzilla: 1053599
f617e61
Upstream-status: 3.13 and 3.12.8
f617e61
f617e61
From 26bef1318adc1b3a530ecc807ef99346db2aa8b0 Mon Sep 17 00:00:00 2001
f617e61
From: Linus Torvalds <torvalds@linux-foundation.org>
f617e61
Date: Sat, 11 Jan 2014 19:15:52 -0800
f617e61
Subject: x86, fpu, amd: Clear exceptions in AMD FXSAVE workaround
f617e61
f617e61
From: Linus Torvalds <torvalds@linux-foundation.org>
f617e61
f617e61
commit 26bef1318adc1b3a530ecc807ef99346db2aa8b0 upstream.
f617e61
f617e61
Before we do an EMMS in the AMD FXSAVE information leak workaround we
f617e61
need to clear any pending exceptions, otherwise we trap with a
f617e61
floating-point exception inside this code.
f617e61
f617e61
Reported-by: halfdog <me@halfdog.net>
f617e61
Tested-by: Borislav Petkov <bp@suse.de>
f617e61
Link: http://lkml.kernel.org/r/CA%2B55aFxQnY_PCG_n4=0w-VG=YLXL-yr7oMxyy0WU2gCBAf3ydg@mail.gmail.com
f617e61
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
f617e61
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
f617e61
f617e61
---
f617e61
 arch/x86/include/asm/fpu-internal.h |   13 +++++++------
f617e61
 1 file changed, 7 insertions(+), 6 deletions(-)
f617e61
f617e61
--- a/arch/x86/include/asm/fpu-internal.h
f617e61
+++ b/arch/x86/include/asm/fpu-internal.h
f617e61
@@ -293,12 +293,13 @@ static inline int restore_fpu_checking(s
f617e61
 	/* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
f617e61
 	   is pending.  Clear the x87 state here by setting it to fixed
f617e61
 	   values. "m" is a random variable that should be in L1 */
f617e61
-	alternative_input(
f617e61
-		ASM_NOP8 ASM_NOP2,
f617e61
-		"emms\n\t"		/* clear stack tags */
f617e61
-		"fildl %P[addr]",	/* set F?P to defined value */
f617e61
-		X86_FEATURE_FXSAVE_LEAK,
f617e61
-		[addr] "m" (tsk->thread.fpu.has_fpu));
f617e61
+	if (unlikely(static_cpu_has(X86_FEATURE_FXSAVE_LEAK))) {
f617e61
+		asm volatile(
f617e61
+			"fnclex\n\t"
f617e61
+			"emms\n\t"
f617e61
+			"fildl %P[addr]"	/* set F?P to defined value */
f617e61
+			: : [addr] "m" (tsk->thread.fpu.has_fpu));
f617e61
+	}
f617e61
 
f617e61
 	return fpu_restore_checking(&tsk->thread.fpu);
f617e61
 }