xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] x86: correct CPUID output for out of bounds input
@ 2016-08-24 15:31 Jan Beulich
  2016-09-01 11:23 ` Andrew Cooper
  2016-09-01 14:27 ` Andrew Cooper
  0 siblings, 2 replies; 11+ messages in thread
From: Jan Beulich @ 2016-08-24 15:31 UTC (permalink / raw)
  To: xen-devel; +Cc: Andrew Cooper

[-- Attachment #1: Type: text/plain, Size: 2540 bytes --]

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

Signed-off-by: Jan Beulich <jbeulich@suse.com>

--- 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 #2: x86-CPUID-level-check.patch --]
[-- Type: text/plain, Size: 2587 bytes --]

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@suse.com>

--- 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 #3: Type: text/plain, Size: 127 bytes --]

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

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2016-09-05 10:05 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-24 15:31 [PATCH] x86: correct CPUID output for out of bounds input Jan Beulich
2016-09-01 11:23 ` Andrew Cooper
2016-09-01 12:56   ` Jan Beulich
2016-09-01 14:17     ` Andrew Cooper
2016-09-01 14:27 ` Andrew Cooper
2016-09-01 15:27   ` Jan Beulich
2016-09-02 15:14     ` Andrew Cooper
2016-09-05  6:32       ` Jan Beulich
2016-09-05  9:43         ` Andrew Cooper
2016-09-05  9:51           ` Jan Beulich
2016-09-05 10:05             ` Andrew Cooper

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).