diff options
| author | Paolo Bonzini <pbonzini@redhat.com> | 2018-01-11 16:55:24 +0100 | 
|---|---|---|
| committer | Paolo Bonzini <pbonzini@redhat.com> | 2018-01-11 16:55:24 +0100 | 
| commit | bd89525a823ce6edddcedbe9aed79faa1b9cf544 (patch) | |
| tree | 0fa8919b8016ba59387b83ca38c0d39cf99bbb73 | |
| parent | ab271bd4dfd568060ffcf5a21b667c7c5df7ab99 (diff) | |
KVM: x86: emulate #UD while in guest mode
This reverts commits ae1f57670703656cc9f293722c3b8b6782f8ab3f
and ac9b305caa0df6f5b75d294e4b86c1027648991e.
If the hardware doesn't support MOVBE, but L0 sets CPUID.01H:ECX.MOVBE
in L1's emulated CPUID information, then L1 is likely to pass that
CPUID bit through to L2. L2 will expect MOVBE to work, but if L1
doesn't intercept #UD, then any MOVBE instruction executed in L2 will
raise #UD, and the exception will be delivered in L2.
Commit ac9b305caa0df6f5b75d294e4b86c1027648991e is a better and more
complete version of ae1f57670703 ("KVM: nVMX: Do not emulate #UD while
in guest mode"); however, neither considers the above case.
Suggested-by: Jim Mattson <jmattson@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
| -rw-r--r-- | arch/x86/kvm/svm.c | 9 | ||||
| -rw-r--r-- | arch/x86/kvm/vmx.c | 5 | 
2 files changed, 2 insertions, 12 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index bb31c801f1fc..3158dac87f82 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -361,7 +361,6 @@ static void recalc_intercepts(struct vcpu_svm *svm)  {  	struct vmcb_control_area *c, *h;  	struct nested_state *g; -	u32 h_intercept_exceptions;  	mark_dirty(svm->vmcb, VMCB_INTERCEPTS); @@ -372,14 +371,9 @@ static void recalc_intercepts(struct vcpu_svm *svm)  	h = &svm->nested.hsave->control;  	g = &svm->nested; -	/* No need to intercept #UD if L1 doesn't intercept it */ -	h_intercept_exceptions = -		h->intercept_exceptions & ~(1U << UD_VECTOR); -  	c->intercept_cr = h->intercept_cr | g->intercept_cr;  	c->intercept_dr = h->intercept_dr | g->intercept_dr; -	c->intercept_exceptions = -		h_intercept_exceptions | g->intercept_exceptions; +	c->intercept_exceptions = h->intercept_exceptions | g->intercept_exceptions;  	c->intercept = h->intercept | g->intercept;  } @@ -2202,7 +2196,6 @@ static int ud_interception(struct vcpu_svm *svm)  {  	int er; -	WARN_ON_ONCE(is_guest_mode(&svm->vcpu));  	er = emulate_instruction(&svm->vcpu, EMULTYPE_TRAP_UD);  	if (er == EMULATE_USER_EXIT)  		return 0; diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 5c14d65f676a..427fd3200dd8 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -1887,7 +1887,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)  {  	u32 eb; -	eb = (1u << PF_VECTOR) | (1u << MC_VECTOR) | +	eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) |  	     (1u << DB_VECTOR) | (1u << AC_VECTOR);  	if ((vcpu->guest_debug &  	     (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) == @@ -1905,8 +1905,6 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)  	 */  	if (is_guest_mode(vcpu))  		eb |= get_vmcs12(vcpu)->exception_bitmap; -	else -		eb |= 1u << UD_VECTOR;  	vmcs_write32(EXCEPTION_BITMAP, eb);  } @@ -5917,7 +5915,6 @@ static int handle_exception(struct kvm_vcpu *vcpu)  		return 1;  /* already handled by vmx_vcpu_run() */  	if (is_invalid_opcode(intr_info)) { -		WARN_ON_ONCE(is_guest_mode(vcpu));  		er = emulate_instruction(vcpu, EMULTYPE_TRAP_UD);  		if (er == EMULATE_USER_EXIT)  			return 0;  | 
