In the vcpu_run path the kernel may notice that a #vmexit is necessary when preemption is already disabled. In the SVM code an emulation of #vmexit may sleep and can't be executed with preemtion disabled. This patch begins to solve this problem by defining a KVM_REQ_VMEXIT bit. When this bit is set the vcpu_run loop is restarted and a #vmexit is emulated. Signed-off-by: Joerg Roedel <joerg.roedel@xxxxxxx> --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/x86.c | 17 +++++++++++++++++ include/linux/kvm_host.h | 1 + 3 files changed, 19 insertions(+), 0 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 179a919..50e5aa4 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -524,6 +524,7 @@ struct kvm_x86_ops { int (*get_tdp_level)(void); u64 (*get_mt_mask)(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio); bool (*gb_page_enable)(void); + void (*emulate_vmexit)(struct kvm_vcpu *vcpu); const struct trace_print_flags *exit_reasons_str; }; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 11a6f2f..97e1d9d 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3610,6 +3610,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) r = 0; goto out; } + if (test_and_clear_bit(KVM_REQ_VMEXIT, &vcpu->requests)) + kvm_x86_ops->emulate_vmexit(vcpu); } preempt_disable(); @@ -3638,6 +3640,21 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) else if (kvm_cpu_has_interrupt(vcpu) || req_int_win) kvm_x86_ops->enable_irq_window(vcpu); + /* + * With nested KVM the enable_irq_window() function may cause an + * #vmexit if the vcpu is running in guest mode. A #vmexit may sleep + * and can't be executed at this stage. So we use the request field to + * tell KVM that a #vmexit has to be done before we can enter the guest + * again. The code below checks for this request. + */ + if (vcpu->requests) { + local_irq_enable(); + preempt_enable(); + r = 1; + goto out; + } + + if (kvm_lapic_enabled(vcpu)) { update_cr8_intercept(vcpu); kvm_lapic_sync_to_vapic(vcpu); diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index b985a29..245463f 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -38,6 +38,7 @@ #define KVM_REQ_MMU_SYNC 7 #define KVM_REQ_KVMCLOCK_UPDATE 8 #define KVM_REQ_KICK 9 +#define KVM_REQ_VMEXIT 10 #define KVM_USERSPACE_IRQ_SOURCE_ID 0 -- 1.6.4.3 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html