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

[Xen-changelog] [xen-unstable] x86 xsave: supports xsave (CPUID:0xD) enumeration for all sub-leaves.



# HG changeset patch
# User Keir Fraser <keir@xxxxxxx>
# Date 1293179982 0
# Node ID 920826e80bee78d725fc3758bc7e378734d85bb8
# Parent  26e7e6c6ff7f9775fb77f58ddc0454ef08a1a908
x86 xsave: supports xsave (CPUID:0xD) enumeration for all sub-leaves.

In specific, it fixes the following issues:

1. The sub-leaves of CPUID:0x0000000D aren't contiguous. Hypervisor
shouldn't use register values to stop the enumeration. This patch
moves checking on XSAVE sub-leaves out of if-else statement. It also
bumps up sub-leaves to 63.
2. It creates a common function for xsave.
3. The main leaf 0 of CPUID:0x0000000D in current Xen is broken,
especially ECX and EBX registers. This patch cleans it up.
4. It adds support to detects EBX value of CPUID:0x0000000D main leaf
0 on-the-fly.

Signed-off-by: Wei Huang2 <wei.huang2@xxxxxxx>
---
 tools/libxc/xc_cpuid_x86.c |  114 +++++++++++++++++++++++++--------------------
 xen/arch/x86/hvm/hvm.c     |   18 +++++++
 2 files changed, 83 insertions(+), 49 deletions(-)

diff -r 26e7e6c6ff7f -r 920826e80bee tools/libxc/xc_cpuid_x86.c
--- a/tools/libxc/xc_cpuid_x86.c        Fri Dec 24 08:38:22 2010 +0000
+++ b/tools/libxc/xc_cpuid_x86.c        Fri Dec 24 08:39:42 2010 +0000
@@ -160,6 +160,58 @@ static void intel_xc_cpuid_policy(
     case 0x80000008:
         /* Mask AMD Number of Cores information. */
         regs[2] = 0;
+        break;
+    }
+}
+
+#define XSAVEOPT        (1 << 0)
+/* Configure extended state enumeration leaves (0x0000000D for xsave) */
+static void xc_cpuid_config_xsave(
+    xc_interface *xch, domid_t domid, uint64_t xfeature_mask,
+    const unsigned int *input, unsigned int *regs)
+{
+    if ( xfeature_mask == 0 )
+    {
+        regs[0] = regs[1] = regs[2] = regs[3] = 0;
+        return;
+    }
+
+    switch ( input[1] )
+    {
+    case 0: 
+        /* EAX: low 32bits of xfeature_enabled_mask */
+        regs[0] = xfeature_mask & 0xFFFFFFFF;
+        /* EDX: high 32bits of xfeature_enabled_mask */
+        regs[3] = (xfeature_mask >> 32) & 0xFFFFFFFF;
+        /* ECX: max size required by all HW features */
+        {
+            unsigned int _input[2] = {0xd, 0x0}, _regs[4];
+            regs[2] = 0;
+            for ( _input[1] = 2; _input[1] < 64; _input[1]++ )
+            {
+                cpuid(_input, _regs);
+                if ( (_regs[0] + _regs[1]) > regs[2] )
+                    regs[2] = _regs[0] + _regs[1];
+            }
+        }
+        /* EBX: max size required by enabled features. 
+         * This register contains a dynamic value, which varies when a guest 
+         * enables or disables XSTATE features (via xsetbv). The default size 
+         * after reset is 576. */ 
+        regs[1] = 512 + 64; /* FP/SSE + XSAVE.HEADER */
+        break;
+    case 1: /* leaf 1 */
+        regs[0] &= XSAVEOPT;
+        regs[1] = regs[2] = regs[3] = 0;
+        break;
+    case 2 ... 63: /* sub-leaves */
+        if ( !(xfeature_mask & (1ULL << input[1])) )
+        {
+            regs[0] = regs[1] = regs[2] = regs[3] = 0;
+            break;
+        }
+        /* Don't touch EAX, EBX. Also cleanup ECX and EDX */
+        regs[2] = regs[3] = 0;
         break;
     }
 }
@@ -244,43 +296,7 @@ static void xc_cpuid_hvm_policy(
         break;
 
     case 0x0000000d:
-#define XSTATE_FP       (1 << 0)
-#define XSTATE_SSE      (1 << 1)
-#define XSTATE_YMM      (1 << 2)
-#define XSAVEOPT        (1 << 0)
-#define XSTATE_YMM_SIZE 256
-        if ( xfeature_mask == 0 )
-        {
-            regs[0] = regs[1] = regs[2] = regs[3] = 0;
-            break;
-        }
-        switch ( input[1] )
-        {
-        case 0:
-            /* We only enable the features we know. */
-            regs[0] = xfeature_mask;
-            /* FP/SSE + XSAVE.HEADER + YMM. */
-            regs[2] = 512 + 64;
-            if ( regs[0] & XSTATE_YMM )
-                regs[2] += XSTATE_YMM_SIZE;
-            regs[1] = regs[2];
-            regs[3] = 0;
-            break;
-        case 1:
-            regs[0] &= XSAVEOPT;
-            regs[1] = regs[2] = regs[3] = 0;
-            break;
-        case 2:
-            if ( !(xfeature_mask & XSTATE_YMM) )
-                break;
-            regs[0] = XSTATE_YMM_SIZE;
-            regs[1] = 512 + 64; /* FP/SSE + XSAVE.HEADER */
-            regs[2] = regs[3] = 0;
-            break;
-        default:
-            regs[0] = regs[1] = regs[2] = regs[3] = 0;
-            break;
-        }
+        xc_cpuid_config_xsave(xch, domid, xfeature_mask, input, regs);
         break;
 
     case 0x80000000:
@@ -501,20 +517,20 @@ int xc_cpuid_apply_policy(xc_interface *
             rc = xc_cpuid_do_domctl(xch, domid, input, regs);
             if ( rc )
                 return rc;
-
-            /* Intel cache descriptor leaves. */
-            if ( input[0] == 4 )
-            {
-                input[1]++;
-                /* More to do? Then loop keeping %%eax==0x00000004. */
-                if ( (regs[0] & 0x1f) != 0 )
-                    continue;
-            }
-
-            /* XSAVE information, subleaves 0-2. */
-            if ( (input[0] == 0xd) && (input[1]++ < 2) )
+        }
+
+        /* Intel cache descriptor leaves. */
+        if ( input[0] == 4 )
+        {
+            input[1]++;
+            /* More to do? Then loop keeping %%eax==0x00000004. */
+            if ( (regs[0] & 0x1f) != 0 )
                 continue;
         }
+
+        /* XSAVE information, subleaves 0-63. */
+        if ( (input[0] == 0xd) && (input[1]++ < 63) )
+            continue;
 
         input[0]++;
         if ( !(input[0] & 0x80000000u) && (input[0] > base_max ) )
diff -r 26e7e6c6ff7f -r 920826e80bee xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Fri Dec 24 08:38:22 2010 +0000
+++ b/xen/arch/x86/hvm/hvm.c    Fri Dec 24 08:39:42 2010 +0000
@@ -2144,6 +2144,24 @@ void hvm_cpuid(unsigned int input, unsig
         /* Fix the x2APIC identifier. */
         *edx = v->vcpu_id * 2;
         break;
+    case 0xd:
+    {
+        unsigned int sub_leaf, _eax, _ebx, _ecx, _edx;
+        /* EBX value of main leaf 0 depends on enabled xsave features */
+        if ( count == 0 && v->arch.xcr0 ) 
+        {
+            for ( sub_leaf = 2; 
+                  (sub_leaf < 64) && (v->arch.xcr0 & (1ULL << sub_leaf));
+                  sub_leaf++ ) 
+            {
+                domain_cpuid(v->domain, input, sub_leaf, &_eax, &_ebx, &_ecx, 
+                             &_edx);
+                if ( (_eax + _ebx) > *ebx )
+                    *ebx = _eax + _ebx;
+            }
+        }
+        break;
+    }
     case 0x80000001:
         /* We expose RDTSCP feature to guest only when
            tsc_mode == TSC_MODE_DEFAULT and host_tsc_is_safe() returns 1 */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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