From 6c68094c84d62eaba4a4a1faa67317603c36f9bd Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 12 Sep 2013 11:18:00 +0200 Subject: 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 Acked-by: Keir Fraser master commit: c6066e78f4a66005b0d5d86c6ade32e2ab78923a master date: 2013-08-30 10:56:07 +0200 --- xen/arch/x86/cpu/common.c | 2 +- xen/arch/x86/xstate.c | 28 +++++++++++++++------------- xen/include/asm-x86/xstate.h | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c index 24c3dd89ac..e1220e658c 100644 --- a/xen/arch/x86/cpu/common.c +++ b/xen/arch/x86/cpu/common.c @@ -304,7 +304,7 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c) clear_bit(X86_FEATURE_XSAVE, boot_cpu_data.x86_capability); if ( cpu_has_xsave ) - xstate_init(); + xstate_init(c == &boot_cpu_data); /* * The vendor-specific functions might have changed features. Now diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c index ce94d282f2..3e7dc5333e 100644 --- a/xen/arch/x86/xstate.c +++ b/xen/arch/x86/xstate.c @@ -247,11 +247,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; @@ -260,6 +259,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; @@ -271,31 +271,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) diff --git a/xen/include/asm-x86/xstate.h b/xen/include/asm-x86/xstate.h index 49168f3293..e3bb271ca9 100644 --- a/xen/include/asm-x86/xstate.h +++ b/xen/include/asm-x86/xstate.h @@ -81,6 +81,6 @@ int __must_check handle_xsetbv(u32 index, u64 new_bv); /* extended state init and cleanup functions */ void xstate_free_save_area(struct vcpu *v); int xstate_alloc_save_area(struct vcpu *v); -void xstate_init(void); +void xstate_init(bool_t bsp); #endif /* __ASM_XSTATE_H */ -- cgit v1.2.3