On Mon, May 31, 2010 at 07:54:11PM +0800, Sheng Yang wrote: > diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c > index 99ae513..8649627 100644 > --- a/arch/x86/kvm/vmx.c > +++ b/arch/x86/kvm/vmx.c > @@ -36,6 +36,8 @@ > #include <asm/vmx.h> > #include <asm/virtext.h> > #include <asm/mce.h> > +#include <asm/i387.h> > +#include <asm/xcr.h> > > #include "trace.h" > > @@ -3354,6 +3356,16 @@ static int handle_wbinvd(struct kvm_vcpu *vcpu) > return 1; > } > > +static int handle_xsetbv(struct kvm_vcpu *vcpu) > +{ > + u64 new_bv = kvm_read_edx_eax(vcpu); > + u32 index = kvm_register_read(vcpu, VCPU_REGS_RCX); > + > + kvm_set_xcr(vcpu, index, new_bv); > + skip_emulated_instruction(vcpu); Should only skip_emulated_instruction if no exception was injected. > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 7be1d36..0fcd8de 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > +int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) > +{ > + u64 xcr0; > + > + /* Only support XCR_XFEATURE_ENABLED_MASK(xcr0) now */ > + if (index != XCR_XFEATURE_ENABLED_MASK) > + return 1; > + xcr0 = xcr; > + if (kvm_x86_ops->get_cpl(vcpu) != 0) > + return 1; > + if (!(xcr0 & XSTATE_FP)) > + return 1; > + if ((xcr0 & XSTATE_YMM) && !(xcr0 & XSTATE_SSE)) > + return 1; > + if (xcr0 & ~host_xcr0) > + return 1; > + vcpu->arch.xcr0 = xcr0; > + xsetbv(XCR_XFEATURE_ENABLED_MASK, vcpu->arch.xcr0); Won't this happen on guest entry, since vcpu->guest_xcr0_loaded == 0? > @@ -4522,6 +4602,24 @@ static void inject_pending_event(struct kvm_vcpu *vcpu) > } > } > > +static void kvm_load_guest_xcr0(struct kvm_vcpu *vcpu) > +{ > + if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE) && > + !vcpu->guest_xcr0_loaded) { > + xsetbv(XCR_XFEATURE_ENABLED_MASK, vcpu->arch.xcr0); Only necessary if guest and hosts XCR0 differ? > + vcpu->guest_xcr0_loaded = 1; > + } > +} > + > +static void kvm_put_guest_xcr0(struct kvm_vcpu *vcpu) > +{ > + if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE) && > + vcpu->guest_xcr0_loaded) { > + xsetbv(XCR_XFEATURE_ENABLED_MASK, host_xcr0); > + vcpu->guest_xcr0_loaded = 0; > + } > +} What if you load guest's XCR0, then guest clears CR4.OSXSAVE? (restore of host_xcr0 should be conditional on guest_xcr0_loaded only). > + > static int vcpu_enter_guest(struct kvm_vcpu *vcpu) > { > int r; > @@ -4567,6 +4665,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) > kvm_x86_ops->prepare_guest_switch(vcpu); > if (vcpu->fpu_active) > kvm_load_guest_fpu(vcpu); > + kvm_load_guest_xcr0(vcpu); > > atomic_set(&vcpu->guest_mode, 1); > smp_wmb(); > @@ -5118,6 +5217,11 @@ void fx_init(struct kvm_vcpu *vcpu) > fpu_alloc(&vcpu->arch.guest_fpu); > fpu_finit(&vcpu->arch.guest_fpu); > > + /* > + * Ensure guest xcr0 is valid for loading > + */ > + vcpu->arch.xcr0 = XSTATE_FP; > + > vcpu->arch.cr0 |= X86_CR0_ET; > } > EXPORT_SYMBOL_GPL(fx_init); > @@ -5132,6 +5236,12 @@ void kvm_load_guest_fpu(struct kvm_vcpu *vcpu) > if (vcpu->guest_fpu_loaded) > return; > > + /* > + * Restore all possible states in the guest, > + * and assume host would use all available bits. > + * Guest xcr0 would be loaded later. > + */ > + kvm_put_guest_xcr0(vcpu); > vcpu->guest_fpu_loaded = 1; > unlazy_fpu(current); > fpu_restore_checking(&vcpu->arch.guest_fpu); > @@ -5140,6 +5250,8 @@ void kvm_load_guest_fpu(struct kvm_vcpu *vcpu) > > void kvm_put_guest_fpu(struct kvm_vcpu *vcpu) > { > + kvm_put_guest_xcr0(vcpu); > + Should be in kvm_arch_vcpu_put? > if (!vcpu->guest_fpu_loaded) > return; > > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h > index 4e8fdbf..3784d58 100644 > --- a/include/linux/kvm_host.h > +++ b/include/linux/kvm_host.h > @@ -88,7 +88,7 @@ struct kvm_vcpu { > int srcu_idx; > > int fpu_active; > - int guest_fpu_loaded; > + int guest_fpu_loaded, guest_xcr0_loaded; > wait_queue_head_t wq; > int sigset_active; > sigset_t sigset; > -- > 1.7.0.1 > > -- > To unsubscribe from this list: send the line "unsubscribe kvm" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html