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

[Xen-changelog] [xen master] x86/cpuid: Introduce recalculate_xstate()



commit af109224109abb9648ea9720505daeeb06f76e4b
Author:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Wed Jan 4 15:00:23 2017 +0000
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Wed Jan 18 14:32:30 2017 +0000

    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.
    
    Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
---
 xen/arch/x86/cpuid.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-x86/cpuid.h | 17 +++++----
 2 files changed, 97 insertions(+), 6 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index bcdac03..619ead8 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -80,6 +80,88 @@ 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 of information preserved in the common
+     * case.  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]);
+    }
+
+    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;
+    }
+}
+
 static void __init calculate_raw_policy(void)
 {
     struct cpuid_policy *p = &raw_policy;
@@ -149,6 +231,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)
@@ -168,6 +251,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)
@@ -221,6 +305,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)
@@ -328,6 +413,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 24ad3e0..e5140ca 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 _res_d;
+        } comp[CPUID_GUEST_NR_XSTATE];
     } xstate;
 
     /* Extended leaves: 0x800000xx */
--
generated by git-patchbot for /home/xen/git/xen.git#master

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

 


Rackspace

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