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

[Xen-devel] [PATCH] x86: correct CPUID output for out of bounds input



Another place where we should try to behave like real hardware; see
the code comments.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3358,6 +3358,31 @@ void hvm_cpuid(unsigned int input, unsig
     if ( !edx )
         edx = &dummy;
 
+    if ( input & 0xffff )
+    {
+        /*
+         * Requests beyond the highest supported leaf within a group return
+         * zero on AMD and the highest basic leaf output on others.
+         */
+        unsigned int lvl;
+
+        hvm_cpuid(input & 0xffff0000, &lvl, NULL, NULL, NULL);
+        if ( ((lvl ^ input) >> 16) || input > lvl )
+        {
+            if ( d->arch.x86_vendor == X86_VENDOR_AMD )
+            {
+                *eax = 0;
+                *ebx = 0;
+                *ecx = 0;
+                *edx = 0;
+                return;
+            }
+            if ( input >> 16 )
+                hvm_cpuid(0, &lvl, NULL, NULL, NULL);
+            input = lvl;
+        }
+    }
+
     if ( cpuid_viridian_leaves(input, eax, ebx, ecx, edx) )
         return;
 
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -944,7 +944,40 @@ void pv_cpuid(struct cpu_user_regs *regs
     struct vcpu *curr = current;
     struct domain *currd = curr->domain;
 
-    leaf = a = regs->eax;
+    leaf = regs->eax;
+
+    if ( leaf & 0xffff )
+    {
+        /*
+         * Requests beyond the highest supported leaf within a group return
+         * zero on AMD and the highest basic leaf output on others.
+         */
+        if ( !is_control_domain(currd) && !is_hardware_domain(currd) )
+            domain_cpuid(currd, leaf & 0xffff0000, 0, &a, &b, &c, &d);
+        else
+            a = cpuid_eax(leaf & 0xffff0000);
+        if ( ((a ^ leaf) >> 16) || leaf > a )
+        {
+            if ( currd->arch.x86_vendor == X86_VENDOR_AMD )
+            {
+                regs->eax = 0;
+                regs->ebx = 0;
+                regs->ecx = 0;
+                regs->edx = 0;
+                return;
+            }
+            if ( leaf >> 16 )
+            {
+                if ( !is_control_domain(currd) && !is_hardware_domain(currd) )
+                    domain_cpuid(currd, 0, 0, &a, &b, &c, &d);
+                else
+                    a = cpuid_eax(0);
+            }
+            leaf = a;
+        }
+    }
+
+    a = regs->eax;
     b = regs->ebx;
     subleaf = c = regs->ecx;
     d = regs->edx;



Attachment: x86-CPUID-level-check.patch
Description: Text document

_______________________________________________
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®.