]> xenbits.xensource.com Git - people/liuw/xen.git/commitdiff
x86/cpuid: Fix handling of the CPUID.7[0].eax levelling MSR
authorAndrew Cooper <andrew.cooper3@citrix.com>
Fri, 6 Sep 2019 15:59:02 +0000 (16:59 +0100)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Tue, 10 Sep 2019 12:33:21 +0000 (13:33 +0100)
7a0 is an integer field, not a mask - taking the logical and of the hardware
and policy values results in nonsense.  Instead, take the policy value
directly.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@cirtrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/domctl.c

index 1e98fc80097555e7880a224ec25d3f2da8aa755b..a744696c6b5d363c280eeff43a6200ecd24ab45d 100644 (file)
@@ -218,11 +218,16 @@ static int update_domain_cpuid_info(struct domain *d,
         if ( is_pv_domain(d) && ((levelling_caps & LCAP_7ab0) == LCAP_7ab0) )
         {
             uint64_t mask = cpuidmask_defaults._7ab0;
-            uint32_t eax = ctl->eax;
-            uint32_t ebx = p->feat._7b0;
 
-            if ( boot_cpu_data.x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON) )
-                mask &= ((uint64_t)eax << 32) | ebx;
+            /*
+             * Leaf 7[0].eax is max_subleaf, not a feature mask.  Take it
+             * wholesale from the policy, but clamp the features in 7[0].ebx
+             * per usual.
+             */
+            if ( boot_cpu_data.x86_vendor &
+                 (X86_VENDOR_AMD | X86_VENDOR_HYGON) )
+                mask = (((uint64_t)p->feat.max_subleaf << 32) |
+                        ((uint32_t)mask & p->feat._7b0));
 
             d->arch.pv.cpuidmasks->_7ab0 = mask;
         }