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