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

[xen staging] x86: Remove fpu_initialised/fpu_dirty



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

    x86: Remove fpu_initialised/fpu_dirty
    
    With lazy FPU removed, fpu_initialised and fpu_dirty are always set to
    true in vcpu_restore_fpu() so remove them and adjust the code
    accordingly.
    
    There is a small user-visible change here. After this commit, calling
    XEN_DOMCTL_getvcpucontext immediately after vCPU creation would show the
    FPU as initialized (with a clean state) whereas before it would show as
    uninitialized.
    
    Signed-off-by: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
    Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
 xen/arch/x86/domctl.c              |  5 ++---
 xen/arch/x86/hvm/emulate.c         |  6 +-----
 xen/arch/x86/hvm/hvm.c             | 15 ++++++---------
 xen/arch/x86/hvm/vlapic.c          |  3 ---
 xen/arch/x86/i387.c                | 31 ++-----------------------------
 xen/arch/x86/include/asm/hvm/hvm.h |  1 -
 xen/arch/x86/include/asm/xstate.h  | 11 -----------
 xen/arch/x86/xstate.c              | 21 +++++----------------
 xen/common/domain.c                |  2 --
 xen/include/xen/sched.h            |  4 ----
 10 files changed, 16 insertions(+), 83 deletions(-)

diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index 942f41c584..8d474b7623 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -1406,11 +1406,10 @@ void arch_get_info_guest(struct vcpu *v, 
vcpu_guest_context_u c)
     VCPU_UNMAP_XSAVE_AREA(v, xsave_area);
 
     if ( is_pv_domain(d) )
-        c(flags = v->arch.pv.vgc_flags & ~(VGCF_i387_valid|VGCF_in_kernel));
+        c(flags = v->arch.pv.vgc_flags & ~VGCF_in_kernel);
     else
         c(flags = 0);
-    if ( v->fpu_initialised )
-        c(flags |= VGCF_i387_valid);
+    c(flags |= VGCF_i387_valid);
     if ( !(v->pause_flags & VPF_down) )
         c(flags |= VGCF_online);
     if ( !compat )
diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index 2daea084f1..48c7320360 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -2517,9 +2517,7 @@ static int cf_check hvmemul_get_fpu(
 {
     struct vcpu *curr = current;
 
-    if ( !curr->fpu_dirtied )
-        alternative_vcall(hvm_funcs.fpu_dirty_intercept);
-    else if ( type == X86EMUL_FPU_fpu )
+    if ( type == X86EMUL_FPU_fpu )
     {
         /* Has a fastpath for `current`, so there's no actual map */
         const struct xsave_struct *xsave_area = VCPU_MAP_XSAVE_AREA(curr);
@@ -2537,8 +2535,6 @@ static int cf_check hvmemul_get_fpu(
          * masking of all exceptions by FNSTENV.)
          */
         save_fpu_enable();
-        curr->fpu_initialised = true;
-        curr->fpu_dirtied = true;
         if ( (fpu_ctxt->fcw & 0x3f) != 0x3f )
         {
             uint16_t fcw;
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index b62b058861..3edc2491e2 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -866,6 +866,7 @@ static int cf_check hvm_save_cpu_ctxt(struct vcpu *v, 
hvm_domain_context_t *h)
         .dr7 = v->arch.dr7,
         .msr_efer = v->arch.hvm.guest_efer,
     };
+    const struct xsave_struct *xsave_area;
 
     /*
      * We don't need to save state for a vcpu that is down; the restore
@@ -933,15 +934,11 @@ static int cf_check hvm_save_cpu_ctxt(struct vcpu *v, 
hvm_domain_context_t *h)
     ctxt.ldtr_base = seg.base;
     ctxt.ldtr_arbytes = seg.attr;
 
-    if ( v->fpu_initialised )
-    {
-        const struct xsave_struct *xsave_area = VCPU_MAP_XSAVE_AREA(v);
-
-        BUILD_BUG_ON(sizeof(ctxt.fpu_regs) != sizeof(xsave_area->fpu_sse));
-        memcpy(ctxt.fpu_regs, &xsave_area->fpu_sse, sizeof(ctxt.fpu_regs));
-        VCPU_UNMAP_XSAVE_AREA(v, xsave_area);
-        ctxt.flags = XEN_X86_FPU_INITIALISED;
-    }
+    xsave_area = VCPU_MAP_XSAVE_AREA(v);
+    BUILD_BUG_ON(sizeof(ctxt.fpu_regs) != sizeof(xsave_area->fpu_sse));
+    memcpy(ctxt.fpu_regs, &xsave_area->fpu_sse, sizeof(ctxt.fpu_regs));
+    VCPU_UNMAP_XSAVE_AREA(v, xsave_area);
+    ctxt.flags = XEN_X86_FPU_INITIALISED;
 
     return hvm_save_entry(CPU, v->vcpu_id, h, &ctxt);
 }
diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c
index 79697487ba..885f5d304b 100644
--- a/xen/arch/x86/hvm/vlapic.c
+++ b/xen/arch/x86/hvm/vlapic.c
@@ -276,7 +276,6 @@ static void vlapic_init_sipi_one(struct vcpu *target, 
uint32_t icr)
     switch ( icr & APIC_DM_MASK )
     {
     case APIC_DM_INIT: {
-        bool fpu_initialised;
         int rc;
 
         /* No work on INIT de-assert for P4-type APIC. */
@@ -289,10 +288,8 @@ static void vlapic_init_sipi_one(struct vcpu *target, 
uint32_t icr)
         hvm_vcpu_down(target);
         domain_lock(target->domain);
         /* Reset necessary VCPU state. This does not include FPU state. */
-        fpu_initialised = target->fpu_initialised;
         rc = vcpu_reset(target);
         ASSERT(!rc);
-        target->fpu_initialised = fpu_initialised;
         vlapic_do_init(vcpu_vlapic(target));
         domain_unlock(target->domain);
         break;
diff --git a/xen/arch/x86/i387.c b/xen/arch/x86/i387.c
index 88018397b1..5e893a2aab 100644
--- a/xen/arch/x86/i387.c
+++ b/xen/arch/x86/i387.c
@@ -110,22 +110,7 @@ static inline void fpu_fxrstor(struct vcpu *v)
 
 static inline uint64_t vcpu_xsave_mask(const struct vcpu *v)
 {
-    if ( v->fpu_dirtied )
-        return v->arch.nonlazy_xstate_used ? XSTATE_ALL : XSTATE_LAZY;
-
-    ASSERT(v->arch.nonlazy_xstate_used);
-
-    /*
-     * The offsets of components which live in the extended region of
-     * compact xsave area are not fixed. Xsave area may be overwritten
-     * when a xsave with v->fpu_dirtied set is followed by one with
-     * v->fpu_dirtied clear.
-     * In such case, if hypervisor uses compact xsave area and guest
-     * has ever used lazy states (checking xcr0_accum excluding
-     * XSTATE_FP_SSE), vcpu_xsave_mask will return XSTATE_ALL. Otherwise
-     * return XSTATE_NONLAZY.
-     */
-    return xstate_all(v) ? XSTATE_ALL : XSTATE_NONLAZY;
+    return v->arch.nonlazy_xstate_used ? XSTATE_ALL : XSTATE_LAZY;
 }
 
 /* Save x87 extended state */
@@ -201,19 +186,11 @@ void vcpu_restore_fpu(struct vcpu *v)
     /* Avoid recursion */
     clts();
 
-    /*
-     * When saving full state even with !v->fpu_dirtied (see vcpu_xsave_mask()
-     * above) we also need to restore full state, to prevent subsequently
-     * saving state belonging to another vCPU.
-     */
     if ( cpu_has_xsave )
         fpu_xrstor(v, XSTATE_ALL);
     else
         fpu_fxrstor(v);
 
-    v->fpu_initialised = 1;
-    v->fpu_dirtied = 1;
-
     /* Xen doesn't need TS set, but the guest might. */
     if ( is_pv_vcpu(v) && (v->arch.pv.ctrlreg[0] & X86_CR0_TS) )
         stts();
@@ -225,7 +202,7 @@ void vcpu_restore_fpu(struct vcpu *v)
  */
 static bool _vcpu_save_fpu(struct vcpu *v)
 {
-    if ( !v->fpu_dirtied && !v->arch.nonlazy_xstate_used )
+    if ( !v->arch.nonlazy_xstate_used )
         return false;
 
     ASSERT(!is_idle_vcpu(v));
@@ -238,8 +215,6 @@ static bool _vcpu_save_fpu(struct vcpu *v)
     else
         fpu_fxsave(v);
 
-    v->fpu_dirtied = 0;
-
     return true;
 }
 
@@ -265,7 +240,6 @@ void vcpu_reset_fpu(struct vcpu *v)
 {
     struct xsave_struct *xsave_area = VCPU_MAP_XSAVE_AREA(v);
 
-    v->fpu_initialised = false;
     *xsave_area = (struct xsave_struct) {
         .xsave_hdr.xstate_bv = X86_XCR0_X87,
     };
@@ -282,7 +256,6 @@ void vcpu_setup_fpu(struct vcpu *v, const void *data)
 {
     struct xsave_struct *xsave_area = VCPU_MAP_XSAVE_AREA(v);
 
-    v->fpu_initialised = true;
     *xsave_area = (struct xsave_struct) {
         .fpu_sse = *(const fpusse_t*)data,
         .xsave_hdr.xstate_bv = XSTATE_FP_SSE,
diff --git a/xen/arch/x86/include/asm/hvm/hvm.h 
b/xen/arch/x86/include/asm/hvm/hvm.h
index a9425c8cff..846b91ebef 100644
--- a/xen/arch/x86/include/asm/hvm/hvm.h
+++ b/xen/arch/x86/include/asm/hvm/hvm.h
@@ -184,7 +184,6 @@ struct hvm_function_table {
 
     /* Instruction intercepts: non-void return values are X86EMUL codes. */
     void (*wbinvd_intercept)(void);
-    void (*fpu_dirty_intercept)(void);
     int (*msr_read_intercept)(unsigned int msr, uint64_t *msr_content);
     int (*msr_write_intercept)(unsigned int msr, uint64_t msr_content);
     void (*handle_cd)(struct vcpu *v, unsigned long value);
diff --git a/xen/arch/x86/include/asm/xstate.h 
b/xen/arch/x86/include/asm/xstate.h
index e3b9745543..ca38c43ec1 100644
--- a/xen/arch/x86/include/asm/xstate.h
+++ b/xen/arch/x86/include/asm/xstate.h
@@ -132,17 +132,6 @@ xsave_area_compressed(const struct xsave_struct 
*xsave_area)
     return xsave_area->xsave_hdr.xcomp_bv & XSTATE_COMPACTION_ENABLED;
 }
 
-static inline bool xstate_all(const struct vcpu *v)
-{
-    /*
-     * XSTATE_FP_SSE may be excluded, because the offsets of XSTATE_FP_SSE
-     * (in the legacy region of xsave area) are fixed, so saving
-     * XSTATE_FP_SSE will not cause overwriting problem with XSAVES/XSAVEC.
-     */
-    return xsave_area_compressed(v->arch.xsave_area) &&
-           (v->arch.xcr0_accum & XSTATE_LAZY & ~XSTATE_FP_SSE);
-}
-
 /*
  * Fetch a pointer to a vCPU's XSAVE area
  *
diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c
index defe9b3f0c..c42cdc9462 100644
--- a/xen/arch/x86/xstate.c
+++ b/xen/arch/x86/xstate.c
@@ -1005,28 +1005,17 @@ int handle_xsetbv(u32 index, u64 new_bv)
     if ( new_bv & XSTATE_NONLAZY )
         curr->arch.nonlazy_xstate_used = 1;
 
-    mask &= curr->fpu_dirtied ? ~XSTATE_FP_SSE : XSTATE_NONLAZY;
+    mask &= ~XSTATE_FP_SSE;
     if ( mask )
     {
         unsigned long cr0 = read_cr0();
+        /* Has a fastpath for `current`, so there's no actual map */
+        struct xsave_struct *xsave_area = VCPU_MAP_XSAVE_AREA(curr);
 
         clts();
-        if ( curr->fpu_dirtied )
-        {
-            /* Has a fastpath for `current`, so there's no actual map */
-            struct xsave_struct *xsave_area = VCPU_MAP_XSAVE_AREA(curr);
 
-            asm ( "stmxcsr %0" : "=m" (xsave_area->fpu_sse.mxcsr) );
-            VCPU_UNMAP_XSAVE_AREA(curr, xsave_area);
-        }
-        else if ( xstate_all(curr) )
-        {
-            /* See the comment in i387.c:vcpu_restore_fpu_eager(). */
-            mask |= XSTATE_LAZY;
-            curr->fpu_initialised = 1;
-            curr->fpu_dirtied = 1;
-            cr0 &= ~X86_CR0_TS;
-        }
+        asm ( "stmxcsr %0" : "=m" (xsave_area->fpu_sse.mxcsr) );
+        VCPU_UNMAP_XSAVE_AREA(curr, xsave_area);
         xrstor(curr, mask);
         if ( cr0 & X86_CR0_TS )
             write_cr0(cr0);
diff --git a/xen/common/domain.c b/xen/common/domain.c
index ab910fcf93..30cfea3045 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -1824,8 +1824,6 @@ int vcpu_reset(struct vcpu *v)
     clear_bit(v->vcpu_id, d->poll_mask);
     v->poll_evtchn = 0;
 
-    v->fpu_initialised = 0;
-    v->fpu_dirtied     = 0;
     v->is_initialised  = 0;
     if ( v->affinity_broken & VCPU_AFFINITY_OVERRIDE )
         vcpu_temporary_affinity(v, NR_CPUS, VCPU_AFFINITY_OVERRIDE);
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 40a35fc15c..212c7d765c 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -212,10 +212,6 @@ struct vcpu
     struct guest_area runstate_guest_area;
     unsigned int     new_state;
 
-    /* Has the FPU been initialised? */
-    bool             fpu_initialised;
-    /* Has the FPU been used since it was last saved? */
-    bool             fpu_dirtied;
     /* Initialization completed for this VCPU? */
     bool             is_initialised;
     /* Currently running on a CPU? */
--
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®.