[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 07/27] x86/cpuid: Recalculate a domains CPUID policy when appropriate
Introduce recalculate_cpuid_policy() which clamps a CPUID policy based on the domains current restrictions. Recalculate on domain creation immediately after copying the appropriate policy, when switching a PV guest to being compat, and when the toolstack sets CPUID policy data. This needs sanitise_featureset() and lookup_deep_deps() to move out of __init From this point on, domains have full and correct feature-leaf information in their CPUID policies, allowing for substantial cleanup and improvements. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- CC: Jan Beulich <JBeulich@xxxxxxxx> --- xen/arch/x86/cpuid.c | 60 +++++++++++++++++++++++++++++++++++----- xen/arch/x86/domain.c | 1 + xen/arch/x86/domctl.c | 23 +++++++++++++++ xen/include/asm-x86/cpufeature.h | 1 + xen/include/asm-x86/cpuid.h | 10 +++---- 5 files changed, 82 insertions(+), 13 deletions(-) diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c index e7bb0d5..36d11c0 100644 --- a/xen/arch/x86/cpuid.c +++ b/xen/arch/x86/cpuid.c @@ -9,10 +9,10 @@ const uint32_t known_features[] = INIT_KNOWN_FEATURES; const uint32_t special_features[] = INIT_SPECIAL_FEATURES; -static const uint32_t __initconst pv_featuremask[] = INIT_PV_FEATURES; -static const uint32_t __initconst hvm_shadow_featuremask[] = INIT_HVM_SHADOW_FEATURES; -static const uint32_t __initconst hvm_hap_featuremask[] = INIT_HVM_HAP_FEATURES; -static const uint32_t __initconst deep_features[] = INIT_DEEP_FEATURES; +static const uint32_t pv_featuremask[] = INIT_PV_FEATURES; +static const uint32_t hvm_shadow_featuremask[] = INIT_HVM_SHADOW_FEATURES; +static const uint32_t hvm_hap_featuremask[] = INIT_HVM_HAP_FEATURES; +static const uint32_t deep_features[] = INIT_DEEP_FEATURES; #define EMPTY_LEAF (struct cpuid_leaf){} @@ -32,7 +32,7 @@ static void cpuid_count_leaf(unsigned int leaf, unsigned int subleaf, cpuid_count(leaf, subleaf, &data->a, &data->b, &data->c, &data->d); } -static void __init sanitise_featureset(uint32_t *fs) +static void sanitise_featureset(uint32_t *fs) { /* for_each_set_bit() uses unsigned longs. Extend with zeroes. */ uint32_t disabled_features[ @@ -228,12 +228,12 @@ void __init init_guest_cpuid(void) calculate_hvm_max_policy(); } -const uint32_t * __init lookup_deep_deps(uint32_t feature) +const uint32_t *lookup_deep_deps(uint32_t feature) { static const struct { uint32_t feature; uint32_t fs[FSCAPINTS]; - } deep_deps[] __initconst = INIT_DEEP_DEPS; + } deep_deps[] = INIT_DEEP_DEPS; unsigned int start = 0, end = ARRAY_SIZE(deep_deps); BUILD_BUG_ON(ARRAY_SIZE(deep_deps) != NR_DEEP_DEPS); @@ -258,6 +258,50 @@ const uint32_t * __init lookup_deep_deps(uint32_t feature) return NULL; } +void recalculate_cpuid_policy(struct domain *d) +{ + struct cpuid_policy *p = d->arch.cpuid; + const struct cpuid_policy *max = + is_pv_domain(d) ? &pv_max_policy : &hvm_max_policy; + uint32_t fs[FSCAPINTS], max_fs[FSCAPINTS]; + unsigned int i; + + cpuid_policy_to_featureset(p, fs); + memcpy(max_fs, max->fs, sizeof(max_fs)); + + /* Allow a toolstack to possibly select ITSC... */ + if ( cpu_has_itsc ) + __set_bit(X86_FEATURE_ITSC, max_fs); + + for ( i = 0; i < ARRAY_SIZE(fs); i++ ) + fs[i] &= max_fs[i]; + + if ( is_pv_32bit_domain(d) ) + { + __clear_bit(X86_FEATURE_LM, fs); + if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD ) + __clear_bit(X86_FEATURE_SYSCALL, fs); + } + + if ( is_hvm_domain(d) && !hap_enabled(d) ) + { + for ( i = 0; i < ARRAY_SIZE(fs); i++ ) + fs[i] &= hvm_shadow_featuremask[i]; + } + + /* ... but hide ITSC in the common case. */ + if ( !d->disable_migrate && !d->arch.vtsc ) + __clear_bit(X86_FEATURE_ITSC, fs); + + /* Fold host's FDP_EXCP_ONLY and NO_FPU_SEL into guest's view. */ + fs[FEATURESET_7b0] &= ~special_features[FEATURESET_7b0]; + fs[FEATURESET_7b0] |= (host_featureset[FEATURESET_7b0] & + special_features[FEATURESET_7b0]); + + sanitise_featureset(fs); + cpuid_featureset_to_policy(fs, p); +} + int init_domain_cpuid_policy(struct domain *d) { d->arch.cpuid = xmalloc(struct cpuid_policy); @@ -267,6 +311,8 @@ int init_domain_cpuid_policy(struct domain *d) *d->arch.cpuid = is_pv_domain(d) ? pv_max_policy : hvm_max_policy; + recalculate_cpuid_policy(d); + return 0; } diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index c1f95cc..7d33c41 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -352,6 +352,7 @@ int switch_compat(struct domain *d) } domain_set_alloc_bitsize(d); + recalculate_cpuid_policy(d); d->arch.x87_fip_width = 4; diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 069f1fe..c7e74dd 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -51,6 +51,29 @@ static int gdbsx_guest_mem_io(domid_t domid, struct xen_domctl_gdbsx_memio *iop) static void update_domain_cpuid_info(struct domain *d, const xen_domctl_cpuid_t *ctl) { + struct cpuid_policy *p = d->arch.cpuid; + struct cpuid_leaf leaf = { ctl->eax, ctl->ebx, ctl->ecx, ctl->edx }; + + if ( ctl->input[0] < ARRAY_SIZE(p->basic.raw) ) + { + if ( ctl->input[0] == 7 ) + { + if ( ctl->input[1] < ARRAY_SIZE(p->feat.raw) ) + p->feat.raw[ctl->input[1]] = leaf; + } + else if ( ctl->input[0] == 0xd ) + { + if ( ctl->input[1] < ARRAY_SIZE(p->xstate.raw) ) + p->xstate.raw[ctl->input[1]] = leaf; + } + else + p->basic.raw[ctl->input[0]] = leaf; + } + else if ( (ctl->input[0] - 0x80000000) < ARRAY_SIZE(p->extd.raw) ) + p->extd.raw[ctl->input[0] - 0x80000000] = leaf; + + recalculate_cpuid_policy(d); + switch ( ctl->input[0] ) { case 0: { diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h index d45e650..e7181bb 100644 --- a/xen/include/asm-x86/cpufeature.h +++ b/xen/include/asm-x86/cpufeature.h @@ -73,6 +73,7 @@ #define cpu_has_eist boot_cpu_has(X86_FEATURE_EIST) #define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR) #define cpu_has_cmp_legacy boot_cpu_has(X86_FEATURE_CMP_LEGACY) +#define cpu_has_itsc boot_cpu_has(X86_FEATURE_ITSC) enum _cache_type { CACHE_TYPE_NULL = 0, diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h index 86fa0b1..e20b0d2 100644 --- a/xen/include/asm-x86/cpuid.h +++ b/xen/include/asm-x86/cpuid.h @@ -86,13 +86,8 @@ struct cpuid_policy * * Per-domain objects: * - * - Host accurate: - * - max_{,sub}leaf - * - {xcr0,xss}_{high,low} - * - All FEATURESET_* words - * * - Guest accurate: - * - Nothing + * - All FEATURESET_* words * * Everything else should be considered inaccurate, and not necesserily 0. */ @@ -216,6 +211,9 @@ extern struct cpuid_policy raw_policy, host_policy, pv_max_policy, /* Allocate and initialise a CPUID policy suitable for the domain. */ int init_domain_cpuid_policy(struct domain *d); +/* Clamp the CPUID policy to reality. */ +void recalculate_cpuid_policy(struct domain *d); + 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |