summaryrefslogtreecommitdiff
path: root/arch/x86/kvm/svm/svm.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2020-04-23 18:02:45 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2020-05-13 12:14:44 -0400
commitfc6f7c03ad80693c953d5cdacfad41f174289531 (patch)
tree0eae46385cc52fa46f7ec48ea109e60c39db9214 /arch/x86/kvm/svm/svm.c
parent1cd2f0b0dd9218fd11ced9ac97237f0c9517f49e (diff)
downloadlwn-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.c23
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)