KVM: x86: Check KVM_REQ_IMMEDIATE_EXIT after enable_irq_window
PATCH 1/1 KVM: x86: Check KVM_REQ_IMMEDIATE_EXIT after enable_irq_window
From: Jan Kiszka <[email protected]>
The VMX implementation of enable_irq_window will raise KVM_REQ_IMMEDIATE_EXIT if an interrupt window shall be opened during nested vmrun. We have to transfer this request into the local variable to avoid looping over a continuously re-asserted request on vmentry.
This issue only affects nested VMX scenarios.
--- arch/x86/kvm/x86.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
arch/x86/kvm/x86.c +3 -0
@@ -5759,6 +5759,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)else if (kvm_cpu_has_injectable_intr (vcpu) || req_int_win) kvm_x86_ops->enable_irq_window (vcpu); + req_immediate_exit = +kvm_check_request (KVM_REQ_IMMEDIATE_EXIT , vcpu); +if (kvm_lapic_enabled (vcpu)) {/* * Update architecture specific hints for APIC
Signature · 1 line
1.7.3.4
Quoted 10 lines · Jan Kiszka
From: Jan Kiszka <[email protected]>
The VMX implementation of
enable_irq_windowwill raiseKVM_REQ_IMMEDIATE_EXITif an interrupt window shall be opened during nested vmrun. We have to transfer this request into the local variable to avoid looping over a continuously re-asserted request on vmentry.This issue only affects nested VMX scenarios.
Signed-off-by Jan Kiszka <[email protected]>
So KVM_REQ_IMMEDIATE_EXIT does not behave like request bit should. What about dropping it and letting enable_irq_window() return true if immediate exit is needed.
Quoted 9 lines
--- arch/x86/kvm/x86.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)arch/x86/kvm/x86.c +0
-0
arch/x86/kvm/x86.c static int vcpu_enter_guest(struct kvm_vcpu *vcpu) · line 5764
Quoted 6 lines
arch/x86/kvm/x86.c +3
-0@@ -5759,6 +5759,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)else if (kvm_cpu_has_injectable_intr (vcpu) || req_int_win) kvm_x86_ops->enable_irq_window (vcpu); + req_immediate_exit = +kvm_check_request (KVM_REQ_IMMEDIATE_EXIT , vcpu); +
The code will become:
req_immediate_exit = kvm_x86_ops->enable_irq_window(vcpu);
Quoted 5 lines
arch/x86/kvm/x86.c +0
-0if (kvm_lapic_enabled (vcpu)) {/* * Update architecture specific hints for APIC Signature · 1 line
1.7.3.4
--
Gleb.
PATCH 1/1 KVM: x86: Rework request for immediate exit
From: Jan Kiszka <[email protected]>
The VMX implementation of enable_irq_window raised KVM_REQ_IMMEDIATE_EXIT after we checked it in vcpu_enter_guest. This caused infinite loops on vmentry. Fix it by letting enable_irq_window signal the need for an immediate exit via its return value and drop KVM_REQ_IMMEDIATE_EXIT.
This issue only affects nested VMX scenarios.
--- arch/x86/include/asm/kvm_host.h | 2 +- arch/x86/kvm/svm.c | 3 ++- arch/x86/kvm/vmx.c | 15 ++++++++------- arch/x86/kvm/x86.c | 7 +++---- include/linux/kvm_host.h | 15 +++++++-------- 5 files changed, 21 insertions(+), 21 deletions(-)
arch/x86/include/asm/kvm_host.h +1 -1
@@ -694,7 +694,7 @@ struct kvm_x86_ops {bool (*get_nmi_mask)(struct kvm_vcpu *vcpu);void (*set_nmi_mask)(struct kvm_vcpu *vcpu,bool masked);void (*enable_nmi_window)(struct kvm_vcpu *vcpu); -void (*enable_irq_window)(struct kvm_vcpu *vcpu); +int (*enable_irq_window)(struct kvm_vcpu *vcpu);void (*update_cr8_intercept)(struct kvm_vcpu *vcpu,int tpr,int irr);int (*vm_has_apicv)(struct kvm *kvm);void (*hwapic_irr_update)(struct kvm_vcpu *vcpu,int max_irr);
arch/x86/kvm/svm.c +2 -1
@@ -3632,7 +3632,7 @@ static int svm_interrupt_allowed(struct kvm_vcpu *vcpu)return ret; } -static void enable_irq_window (struct kvm_vcpu *vcpu) +static int enable_irq_window (struct kvm_vcpu *vcpu) {struct vcpu_svm *svm =to_svm (vcpu);
@@ -3646,6 +3646,7 @@ static void enable_irq_window(struct kvm_vcpu *vcpu)svm_set_vintr (svm);svm_inject_irq (svm,0x0 ); } +return 0 ; }static void enable_nmi_window (struct kvm_vcpu *vcpu)
arch/x86/kvm/vmx.c +8 -7
@@ -4398,22 +4398,23 @@ static bool nested_exit_on_nmi(struct kvm_vcpu *vcpu)PIN_BASED_NMI_EXITING ; } -static void enable_irq_window (struct kvm_vcpu *vcpu) +static int enable_irq_window (struct kvm_vcpu *vcpu) {u32 cpu_based_vm_exec_control; -if (is_guest_mode (vcpu) &&nested_exit_on_intr (vcpu)) { + +if (is_guest_mode (vcpu) &&nested_exit_on_intr (vcpu))/* * We get here if vmx_interrupt_allowed() said we can't -* inject to L1 now because L2 must run. Ask L2 to exit -* right after entry, so we can inject to L1 more promptly. +* inject to L1 now because L2 must run. The caller will have +* to make L2 exit right after entry, so we can inject to L1 +* more promptly. */ -kvm_make_request (KVM_REQ_IMMEDIATE_EXIT , vcpu); -return ; - } +return -EBUSY ; cpu_based_vm_exec_control =vmcs_read32 (CPU_BASED_VM_EXEC_CONTROL ); cpu_based_vm_exec_control |=CPU_BASED_VIRTUAL_INTR_PENDING ;vmcs_write32 (CPU_BASED_VM_EXEC_CONTROL , cpu_based_vm_exec_control); +return 0 ; }static void enable_nmi_window (struct kvm_vcpu *vcpu)
arch/x86/kvm/x86.c +3 -4
@@ -5692,7 +5692,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)int r;bool req_int_win = !irqchip_in_kernel (vcpu->kvm) && vcpu->run->request_interrupt_window; -bool req_immediate_exit =0 ; +bool req_immediate_exit = false;if (vcpu->requests) {if (kvm_check_request (KVM_REQ_MMU_RELOAD , vcpu))
@@ -5734,8 +5734,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)record_steal_time (vcpu);if (kvm_check_request (KVM_REQ_NMI , vcpu))process_nmi (vcpu); - req_immediate_exit = -kvm_check_request (KVM_REQ_IMMEDIATE_EXIT , vcpu);if (kvm_check_request (KVM_REQ_PMU , vcpu))kvm_handle_pmu_event (vcpu);if (kvm_check_request (KVM_REQ_PMI , vcpu))
@@ -5757,7 +5755,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)if (vcpu->arch.nmi_pending) kvm_x86_ops->enable_nmi_window (vcpu);else if (kvm_cpu_has_injectable_intr (vcpu) || req_int_win) - kvm_x86_ops->enable_irq_window (vcpu); + req_immediate_exit = + kvm_x86_ops->enable_irq_window (vcpu) !=0 ;if (kvm_lapic_enabled (vcpu)) {/*
include/linux/kvm_host.h +7 -8
@@ -119,14 +119,13 @@ static inline bool is_error_page(struct page *page)#define KVM_REQ_APF_HALT 12#define KVM_REQ_STEAL_UPDATE 13#define KVM_REQ_NMI 14 -#define KVM_REQ_IMMEDIATE_EXIT 15 -#define KVM_REQ_PMU 16 -#define KVM_REQ_PMI 17 -#define KVM_REQ_WATCHDOG 18 -#define KVM_REQ_MASTERCLOCK_UPDATE 19 -#define KVM_REQ_MCLOCK_INPROGRESS 20 -#define KVM_REQ_EPR_EXIT 21 -#define KVM_REQ_SCAN_IOAPIC 22 +#define KVM_REQ_PMU 15 +#define KVM_REQ_PMI 16 +#define KVM_REQ_WATCHDOG 17 +#define KVM_REQ_MASTERCLOCK_UPDATE 18 +#define KVM_REQ_MCLOCK_INPROGRESS 19 +#define KVM_REQ_EPR_EXIT 20 +#define KVM_REQ_SCAN_IOAPIC 21#define KVM_USERSPACE_IRQ_SOURCE_ID 0#define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1
Signature · 1 line
1.7.3.4
Re: [PATCH] KVM: x86: Rework request for immediate exit
Quoted 11 lines · Jan Kiszka
From: Jan Kiszka <[email protected]>
The VMX implementation of
enable_irq_windowraisedKVM_REQ_IMMEDIATE_EXITafter we checked it invcpu_enter_guest. This caused infinite loops on vmentry. Fix it by lettingenable_irq_windowsignal the need for an immediate exit via its return value and dropKVM_REQ_IMMEDIATE_EXIT.This issue only affects nested VMX scenarios.
Signed-off-by Jan Kiszka <[email protected]>
Please rebase against "KVM: x86: Account for failing enable_irq_window for NMI window request".
Re: [PATCH] KVM: x86: Rework request for immediate exit
Quoted 9 lines · Marcelo Tosatti
Quoted 8 lines · Jan Kiszka
From: Jan Kiszka <[email protected]>
The VMX implementation of
enable_irq_windowraisedKVM_REQ_IMMEDIATE_EXITafter we checked it invcpu_enter_guest. This caused infinite loops on vmentry. Fix it by lettingenable_irq_windowsignal the need for an immediate exit via its return value and dropKVM_REQ_IMMEDIATE_EXIT.
Quoted 6 lines
Quoted 3 lines
This issue only affects nested VMX scenarios.
Signed-off-by Jan Kiszka <[email protected]>Please rebase against "KVM: x86: Account for failing
enable_irq_windowfor NMI window request".
This one is applied already. Looks like I forgot to send an email about it.
--
Gleb.