aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2011-12-16 15:45:40 +0100
committerJan Beulich <jbeulich@suse.com>2011-12-16 15:45:40 +0100
commita1b22e625dee30b9ca572e5b7fe66f1aebd44d7d (patch)
tree3284bfa225b3b7e5716d3aede98720684e1f46f0
parent6e359548a1c9afdaee765ccd8b9635424acdb1bd (diff)
downloadxen-a1b22e625dee30b9ca572e5b7fe66f1aebd44d7d.tar.gz
xen-a1b22e625dee30b9ca572e5b7fe66f1aebd44d7d.tar.bz2
xen-a1b22e625dee30b9ca572e5b7fe66f1aebd44d7d.zip
x86/emulator: workaround for AMD erratum 573
The only cases where we might end up emulating fsincos (as any other x87 operations without memory operands) are - when a HVM guest is in real mode (not applicable on AMD) - between two half page table updates in PAE mode (unlikely, and not doing the emulation here does affect only performance, not correctness) - when a guest maliciously (or erroneously) modifies an (MMIO or page table update) instruction under emulation (unspecified behavior) Hence, in order to avoid the erratum to cause harm to the entire host, don't emulate fsincos on the affected AMD CPU families. Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Keir Fraser <keir@xen.org>
-rw-r--r--tools/tests/x86_emulator/x86_emulate.c2
-rw-r--r--xen/arch/x86/x86_emulate.c6
-rw-r--r--xen/arch/x86/x86_emulate/x86_emulate.c4
-rw-r--r--xen/include/asm-x86/amd.h6
4 files changed, 17 insertions, 1 deletions
diff --git a/tools/tests/x86_emulator/x86_emulate.c b/tools/tests/x86_emulator/x86_emulate.c
index 9e1b124410..0306f8ebc6 100644
--- a/tools/tests/x86_emulator/x86_emulate.c
+++ b/tools/tests/x86_emulator/x86_emulate.c
@@ -9,5 +9,7 @@ typedef bool bool_t;
#define BUG() abort()
+#define cpu_has_amd_erratum(nr) 0
+
#include "x86_emulate/x86_emulate.h"
#include "x86_emulate/x86_emulate.c"
diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c
index fbf740efee..91f524fc87 100644
--- a/xen/arch/x86/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate.c
@@ -10,8 +10,14 @@
*/
#include <asm/x86_emulate.h>
+#include <asm/processor.h> /* current_cpu_info */
+#include <asm/amd.h> /* cpu_has_amd_erratum() */
/* Avoid namespace pollution. */
#undef cmpxchg
+#undef cpuid
+
+#define cpu_has_amd_erratum(nr) \
+ cpu_has_amd_erratum(&current_cpu_data, AMD_ERRATUM_##nr)
#include "x86_emulate/x86_emulate.c"
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c
index d6eeb6562a..c7489276a8 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -2761,6 +2761,9 @@ x86_emulate(
case 0xd9: /* FPU 0xd9 */
switch ( modrm )
{
+ case 0xfb: /* fsincos */
+ fail_if(cpu_has_amd_erratum(573));
+ /* fall through */
case 0xc0 ... 0xc7: /* fld %stN */
case 0xc8 ... 0xcf: /* fxch %stN */
case 0xd0: /* fnop */
@@ -2786,7 +2789,6 @@ x86_emulate(
case 0xf8: /* fprem */
case 0xf9: /* fyl2xp1 */
case 0xfa: /* fsqrt */
- case 0xfb: /* fsincos */
case 0xfc: /* frndint */
case 0xfd: /* fscale */
case 0xfe: /* fsin */
diff --git a/xen/include/asm-x86/amd.h b/xen/include/asm-x86/amd.h
index d7fb1a5b53..2ff818872f 100644
--- a/xen/include/asm-x86/amd.h
+++ b/xen/include/asm-x86/amd.h
@@ -134,6 +134,12 @@
AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf), \
AMD_MODEL_RANGE(0x12, 0x0, 0x0, 0x1, 0x0))
+#define AMD_ERRATUM_573 \
+ AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x0f, 0x0, 0x0, 0xff, 0xf), \
+ AMD_MODEL_RANGE(0x10, 0x0, 0x0, 0xff, 0xf), \
+ AMD_MODEL_RANGE(0x11, 0x0, 0x0, 0xff, 0xf), \
+ AMD_MODEL_RANGE(0x12, 0x0, 0x0, 0xff, 0xf))
+
struct cpuinfo_x86;
int cpu_has_amd_erratum(const struct cpuinfo_x86 *, int, ...);