[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 5/6] x86/AMD: Fix handling of FPU pointer on Zen hardware



AMD hardware before Zen doesn't safe/restore the FPU error pointers
unless an unmasked FPU exception is pending.  Zen processors have a
feature bit indicating that this (mis)behaviour no longer exists.

Express the common logic in terms of cpu_bug_fpu_err_ptr as Hygon
processors (being Zen derivatives) won't inherit this behaviour.

While at it, fix a performance issue with the workaround, which I should
have noticed by now.  Looking at the FPU state slows the context switch
path down, as it is a moderately complicated unpredictable condition
which will evaluate to true for all 64bit OSes and most 32bit ones.

Leave the sole condition being the easily-predictable
cpu_bug_fpu_err_ptr as the asm sequence is needed in ~100% of cases
these days on affected hardware.

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Wei Liu <wei.liu2@xxxxxxxxxx>
CC: Roger Pau Monné <roger.pau@xxxxxxxxxx>
CC: Pu Wen <puwen@xxxxxxxx>
---
 xen/arch/x86/cpu/amd.c                      | 7 +++++++
 xen/arch/x86/xstate.c                       | 6 ++----
 xen/include/asm-x86/cpufeature.h            | 1 +
 xen/include/asm-x86/cpufeatures.h           | 1 +
 xen/include/public/arch-x86/cpufeatureset.h | 1 +
 5 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index 21c82bb..8c4521c 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -713,6 +713,13 @@ static void init_amd(struct cpuinfo_x86 *c)
        setup_force_cpu_cap(X86_BUG_NULL_SEG);
 
        /*
+        * Older AMD CPUs don't save/load FOP/FIP/FDP unless an FPU exception
+        * is pending.
+        */
+       if ( !cpu_has(c, X86_FEATURE_XSAVEERRPTR) )
+               setup_force_cpu_cap(X86_BUG_FPU_PTR_LEAK);
+
+       /*
         * Attempt to set lfence to be Dispatch Serialising.  This MSR almost
         * certainly isn't virtualised (and Xen at least will leak the real
         * value in but silently discard writes), as well as being per-core
diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c
index 15edd5d..7ca5684 100644
--- a/xen/arch/x86/xstate.c
+++ b/xen/arch/x86/xstate.c
@@ -369,15 +369,13 @@ void xrstor(struct vcpu *v, uint64_t mask)
     unsigned int faults, prev_faults;
 
     /*
-     * AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
+     * Some CPUs don't save/restore FDP/FIP/FOP unless an exception
      * is pending. Clear the x87 state here by setting it to fixed
      * values. The hypervisor data segment can be sometimes 0 and
      * sometimes new user value. Both should be ok. Use the FPU saved
      * data block as a safe address because it should be in L1.
      */
-    if ( (mask & ptr->xsave_hdr.xstate_bv & X86_XCR0_FP) &&
-         !(ptr->fpu_sse.fsw & ~ptr->fpu_sse.fcw & 0x003f) &&
-         boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
+    if ( cpu_bug_fpu_err_ptr )
         asm volatile ( "fnclex\n\t"        /* clear exceptions */
                        "ffree %%st(7)\n\t" /* clear stack tag */
                        "fildl %0"          /* load to clear state */
diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h
index de45b6c..0f3bb5a 100644
--- a/xen/include/asm-x86/cpufeature.h
+++ b/xen/include/asm-x86/cpufeature.h
@@ -125,6 +125,7 @@
 /* Bugs. */
 #define cpu_bug_amd_erratum_121 boot_cpu_has(X86_BUG_AMD_ERRATUM_121)
 #define cpu_bug_null_seg        boot_cpu_has(X86_BUG_NULL_SEG)
+#define cpu_bug_fpu_err_ptr     boot_cpu_has(X86_BUG_FPU_PTR_LEAK)
 
 enum _cache_type {
     CACHE_TYPE_NULL = 0,
diff --git a/xen/include/asm-x86/cpufeatures.h 
b/xen/include/asm-x86/cpufeatures.h
index 8a73a09..e7d4171 100644
--- a/xen/include/asm-x86/cpufeatures.h
+++ b/xen/include/asm-x86/cpufeatures.h
@@ -40,6 +40,7 @@ XEN_CPUFEATURE(XEN_LBR,           X86_SYNTH(22)) /* Xen uses 
MSR_DEBUGCTL.LBR */
 
 #define X86_BUG_AMD_ERRATUM_121   X86_BUG( 0) /* Hang on fetch across 
non-canonical boundary. */
 #define X86_BUG_NULL_SEG          X86_BUG( 1) /* NULL-ing a selector preserves 
the base and limit. */
+#define X86_BUG_FPU_PTR_LEAK      X86_BUG( 2) /* (F)XRSTOR doesn't load 
FOP/FIP/FDP. */
 
 /* Total number of capability words, inc synth and bug words. */
 #define NCAPINTS (FSCAPINTS + X86_NR_SYNTH + X86_NR_BUG) /* N 32-bit words 
worth of info */
diff --git a/xen/include/public/arch-x86/cpufeatureset.h 
b/xen/include/public/arch-x86/cpufeatureset.h
index fbc68fa..6beaab9 100644
--- a/xen/include/public/arch-x86/cpufeatureset.h
+++ b/xen/include/public/arch-x86/cpufeatureset.h
@@ -237,6 +237,7 @@ XEN_CPUFEATURE(EFRO,          7*32+10) /*   APERF/MPERF 
Read Only interface */
 
 /* AMD-defined CPU features, CPUID level 0x80000008.ebx, word 8 */
 XEN_CPUFEATURE(CLZERO,        8*32+ 0) /*A  CLZERO instruction */
+XEN_CPUFEATURE(XSAVEERRPTR,   8*32+ 2) /*A  (F)XSAVE Error pointers always 
updated. */
 XEN_CPUFEATURE(IBPB,          8*32+12) /*A  IBPB support only (no IBRS, used 
by AMD) */
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0.edx, word 9 */
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.