diff options
author | Jan Beulich <jbeulich@suse.com> | 2013-08-30 10:56:07 +0200 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2013-08-30 10:56:07 +0200 |
commit | c6066e78f4a66005b0d5d86c6ade32e2ab78923a (patch) | |
tree | 459867cd02ec02d97349a957aca0933a3e7c3c07 /xen/arch/x86/xstate.c | |
parent | a497fc19b20e905d3e1b7bf2a845a243d55e0737 (diff) | |
download | xen-c6066e78f4a66005b0d5d86c6ade32e2ab78923a.tar.gz xen-c6066e78f4a66005b0d5d86c6ade32e2ab78923a.tar.bz2 xen-c6066e78f4a66005b0d5d86c6ade32e2ab78923a.zip |
x86/xsave: initialization improvements
- properly validate available feature set on APs
- also validate xsaveopt availability on APs
- properly indicate whether the initialization is on the BSP (we
shouldn't be using "cpu == 0" checks for this)
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen/arch/x86/xstate.c')
-rw-r--r-- | xen/arch/x86/xstate.c | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c index 2c007062ab..7e459d0256 100644 --- a/xen/arch/x86/xstate.c +++ b/xen/arch/x86/xstate.c @@ -251,11 +251,10 @@ void xstate_free_save_area(struct vcpu *v) } /* Collect the information of processor's extended state */ -void xstate_init(void) +void xstate_init(bool_t bsp) { - u32 eax, ebx, ecx, edx; - int cpu = smp_processor_id(); - u32 min_size; + u32 eax, ebx, ecx, edx, min_size; + u64 feature_mask; if ( boot_cpu_data.cpuid_level < XSTATE_CPUID ) return; @@ -264,6 +263,7 @@ void xstate_init(void) BUG_ON((eax & XSTATE_FP_SSE) != XSTATE_FP_SSE); BUG_ON((eax & XSTATE_YMM) && !(eax & XSTATE_SSE)); + feature_mask = (((u64)edx << 32) | eax) & XCNTXT_MASK; /* FP/SSE, XSAVE.HEADER, YMM */ min_size = XSTATE_AREA_MIN_SIZE; @@ -275,31 +275,33 @@ void xstate_init(void) * Set CR4_OSXSAVE and run "cpuid" to get xsave_cntxt_size. */ set_in_cr4(X86_CR4_OSXSAVE); - if ( !set_xcr0((((u64)edx << 32) | eax) & XCNTXT_MASK) ) + if ( !set_xcr0(feature_mask) ) BUG(); cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx); - if ( cpu == 0 ) + if ( bsp ) { + xfeature_mask = feature_mask; /* * xsave_cntxt_size is the max size required by enabled features. * We know FP/SSE and YMM about eax, and nothing about edx at present. */ xsave_cntxt_size = ebx; - xfeature_mask = eax + ((u64)edx << 32); - xfeature_mask &= XCNTXT_MASK; printk("%s: using cntxt_size: %#x and states: %#"PRIx64"\n", __func__, xsave_cntxt_size, xfeature_mask); - - /* Check XSAVEOPT feature. */ - cpuid_count(XSTATE_CPUID, 1, &eax, &ebx, &ecx, &edx); - cpu_has_xsaveopt = !!(eax & XSTATE_FEATURE_XSAVEOPT); } else { + BUG_ON(xfeature_mask != feature_mask); BUG_ON(xsave_cntxt_size != ebx); - BUG_ON(xfeature_mask != (xfeature_mask & XCNTXT_MASK)); } + + /* Check XSAVEOPT feature. */ + cpuid_count(XSTATE_CPUID, 1, &eax, &ebx, &ecx, &edx); + if ( bsp ) + cpu_has_xsaveopt = !!(eax & XSTATE_FEATURE_XSAVEOPT); + else + BUG_ON(!cpu_has_xsaveopt != !(eax & XSTATE_FEATURE_XSAVEOPT)); } int handle_xsetbv(u32 index, u64 new_bv) |