[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 02/25] 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> v2: * Defer leaves 2 and 4 for now. More per-vcpu policy logic is required before they can work sensibly. * Fix collection of xstate leaves beyond subleaf 31. * Consistently use uint32_t. * Drop the double structs. --- xen/arch/x86/cpuid.c | 81 ++++++++++++++++++++++++++++++++++++++++++++- xen/arch/x86/setup.c | 2 +- xen/include/asm-x86/cpuid.h | 69 +++++++++++++++++++++++++++++++++++++- 3 files changed, 149 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c index f3491ed..1bfa7d7 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(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 +80,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 >= 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 & (1ul << 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 +246,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(); @@ -259,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); -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |