diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2020-04-23 18:02:45 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2020-05-13 12:14:44 -0400 |
commit | fc6f7c03ad80693c953d5cdacfad41f174289531 (patch) | |
tree | 0eae46385cc52fa46f7ec48ea109e60c39db9214 /arch/x86/kvm/svm/svm.c | |
parent | 1cd2f0b0dd9218fd11ced9ac97237f0c9517f49e (diff) | |
download | lwn-fc6f7c03ad80693c953d5cdacfad41f174289531.tar.gz lwn-fc6f7c03ad80693c953d5cdacfad41f174289531.zip |
KVM: nSVM: Report interrupts as allowed when in L2 and exit-on-interrupt is set
Report interrupts as allowed when the vCPU is in L2 and L2 is being run with
exit-on-interrupts enabled and EFLAGS.IF=1 (either on the host or on the guest
according to VINTR). Interrupts are always unblocked from L1's perspective
in this case.
While moving nested_exit_on_intr to svm.h, use INTERCEPT_INTR properly instead
of assuming it's zero (which it is of course).
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm/svm/svm.c')
-rw-r--r-- | arch/x86/kvm/svm/svm.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 5738be661a1f..fba8bdcfed0e 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -3117,14 +3117,25 @@ bool svm_interrupt_blocked(struct kvm_vcpu *vcpu) struct vcpu_svm *svm = to_svm(vcpu); struct vmcb *vmcb = svm->vmcb; - if (!gif_set(svm) || - (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK)) + if (!gif_set(svm)) return true; - if (is_guest_mode(vcpu) && (svm->vcpu.arch.hflags & HF_VINTR_MASK)) - return !(svm->vcpu.arch.hflags & HF_HIF_MASK); - else - return !(kvm_get_rflags(vcpu) & X86_EFLAGS_IF); + if (is_guest_mode(vcpu)) { + /* As long as interrupts are being delivered... */ + if ((svm->vcpu.arch.hflags & HF_VINTR_MASK) + ? !(svm->vcpu.arch.hflags & HF_HIF_MASK) + : !(kvm_get_rflags(vcpu) & X86_EFLAGS_IF)) + return true; + + /* ... vmexits aren't blocked by the interrupt shadow */ + if (nested_exit_on_intr(svm)) + return false; + } else { + if (!(kvm_get_rflags(vcpu) & X86_EFLAGS_IF)) + return true; + } + + return (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK); } static bool svm_interrupt_allowed(struct kvm_vcpu *vcpu) |