Message ID | 20210323175006.73249-2-krish.sadhukhan@oracle.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | nSVM: Test host RFLAGS.TF on VMRUN | expand |
On 23/03/21 18:50, Krish Sadhukhan wrote: > According to APM, the #DB intercept for a single-stepped VMRUN must happen > after the completion of that instruction, when the guest does #VMEXIT to > the host. However, in the current implementation of KVM, the #DB intercept > for a single-stepped VMRUN happens after the completion of the instruction > that follows the VMRUN instruction. When the #DB intercept handler is > invoked, it shows the RIP of the instruction that follows VMRUN, instead of > of VMRUN itself. This is an incorrect RIP as far as single-stepping VMRUN > is concerned. > > This patch fixes the problem by checking, in nested_svm_vmexit(), for the > condition that the VMRUN instruction is being single-stepped and if so, > queues the pending #DB intercept so that the #DB is accounted for before > we execute L1's next instruction. > > Suggested-by: Paolo Bonzini <pbonzini@redhat.com> > Signed-off-by: Krish Sadhukhan <krish.sadhukhan@oraacle.com> > --- > arch/x86/kvm/svm/nested.c | 10 ++++++++++ > 1 file changed, 10 insertions(+) > > diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c > index 35891d9a1099..713ce5cfb0db 100644 > --- a/arch/x86/kvm/svm/nested.c > +++ b/arch/x86/kvm/svm/nested.c > @@ -720,6 +720,16 @@ int nested_svm_vmexit(struct vcpu_svm *svm) > kvm_clear_exception_queue(&svm->vcpu); > kvm_clear_interrupt_queue(&svm->vcpu); > > + /* > + * If we are here following the completion of a VMRUN that > + * is being single-stepped, queue the pending #DB intercept > + * right now so that it an be accounted for before we execute > + * L1's next instruction. > + */ > + if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_VMRUN && > + svm->vmcb->save.rflags & X86_EFLAGS_TF)) > + kvm_queue_exception(&(svm->vcpu), DB_VECTOR); > + > return 0; > } Wouldn't the exit code always be SVM_EXIT_VMRUN after the vmcb01/vmcb02 split? I can take care of adding a WARN_ON myself, but I wouldn't mind if you checked that my reasoning is true. :) Paolo
On 3/26/21 10:32 AM, Paolo Bonzini wrote: > On 23/03/21 18:50, Krish Sadhukhan wrote: >> According to APM, the #DB intercept for a single-stepped VMRUN must >> happen >> after the completion of that instruction, when the guest does #VMEXIT to >> the host. However, in the current implementation of KVM, the #DB >> intercept >> for a single-stepped VMRUN happens after the completion of the >> instruction >> that follows the VMRUN instruction. When the #DB intercept handler is >> invoked, it shows the RIP of the instruction that follows VMRUN, >> instead of >> of VMRUN itself. This is an incorrect RIP as far as single-stepping >> VMRUN >> is concerned. >> >> This patch fixes the problem by checking, in nested_svm_vmexit(), for >> the >> condition that the VMRUN instruction is being single-stepped and if so, >> queues the pending #DB intercept so that the #DB is accounted for before >> we execute L1's next instruction. >> >> Suggested-by: Paolo Bonzini <pbonzini@redhat.com> >> Signed-off-by: Krish Sadhukhan <krish.sadhukhan@oraacle.com> >> --- >> arch/x86/kvm/svm/nested.c | 10 ++++++++++ >> 1 file changed, 10 insertions(+) >> >> diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c >> index 35891d9a1099..713ce5cfb0db 100644 >> --- a/arch/x86/kvm/svm/nested.c >> +++ b/arch/x86/kvm/svm/nested.c >> @@ -720,6 +720,16 @@ int nested_svm_vmexit(struct vcpu_svm *svm) >> kvm_clear_exception_queue(&svm->vcpu); >> kvm_clear_interrupt_queue(&svm->vcpu); >> + /* >> + * If we are here following the completion of a VMRUN that >> + * is being single-stepped, queue the pending #DB intercept >> + * right now so that it an be accounted for before we execute >> + * L1's next instruction. >> + */ >> + if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_VMRUN && >> + svm->vmcb->save.rflags & X86_EFLAGS_TF)) >> + kvm_queue_exception(&(svm->vcpu), DB_VECTOR); >> + >> return 0; >> } > > Wouldn't the exit code always be SVM_EXIT_VMRUN after the > vmcb01/vmcb02 split? I can take care of adding a WARN_ON myself, but > I wouldn't mind if you checked that my reasoning is true. :) Looking at the patchset on "vmcb01/vmcb02 split", I see that we are calling svm_switch_vmcb(svm, &svm->vmcb01) in nested_svm_vmexiit(). So, yes, by the time we reach the above check we should always have an exit code of SVM_EXIT_VMRUN. > > Paolo >
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 35891d9a1099..713ce5cfb0db 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -720,6 +720,16 @@ int nested_svm_vmexit(struct vcpu_svm *svm) kvm_clear_exception_queue(&svm->vcpu); kvm_clear_interrupt_queue(&svm->vcpu); + /* + * If we are here following the completion of a VMRUN that + * is being single-stepped, queue the pending #DB intercept + * right now so that it an be accounted for before we execute + * L1's next instruction. + */ + if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_VMRUN && + svm->vmcb->save.rflags & X86_EFLAGS_TF)) + kvm_queue_exception(&(svm->vcpu), DB_VECTOR); + return 0; }
According to APM, the #DB intercept for a single-stepped VMRUN must happen after the completion of that instruction, when the guest does #VMEXIT to the host. However, in the current implementation of KVM, the #DB intercept for a single-stepped VMRUN happens after the completion of the instruction that follows the VMRUN instruction. When the #DB intercept handler is invoked, it shows the RIP of the instruction that follows VMRUN, instead of of VMRUN itself. This is an incorrect RIP as far as single-stepping VMRUN is concerned. This patch fixes the problem by checking, in nested_svm_vmexit(), for the condition that the VMRUN instruction is being single-stepped and if so, queues the pending #DB intercept so that the #DB is accounted for before we execute L1's next instruction. Suggested-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Krish Sadhukhan <krish.sadhukhan@oraacle.com> --- arch/x86/kvm/svm/nested.c | 10 ++++++++++ 1 file changed, 10 insertions(+)