x86/cpuid: Handle leaf 0 in guest_cpuid()
authorAndrew Cooper <andrew.cooper3@citrix.com>
Tue, 17 Jan 2017 16:48:58 +0000 (16:48 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Fri, 20 Jan 2017 16:12:10 +0000 (16:12 +0000)
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 <andrew.cooper3@citrix.com>
Reviewed-by: Doug Goldstein <cardoe@cardoe.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/cpuid.c
xen/arch/x86/domctl.c
xen/include/asm-x86/cpuid.h

index 076fab30ac60609535df84422e780cbd9ef502dc..85c829deae44a3719b1d0727b2249bea50a9a9c0 100644 (file)
@@ -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;
 
index a3f51f38c7b070dbe19ef1ad9751afa128844761..8e5259fec1c399fe6614eb984754d18a11673ad5 100644 (file)
@@ -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) )
index e5140cac718aebdd6f0969c4252fed51abb44ebf..299a02643bb620902d348693a025644a9c09180e 100644 (file)
@@ -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;