[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |