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

[Xen-devel] [PATCH 2/6] x86/cpuid: Introduce recalculate_xstate()



All data in the xstate union, other than the Da1 feature word, is derived from
other state; either feature bits from other words, or layout information which
has already been collected by Xen's xstate driver.

Recalculate the xstate information for each policy object when the feature
bits may have changed.

The XSTATE_XSAVES_ONLY define needs extending to a 64bit value to avoid
problems when taking its converse for masking purposes.

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
---
 xen/arch/x86/cpuid.c         | 101 +++++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-x86/cpuid.h  |  17 +++++---
 xen/include/asm-x86/xstate.h |   2 +-
 3 files changed, 113 insertions(+), 7 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index 95040f9..303568d 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -80,6 +80,103 @@ static void sanitise_featureset(uint32_t *fs)
                           (fs[FEATURESET_e1d] & ~CPUID_COMMON_1D_FEATURES));
 }
 
+static void recalculate_xstate(struct cpuid_policy *p)
+{
+    uint64_t xstates = XSTATE_FP_SSE;
+    uint32_t xstate_size = XSTATE_AREA_MIN_SIZE;
+    unsigned int i, Da1 = p->xstate.Da1;
+
+    /*
+     * The Da1 leaf is the only piece if information preserved.  Everything
+     * else is derived from other feature state.
+     */
+    memset(&p->xstate, 0, sizeof(p->xstate));
+
+    if ( !p->basic.xsave )
+        return;
+
+    if ( p->basic.avx )
+    {
+        xstates |= XSTATE_YMM;
+        xstate_size = max(xstate_size,
+                          xstate_offsets[_XSTATE_YMM] +
+                          xstate_sizes[_XSTATE_YMM]);
+    }
+
+    if ( p->feat.mpx )
+    {
+        xstates |= XSTATE_BNDREGS | XSTATE_BNDCSR;
+        xstate_size = max(xstate_size,
+                          xstate_offsets[_XSTATE_BNDCSR] +
+                          xstate_sizes[_XSTATE_BNDCSR]);
+    }
+
+    if ( p->feat.avx512f )
+    {
+        xstates |= XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM;
+        xstate_size = max(xstate_size,
+                          xstate_offsets[_XSTATE_HI_ZMM] +
+                          xstate_sizes[_XSTATE_HI_ZMM]);
+    }
+
+    if ( p->feat.pku )
+    {
+        xstates |= XSTATE_PKRU;
+        xstate_size = max(xstate_size,
+                          xstate_offsets[_XSTATE_PKRU] +
+                          xstate_sizes[_XSTATE_PKRU]);
+    }
+
+    if ( p->extd.lwp )
+    {
+        xstates |= XSTATE_LWP;
+        xstate_size = max(xstate_size,
+                          xstate_offsets[_XSTATE_LWP] +
+                          xstate_sizes[_XSTATE_LWP]);
+    }
+
+    /* Sanity check we aren't advertising unknown states. */
+    ASSERT((xstates & ~XCNTXT_MASK) == 0);
+
+    p->xstate.max_size  =  xstate_size;
+    p->xstate.xcr0_low  =  xstates & ~XSTATE_XSAVES_ONLY;
+    p->xstate.xcr0_high = (xstates & ~XSTATE_XSAVES_ONLY) >> 32;
+
+    p->xstate.Da1 = Da1;
+    if ( p->xstate.xsaves )
+    {
+        p->xstate.xss_low   =  xstates & XSTATE_XSAVES_ONLY;
+        p->xstate.xss_high  = (xstates & XSTATE_XSAVES_ONLY) >> 32;
+    }
+    else
+        xstates &= ~XSTATE_XSAVES_ONLY;
+
+    for ( i = 2; i < min(63ul, ARRAY_SIZE(p->xstate.comp)); ++i )
+    {
+        uint64_t curr_xstate = 1ul << i;
+
+        if ( !(xstates & curr_xstate) )
+            continue;
+
+        p->xstate.comp[i].size   = xstate_sizes[i];
+        p->xstate.comp[i].offset = xstate_offsets[i];
+        p->xstate.comp[i].xss    = curr_xstate & XSTATE_XSAVES_ONLY;
+        p->xstate.comp[i].align  = curr_xstate & xstate_align;
+
+        /*
+         * Sanity checks:
+         * - All valid components should have non-zero size.
+         * - All xcr0 components should have non-zero offset.
+         * - All xss components should report 0 offset.
+         */
+        ASSERT(xstate_sizes[i]);
+        if ( curr_xstate & XSTATE_XSAVES_ONLY )
+            ASSERT(xstate_offsets[i] == 0);
+        else
+            ASSERT(xstate_offsets[i]);
+    }
+}
+
 static void __init calculate_raw_policy(void)
 {
     struct cpuid_policy *p = &raw_policy;
@@ -147,6 +244,7 @@ static void __init calculate_host_policy(void)
               0x80000000u + ARRAY_SIZE(p->extd.raw) - 1);
 
     cpuid_featureset_to_policy(boot_cpu_data.x86_capability, p);
+    recalculate_xstate(p);
 }
 
 static void __init calculate_pv_max_policy(void)
@@ -166,6 +264,7 @@ static void __init calculate_pv_max_policy(void)
 
     sanitise_featureset(pv_featureset);
     cpuid_featureset_to_policy(pv_featureset, p);
+    recalculate_xstate(p);
 }
 
 static void __init calculate_hvm_max_policy(void)
@@ -219,6 +318,7 @@ static void __init calculate_hvm_max_policy(void)
 
     sanitise_featureset(hvm_featureset);
     cpuid_featureset_to_policy(hvm_featureset, p);
+    recalculate_xstate(p);
 }
 
 void __init init_guest_cpuid(void)
@@ -326,6 +426,7 @@ void recalculate_cpuid_policy(struct domain *d)
                            special_features[FEATURESET_7b0]);
 
     cpuid_featureset_to_policy(fs, p);
+    recalculate_xstate(p);
 }
 
 int init_domain_cpuid_policy(struct domain *d)
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index b359b38..3f92955 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -77,18 +77,15 @@ struct cpuid_policy
      *
      * Global *_policy objects:
      *
-     * - Host accurate:
-     *   - {xcr0,xss}_{high,low}
-     *
      * - Guest accurate:
-     *   - All of the feat union
+     *   - All of the feat and xstate unions
      *   - max_{,sub}leaf
      *   - All FEATURESET_* words
      *
      * Per-domain objects:
      *
      * - Guest accurate:
-     *   - All of the feat union
+     *   - All of the feat and xstate unions
      *   - max_{,sub}leaf
      *   - All FEATURESET_* words
      *
@@ -143,9 +140,10 @@ struct cpuid_policy
     /* Xstate feature leaf: 0x0000000D[xx] */
     union {
         struct cpuid_leaf raw[CPUID_GUEST_NR_XSTATE];
+
         struct {
             /* Subleaf 0. */
-            uint32_t xcr0_low, /* b */:32, /* c */:32, xcr0_high;
+            uint32_t xcr0_low, /* b */:32, max_size, xcr0_high;
 
             /* Subleaf 1. */
             union {
@@ -154,6 +152,13 @@ struct cpuid_policy
             };
             uint32_t /* b */:32, xss_low, xss_high;
         };
+
+        /* Per-component common state.  Valid for i >= 2. */
+        struct {
+            uint32_t size, offset;
+            bool xss:1, align:1;
+            uint32_t /* c */:30, /* d */:32;
+        } comp[CPUID_GUEST_NR_XSTATE];
     } xstate;
 
     /* Extended leaves: 0x800000xx */
diff --git a/xen/include/asm-x86/xstate.h b/xen/include/asm-x86/xstate.h
index a3d37b8..c27735a 100644
--- a/xen/include/asm-x86/xstate.h
+++ b/xen/include/asm-x86/xstate.h
@@ -55,7 +55,7 @@
 #define XSTATE_NONLAZY (XSTATE_LWP | XSTATE_BNDREGS | XSTATE_BNDCSR | \
                         XSTATE_PKRU)
 #define XSTATE_LAZY    (XSTATE_ALL & ~XSTATE_NONLAZY)
-#define XSTATE_XSAVES_ONLY         0
+#define XSTATE_XSAVES_ONLY         0ULL
 #define XSTATE_COMPACTION_ENABLED  (1ULL << 63)
 
 #define XSTATE_ALIGN64 (1U << 1)
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

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