]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: x86: Add emulation status for unhandleable exception vectoring
authorIvan Orlov <iorlov@amazon.com>
Tue, 17 Dec 2024 18:14:53 +0000 (18:14 +0000)
committerSean Christopherson <seanjc@google.com>
Wed, 18 Dec 2024 23:14:42 +0000 (15:14 -0800)
Add emulation status for unhandleable vectoring, i.e. when KVM can't
emulate an instruction because emulation was triggered on an exit that
occurred while the CPU was vectoring an event.  Such a situation can
occur if guest sets the IDT descriptor base to point to MMIO region,
and triggers an exception after that.

Exit to userspace with event delivery error when KVM can't emulate
an instruction when vectoring an event.

Signed-off-by: Ivan Orlov <iorlov@amazon.com>
Link: https://lore.kernel.org/r/20241217181458.68690-3-iorlov@amazon.com
[sean: massage changelog and X86EMUL_UNHANDLEABLE_VECTORING comment]
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/kvm_emulate.h
arch/x86/kvm/x86.c

index 10495fffb8905ca0836cc7eba8e8439ff86eadd9..73072585e1642c344bc32952294efbfab46a78b1 100644 (file)
@@ -88,6 +88,8 @@ struct x86_instruction_info {
 #define X86EMUL_CMPXCHG_FAILED  4 /* cmpxchg did not see expected value */
 #define X86EMUL_IO_NEEDED       5 /* IO is needed to complete emulation */
 #define X86EMUL_INTERCEPTED     6 /* Intercepted by nested VMCB/VMCS */
+/* Emulation during event vectoring is unhandleable. */
+#define X86EMUL_UNHANDLEABLE_VECTORING 7
 
 /* x86-specific emulation flags */
 #define X86EMUL_F_WRITE                        BIT(0)
index 7fcdfafb25a24cda3fa65879bb2e162904fdcbe2..26dd74512b677a4c0830cabc7390ed772ff6cc86 100644 (file)
@@ -9098,6 +9098,11 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
                if (r == X86EMUL_RETRY_INSTR || r == X86EMUL_PROPAGATE_FAULT)
                        return 1;
 
+               if (r == X86EMUL_UNHANDLEABLE_VECTORING) {
+                       kvm_prepare_event_vectoring_exit(vcpu, cr2_or_gpa);
+                       return 0;
+               }
+
                WARN_ON_ONCE(r != X86EMUL_UNHANDLEABLE);
                return handle_emulation_failure(vcpu, emulation_type);
        }