diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h index d5e9a1b1dba3..e001ddac2e79 100644 --- a/arch/x86/include/asm/kvm-x86-ops.h +++ b/arch/x86/include/asm/kvm-x86-ops.h @@ -68,6 +68,7 @@ KVM_X86_OP(vcpu_run) KVM_X86_OP(handle_exit) KVM_X86_OP(skip_emulated_instruction) KVM_X86_OP_OPTIONAL(update_emulated_instruction) +KVM_X86_OP_OPTIONAL_RET0(unhandleable_emulation_required) KVM_X86_OP(set_interrupt_shadow) KVM_X86_OP(get_interrupt_shadow) KVM_X86_OP(patch_hypercall) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 6077f4e00d79..afe31fce67bd 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1591,6 +1591,8 @@ struct kvm_x86_ops { enum exit_fastpath_completion exit_fastpath); int (*skip_emulated_instruction)(struct kvm_vcpu *vcpu); void (*update_emulated_instruction)(struct kvm_vcpu *vcpu); + bool (*unhandleable_emulation_required)(struct kvm_vcpu *vcpu); + void (*set_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask); u32 (*get_interrupt_shadow)(struct kvm_vcpu *vcpu); void (*patch_hypercall)(struct kvm_vcpu *vcpu, diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c index 04f986e3d439..2a69dc3ac690 100644 --- a/arch/x86/kvm/vmx/main.c +++ b/arch/x86/kvm/vmx/main.c @@ -165,6 +165,16 @@ static int vt_handle_exit(struct kvm_vcpu *vcpu, return vmx_handle_exit(vcpu, fastpath); } +static bool vt_unhandleable_emulation_required(struct kvm_vcpu *vcpu) +{ + if (is_td_vcpu(vcpu)) { + WARN_ON_ONCE(to_vt(vcpu)->emulation_required); + return false; + } + + return vmx_unhandleable_emulation_required(vcpu); +} + static int vt_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) { if (unlikely(is_td_vcpu(vcpu))) @@ -944,6 +954,7 @@ struct kvm_x86_ops vt_x86_ops __initdata = { .handle_exit = vt_op(handle_exit), .skip_emulated_instruction = vmx_skip_emulated_instruction, .update_emulated_instruction = vmx_update_emulated_instruction, + .unhandleable_emulation_required = vt_op(unhandleable_emulation_required), .set_interrupt_shadow = vt_op(set_interrupt_shadow), .get_interrupt_shadow = vt_op(get_interrupt_shadow), .patch_hypercall = vt_op(patch_hypercall), diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 5ef6bdb334c7..b69062db3825 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6034,7 +6034,7 @@ static int handle_nmi_window(struct kvm_vcpu *vcpu) * with unsrestricted guest mode disabled) and KVM can't faithfully emulate the * current vCPU state. */ -static bool vmx_unhandleable_emulation_required(struct kvm_vcpu *vcpu) +bool vmx_unhandleable_emulation_required(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx = to_vmx(vcpu); @@ -6111,11 +6111,6 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu) int vmx_vcpu_pre_run(struct kvm_vcpu *vcpu) { - if (vmx_unhandleable_emulation_required(vcpu)) { - kvm_prepare_emulation_failure_exit(vcpu); - return 0; - } - return 1; } diff --git a/arch/x86/kvm/vmx/x86_ops.h b/arch/x86/kvm/vmx/x86_ops.h index 409858074246..551b4195bc1b 100644 --- a/arch/x86/kvm/vmx/x86_ops.h +++ b/arch/x86/kvm/vmx/x86_ops.h @@ -31,6 +31,7 @@ int vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath); void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu); int vmx_skip_emulated_instruction(struct kvm_vcpu *vcpu); void vmx_update_emulated_instruction(struct kvm_vcpu *vcpu); +bool vmx_unhandleable_emulation_required(struct kvm_vcpu *vcpu); int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info); #ifdef CONFIG_KVM_SMM int vmx_smi_allowed(struct kvm_vcpu *vcpu, bool for_injection); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 3be5024045da..4836f2d17cd4 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -8862,6 +8862,11 @@ static int kvm_x86_vcpu_pre_run(struct kvm_vcpu *vcpu) !kvm_apic_init_sipi_allowed(vcpu)) return -EINVAL; + if (kvm_x86_call(unhandleable_emulation_required)(vcpu)) { + kvm_prepare_emulation_failure_exit(vcpu); + return 0; + } + return kvm_x86_call(vcpu_pre_run)(vcpu); }