Messages in this thread | | | Date | Fri, 29 Jul 2022 14:41:20 +0000 | From | Sean Christopherson <> | Subject | Re: [PATCHv2 4/7] KVM: SVM: Report NMI not allowed when Guest busy handling VNMI |
| |
On Fri, Jul 29, 2022, Shukla, Santosh wrote: > Hello Sean, > > On 7/21/2022 3:24 AM, Sean Christopherson wrote: > > On Sat, Jul 09, 2022, Santosh Shukla wrote:
...
> >> @@ -3609,6 +3612,9 @@ static void svm_enable_nmi_window(struct kvm_vcpu *vcpu) > >> { > >> struct vcpu_svm *svm = to_svm(vcpu); > >> > >> + if (is_vnmi_enabled(svm)) > >> + return; > > > > Ugh, is there really no way to trigger an exit when NMIs become unmasked? Because > > if there isn't, this is broken for KVM. > > > > Yes. there is. > > NMI_INTERCEPT will trigger VMEXIT when second NMI arrives while guest is busy handling first NMI.
But NMI_INTERCEPT only applies to "real" NMIs. The scenario laid out below is where KVM wants to inject a virtual NMI without an associated hardware/real NMI, e.g. if multiple vCPUs send NMI IPIs to the target.
> And in that scenario, Guest will exit with V_NMI_MASK set to 1, KVM can inject pending(Second) > NMI(V_NMI=1). Guest will resume handling the first NMI, then HW will > clear the V_NMI_MASK and later HW will take the pending V_NMI in side the guest. > > I'll handle above case in v3. > > Thanks, > Santosh > > > On bare metal, if two NMIs arrive "simultaneously", so long as NMIs aren't blocked, > > the first NMI will be delivered and the second will be pended, i.e. software will > > see both NMIs. And if that doesn't hold true, the window for a true collision is > > really, really tiny. > > > > But in KVM, because a vCPU may not be run a long duration, that window becomes > > very large. To not drop NMIs and more faithfully emulate hardware, KVM allows two > > NMIs to be _pending_. And when that happens, KVM needs to trigger an exit when > > NMIs become unmasked _after_ the first NMI is injected. > > > >> + > >> if ((vcpu->arch.hflags & (HF_NMI_MASK | HF_IRET_MASK)) == HF_NMI_MASK) > >> return; /* IRET will cause a vm exit */ > >> > >> -- > >> 2.25.1 > >>
| |