Currently, svm_vcpu_run() advances the RIP following VMRUN completion when control returns to host. This works fine if there is no trap flag set on the VMRUN instruction i.e., if VMRUN is not single-stepped. But if VMRUN is single-stepped, this advancement of the RIP leads to an incorrect RIP in the #DB handler invoked for the single-step trap. Therefore, check if the VMRUN instruction is single-stepped and if so, do not advance the RIP when the #DB intercept #VMEXIT happens. Signed-off-by: Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxxx> --- arch/x86/kvm/svm/svm.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 3442d44ca53b..427d32213f51 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -3740,6 +3740,8 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, instrumentation_end(); } +static bool single_step_vmrun = false; + static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); @@ -3800,6 +3802,10 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu) svm_vcpu_enter_exit(vcpu, svm); + if (svm->vmcb->control.exit_code == SVM_EXIT_VMRUN && + (svm->vmcb->save.rflags & X86_EFLAGS_TF)) + single_step_vmrun = true; + /* * We do not use IBRS in the kernel. If this vCPU has used the * SPEC_CTRL MSR it may have left it on; save the value and @@ -3827,7 +3833,11 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu) vcpu->arch.cr2 = svm->vmcb->save.cr2; vcpu->arch.regs[VCPU_REGS_RAX] = svm->vmcb->save.rax; vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp; - vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip; + if (single_step_vmrun && svm->vmcb->control.exit_code == + SVM_EXIT_EXCP_BASE + DB_VECTOR) + single_step_vmrun = false; + else + vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip; } if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI)) -- 2.27.0