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

[xen staging] x86: Cleanup cr0.TS flag handling



commit 1792bb9a99d27d6b42e72fa28158e32d3ad05cc0
Author:     Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
AuthorDate: Tue Mar 24 18:19:37 2026 +0000
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Mon Mar 30 15:48:13 2026 +0100

    x86: Cleanup cr0.TS flag handling
    
    Setting/clearing the cr0.TS bit is serializing and setting the cr0.TS
    bit in particular requires a write to CR0 which is implemented in
    microcode and is very slow. Therefore and with lazy FPU removed, avoid
    setting/clearing the cr0.TS flag on context switch except when
    saving/restoring the FPU for a PV guest.
    
    After this, Xen's context switch code and idle CPUs run with the TS bit
    cleared. An unfortunate side effect of this is that any mistaken use of
    XMM registers or extended state will not trap and will therefore be more
    difficult to detect.
    
    Signed-off-by: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
    Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
 xen/arch/x86/cpu/common.c       |  3 ---
 xen/arch/x86/hvm/emulate.c      | 14 ++------------
 xen/arch/x86/i387.c             | 19 +------------------
 xen/arch/x86/include/asm/i387.h |  1 -
 xen/common/efi/runtime.c        |  2 +-
 5 files changed, 4 insertions(+), 35 deletions(-)

diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c
index 5ac76897ae..057592b7c8 100644
--- a/xen/arch/x86/cpu/common.c
+++ b/xen/arch/x86/cpu/common.c
@@ -887,9 +887,6 @@ void cpu_init(void)
        /* Install correct page table. */
        write_ptbase(current);
 
-       /* Ensure FPU gets initialised for each domain. */
-       stts();
-
        /* Reset debug registers: */
        write_debugreg(0, 0);
        write_debugreg(1, 0);
diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index 48c7320360..f3aae158e9 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -2527,14 +2527,8 @@ static int cf_check hvmemul_get_fpu(
          * Latch current register state so that we can back out changes
          * if needed (namely when a memory write fails after register state
          * has already been updated).
-         * NB: We don't really need the "enable" part of the called function
-         * (->fpu_dirtied set implies CR0.TS clear), but the additional
-         * overhead should be low enough to not warrant introduction of yet
-         * another slightly different function. However, we need to undo the
-         * ->fpu_dirtied clearing the function does as well as the possible
-         * masking of all exceptions by FNSTENV.)
          */
-        save_fpu_enable();
+        vcpu_save_fpu(curr);
         if ( (fpu_ctxt->fcw & 0x3f) != 0x3f )
         {
             uint16_t fcw;
@@ -2572,12 +2566,8 @@ static void cf_check hvmemul_put_fpu(
          * Latch current register state so that we can replace FIP/FDP/FOP
          * (which have values resulting from our own invocation of the FPU
          * instruction during emulation).
-         * NB: See also the comment in hvmemul_get_fpu(); we don't need to
-         * set ->fpu_dirtied here as it is going to be cleared below, and
-         * we also don't need to reload FCW as we're forcing full state to
-         * be reloaded anyway.
          */
-        save_fpu_enable();
+        vcpu_save_fpu(curr);
 
         if ( boot_cpu_has(X86_FEATURE_FDP_EXCP_ONLY) &&
              !(fpu_ctxt->fsw & ~fpu_ctxt->fcw & 0x003f) )
diff --git a/xen/arch/x86/i387.c b/xen/arch/x86/i387.c
index 9acaaf4673..c6796bc97b 100644
--- a/xen/arch/x86/i387.c
+++ b/xen/arch/x86/i387.c
@@ -176,9 +176,6 @@ void vcpu_restore_fpu(struct vcpu *v)
 {
     ASSERT(!is_idle_vcpu(v));
 
-    /* Avoid recursion */
-    clts();
-
     if ( cpu_has_xsave )
         fpu_xrstor(v, XSTATE_ALL);
     else
@@ -193,7 +190,7 @@ void vcpu_restore_fpu(struct vcpu *v)
  * On each context switch, save the necessary FPU info of VCPU being switch 
  * out. It dispatches saving operation based on CPU's capability.
  */
-static bool _vcpu_save_fpu(struct vcpu *v)
+void vcpu_save_fpu(struct vcpu *v)
 {
     ASSERT(!is_idle_vcpu(v));
 
@@ -204,20 +201,6 @@ static bool _vcpu_save_fpu(struct vcpu *v)
         fpu_xsave(v);
     else
         fpu_fxsave(v);
-
-    return true;
-}
-
-void vcpu_save_fpu(struct vcpu *v)
-{
-    _vcpu_save_fpu(v);
-    stts();
-}
-
-void save_fpu_enable(void)
-{
-    if ( !_vcpu_save_fpu(current) )
-        clts();
 }
 
 /* Initialize FPU's context save area */
diff --git a/xen/arch/x86/include/asm/i387.h b/xen/arch/x86/include/asm/i387.h
index fe5e4419b6..0717005d31 100644
--- a/xen/arch/x86/include/asm/i387.h
+++ b/xen/arch/x86/include/asm/i387.h
@@ -29,7 +29,6 @@ struct ix87_env {
 
 void vcpu_restore_fpu(struct vcpu *v);
 void vcpu_save_fpu(struct vcpu *v);
-void save_fpu_enable(void);
 int vcpu_init_fpu(struct vcpu *v);
 void vcpu_destroy_fpu(struct vcpu *v);
 
diff --git a/xen/common/efi/runtime.c b/xen/common/efi/runtime.c
index 982e42e8f3..0f1cc765ec 100644
--- a/xen/common/efi/runtime.c
+++ b/xen/common/efi/runtime.c
@@ -94,7 +94,7 @@ struct efi_rs_state efi_rs_enter(void)
         return state;
 
     state.cr3 = read_cr3();
-    save_fpu_enable();
+    vcpu_save_fpu(current);
     asm volatile ( "fnclex; fldcw %0" :: "m" (fcw) );
     asm volatile ( "ldmxcsr %0" :: "m" (mxcsr) );
 
--
generated by git-patchbot for /home/xen/git/xen.git#staging



 


Rackspace

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