diff -r f963fa2d256d tools/libxc/xc_cpuid_x86.c --- a/tools/libxc/xc_cpuid_x86.c Wed Dec 22 13:23:55 2010 -0600 +++ b/tools/libxc/xc_cpuid_x86.c Wed Dec 22 14:44:06 2010 -0600 @@ -164,6 +164,58 @@ } } +#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; + } +} + static void xc_cpuid_hvm_policy( xc_interface *xch, domid_t domid, const unsigned int *input, unsigned int *regs) @@ -244,43 +296,7 @@ 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,21 +517,21 @@ 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 ) ) input[0] = 0x80000000u; diff -r f963fa2d256d xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Wed Dec 22 13:23:55 2010 -0600 +++ b/xen/arch/x86/hvm/hvm.c Wed Dec 22 14:44:06 2010 -0600 @@ -2144,6 +2144,24 @@ /* 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 */