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

[Xen-devel] [PATCH 4/6] tools/libxc: Remove xsave calculations from libxc



libxc performs a lot of calculations for the xstate leaf when generating a
guests cpuid policy.  To correctly construct a policy for an HVM guest, this
logic depends on native cpuid leaking through from real hardware.

In particular, the logic is potentially wrong for an HVM-based toolstack
domain (e.g. PVH dom0), and definitely wrong if cpuid faulting is applied to a
PV domain.

Xen now performs all the necessary calculations, using native values.  The
only piece of information the toolstack need worry about is single xstate
feature leaf.

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
CC: Wei Liu <wei.liu2@xxxxxxxxxx>
---
 tools/libxc/xc_cpuid_x86.c | 143 +++++----------------------------------------
 1 file changed, 15 insertions(+), 128 deletions(-)

diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
index b32001b3..96d6025 100644
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -400,125 +400,6 @@ static void intel_xc_cpuid_policy(xc_interface *xch,
     }
 }
 
-/* XSTATE bits in XCR0. */
-#define X86_XCR0_X87    (1ULL <<  0)
-#define X86_XCR0_SSE    (1ULL <<  1)
-#define X86_XCR0_AVX    (1ULL <<  2)
-#define X86_XCR0_BNDREG (1ULL <<  3)
-#define X86_XCR0_BNDCSR (1ULL <<  4)
-#define X86_XCR0_OPMASK (1ULL <<  5)
-#define X86_XCR0_ZMM    (1ULL <<  6)
-#define X86_XCR0_HI_ZMM (1ULL <<  7)
-#define X86_XCR0_PKRU   (1ULL <<  9)
-#define X86_XCR0_LWP    (1ULL << 62)
-
-#define X86_XSS_MASK    (0) /* No XSS states supported yet. */
-
-/* Per-component subleaf flags. */
-#define XSTATE_XSS      (1ULL <<  0)
-#define XSTATE_ALIGN64  (1ULL <<  1)
-
-/* Configure extended state enumeration leaves (0x0000000D for xsave) */
-static void xc_cpuid_config_xsave(xc_interface *xch,
-                                  const struct cpuid_domain_info *info,
-                                  const unsigned int *input, unsigned int 
*regs)
-{
-    uint64_t guest_xfeature_mask;
-
-    if ( info->xfeature_mask == 0 ||
-         !test_bit(X86_FEATURE_XSAVE, info->featureset) )
-    {
-        regs[0] = regs[1] = regs[2] = regs[3] = 0;
-        return;
-    }
-
-    guest_xfeature_mask = X86_XCR0_SSE | X86_XCR0_X87;
-
-    if ( test_bit(X86_FEATURE_AVX, info->featureset) )
-        guest_xfeature_mask |= X86_XCR0_AVX;
-
-    if ( test_bit(X86_FEATURE_MPX, info->featureset) )
-        guest_xfeature_mask |= X86_XCR0_BNDREG | X86_XCR0_BNDCSR;
-
-    if ( test_bit(X86_FEATURE_AVX512F, info->featureset) )
-        guest_xfeature_mask |= X86_XCR0_OPMASK | X86_XCR0_ZMM | 
X86_XCR0_HI_ZMM;
-
-    if ( test_bit(X86_FEATURE_PKU, info->featureset) )
-        guest_xfeature_mask |= X86_XCR0_PKRU;
-
-    if ( test_bit(X86_FEATURE_LWP, info->featureset) )
-        guest_xfeature_mask |= X86_XCR0_LWP;
-
-    /*
-     * In the common case, the toolstack will have queried Xen for the maximum
-     * available featureset, and guest_xfeature_mask should not able to be
-     * calculated as being greater than the host limit, info->xfeature_mask.
-     *
-     * Nothing currently prevents a toolstack (or an optimistic user) from
-     * purposefully trying to select a larger-than-available xstate set.
-     *
-     * To avoid the domain dying with an unexpected fault, clamp the
-     * calculated mask to the host limit.  Future development work will remove
-     * this possibility, when Xen fully audits the complete cpuid polcy set
-     * for a domain.
-     */
-    guest_xfeature_mask &= info->xfeature_mask;
-
-    switch ( input[1] )
-    {
-    case 0:
-        /* EAX: low 32bits of xfeature_enabled_mask */
-        regs[0] = (uint32_t)guest_xfeature_mask;
-        /* EDX: high 32bits of xfeature_enabled_mask */
-        regs[3] = guest_xfeature_mask >> 32;
-        /* 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] <= 62; _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] = info->featureset[featureword_of(X86_FEATURE_XSAVEOPT)];
-        regs[1] = 0;
-
-        if ( test_bit(X86_FEATURE_XSAVES, info->featureset) )
-        {
-            regs[2] = (uint32_t)(guest_xfeature_mask & X86_XSS_MASK);
-            regs[3] = (guest_xfeature_mask & X86_XSS_MASK) >> 32;
-        }
-        else
-            regs[2] = regs[3] = 0;
-        break;
-
-    case 2 ... 62: /* per-component sub-leaves */
-        if ( !(guest_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] &= XSTATE_XSS | XSTATE_ALIGN64;
-        regs[3] = 0;
-        break;
-
-    default:
-        regs[0] = regs[1] = regs[2] = regs[3] = 0;
-        break;
-    }
-}
-
 static void xc_cpuid_hvm_policy(xc_interface *xch,
                                 const struct cpuid_domain_info *info,
                                 const unsigned int *input, unsigned int *regs)
@@ -558,8 +439,12 @@ static void xc_cpuid_hvm_policy(xc_interface *xch,
         regs[0] = 0;
         break;
 
-    case 0x0000000d:
-        xc_cpuid_config_xsave(xch, info, input, regs);
+    case 0x0000000d: /* Xen automatically calculates almost everything. */
+        if ( input[1] == 1 )
+            regs[0] = info->featureset[featureword_of(X86_FEATURE_XSAVEOPT)];
+        else
+            regs[0] = 0;
+        regs[1] = regs[2] = regs[3] = 0;
         break;
 
     case 0x80000000:
@@ -656,8 +541,12 @@ static void xc_cpuid_pv_policy(xc_interface *xch,
         regs[0] = 0;
         break;
 
-    case 0x0000000d:
-        xc_cpuid_config_xsave(xch, info, input, regs);
+    case 0x0000000d: /* Xen automatically calculates almost everything. */
+        if ( input[1] == 1 )
+            regs[0] = info->featureset[featureword_of(X86_FEATURE_XSAVEOPT)];
+        else
+            regs[0] = 0;
+        regs[1] = regs[2] = regs[3] = 0;
         break;
 
     case 0x80000000:
@@ -891,17 +780,15 @@ int xc_cpuid_apply_policy(xc_interface *xch, domid_t 
domid,
                 continue;
         }
 
-        /* XSAVE information, subleaves 0-63. */
-        if ( (input[0] == 0xd) && (input[1]++ < 63) )
-            continue;
-
         input[0]++;
         if ( !(input[0] & 0x80000000u) && (input[0] > base_max ) )
             input[0] = 0x80000000u;
 
         input[1] = XEN_CPUID_INPUT_UNUSED;
-        if ( (input[0] == 4) || (input[0] == 7) || (input[0] == 0xd) )
+        if ( (input[0] == 4) || (input[0] == 7) )
             input[1] = 0;
+        else if ( input[0] == 0xd )
+            input[1] = 1; /* Xen automatically calculates almost everything. */
 
         if ( (input[0] & 0x80000000u) && (input[0] > ext_max) )
             break;
-- 
2.1.4


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