diff -r 343470b5ad6b xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Tue May 03 14:05:28 2011 -0500 +++ b/xen/arch/x86/hvm/svm/svm.c Thu May 05 16:40:41 2011 -0500 @@ -716,7 +716,7 @@ unsigned int eax, ebx, ecx, edx; uint32_t msr_low; - if ( cpu_has_lwp ) + if ( xsave_enabled(v) && cpu_has_lwp ) { hvm_cpuid(0x8000001c, &eax, &ebx, &ecx, &edx); msr_low = (uint32_t)msr_content; @@ -729,6 +729,9 @@ /* CPU might automatically correct reserved bits. So read it back. */ rdmsrl(MSR_AMD64_LWP_CFG, msr_content); v->arch.hvm_svm.guest_lwp_cfg = msr_content; + + /* track nonalzy state if LWP_CFG is non-zero. */ + v->arch.nonlazy_xstate_dirty = !!(msr_content); } return 0; diff -r 343470b5ad6b xen/arch/x86/i387.c --- a/xen/arch/x86/i387.c Tue May 03 14:05:28 2011 -0500 +++ b/xen/arch/x86/i387.c Thu May 05 16:40:41 2011 -0500 @@ -98,13 +98,13 @@ /* FPU Save Functions */ /*******************************/ /* Save x87 extended state */ -static inline void fpu_xsave(struct vcpu *v, uint64_t mask) +static inline void fpu_xsave(struct vcpu *v) { /* XCR0 normally represents what guest OS set. In case of Xen itself, * we set all accumulated feature mask before doing save/restore. */ set_xcr0(v->arch.xcr0_accum); - xsave(v, mask); + xsave(v, v->arch.nonlazy_xstate_dirty ? XSTATE_ALL : XSTATE_LAZY); set_xcr0(v->arch.xcr0); } @@ -164,15 +164,15 @@ void vcpu_restore_fpu_eager(struct vcpu *v) { ASSERT(!is_idle_vcpu(v)); - - /* Avoid recursion */ - clts(); /* save the nonlazy extended state which is not tracked by CR0.TS bit */ - if ( xsave_enabled(v) ) + if ( xsave_enabled(v) && v->arch.nonlazy_xstate_dirty ) + { + /* Avoid recursion */ + clts(); fpu_xrstor(v, XSTATE_NONLAZY); - - stts(); + stts(); + } } /* @@ -219,7 +219,7 @@ clts(); if ( xsave_enabled(v) ) - fpu_xsave(v, XSTATE_ALL); + fpu_xsave(v); else if ( cpu_has_fxsr ) fpu_fxsave(v); else diff -r 343470b5ad6b xen/include/asm-x86/domain.h --- a/xen/include/asm-x86/domain.h Tue May 03 14:05:28 2011 -0500 +++ b/xen/include/asm-x86/domain.h Thu May 05 16:40:41 2011 -0500 @@ -492,6 +492,9 @@ * it explicitly enables it via xcr0. */ uint64_t xcr0_accum; + /* This variable determines whether nonlazy extended state is dirty and + * needs to be tracked. */ + bool_t nonlazy_xstate_dirty; struct paging_vcpu paging;