From: Andrew Cooper Date: Tue, 17 Jan 2017 16:48:58 +0000 (+0000) Subject: x86/cpuid: Handle leaf 0 in guest_cpuid() X-Git-Tag: archive/raspbian/4.11.1-1+rpi1~1^2~66^2~2939 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=e225a1c7c06037e4f938efa43d4407e7abb088c1;p=xen.git x86/cpuid: Handle leaf 0 in guest_cpuid() Calculate a domains x86_vendor early in recalculate_cpuid_policy(); subsequent patches need to make other recalculation decisions based on it. Signed-off-by: Andrew Cooper Reviewed-by: Doug Goldstein Reviewed-by: Jan Beulich --- diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c index 076fab30ac..85c829deae 100644 --- a/xen/arch/x86/cpuid.c +++ b/xen/arch/x86/cpuid.c @@ -355,6 +355,9 @@ void recalculate_cpuid_policy(struct domain *d) uint32_t fs[FSCAPINTS], max_fs[FSCAPINTS]; unsigned int i; + p->x86_vendor = get_cpu_vendor(p->basic.vendor_ebx, p->basic.vendor_ecx, + p->basic.vendor_edx, gcv_guest); + p->basic.max_leaf = min(p->basic.max_leaf, max->basic.max_leaf); p->feat.max_subleaf = min(p->feat.max_subleaf, max->feat.max_subleaf); p->extd.max_leaf = min(p->extd.max_leaf, max->extd.max_leaf); @@ -677,6 +680,7 @@ static void pv_cpuid(uint32_t leaf, uint32_t subleaf, struct cpuid_leaf *res) *res = EMPTY_LEAF; break; + case 0x0: case 0x7: case XSTATE_CPUID: ASSERT_UNREACHABLE(); @@ -825,6 +829,7 @@ static void hvm_cpuid(uint32_t leaf, uint32_t subleaf, struct cpuid_leaf *res) res->a = 0; break; + case 0x0: case 0x7: case XSTATE_CPUID: ASSERT_UNREACHABLE(); @@ -850,7 +855,9 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf, switch ( leaf ) { case 0 ... CPUID_GUEST_NR_BASIC - 1: - if ( leaf > p->basic.max_leaf ) + ASSERT(p->basic.max_leaf < ARRAY_SIZE(p->basic.raw)); + if ( leaf > min_t(uint32_t, p->basic.max_leaf, + ARRAY_SIZE(p->basic.raw) - 1) ) return; switch ( leaf ) @@ -873,6 +880,10 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf, default: goto legacy; + + case 0x0: + *res = p->basic.raw[leaf]; + break; } break; diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index a3f51f38c7..8e5259fec1 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -92,7 +92,7 @@ static int update_domain_cpuid_info(struct domain *d, { struct cpuid_policy *p = d->arch.cpuid; const struct cpuid_leaf leaf = { ctl->eax, ctl->ebx, ctl->ecx, ctl->edx }; - int rc; + int rc, old_vendor = p->x86_vendor; /* * Skip update for leaves we don't care about. This avoids the overhead @@ -155,11 +155,7 @@ static int update_domain_cpuid_info(struct domain *d, switch ( ctl->input[0] ) { - case 0: { - int old_vendor = p->x86_vendor; - - p->x86_vendor = get_cpu_vendor(ctl->ebx, ctl->ecx, ctl->edx, gcv_guest); - + case 0: if ( is_hvm_domain(d) && (p->x86_vendor != old_vendor) ) { struct vcpu *v; @@ -167,9 +163,7 @@ static int update_domain_cpuid_info(struct domain *d, for_each_vcpu( d, v ) hvm_update_guest_vendor(v); } - break; - } case 1: if ( is_pv_domain(d) && ((levelling_caps & LCAP_1cd) == LCAP_1cd) ) diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h index e5140cac71..299a02643b 100644 --- a/xen/include/asm-x86/cpuid.h +++ b/xen/include/asm-x86/cpuid.h @@ -81,6 +81,7 @@ struct cpuid_policy * - All of the feat and xstate unions * - max_{,sub}leaf * - All FEATURESET_* words + * - Low short vendor infomation * * Per-domain objects: * @@ -88,6 +89,7 @@ struct cpuid_policy * - All of the feat and xstate unions * - max_{,sub}leaf * - All FEATURESET_* words + * - Low short vendor infomation * * Everything else should be considered inaccurate, and not necesserily 0. */ @@ -101,7 +103,7 @@ struct cpuid_policy struct cpuid_leaf raw[CPUID_GUEST_NR_BASIC]; struct { /* Leaf 0x0 - Max and vendor. */ - uint32_t max_leaf, /* b */:32, /* c */:32, /* d */:32; + uint32_t max_leaf, vendor_ebx, vendor_ecx, vendor_edx; /* Leaf 0x1 - Family/model/stepping and features. */ uint32_t raw_fms, /* b */:32;