x86 hvm: Move CPUID.0xd (XSAVE) configuration into libxc.
authorKeir Fraser <keir@xen.org>
Fri, 17 Dec 2010 09:54:22 +0000 (09:54 +0000)
committerKeir Fraser <keir@xen.org>
Fri, 17 Dec 2010 09:54:22 +0000 (09:54 +0000)
Signed-off-by: Keir Fraser <keir@xen.org>
tools/libxc/xc_cpuid_x86.c
xen/arch/x86/hvm/hvm.c

index c5b452488a9437af030547dbe171a8c3c66be36d..6b5a915b0ae057889ea6668e444a86ca4330b58b 100644 (file)
@@ -171,7 +171,8 @@ static void xc_cpuid_hvm_policy(
     DECLARE_DOMCTL;
     char brand[13];
     unsigned long pae;
-    int is_pae, xsave_supported;
+    int is_pae;
+    uint64_t xfeature_mask;
 
     xc_get_hvm_param(xch, domid, HVM_PARAM_PAE_ENABLED, &pae);
     is_pae = !!pae;
@@ -181,7 +182,7 @@ static void xc_cpuid_hvm_policy(
     domctl.cmd = XEN_DOMCTL_getvcpuextstate;
     domctl.domain = domid;
     do_domctl(xch, &domctl);
-    xsave_supported = (domctl.u.vcpuextstate.xfeature_mask != 0);
+    xfeature_mask = domctl.u.vcpuextstate.xfeature_mask;
 
     switch ( input[0] )
     {
@@ -204,7 +205,7 @@ static void xc_cpuid_hvm_policy(
                     bitmaskof(X86_FEATURE_SSE4_2) |
                     bitmaskof(X86_FEATURE_POPCNT) |
                     bitmaskof(X86_FEATURE_AES) |
-                    (xsave_supported ?
+                    ((xfeature_mask != 0) ?
                      (bitmaskof(X86_FEATURE_AVX) |
                       bitmaskof(X86_FEATURE_XSAVE)) : 0));
 
@@ -242,6 +243,46 @@ static void xc_cpuid_hvm_policy(
             clear_bit(X86_FEATURE_PAE, regs[3]);
         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;
+        }
+        break;
+
     case 0x80000000:
         if ( regs[0] > DEF_MAX_EXT )
             regs[0] = DEF_MAX_EXT;
@@ -373,6 +414,7 @@ static void xc_cpuid_pv_policy(
         break;
     case 5: /* MONITOR/MWAIT */
     case 0xa: /* Architectural Performance Monitor Features */
+    case 0xd: /* XSAVE */
     case 0x8000000a: /* SVM revision and features */
     case 0x8000001b: /* Instruction Based Sampling */
         regs[0] = regs[1] = regs[2] = regs[3] = 0;
@@ -468,13 +510,20 @@ int xc_cpuid_apply_policy(xc_interface *xch, domid_t domid)
                 if ( (regs[0] & 0x1f) != 0 )
                     continue;
             }
+
+            /* XSAVE information, subleaves 0-2. */
+            if ( (input[0] == 0xd) && (input[1]++ < 2) )
+                continue;
         }
 
         input[0]++;
-        input[1] = (input[0] == 4) ? 0 : XEN_CPUID_INPUT_UNUSED;
         if ( !(input[0] & 0x80000000u) && (input[0] > base_max ) )
             input[0] = 0x80000000u;
 
+        input[1] = XEN_CPUID_INPUT_UNUSED;
+        if ( (input[0] == 4) || (input[0] == 0xd) )
+            input[1] = 0;
+
         if ( (input[0] & 0x80000000u) && (input[0] > ext_max) )
             break;
     }
index 19c8ba0794a84104c07e34a75328ea9f91c2beb0..91563da8e4c92ee0a6d69df5a44624aa6cd0e090 100644 (file)
@@ -2144,41 +2144,6 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
         /* Fix the x2APIC identifier. */
         *edx = v->vcpu_id * 2;
         break;
-    case 0xd:
-        if ( cpu_has_xsave )
-        {
-            /*
-             *  Fix up "Processor Extended State Enumeration". We present
-             *  FPU(bit0), SSE(bit1) and YMM(bit2) to HVM guest for now.
-             */
-            *eax = *ebx = *ecx = *edx = 0;
-            switch ( count )
-            {
-            case 0:
-                /* No HW defines bit in EDX yet. */
-                *edx = 0;
-                /* We only enable the features we know. */
-                *eax = xfeature_mask;
-                /* FP/SSE + XSAVE.HEADER + YMM. */
-                *ecx = 512 + 64 + ((*eax & XSTATE_YMM) ? XSTATE_YMM_SIZE : 0);
-                /* Let ebx equal ecx at present. */
-                *ebx = *ecx;
-                break;
-            case 2:
-                if ( !(xfeature_mask & XSTATE_YMM) )
-                    break;
-                *eax = XSTATE_YMM_SIZE;
-                *ebx = XSTATE_YMM_OFFSET;
-                break;
-            case 1:
-                if ( cpu_has_xsaveopt )
-                    *eax = XSAVEOPT;
-                break;
-            default:
-                break;
-            }
-        }
-        break;
     case 0x80000001:
         /* We expose RDTSCP feature to guest only when
            tsc_mode == TSC_MODE_DEFAULT and host_tsc_is_safe() returns 1 */