diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2020-05-22 07:38:20 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2020-06-01 04:26:00 -0400 |
commit | d8e4e58f4bd4bb55d2640a841c3606333930f0e1 (patch) | |
tree | 614567b8fb5ca0dfcb2e3cd07bed858d1b9cc1b2 /arch/x86/kvm | |
parent | e670bf68f4b701506d51f007917ab633894294d0 (diff) | |
download | linux-d8e4e58f4bd4bb55d2640a841c3606333930f0e1.tar.bz2 |
KVM: nSVM: restore clobbered INT_CTL fields after clearing VINTR
Restore the INT_CTL value from the guest's VMCB once we've stopped using
it, so that virtual interrupts can be injected as requested by L1.
V_TPR is up-to-date however, and it can change if the guest writes to CR8,
so keep it.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r-- | arch/x86/kvm/svm/svm.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index ec98c5979656..4122ba86bac2 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -1365,9 +1365,17 @@ static void svm_set_vintr(struct vcpu_svm *svm) static void svm_clear_vintr(struct vcpu_svm *svm) { + const u32 mask = V_TPR_MASK | V_GIF_ENABLE_MASK | V_GIF_MASK | V_INTR_MASKING_MASK; clr_intercept(svm, INTERCEPT_VINTR); - svm->vmcb->control.int_ctl &= ~V_IRQ_MASK; + /* Drop int_ctl fields related to VINTR injection. */ + svm->vmcb->control.int_ctl &= mask; + if (is_guest_mode(&svm->vcpu)) { + WARN_ON((svm->vmcb->control.int_ctl & V_TPR_MASK) != + (svm->nested.ctl.int_ctl & V_TPR_MASK)); + svm->vmcb->control.int_ctl |= svm->nested.ctl.int_ctl & ~mask; + } + mark_dirty(svm->vmcb, VMCB_INTR); } |