[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v2 02/14] x86/cpuid: Handle leaf 0x80000000 in guest_cpuid()



The calculations for p->extd.max_leaf are reworked to force a value of at
least 0x80000000, and to take the domains chosen vendor into account when
clamping maximum value.

The high short vendor information is clobbered or duplicated according to the
chosen vendor.

As a side effect of handing out an audited max_leaf value, the 0x8000001e case
can be dropped from pv_cpuid(), as it outside of the visible range.

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Reviewed-by: Doug Goldstein <cardoe@xxxxxxxxxx>
Reviewed-by: Jan Beulich <JBeulich@xxxxxxxx>
---
v2:
 * Drop 0x8000001e from pv_cpuid()
 * s/recalculate_common/recalculate_misc/
---
 xen/arch/x86/cpuid.c        | 53 +++++++++++++++++++++++++++++++++++++++------
 xen/include/asm-x86/cpuid.h |  6 ++---
 2 files changed, 49 insertions(+), 10 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index 85c829d..3f398b5 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -163,6 +163,28 @@ static void recalculate_xstate(struct cpuid_policy *p)
     }
 }
 
+/*
+ * Misc adjustments to the policy.  Mostly clobbering reserved fields and
+ * duplicating shared fields.
+ */
+static void recalculate_misc(struct cpuid_policy *p)
+{
+    switch ( p->x86_vendor )
+    {
+    case X86_VENDOR_INTEL:
+        p->extd.vendor_ebx = 0;
+        p->extd.vendor_ecx = 0;
+        p->extd.vendor_edx = 0;
+        break;
+
+    case X86_VENDOR_AMD:
+        p->extd.vendor_ebx = p->basic.vendor_ebx;
+        p->extd.vendor_ecx = p->basic.vendor_ecx;
+        p->extd.vendor_edx = p->basic.vendor_edx;
+        break;
+    }
+}
+
 static void __init calculate_raw_policy(void)
 {
     struct cpuid_policy *p = &raw_policy;
@@ -227,12 +249,12 @@ static void __init calculate_host_policy(void)
         min_t(uint32_t, p->basic.max_leaf,   ARRAY_SIZE(p->basic.raw) - 1);
     p->feat.max_subleaf =
         min_t(uint32_t, p->feat.max_subleaf, ARRAY_SIZE(p->feat.raw) - 1);
-    p->extd.max_leaf =
-        min_t(uint32_t, p->extd.max_leaf,
-              0x80000000u + ARRAY_SIZE(p->extd.raw) - 1);
+    p->extd.max_leaf = 0x80000000 | min_t(uint32_t, p->extd.max_leaf & 0xffff,
+                                          ARRAY_SIZE(p->extd.raw) - 1);
 
     cpuid_featureset_to_policy(boot_cpu_data.x86_capability, p);
     recalculate_xstate(p);
+    recalculate_misc(p);
 }
 
 static void __init calculate_pv_max_policy(void)
@@ -360,7 +382,10 @@ void recalculate_cpuid_policy(struct domain *d)
 
     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);
+    p->extd.max_leaf    = 0x80000000 | min(p->extd.max_leaf & 0xffff,
+                                           (p->x86_vendor == X86_VENDOR_AMD
+                                            ? CPUID_GUEST_NR_EXTD_AMD
+                                            : CPUID_GUEST_NR_EXTD_INTEL) - 1);
 
     cpuid_policy_to_featureset(p, fs);
     cpuid_policy_to_featureset(max, max_fs);
@@ -428,6 +453,7 @@ void recalculate_cpuid_policy(struct domain *d)
 
     cpuid_featureset_to_policy(fs, p);
     recalculate_xstate(p);
+    recalculate_misc(p);
 }
 
 int init_domain_cpuid_policy(struct domain *d)
@@ -675,7 +701,6 @@ static void pv_cpuid(uint32_t leaf, uint32_t subleaf, 
struct cpuid_leaf *res)
     case 0x8000000a: /* SVM revision and features */
     case 0x8000001b: /* Instruction Based Sampling */
     case 0x8000001c: /* Light Weight Profiling */
-    case 0x8000001e: /* Extended topology reporting */
     unsupported:
         *res = EMPTY_LEAF;
         break;
@@ -683,6 +708,7 @@ static void pv_cpuid(uint32_t leaf, uint32_t subleaf, 
struct cpuid_leaf *res)
     case 0x0:
     case 0x7:
     case XSTATE_CPUID:
+    case 0x80000000:
         ASSERT_UNREACHABLE();
         /* Now handled in guest_cpuid(). */
     }
@@ -832,6 +858,7 @@ static void hvm_cpuid(uint32_t leaf, uint32_t subleaf, 
struct cpuid_leaf *res)
     case 0x0:
     case 0x7:
     case XSTATE_CPUID:
+    case 0x80000000:
         ASSERT_UNREACHABLE();
         /* Now handled in guest_cpuid(). */
     }
@@ -901,9 +928,21 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
         return cpuid_hypervisor_leaves(v, leaf, subleaf, res);
 
     case 0x80000000 ... 0x80000000 + CPUID_GUEST_NR_EXTD - 1:
-        if ( leaf > p->extd.max_leaf )
+        ASSERT((p->extd.max_leaf & 0xffff) < ARRAY_SIZE(p->extd.raw));
+        if ( (leaf & 0xffff) > min_t(uint32_t, p->extd.max_leaf & 0xffff,
+                                     ARRAY_SIZE(p->extd.raw) - 1) )
             return;
-        goto legacy;
+
+        switch ( leaf )
+        {
+        default:
+            goto legacy;
+
+        case 0x80000000:
+            *res = p->extd.raw[leaf & 0xffff];
+            break;
+        }
+        break;
 
     default:
         return;
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index 299a026..4712b73 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -81,7 +81,7 @@ struct cpuid_policy
      *   - All of the feat and xstate unions
      *   - max_{,sub}leaf
      *   - All FEATURESET_* words
-     *   - Low short vendor infomation
+     *   - Short vendor infomation
      *
      * Per-domain objects:
      *
@@ -89,7 +89,7 @@ struct cpuid_policy
      *   - All of the feat and xstate unions
      *   - max_{,sub}leaf
      *   - All FEATURESET_* words
-     *   - Low short vendor infomation
+     *   - Short vendor infomation
      *
      * Everything else should be considered inaccurate, and not necesserily 0.
      */
@@ -168,7 +168,7 @@ struct cpuid_policy
         struct cpuid_leaf raw[CPUID_GUEST_NR_EXTD];
         struct {
             /* Leaf 0x80000000 - Max and vendor. */
-            uint32_t max_leaf, /* b */:32, /* c */:32, /* d */:32;
+            uint32_t max_leaf, vendor_ebx, vendor_ecx, vendor_edx;
 
             /* Leaf 0x80000001 - Family/model/stepping and features. */
             uint32_t /* a */:32, /* b */:32;
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.