]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: SVM: Handle event vectoring error in check_emulate_instruction()
authorIvan Orlov <iorlov@amazon.com>
Tue, 17 Dec 2024 18:14:56 +0000 (18:14 +0000)
committerSean Christopherson <seanjc@google.com>
Wed, 18 Dec 2024 23:14:45 +0000 (15:14 -0800)
Detect unhandleable vectoring in check_emulate_instruction() to prevent
infinite retry loops on SVM, and to eliminate the main differences in how
VM-Exits during event vectoring are handled on SVM versus VMX.  E.g. if
the vCPU puts its IDT in emulated MMIO memory and generates an event,
without the check_emulate_instruction() change, SVM will re-inject the
event and resume the guest, and effectively put the vCPU into an infinite
loop.

Signed-off-by: Ivan Orlov <iorlov@amazon.com>
Link: https://lore.kernel.org/r/20241217181458.68690-6-iorlov@amazon.com
[sean: grab "svm" locally, massage changelog]
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/svm/svm.c

index 07911ddf1efefe619fe1ebd12a9ebff2196a3cf9..8fc2f4a97495ee57e9ace0a60f098ad4050a63d5 100644 (file)
@@ -4789,9 +4789,15 @@ static void svm_enable_smi_window(struct kvm_vcpu *vcpu)
 static int svm_check_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
                                         void *insn, int insn_len)
 {
+       struct vcpu_svm *svm = to_svm(vcpu);
        bool smep, smap, is_user;
        u64 error_code;
 
+       /* Check that emulation is possible during event vectoring */
+       if ((svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_TYPE_MASK) &&
+           !kvm_can_emulate_event_vectoring(emul_type))
+               return X86EMUL_UNHANDLEABLE_VECTORING;
+
        /* Emulation is always possible when KVM has access to all guest state. */
        if (!sev_guest(vcpu->kvm))
                return X86EMUL_CONTINUE;
@@ -4888,7 +4894,7 @@ static int svm_check_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
         * In addition, don't apply the erratum workaround if the #NPF occurred
         * while translating guest page tables (see below).
         */
-       error_code = to_svm(vcpu)->vmcb->control.exit_info_1;
+       error_code = svm->vmcb->control.exit_info_1;
        if (error_code & (PFERR_GUEST_PAGE_MASK | PFERR_FETCH_MASK))
                goto resume_guest;