x86/cpuid: Store the toolstacks choice of hypervisor max leaf
authorAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 4 Jan 2017 12:20:51 +0000 (12:20 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Fri, 13 Jan 2017 13:16:57 +0000 (13:16 +0000)
This removes all dependencies on the legacy cpuids[] array from
cpuid_hypervisor_leaves().  Swap a BUG() to an ASSERT_UNREACHABLE(), because
in the unlikely case that we hit it, returning all zeros to the guest is fine.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/domctl.c
xen/arch/x86/traps.c
xen/include/asm-x86/cpuid.h

index a5a56ee2bf276974114e871f7e0990da49ccda39..038521a34cced148d460dc443babae51707e6581 100644 (file)
@@ -136,6 +136,14 @@ static int update_domain_cpuid_info(struct domain *d,
             p->basic.raw[ctl->input[0]] = leaf;
         break;
 
+    case 0x40000000:
+        p->hv_limit = ctl->eax;
+        break;
+
+    case 0x40000100:
+        p->hv2_limit = ctl->eax;
+        break;
+
     case 0x80000000 ... 0x80000000 + ARRAY_SIZE(p->extd.raw) - 1:
         p->extd.raw[ctl->input[0] - 0x80000000] = leaf;
         break;
index 7bb42acebf42efbb4fb7feef2d744f977ed21266..4f29c3af93491475bceea567edb39fdcc1f1a0d9 100644 (file)
@@ -906,26 +906,17 @@ void cpuid_hypervisor_leaves(const struct vcpu *v, uint32_t leaf,
                              uint32_t subleaf, struct cpuid_leaf *res)
 {
     const struct domain *d = v->domain;
+    const struct cpuid_policy *p = d->arch.cpuid;
     uint32_t base = is_viridian_domain(d) ? 0x40000100 : 0x40000000;
     uint32_t idx  = leaf - base;
-    uint32_t limit, dummy;
+    unsigned int limit = is_viridian_domain(d) ? p->hv2_limit : p->hv_limit;
 
-    if ( idx > XEN_CPUID_MAX_NUM_LEAVES )
-        return; /* Avoid unnecessary pass through domain_cpuid() */
-
-    domain_cpuid(d, base, 0, &limit, &dummy, &dummy, &dummy);
     if ( limit == 0 )
         /* Default number of leaves */
         limit = XEN_CPUID_MAX_NUM_LEAVES;
     else
-    {
-        /* User-specified number of leaves */
-        limit &= 0xff;
-        if ( limit < 2 )
-            limit = 2;
-        else if ( limit > XEN_CPUID_MAX_NUM_LEAVES )
-            limit = XEN_CPUID_MAX_NUM_LEAVES;
-    }
+        /* Clamp toolstack value between 2 and MAX_NUM_LEAVES. */
+        limit = min(max(limit, 2u), XEN_CPUID_MAX_NUM_LEAVES + 0u);
 
     if ( idx > limit )
         return;
@@ -1015,7 +1006,7 @@ void cpuid_hypervisor_leaves(const struct vcpu *v, uint32_t leaf,
         break;
 
     default:
-        BUG();
+        ASSERT_UNREACHABLE();
     }
 }
 
index 5b1448ac0f565680aec7835bf38044b82c728e43..38e3975a3b344ed2ba5194961899bf740e4fc36c 100644 (file)
@@ -200,6 +200,9 @@ struct cpuid_policy
 #undef __DECL_BITFIELD
 #undef _DECL_BITFIELD
 #undef DECL_BITFIELD
+
+    /* Toolstack selected Hypervisor max_leaf (if non-zero). */
+    uint8_t hv_limit, hv2_limit;
 };
 
 /* Fill in a featureset bitmap from a CPUID policy. */