Skip to contentSkip to conversation

KVM: x86: Check KVM_REQ_IMMEDIATE_EXIT after enable_irq_window

PATCH In review Jan Kiszka 3 participants 5 messages Apr 28, 2013 – May 3, 2013

Subsystems (3)
lore
Share & tools
lore

Jan Kiszka

author
#0 lore raw

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
index 2a434bf..57ff14a 100644
@@ -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
#1 lore raw
Quoted 10 lines · Jan Kiszka

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.

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
index 2a434bf..57ff14a 100644

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 -0
 		if (kvm_lapic_enabled(vcpu)) {
 			/*
 			 * Update architecture specific hints for APIC
Signature · 1 line
1.7.3.4

--
Gleb.

author
#2 lore raw

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
index 18635ae..111b4a0 100644
@@ -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
index d6713e1..91a7431 100644
@@ -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
index d663a59..1795512 100644
@@ -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
index 2a434bf..c522260 100644
@@ -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
index 93a5005..7bde424 100644
@@ -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
#3 lore raw

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_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.

Please rebase against "KVM: x86: Account for failing enable_irq_window for NMI window request".

#4 lore raw

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_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.

Quoted 6 lines
Quoted 3 lines

This issue only affects nested VMX scenarios.

Please rebase against "KVM: x86: Account for failing enable_irq_window for NMI window request".

This one is applied already. Looks like I forgot to send an email about it.

--
Gleb.