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

[Xen-devel] [PATCH 03/27] 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>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
---
 xen/arch/x86/cpuid.c        | 78 ++++++++++++++++++++++++++++++++++++++++++++-
 xen/arch/x86/setup.c        |  2 +-
 xen/include/asm-x86/cpuid.h | 75 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 152 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index 7796df6..e0751c9 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -20,6 +20,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(unsigned int leaf, struct cpuid_leaf *data)
+{
+    cpuid(leaf, &data->a, &data->b, &data->c, &data->d);
+}
+
+static void cpuid_count_leaf(unsigned int leaf, unsigned int 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 +80,55 @@ 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 )
+    {
+        /* Collected later. */
+        if ( i == 0x7 || i == 0xd )
+            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 >= 0xd )
+    {
+        uint64_t xstates;
+
+        cpuid_count_leaf(0xd, 0, &p->xstate.raw[0]);
+        cpuid_count_leaf(0xd, 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 < 63; ++i )
+        {
+            if ( xstates & (1u << i) )
+                cpuid_count_leaf(0xd, 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 +243,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();
@@ -256,6 +320,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 a6488af..50844f2 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,78 @@ 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 appropriate:
+     *   - 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. */
+            struct {
+                uint32_t max_leaf, :32, :32, :32;
+            };
+        };
+    } basic;
+
+    /* Structured feature leaf: 0x00000007[xx] */
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_FEAT];
+        struct {
+            struct {
+                uint32_t max_subleaf, :32, :32, :32;
+            };
+        };
+    } feat;
+
+    /* Xstate feature leaf: 0x0000000D[xx] */
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_XSTATE];
+        struct {
+            struct {
+                uint32_t xcr0_low, :32, :32, xcr0_high;
+            };
+            struct {
+                uint32_t :32, :32, xss_low, xss_high;
+            };
+        };
+    } xstate;
+
+    /* Extended leaves: 0x800000xx */
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_EXTD];
+        struct {
+            /* Leaf 0x80000000 - Max and vendor. */
+            struct {
+                uint32_t max_leaf, :32, :32, :32;
+            };
+        };
+    } extd;
+};
+
 void guest_cpuid(const struct vcpu *v, unsigned int leaf,
                  unsigned int subleaf, struct cpuid_leaf *res);
 
-- 
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®.