[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 2/6] libx86: Split x86_cpuid_policy_fill_native() out of calculate_raw_policy()
This will shortly be wanted by the userspace emulator harnesses as well. Consolidate the cpuid{,_count}_leaf() helpers beside the structure definition, rather than having them scattered throughout Xen. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- CC: Jan Beulich <JBeulich@xxxxxxxx> CC: Wei Liu <wei.liu2@xxxxxxxxxx> --- xen/arch/x86/cpuid.c | 105 +------------------------------------- xen/include/asm-x86/processor.h | 6 --- xen/include/xen/lib/x86/cpuid.h | 18 +++++++ xen/lib/x86/cpuid.c | 108 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 110 deletions(-) diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c index d21e745..0591a7d 100644 --- a/xen/arch/x86/cpuid.c +++ b/xen/arch/x86/cpuid.c @@ -75,11 +75,6 @@ struct cpuid_policy __read_mostly raw_cpuid_policy, __read_mostly pv_max_cpuid_policy, __read_mostly hvm_max_cpuid_policy; -static void cpuid_leaf(uint32_t leaf, struct cpuid_leaf *data) -{ - cpuid(leaf, &data->a, &data->b, &data->c, &data->d); -} - static void sanitise_featureset(uint32_t *fs) { /* for_each_set_bit() uses unsigned longs. Extend with zeroes. */ @@ -273,106 +268,8 @@ static void recalculate_misc(struct cpuid_policy *p) static void __init calculate_raw_policy(void) { struct cpuid_policy *p = &raw_cpuid_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 0x4: case 0x7: case 0xb: case 0xd: - /* Multi-invocation leaves. Deferred. */ - continue; - } - - cpuid_leaf(i, &p->basic.raw[i]); - } - - if ( p->basic.max_leaf >= 4 ) - { - for ( i = 0; i < ARRAY_SIZE(p->cache.raw); ++i ) - { - union { - struct cpuid_leaf l; - struct cpuid_cache_leaf c; - } u; - - cpuid_count_leaf(4, i, &u.l); - - if ( u.c.type == 0 ) - break; - - p->cache.subleaf[i] = u.c; - } - - /* - * The choice of CPUID_GUEST_NR_CACHE is arbitrary. It is expected - * that it will eventually need increasing for future hardware. - */ - if ( i == ARRAY_SIZE(p->cache.raw) ) - printk(XENLOG_WARNING - "CPUID: Insufficient Leaf 4 space for this hardware\n"); - } - - 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 >= 0xb ) - { - union { - struct cpuid_leaf l; - struct cpuid_topo_leaf t; - } u; - - for ( i = 0; i < ARRAY_SIZE(p->topo.raw); ++i ) - { - cpuid_count_leaf(0xb, i, &u.l); - - if ( u.t.type == 0 ) - break; - - p->topo.subleaf[i] = u.t; - } - - /* - * The choice of CPUID_GUEST_NR_TOPO is per the manual. It may need - * to grow for future hardware. - */ - if ( i == ARRAY_SIZE(p->topo.raw) && - (cpuid_count_leaf(0xb, i, &u.l), u.t.type != 0) ) - printk(XENLOG_WARNING - "CPUID: Insufficient Leaf 0xb space for this hardware\n"); - } - - 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]); + x86_cpuid_policy_fill_native(p); p->x86_vendor = boot_cpu_data.x86_vendor; } diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index 03555e1..df01ae3 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -263,12 +263,6 @@ static always_inline unsigned int cpuid_count_ebx( return ebx; } -static always_inline 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 inline unsigned long read_cr0(void) { unsigned long cr0; diff --git a/xen/include/xen/lib/x86/cpuid.h b/xen/include/xen/lib/x86/cpuid.h index 93ada23..5e4ec09 100644 --- a/xen/include/xen/lib/x86/cpuid.h +++ b/xen/include/xen/lib/x86/cpuid.h @@ -20,6 +20,21 @@ struct cpuid_leaf uint32_t a, b, c, d; }; +static inline void cpuid_leaf(uint32_t leaf, struct cpuid_leaf *l) +{ + asm volatile ( "cpuid" + : "=a" (l->a), "=b" (l->b), "=c" (l->c), "=d" (l->d) + : "a" (leaf) ); +} + +static inline void cpuid_count_leaf( + uint32_t leaf, uint32_t subleaf, struct cpuid_leaf *l) +{ + asm volatile ( "cpuid" + : "=a" (l->a), "=b" (l->b), "=c" (l->c), "=d" (l->d) + : "a" (leaf), "c" (subleaf) ); +} + #define CPUID_GUEST_NR_BASIC (0xdu + 1) #define CPUID_GUEST_NR_FEAT (0u + 1) #define CPUID_GUEST_NR_CACHE (5u + 1) @@ -228,6 +243,9 @@ static inline void cpuid_featureset_to_policy( p->feat._7d0 = fs[FEATURESET_7d0]; } +/* Fill a CPUID policy using the native CPUID instruction. */ +void x86_cpuid_policy_fill_native(struct cpuid_policy *p); + const uint32_t *x86_cpuid_lookup_deep_deps(uint32_t feature); #endif /* !XEN_LIB_X86_CPUID_H */ diff --git a/xen/lib/x86/cpuid.c b/xen/lib/x86/cpuid.c index a63e42b..ddd3821 100644 --- a/xen/lib/x86/cpuid.c +++ b/xen/lib/x86/cpuid.c @@ -2,6 +2,114 @@ #include <xen/lib/x86/cpuid.h> +void x86_cpuid_policy_fill_native(struct cpuid_policy *p) +{ + 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 0x4: case 0x7: case 0xb: case 0xd: + /* Multi-invocation leaves. Deferred. */ + continue; + } + + cpuid_leaf(i, &p->basic.raw[i]); + } + + if ( p->basic.max_leaf >= 4 ) + { + for ( i = 0; i < ARRAY_SIZE(p->cache.raw); ++i ) + { + union { + struct cpuid_leaf l; + struct cpuid_cache_leaf c; + } u; + + cpuid_count_leaf(4, i, &u.l); + + if ( u.c.type == 0 ) + break; + + p->cache.subleaf[i] = u.c; + } + + /* + * The choice of CPUID_GUEST_NR_CACHE is arbitrary. It is expected + * that it will eventually need increasing for future hardware. + */ +#ifdef __XEN__ + if ( i == ARRAY_SIZE(p->cache.raw) ) + printk(XENLOG_WARNING + "CPUID: Insufficient Leaf 4 space for this hardware\n"); +#endif + } + + 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 >= 0xb ) + { + union { + struct cpuid_leaf l; + struct cpuid_topo_leaf t; + } u; + + for ( i = 0; i < ARRAY_SIZE(p->topo.raw); ++i ) + { + cpuid_count_leaf(0xb, i, &u.l); + + if ( u.t.type == 0 ) + break; + + p->topo.subleaf[i] = u.t; + } + + /* + * The choice of CPUID_GUEST_NR_TOPO is per the manual. It may need + * to grow for future hardware. + */ +#ifdef __XEN__ + if ( i == ARRAY_SIZE(p->topo.raw) && + (cpuid_count_leaf(0xb, i, &u.l), u.t.type != 0) ) + printk(XENLOG_WARNING + "CPUID: Insufficient Leaf 0xb space for this hardware\n"); +#endif + } + + 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); + xstates |= (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(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]); +} + const uint32_t *x86_cpuid_lookup_deep_deps(uint32_t feature) { static const uint32_t deep_features[] = INIT_DEEP_FEATURES; -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |