x86/cpuid: Handle leaf 0x8000001c in guest_cpuid()
authorAndrew Cooper <andrew.cooper3@citrix.com>
Fri, 20 Jan 2017 13:56:10 +0000 (13:56 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 25 Jan 2017 10:26:29 +0000 (10:26 +0000)
Leaf 0x8000001c contains LWP information.  edx contains hardware supported
features (and is clamped against the maximum), while ecx and ebx contain
various properties of the implementation.  eax is entirely dynamic, depending
on xcr0 and MSR_LWP_CFG.

The call to guest_cpuid() in svm_update_lwp_cfg() can now be replaced by
reading the data straight out of the cpuid_policy block.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/cpuid.c
xen/arch/x86/hvm/svm/svm.c

index dc4ddd5041a437c25bd65d86eced8aba0e70d40c..97a3dd4473662d09a5c145efc74a90fdf5825654 100644 (file)
@@ -213,6 +213,8 @@ static void recalculate_misc(struct cpuid_policy *p)
         zero_leaves(p->extd.raw, 0xb, 0x18);
 
         p->extd.raw[0x1b] = EMPTY_LEAF; /* IBS - not supported. */
+
+        p->extd.raw[0x1c].a = 0; /* LWP.a entirely dynamic. */
         break;
     }
 }
@@ -516,6 +518,11 @@ void recalculate_cpuid_policy(struct domain *d)
 
     if ( !p->extd.page1gb )
         p->extd.raw[0x19] = EMPTY_LEAF;
+
+    if ( p->extd.lwp )
+        p->extd.raw[0x1c].d &= max->extd.raw[0x1c].d;
+    else
+        p->extd.raw[0x1c] = EMPTY_LEAF;
 }
 
 int init_domain_cpuid_policy(struct domain *d)
@@ -729,7 +736,6 @@ static void pv_cpuid(uint32_t leaf, uint32_t subleaf, struct cpuid_leaf *res)
 
     case 0x00000005: /* MONITOR/MWAIT */
     case 0x0000000b: /* Extended Topology Enumeration */
-    case 0x8000001c: /* Light Weight Profiling */
     unsupported:
         *res = EMPTY_LEAF;
         break;
@@ -738,7 +744,7 @@ static void pv_cpuid(uint32_t leaf, uint32_t subleaf, struct cpuid_leaf *res)
     case 0x2 ... 0x3:
     case 0x7 ... 0x9:
     case 0xc ... XSTATE_CPUID:
-    case 0x80000000 ... 0x8000001b:
+    case 0x80000000 ... 0x8000001c:
         ASSERT_UNREACHABLE();
         /* Now handled in guest_cpuid(). */
     }
@@ -816,25 +822,11 @@ static void hvm_cpuid(uint32_t leaf, uint32_t subleaf, struct cpuid_leaf *res)
             res->a = (res->a & ~0xff) | 3;
         break;
 
-    case 0x8000001c:
-        if ( !cpu_has_svm )
-        {
-            *res = EMPTY_LEAF;
-            break;
-        }
-
-        if ( cpu_has_lwp && (v->arch.xcr0 & XSTATE_LWP) )
-            /* Turn on available bit and other features specified in lwp_cfg. */
-            res->a = (res->d & v->arch.hvm_svm.guest_lwp_cfg) | 1;
-        else
-            res->a = 0;
-        break;
-
     case 0x0:
     case 0x2 ... 0x3:
     case 0x7 ... 0x9:
     case 0xc ... XSTATE_CPUID:
-    case 0x80000000 ... 0x8000001b:
+    case 0x80000000 ... 0x8000001c:
         ASSERT_UNREACHABLE();
         /* Now handled in guest_cpuid(). */
     }
@@ -917,7 +909,7 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
         default:
             goto legacy;
 
-        case 0x80000000 ... 0x8000001b:
+        case 0x80000000 ... 0x8000001c:
             *res = p->extd.raw[leaf & 0xffff];
             break;
         }
@@ -1027,6 +1019,12 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
                 res->d |= cpufeat_mask(X86_FEATURE_MTRR);
         }
         break;
+
+    case 0x8000001c:
+        if ( (v->arch.xcr0 & XSTATE_LWP) && cpu_has_svm )
+            /* Turn on available bit and other features specified in lwp_cfg. */
+            res->a = (res->d & v->arch.hvm_svm.guest_lwp_cfg) | 1;
+        break;
     }
 
     /* Done. */
index e8ef88da4413e25e1228a1d6814f2d32f0d6b0ae..01c7b580c4a5893e65dd4bb74e6df3a348de7c95 100644 (file)
@@ -931,13 +931,10 @@ static int svm_update_lwp_cfg(struct vcpu *v, uint64_t msr_content)
 
     if ( xsave_enabled(v) && cpu_has_lwp )
     {
-        struct cpuid_leaf res;
-
-        guest_cpuid(v, 0x8000001c, 0, &res);
         msr_low = (uint32_t)msr_content;
         
         /* generate #GP if guest tries to turn on unsupported features. */
-        if ( msr_low & ~res.d)
+        if ( msr_low & ~v->domain->arch.cpuid->extd.raw[0x1c].d )
             return -1;
 
         v->arch.hvm_svm.guest_lwp_cfg = msr_content;