diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-05-25 09:11:19 +0200 | 
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-05-25 09:11:19 +0200 | 
| commit | c2312ff575fcaed96889d5bb5392afcc604c9442 (patch) | |
| tree | 475d63360ee17732fac41c7c1e4a1636ed92e7cb /arch/x86/kvm/svm/nested.c | |
| parent | a3975dea1696b7c81319dc4b66e3c378dd47ccfb (diff) | |
| parent | 9cb1fd0efd195590b828b9b865421ad345a4a145 (diff) | |
Merge 5.7-rc7 into staging-next
We need the staging/iio fixes in here as well.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch/x86/kvm/svm/nested.c')
| -rw-r--r-- | arch/x86/kvm/svm/nested.c | 39 | 
1 files changed, 31 insertions, 8 deletions
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 90a1ca939627..9a2a62e5afeb 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -19,6 +19,7 @@  #include <linux/kernel.h>  #include <asm/msr-index.h> +#include <asm/debugreg.h>  #include "kvm_emulate.h"  #include "trace.h" @@ -267,7 +268,7 @@ void enter_svm_guest_mode(struct vcpu_svm *svm, u64 vmcb_gpa,  	svm->vmcb->save.rsp = nested_vmcb->save.rsp;  	svm->vmcb->save.rip = nested_vmcb->save.rip;  	svm->vmcb->save.dr7 = nested_vmcb->save.dr7; -	svm->vmcb->save.dr6 = nested_vmcb->save.dr6; +	svm->vcpu.arch.dr6  = nested_vmcb->save.dr6;  	svm->vmcb->save.cpl = nested_vmcb->save.cpl;  	svm->nested.vmcb_msrpm = nested_vmcb->control.msrpm_base_pa & ~0x0fffULL; @@ -482,7 +483,7 @@ int nested_svm_vmexit(struct vcpu_svm *svm)  	nested_vmcb->save.rsp    = vmcb->save.rsp;  	nested_vmcb->save.rax    = vmcb->save.rax;  	nested_vmcb->save.dr7    = vmcb->save.dr7; -	nested_vmcb->save.dr6    = vmcb->save.dr6; +	nested_vmcb->save.dr6    = svm->vcpu.arch.dr6;  	nested_vmcb->save.cpl    = vmcb->save.cpl;  	nested_vmcb->control.int_ctl           = vmcb->control.int_ctl; @@ -606,26 +607,45 @@ static int nested_svm_exit_handled_msr(struct vcpu_svm *svm)  /* DB exceptions for our internal use must not cause vmexit */  static int nested_svm_intercept_db(struct vcpu_svm *svm)  { -	unsigned long dr6; +	unsigned long dr6 = svm->vmcb->save.dr6; + +	/* Always catch it and pass it to userspace if debugging.  */ +	if (svm->vcpu.guest_debug & +	    (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) +		return NESTED_EXIT_HOST;  	/* if we're not singlestepping, it's not ours */  	if (!svm->nmi_singlestep) -		return NESTED_EXIT_DONE; +		goto reflected_db;  	/* if it's not a singlestep exception, it's not ours */ -	if (kvm_get_dr(&svm->vcpu, 6, &dr6)) -		return NESTED_EXIT_DONE;  	if (!(dr6 & DR6_BS)) -		return NESTED_EXIT_DONE; +		goto reflected_db;  	/* if the guest is singlestepping, it should get the vmexit */  	if (svm->nmi_singlestep_guest_rflags & X86_EFLAGS_TF) {  		disable_nmi_singlestep(svm); -		return NESTED_EXIT_DONE; +		goto reflected_db;  	}  	/* it's ours, the nested hypervisor must not see this one */  	return NESTED_EXIT_HOST; + +reflected_db: +	/* +	 * Synchronize guest DR6 here just like in kvm_deliver_exception_payload; +	 * it will be moved into the nested VMCB by nested_svm_vmexit.  Once +	 * exceptions will be moved to svm_check_nested_events, all this stuff +	 * will just go away and we could just return NESTED_EXIT_HOST +	 * unconditionally.  db_interception will queue the exception, which +	 * will be processed by svm_check_nested_events if a nested vmexit is +	 * required, and we will just use kvm_deliver_exception_payload to copy +	 * the payload to DR6 before vmexit. +	 */ +	WARN_ON(svm->vcpu.arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT); +	svm->vcpu.arch.dr6 &= ~(DR_TRAP_BITS | DR6_RTM); +	svm->vcpu.arch.dr6 |= dr6 & ~DR6_FIXED_1; +	return NESTED_EXIT_DONE;  }  static int nested_svm_intercept_ioio(struct vcpu_svm *svm) @@ -682,6 +702,9 @@ static int nested_svm_intercept(struct vcpu_svm *svm)  		if (svm->nested.intercept_exceptions & excp_bits) {  			if (exit_code == SVM_EXIT_EXCP_BASE + DB_VECTOR)  				vmexit = nested_svm_intercept_db(svm); +			else if (exit_code == SVM_EXIT_EXCP_BASE + BP_VECTOR && +				 svm->vcpu.guest_debug & KVM_GUESTDBG_USE_SW_BP) +				vmexit = NESTED_EXIT_HOST;  			else  				vmexit = NESTED_EXIT_DONE;  		}  | 
