diff options
Diffstat (limited to 'arch/x86/kvm/vmx.c')
| -rw-r--r-- | arch/x86/kvm/vmx.c | 25 | 
1 files changed, 16 insertions, 9 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 14873b9f843..bc933cfb4e6 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -26,6 +26,7 @@  #include <linux/sched.h>  #include <linux/moduleparam.h>  #include <linux/ftrace_event.h> +#include <linux/slab.h>  #include "kvm_cache_regs.h"  #include "x86.h" @@ -76,6 +77,8 @@ module_param(emulate_invalid_guest_state, bool, S_IRUGO);  #define KVM_PMODE_VM_CR4_ALWAYS_ON (X86_CR4_PAE | X86_CR4_VMXE)  #define KVM_RMODE_VM_CR4_ALWAYS_ON (X86_CR4_VME | X86_CR4_PAE | X86_CR4_VMXE) +#define RMODE_GUEST_OWNED_EFLAGS_BITS (~(X86_EFLAGS_IOPL | X86_EFLAGS_VM)) +  /*   * These 2 parameters are used to config the controls for Pause-Loop Exiting:   * ple_gap:    upper bound on the amount of time between two successive @@ -130,7 +133,7 @@ struct vcpu_vmx {  	} host_state;  	struct {  		int vm86_active; -		u8 save_iopl; +		ulong save_rflags;  		struct kvm_save_segment {  			u16 selector;  			unsigned long base; @@ -817,18 +820,23 @@ static void vmx_fpu_deactivate(struct kvm_vcpu *vcpu)  static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)  { -	unsigned long rflags; +	unsigned long rflags, save_rflags;  	rflags = vmcs_readl(GUEST_RFLAGS); -	if (to_vmx(vcpu)->rmode.vm86_active) -		rflags &= ~(unsigned long)(X86_EFLAGS_IOPL | X86_EFLAGS_VM); +	if (to_vmx(vcpu)->rmode.vm86_active) { +		rflags &= RMODE_GUEST_OWNED_EFLAGS_BITS; +		save_rflags = to_vmx(vcpu)->rmode.save_rflags; +		rflags |= save_rflags & ~RMODE_GUEST_OWNED_EFLAGS_BITS; +	}  	return rflags;  }  static void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)  { -	if (to_vmx(vcpu)->rmode.vm86_active) +	if (to_vmx(vcpu)->rmode.vm86_active) { +		to_vmx(vcpu)->rmode.save_rflags = rflags;  		rflags |= X86_EFLAGS_IOPL | X86_EFLAGS_VM; +	}  	vmcs_writel(GUEST_RFLAGS, rflags);  } @@ -1482,8 +1490,8 @@ static void enter_pmode(struct kvm_vcpu *vcpu)  	vmcs_write32(GUEST_TR_AR_BYTES, vmx->rmode.tr.ar);  	flags = vmcs_readl(GUEST_RFLAGS); -	flags &= ~(X86_EFLAGS_IOPL | X86_EFLAGS_VM); -	flags |= (vmx->rmode.save_iopl << IOPL_SHIFT); +	flags &= RMODE_GUEST_OWNED_EFLAGS_BITS; +	flags |= vmx->rmode.save_rflags & ~RMODE_GUEST_OWNED_EFLAGS_BITS;  	vmcs_writel(GUEST_RFLAGS, flags);  	vmcs_writel(GUEST_CR4, (vmcs_readl(GUEST_CR4) & ~X86_CR4_VME) | @@ -1556,8 +1564,7 @@ static void enter_rmode(struct kvm_vcpu *vcpu)  	vmcs_write32(GUEST_TR_AR_BYTES, 0x008b);  	flags = vmcs_readl(GUEST_RFLAGS); -	vmx->rmode.save_iopl -		= (flags & X86_EFLAGS_IOPL) >> IOPL_SHIFT; +	vmx->rmode.save_rflags = flags;  	flags |= X86_EFLAGS_IOPL | X86_EFLAGS_VM;  |