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

[Xen-changelog] [xen master] x86/cpuid: Introduce struct cpuid_policy



commit 90337812ee07fc185bd22ad9791732b47f94fc50
Author:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Wed Jan 11 11:59:02 2017 +0000
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Wed Jan 11 11:59:02 2017 +0000

    x86/cpuid: Introduce struct cpuid_policy
    
    struct cpuid_policy will eventually be a complete replacement for the 
cpuids[]
    array, with a fixed layout and named fields to allow O(1) access to specific
    information.
    
    For now, the CPUID content is capped at the 0xd and 0x8000001c leaves, which
    matches the maximum policy that the toolstack will generate for a domain.  
The
    xstate leaves extend up to LWP, and the structured features leaf is
    implemented with subleaf properties (in anticipation of subleaf 1 appearing
    soon), although only subleaf 0 is currently implemented.
    
    Introduce calculate_raw_policy() which fills raw_policy with information,
    making use of the new helpers, cpuid_{,count_}leaf().
    
    Finally, rename calculate_featuresets() to init_guest_cpuid(), as it is 
going
    to perform rather more work.
    
    Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
---
 xen/arch/x86/cpuid.c        | 82 ++++++++++++++++++++++++++++++++++++++++++++-
 xen/arch/x86/setup.c        |  2 +-
 xen/include/asm-x86/cpuid.h | 69 +++++++++++++++++++++++++++++++++++++-
 3 files changed, 150 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index 6877a52..e17cc80 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -5,6 +5,7 @@
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/vmx/vmcs.h>
 #include <asm/processor.h>
+#include <asm/xstate.h>
 
 const uint32_t known_features[] = INIT_KNOWN_FEATURES;
 const uint32_t special_features[] = INIT_SPECIAL_FEATURES;
@@ -20,6 +21,19 @@ uint32_t __read_mostly hvm_featureset[FSCAPINTS];
 
 #define EMPTY_LEAF ((struct cpuid_leaf){})
 
+static struct cpuid_policy __read_mostly raw_policy;
+
+static void cpuid_leaf(uint32_t leaf, struct cpuid_leaf *data)
+{
+    cpuid(leaf, &data->a, &data->b, &data->c, &data->d);
+}
+
+static void cpuid_count_leaf(uint32_t leaf, uint32_t subleaf,
+                             struct cpuid_leaf *data)
+{
+    cpuid_count(leaf, subleaf, &data->a, &data->b, &data->c, &data->d);
+}
+
 static void __init sanitise_featureset(uint32_t *fs)
 {
     /* for_each_set_bit() uses unsigned longs.  Extend with zeroes. */
@@ -67,6 +81,58 @@ static void __init sanitise_featureset(uint32_t *fs)
                           (fs[FEATURESET_e1d] & ~CPUID_COMMON_1D_FEATURES));
 }
 
+static void __init calculate_raw_policy(void)
+{
+    struct cpuid_policy *p = &raw_policy;
+    unsigned int i;
+
+    cpuid_leaf(0, &p->basic.raw[0]);
+    for ( i = 1; i < min(ARRAY_SIZE(p->basic.raw),
+                         p->basic.max_leaf + 1ul); ++i )
+    {
+        switch ( i )
+        {
+        case 0x2: case 0x4: case 0x7: case 0xd:
+            /* Multi-invocation leaves.  Deferred. */
+            continue;
+        }
+
+        cpuid_leaf(i, &p->basic.raw[i]);
+    }
+
+    if ( p->basic.max_leaf >= 7 )
+    {
+        cpuid_count_leaf(7, 0, &p->feat.raw[0]);
+
+        for ( i = 1; i < min(ARRAY_SIZE(p->feat.raw),
+                             p->feat.max_subleaf + 1ul); ++i )
+            cpuid_count_leaf(7, i, &p->feat.raw[i]);
+    }
+
+    if ( p->basic.max_leaf >= XSTATE_CPUID )
+    {
+        uint64_t xstates;
+
+        cpuid_count_leaf(XSTATE_CPUID, 0, &p->xstate.raw[0]);
+        cpuid_count_leaf(XSTATE_CPUID, 1, &p->xstate.raw[1]);
+
+        xstates = ((uint64_t)(p->xstate.xcr0_high | p->xstate.xss_high) << 32) 
|
+            (p->xstate.xcr0_low | p->xstate.xss_low);
+
+        for ( i = 2; i < min(63ul, ARRAY_SIZE(p->xstate.raw)); ++i )
+        {
+            if ( xstates & (1ul << i) )
+                cpuid_count_leaf(XSTATE_CPUID, i, &p->xstate.raw[i]);
+        }
+    }
+
+    /* Extended leaves. */
+    cpuid_leaf(0x80000000, &p->extd.raw[0]);
+    for ( i = 1; i < min(ARRAY_SIZE(p->extd.raw),
+                         p->extd.max_leaf + 1 - 0x80000000ul); ++i )
+        cpuid_leaf(0x80000000 + i, &p->extd.raw[i]);
+}
+
 static void __init calculate_raw_featureset(void)
 {
     unsigned int max, tmp;
@@ -181,8 +247,10 @@ static void __init calculate_hvm_featureset(void)
     sanitise_featureset(hvm_featureset);
 }
 
-void __init calculate_featuresets(void)
+void __init init_guest_cpuid(void)
 {
+    calculate_raw_policy();
+
     calculate_raw_featureset();
     calculate_pv_featureset();
     calculate_hvm_featureset();
@@ -258,6 +326,18 @@ static void __init __maybe_unused build_assertions(void)
     BUILD_BUG_ON(ARRAY_SIZE(hvm_shadow_featuremask) != FSCAPINTS);
     BUILD_BUG_ON(ARRAY_SIZE(hvm_hap_featuremask) != FSCAPINTS);
     BUILD_BUG_ON(ARRAY_SIZE(deep_features) != FSCAPINTS);
+
+    /* Find some more clever allocation scheme if this trips. */
+    BUILD_BUG_ON(sizeof(struct cpuid_policy) > PAGE_SIZE);
+
+    BUILD_BUG_ON(sizeof(raw_policy.basic) !=
+                 sizeof(raw_policy.basic.raw));
+    BUILD_BUG_ON(sizeof(raw_policy.feat) !=
+                 sizeof(raw_policy.feat.raw));
+    BUILD_BUG_ON(sizeof(raw_policy.xstate) !=
+                 sizeof(raw_policy.xstate.raw));
+    BUILD_BUG_ON(sizeof(raw_policy.extd) !=
+                 sizeof(raw_policy.extd.raw));
 }
 
 /*
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index d473ac8..94db514 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1590,7 +1590,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
                "Multiple initrd candidates, picking module #%u\n",
                initrdidx);
 
-    calculate_featuresets();
+    init_guest_cpuid();
 
     /*
      * Temporarily clear SMAP in CR4 to allow user-accesses in 
construct_dom0().
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index 4586c7d..6176da7 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -17,6 +17,7 @@
 
 #ifndef __ASSEMBLY__
 #include <xen/types.h>
+#include <xen/kernel.h>
 #include <asm/x86_emulate.h>
 #include <public/sysctl.h>
 
@@ -28,7 +29,7 @@ extern uint32_t raw_featureset[FSCAPINTS];
 extern uint32_t pv_featureset[FSCAPINTS];
 extern uint32_t hvm_featureset[FSCAPINTS];
 
-void calculate_featuresets(void);
+void init_guest_cpuid(void);
 
 const uint32_t *lookup_deep_deps(uint32_t feature);
 
@@ -65,6 +66,72 @@ extern struct cpuidmasks cpuidmask_defaults;
 /* Whether or not cpuid faulting is available for the current domain. */
 DECLARE_PER_CPU(bool, cpuid_faulting_enabled);
 
+#define CPUID_GUEST_NR_BASIC      (0xdu + 1)
+#define CPUID_GUEST_NR_FEAT       (0u + 1)
+#define CPUID_GUEST_NR_XSTATE     (62u + 1)
+#define CPUID_GUEST_NR_EXTD_INTEL (0x8u + 1)
+#define CPUID_GUEST_NR_EXTD_AMD   (0x1cu + 1)
+#define CPUID_GUEST_NR_EXTD       MAX(CPUID_GUEST_NR_EXTD_INTEL, \
+                                      CPUID_GUEST_NR_EXTD_AMD)
+
+struct cpuid_policy
+{
+    /*
+     * WARNING: During the CPUID transition period, not all information here
+     * is accurate.  The following items are accurate, and can be relied upon.
+     *
+     * Global *_policy objects:
+     *
+     * - Host accurate:
+     *   - max_{,sub}leaf
+     *   - {xcr0,xss}_{high,low}
+     *
+     * - Guest accurate:
+     *   - Nothing
+     *
+     * Everything else should be considered inaccurate, and not necesserily 0.
+     */
+
+    /* Basic leaves: 0x000000xx */
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_BASIC];
+        struct {
+            /* Leaf 0x0 - Max and vendor. */
+            uint32_t max_leaf, /* b */:32, /* c */:32, /* d */:32;
+        };
+    } basic;
+
+    /* Structured feature leaf: 0x00000007[xx] */
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_FEAT];
+        struct {
+            /* Subleaf 0. */
+            uint32_t max_subleaf, /* b */:32, /* c */:32, /* d */:32;
+        };
+    } feat;
+
+    /* 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;
+
+            /* Subleaf 1. */
+            uint32_t /* a */:32, /* b */:32, xss_low, xss_high;
+        };
+    } xstate;
+
+    /* Extended leaves: 0x800000xx */
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_EXTD];
+        struct {
+            /* Leaf 0x80000000 - Max and vendor. */
+            uint32_t max_leaf, /* b */:32, /* c */:32, /* d */:32;
+        };
+    } extd;
+};
+
 void guest_cpuid(const struct vcpu *v, uint32_t leaf,
                  uint32_t subleaf, struct cpuid_leaf *res);
 
--
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®.