From 9d313bdebb86ff4dc663f740e7a9a158e238303d Mon Sep 17 00:00:00 2001 From: Shuai Ruan Date: Fri, 8 Apr 2016 00:04:39 +0200 Subject: [PATCH] x86/xsaves: ebx may return wrong value using CPUID eax=0xd,ecx =1 Refer to SDM Volume 1 Extended Region of an XSAVE Area. The value returned by ecx[1] with cpuid function 0xd and sub-function i (i>1) indicates the alignment of the state component i when the compacted format of the extended region of an xsave area is used. So when hvm guest using CPUID eax=0xd, ecx=1 to get the size of area used for compacted format, we need to take alignment into consideration. tools side is fixed by "tools/libxc: Calculate xstate cpuid leaf from guest information" by Andrew Cooper Signed-off-by: Shuai Ruan Reviewed-by: Jan Beulich --- xen/arch/x86/hvm/hvm.c | 12 ++++++++---- xen/arch/x86/xstate.c | 2 +- xen/include/asm-x86/xstate.h | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index b239f74831..8313cf90d2 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -3432,14 +3432,18 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx, } if ( count == 1 ) { - if ( cpu_has_xsaves && cpu_has_vmx_xsaves ) + uint64_t xfeatures = v->arch.xcr0 | v->arch.hvm_vcpu.msr_xss; + if ( cpu_has_xsaves && cpu_has_vmx_xsaves && xfeatures ) { *ebx = XSTATE_AREA_MIN_SIZE; - if ( v->arch.xcr0 | v->arch.hvm_vcpu.msr_xss ) + if ( xfeatures & ~XSTATE_FP_SSE ) for ( sub_leaf = 2; sub_leaf < 63; sub_leaf++ ) - if ( (v->arch.xcr0 | v->arch.hvm_vcpu.msr_xss) & - (1ULL << sub_leaf) ) + if ( xfeatures & (1ULL << sub_leaf) ) + { + if ( test_bit(sub_leaf, &xstate_align) ) + *ebx = ROUNDUP(*ebx, 64); *ebx += xstate_sizes[sub_leaf]; + } } else *ebx = *ecx = *edx = 0; diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c index 047ac74fa7..48c01957b8 100644 --- a/xen/arch/x86/xstate.c +++ b/xen/arch/x86/xstate.c @@ -26,7 +26,7 @@ u64 __read_mostly xfeature_mask; static unsigned int *__read_mostly xstate_offsets; unsigned int *__read_mostly xstate_sizes; -static u64 __read_mostly xstate_align; +u64 __read_mostly xstate_align; static unsigned int __read_mostly xstate_features; static uint32_t __read_mostly mxcsr_mask = 0x0000ffbf; diff --git a/xen/include/asm-x86/xstate.h b/xen/include/asm-x86/xstate.h index 91d1c391b2..535443ac21 100644 --- a/xen/include/asm-x86/xstate.h +++ b/xen/include/asm-x86/xstate.h @@ -50,6 +50,7 @@ #define XSTATE_ALIGN64 (1U << 1) extern u64 xfeature_mask; +extern u64 xstate_align; extern unsigned int *xstate_sizes; /* extended state save area */ -- 2.30.2