Skip to contentSkip to conversation

KVM: VMX: Add Posted Interrupt supporting

PATCH Applied Yang Zhang 5 participants 16 messages Apr 11, 2013 – May 7, 2013

Subsystems (3)
lore
Share & tools
lore

Yang Zhang

author
#0 lore raw

v10 cover KVM: VMX: Add Posted Interrupt supporting

From: Yang Zhang <[email protected]>

The follwoing patches are adding the Posted Interrupt supporting to KVM:
The first patch enables the feature 'acknowledge interrupt on vmexit'.Since it is required by Posted interrupt, we need to enable it firstly.

And the subsequent patches are adding the posted interrupt supporting:
Posted Interrupt allows APIC interrupts to inject into guest directly without any vmexit.

- When delivering a interrupt to guest, if target vcpu is running, update Posted-interrupt requests bitmap and send a notification event to the vcpu. Then the vcpu will handle this interrupt automatically, without any software involvemnt.

- If target vcpu is not running or there already a notification event pending in the vcpu, do nothing. The interrupt will be handled by next vm entry

Changes from v9 to v10:
* Only check kvm_apic_hw_enable() in vcpu_sacn_ioapic().
* Remove repeated tracing in __apic_accept_irq().
* Rebase on top of KVM upstream + RTC eoi tracking patch.

Changes from v8 to v9:
* Add tracing in PI case when deliver interrupt.
* Scan ioapic when updating SPIV register.
* Rebase on top of KVM upstream + RTC eoi tracking patch.

Changes from v7 to v8:
* Remove unused memeber 'on' from struct pi_desc.
* Register a dummy function to sync_pir_to_irr is apicv is disabled.
* Minor fixup.
* Rebase on top of KVM upstream + RTC eoi tracking patch.

Yang Zhang (7):
KVM: VMX: Enable acknowledge interupt on vmexit
KVM: VMX: Register a new IPI for posted interrupt
KVM: VMX: Check the posted interrupt capability
KVM: Call common update function when ioapic entry changed.
KVM: Set TMR when programming ioapic entry
KVM: VMX: Add the algorithm of deliver posted interrupt
KVM: VMX: Use posted interrupt to deliver virtual interrupt

 arch/ia64/kvm/lapic.h              |    6 -
 arch/x86/include/asm/entry_arch.h  |    4 +
 arch/x86/include/asm/hardirq.h     |    3 +
 arch/x86/include/asm/hw_irq.h      |    1 +
 arch/x86/include/asm/irq_vectors.h |    5 +
 arch/x86/include/asm/kvm_host.h    |    3 +
 arch/x86/include/asm/vmx.h         |    4 +
 arch/x86/kernel/entry_64.S         |    5 +
 arch/x86/kernel/irq.c              |   22 ++++
 arch/x86/kernel/irqinit.c          |    4 +
 arch/x86/kvm/lapic.c               |   58 +++++++---
 arch/x86/kvm/lapic.h               |    2 +
 arch/x86/kvm/svm.c                 |   12 ++
 arch/x86/kvm/vmx.c                 |  207 +++++++++++++++++++++++++++++++-----
 arch/x86/kvm/x86.c                 |   19 +++-
 include/linux/kvm_host.h           |    4 +-
 virt/kvm/ioapic.c                  |   32 ++++--
 virt/kvm/ioapic.h                  |    7 +-
 virt/kvm/irq_comm.c                |    4 +-
 virt/kvm/kvm_main.c                |    5 +-
 20 files changed, 333 insertions(+), 74 deletions(-)
author
#1 lore raw

PATCH v10 1/7 KVM: VMX: Enable acknowledge interupt on vmexit

From: Yang Zhang <[email protected]>

The "acknowledge interrupt on exit" feature controls processor behavior for external interrupt acknowledgement. When this control is set, the processor acknowledges the interrupt controller to acquire the interrupt vector on VM exit.

After enabling this feature, an interrupt which arrived when target cpu is running in vmx non-root mode will be handled by vmx handler instead of handler in idt. Currently, vmx handler only fakes an interrupt stack and jump to idt table to let real handler to handle it. Further, we will recognize the interrupt and only delivery the interrupt which not belong to current vcpu through idt table. The interrupt which belonged to current vcpu will be handled inside vmx handler. This will reduce the interrupt handle cost of KVM.

Also, interrupt enable logic is changed if this feature is turnning on:
Before this patch, hypervior call local_irq_enable() to enable it directly. Now IF bit is set on interrupt stack frame, and will be enabled on a return from interrupt handler if exterrupt interrupt exists. If no external interrupt, still call local_irq_enable() to enable it.

Refer to Intel SDM volum 3, chapter 33.2.

---
 arch/x86/include/asm/kvm_host.h |    1 +
 arch/x86/kvm/svm.c              |    6 ++++
 arch/x86/kvm/vmx.c              |   58 ++++++++++++++++++++++++++++++++++++---
 arch/x86/kvm/x86.c              |    4 ++-
 4 files changed, 64 insertions(+), 5 deletions(-)
arch/x86/include/asm/kvm_host.h +1 -0
index b5a6462..8e95512 100644
@@ -730,6 +730,7 @@ struct kvm_x86_ops {
 	int (*check_intercept)(struct kvm_vcpu *vcpu,
 			       struct x86_instruction_info *info,
 			       enum x86_intercept_stage stage);
+	void (*handle_external_intr)(struct kvm_vcpu *vcpu);
 };
 
 struct kvm_arch_async_pf {
arch/x86/kvm/svm.c +6 -0
index 7a46c1f..2f8fe3f 100644
@@ -4233,6 +4233,11 @@ out:
 	return ret;
 }
 
+static void svm_handle_external_intr(struct kvm_vcpu *vcpu)
+{
+	local_irq_enable();
+}
+
 static struct kvm_x86_ops svm_x86_ops = {
 	.cpu_has_kvm_support = has_svm,
 	.disabled_by_bios = is_disabled,
@@ -4328,6 +4333,7 @@ static struct kvm_x86_ops svm_x86_ops = {
 	.set_tdp_cr3 = set_tdp_cr3,
 
 	.check_intercept = svm_check_intercept,
+	.handle_external_intr = svm_handle_external_intr,
 };
 
 static int __init svm_init(void)
arch/x86/kvm/vmx.c +54 -4

106 lines not on this page · raw message

arch/x86/kvm/x86.c +3 -1
index 5e85d8d..5b146d2 100644
@@ -5808,7 +5808,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 
 	vcpu->mode = OUTSIDE_GUEST_MODE;
 	smp_wmb();
-	local_irq_enable();
+
+	/* Interrupt is enabled by handle_external_intr() */
+	kvm_x86_ops->handle_external_intr(vcpu);
 
 	++vcpu->stat.exits;
 
Signature · 1 line
1.7.1
author
#2 lore raw

PATCH v10 2/7 KVM: VMX: Register a new IPI for posted interrupt

In reply to Yang Zhang

From: Yang Zhang <[email protected]>

Posted Interrupt feature requires a special IPI to deliver posted interrupt to guest. And it should has a high priority so the interrupt will not be blocked by others.
Normally, the posted interrupt will be consumed by vcpu if target vcpu is running and transparent to OS. But in some cases, the interrupt will arrive when target vcpu is scheduled out. And host will see it. So we need to register a dump handler to handle it.

---
 arch/x86/include/asm/entry_arch.h  |    4 ++++
 arch/x86/include/asm/hardirq.h     |    3 +++
 arch/x86/include/asm/hw_irq.h      |    1 +
 arch/x86/include/asm/irq_vectors.h |    5 +++++
 arch/x86/kernel/entry_64.S         |    5 +++++
 arch/x86/kernel/irq.c              |   22 ++++++++++++++++++++++
 arch/x86/kernel/irqinit.c          |    4 ++++
 7 files changed, 44 insertions(+), 0 deletions(-)
arch/x86/include/asm/entry_arch.h +4 -0
index 40afa00..9bd4eca 100644
@@ -19,6 +19,10 @@ BUILD_INTERRUPT(reboot_interrupt,REBOOT_VECTOR)
 
 BUILD_INTERRUPT(x86_platform_ipi, X86_PLATFORM_IPI_VECTOR)
 
+#ifdef CONFIG_HAVE_KVM
+BUILD_INTERRUPT(kvm_posted_intr_ipi, POSTED_INTR_VECTOR)
+#endif
+
 /*
  * every pentium local APIC has two 'local interrupts', with a
  * soft-definable vector attached to both interrupts, one of
arch/x86/include/asm/hardirq.h +3 -0
index 81f04ce..ab0ae1a 100644
@@ -12,6 +12,9 @@ typedef struct {
 	unsigned int irq_spurious_count;
 	unsigned int icr_read_retry_count;
 #endif
+#ifdef CONFIG_HAVE_KVM
+	unsigned int kvm_posted_intr_ipis;
+#endif
 	unsigned int x86_platform_ipis;	/* arch dependent */
 	unsigned int apic_perf_irqs;
 	unsigned int apic_irq_work_irqs;
arch/x86/include/asm/hw_irq.h +1 -0
index 10a78c3..1da97ef 100644
@@ -28,6 +28,7 @@
 /* Interrupt handlers registered during init_IRQ */
 extern void apic_timer_interrupt(void);
 extern void x86_platform_ipi(void);
+extern void kvm_posted_intr_ipi(void);
 extern void error_interrupt(void);
 extern void irq_work_interrupt(void);
 
arch/x86/include/asm/irq_vectors.h +5 -0
index aac5fa6..5702d7e 100644
@@ -102,6 +102,11 @@
  */
 #define X86_PLATFORM_IPI_VECTOR		0xf7
 
+/* Vector for KVM to deliver posted interrupt IPI */
+#ifdef CONFIG_HAVE_KVM
+#define POSTED_INTR_VECTOR		0xf2
+#endif
+
 /*
  * IRQ work vector:
  */
arch/x86/kernel/entry_64.S +5 -0
index c1d01e6..7272089 100644
@@ -1166,6 +1166,11 @@ apicinterrupt LOCAL_TIMER_VECTOR \
 apicinterrupt X86_PLATFORM_IPI_VECTOR \
 	x86_platform_ipi smp_x86_platform_ipi
 
+#ifdef CONFIG_HAVE_KVM
+apicinterrupt POSTED_INTR_VECTOR \
+	kvm_posted_intr_ipi smp_kvm_posted_intr_ipi
+#endif
+
 apicinterrupt THRESHOLD_APIC_VECTOR \
 	threshold_interrupt smp_threshold_interrupt
 apicinterrupt THERMAL_APIC_VECTOR \
arch/x86/kernel/irq.c +22 -0
index e4595f1..6ae6ea1 100644
@@ -228,6 +228,28 @@ void smp_x86_platform_ipi(struct pt_regs *regs)
 	set_irq_regs(old_regs);
 }
 
+#ifdef CONFIG_HAVE_KVM
+/*
+ * Handler for POSTED_INTERRUPT_VECTOR.
+ */
+void smp_kvm_posted_intr_ipi(struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
+	ack_APIC_irq();
+
+	irq_enter();
+
+	exit_idle();
+
+	inc_irq_stat(kvm_posted_intr_ipis);
+
+	irq_exit();
+
+	set_irq_regs(old_regs);
+}
+#endif
+
 EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
 
 #ifdef CONFIG_HOTPLUG_CPU
arch/x86/kernel/irqinit.c +4 -0
index 7dc4e45..a2a1fbc 100644
@@ -172,6 +172,10 @@ static void __init apic_intr_init(void)
 
 	/* IPI for X86 platform specific use */
 	alloc_intr_gate(X86_PLATFORM_IPI_VECTOR, x86_platform_ipi);
+#ifdef CONFIG_HAVE_KVM
+	/* IPI for KVM to deliver posted interrupt */
+	alloc_intr_gate(POSTED_INTR_VECTOR, kvm_posted_intr_ipi);
+#endif
 
 	/* IPI vectors for APIC spurious and error interrupts */
 	alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
Signature · 1 line
1.7.1
author
#3 lore raw

PATCH v10 3/7 KVM: VMX: Check the posted interrupt capability

In reply to Yang Zhang

From: Yang Zhang <[email protected]>

Detect the posted interrupt feature. If it exists, then set it in vmcs_config.

---
 arch/x86/include/asm/vmx.h |    4 ++
 arch/x86/kvm/vmx.c         |   82 +++++++++++++++++++++++++++++++++-----------
 2 files changed, 66 insertions(+), 20 deletions(-)
arch/x86/include/asm/vmx.h +4 -0
index fc1c313..6f07f19 100644
@@ -71,6 +71,7 @@
 #define PIN_BASED_NMI_EXITING                   0x00000008
 #define PIN_BASED_VIRTUAL_NMIS                  0x00000020
 #define PIN_BASED_VMX_PREEMPTION_TIMER          0x00000040
+#define PIN_BASED_POSTED_INTR                   0x00000080
 
 #define PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR	0x00000016
 
@@ -102,6 +103,7 @@
 /* VMCS Encodings */
 enum vmcs_field {
 	VIRTUAL_PROCESSOR_ID            = 0x00000000,
+	POSTED_INTR_NV                  = 0x00000002,
 	GUEST_ES_SELECTOR               = 0x00000800,
 	GUEST_CS_SELECTOR               = 0x00000802,
 	GUEST_SS_SELECTOR               = 0x00000804,
@@ -136,6 +138,8 @@ enum vmcs_field {
 	VIRTUAL_APIC_PAGE_ADDR_HIGH     = 0x00002013,
 	APIC_ACCESS_ADDR		= 0x00002014,
 	APIC_ACCESS_ADDR_HIGH		= 0x00002015,
+	POSTED_INTR_DESC_ADDR           = 0x00002016,
+	POSTED_INTR_DESC_ADDR_HIGH      = 0x00002017,
 	EPT_POINTER                     = 0x0000201a,
 	EPT_POINTER_HIGH                = 0x0000201b,
 	EOI_EXIT_BITMAP0                = 0x0000201c,
arch/x86/kvm/vmx.c +62 -20

173 lines not on this page · raw message

Signature · 1 line
1.7.1
author
#4 lore raw

PATCH v10 4/7 KVM: Call common update function when ioapic entry changed.

In reply to Yang Zhang

From: Yang Zhang <[email protected]>

Both TMR and EOI exit bitmap need to be updated when ioapic changed or vcpu's id/ldr/dfr changed. So use common function instead eoi exit bitmap specific function.

---
 arch/ia64/kvm/lapic.h    |    6 ------
 arch/x86/kvm/lapic.c     |    2 +-
 arch/x86/kvm/vmx.c       |    3 +++
 arch/x86/kvm/x86.c       |   11 +++++++----
 include/linux/kvm_host.h |    4 ++--
 virt/kvm/ioapic.c        |   22 +++++++++++++---------
 virt/kvm/ioapic.h        |    6 ++----
 virt/kvm/irq_comm.c      |    4 ++--
 virt/kvm/kvm_main.c      |    4 ++--
 9 files changed, 32 insertions(+), 30 deletions(-)
arch/ia64/kvm/lapic.h +0 -6
index c3e2935..c5f92a9 100644
@@ -27,10 +27,4 @@ int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq);
 #define kvm_apic_present(x) (true)
 #define kvm_lapic_enabled(x) (true)
 
-static inline bool kvm_apic_vid_enabled(void)
-{
-	/* IA64 has no apicv supporting, do nothing here */
-	return false;
-}
-
 #endif
arch/x86/kvm/lapic.c +1 -1
index 6796218..34a8ca8 100644
@@ -217,7 +217,7 @@ out:
 	if (old)
 		kfree_rcu(old, rcu);
 
-	kvm_ioapic_make_eoibitmap_request(kvm);
+	kvm_vcpu_request_scan_ioapic(kvm);
 }
 
 static inline void kvm_apic_set_id(struct kvm_lapic *apic, u8 id)
arch/x86/kvm/vmx.c +3 -0
index 05da991..5637a8a 100644
@@ -6415,6 +6415,9 @@ static void vmx_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr)
 
 static void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
 {
+	if (!vmx_vm_has_apicv(vcpu->kvm))
+		return;
+
 	vmcs_write64(EOI_EXIT_BITMAP0, eoi_exit_bitmap[0]);
 	vmcs_write64(EOI_EXIT_BITMAP1, eoi_exit_bitmap[1]);
 	vmcs_write64(EOI_EXIT_BITMAP2, eoi_exit_bitmap[2]);
arch/x86/kvm/x86.c +7 -4
index 5b146d2..d8e9a32 100644
@@ -5649,13 +5649,16 @@ static void kvm_gen_update_masterclock(struct kvm *kvm)
 #endif
 }
 
-static void update_eoi_exitmap(struct kvm_vcpu *vcpu)
+static void vcpu_scan_ioapic(struct kvm_vcpu *vcpu)
 {
 	u64 eoi_exit_bitmap[4];
 
+	if (!kvm_apic_hw_enabled(vcpu->arch.apic))
+		return;
+
 	memset(eoi_exit_bitmap, 0, 32);
 
-	kvm_ioapic_calculate_eoi_exitmap(vcpu, eoi_exit_bitmap);
+	kvm_ioapic_scan_entry(vcpu, eoi_exit_bitmap);
 	kvm_x86_ops->load_eoi_exitmap(vcpu, eoi_exit_bitmap);
 }
 
@@ -5712,8 +5715,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 			kvm_handle_pmu_event(vcpu);
 		if (kvm_check_request(KVM_REQ_PMI, vcpu))
 			kvm_deliver_pmi(vcpu);
-		if (kvm_check_request(KVM_REQ_EOIBITMAP, vcpu))
-			update_eoi_exitmap(vcpu);
+		if (kvm_check_request(KVM_REQ_SCAN_IOAPIC, vcpu))
+			vcpu_scan_ioapic(vcpu);
 	}
 
 	if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) {
include/linux/kvm_host.h +2 -2
index 7bcdb6b..6f49d9d 100644
@@ -126,7 +126,7 @@ static inline bool is_error_page(struct page *page)
 #define KVM_REQ_MASTERCLOCK_UPDATE 19
 #define KVM_REQ_MCLOCK_INPROGRESS 20
 #define KVM_REQ_EPR_EXIT          21
-#define KVM_REQ_EOIBITMAP         22
+#define KVM_REQ_SCAN_IOAPIC       22
 
 #define KVM_USERSPACE_IRQ_SOURCE_ID		0
 #define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID	1
@@ -572,7 +572,7 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu);
 void kvm_flush_remote_tlbs(struct kvm *kvm);
 void kvm_reload_remote_mmus(struct kvm *kvm);
 void kvm_make_mclock_inprogress_request(struct kvm *kvm);
-void kvm_make_update_eoibitmap_request(struct kvm *kvm);
+void kvm_make_scan_ioapic_request(struct kvm *kvm);
 
 long kvm_arch_dev_ioctl(struct file *filp,
 			unsigned int ioctl, unsigned long arg);
virt/kvm/ioapic.c +13 -9
index 97c67a5..f2157a9 100644
@@ -193,15 +193,13 @@ static void update_handled_vectors(struct kvm_ioapic *ioapic)
 	smp_wmb();
 }
 
-void kvm_ioapic_calculate_eoi_exitmap(struct kvm_vcpu *vcpu,
-					u64 *eoi_exit_bitmap)
+void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
 {
 	struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic;
 	union kvm_ioapic_redirect_entry *e;
 	int index;
 
 	spin_lock(&ioapic->lock);
-	/* traverse ioapic entry to set eoi exit bitmap*/
 	for (index = 0; index < IOAPIC_NUM_PINS; index++) {
 		e = &ioapic->redirtbl[index];
 		if (!e->fields.mask &&
@@ -215,16 +213,22 @@ void kvm_ioapic_calculate_eoi_exitmap(struct kvm_vcpu *vcpu,
 	}
 	spin_unlock(&ioapic->lock);
 }
-EXPORT_SYMBOL_GPL(kvm_ioapic_calculate_eoi_exitmap);
 
-void kvm_ioapic_make_eoibitmap_request(struct kvm *kvm)
+#ifdef CONFIG_X86
+void kvm_vcpu_request_scan_ioapic(struct kvm *kvm)
 {
 	struct kvm_ioapic *ioapic = kvm->arch.vioapic;
 
-	if (!kvm_apic_vid_enabled(kvm) || !ioapic)
+	if (!ioapic)
 		return;
-	kvm_make_update_eoibitmap_request(kvm);
+	kvm_make_scan_ioapic_request(kvm);
 }
+#else
+void kvm_vcpu_request_scan_ioapic(struct kvm *kvm)
+{
+	return;
+}
+#endif
 
 static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
 {
@@ -267,7 +271,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
 		if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG
 		    && ioapic->irr & (1 << index))
 			ioapic_service(ioapic, index, false);
-		kvm_ioapic_make_eoibitmap_request(ioapic->kvm);
+		kvm_vcpu_request_scan_ioapic(ioapic->kvm);
 		break;
 	}
 }
@@ -586,7 +590,7 @@ int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state)
 	spin_lock(&ioapic->lock);
 	memcpy(ioapic, state, sizeof(struct kvm_ioapic_state));
 	update_handled_vectors(ioapic);
-	kvm_ioapic_make_eoibitmap_request(kvm);
+	kvm_vcpu_request_scan_ioapic(kvm);
 	kvm_rtc_eoi_tracking_restore_all(ioapic);
 	spin_unlock(&ioapic->lock);
 	return 0;
virt/kvm/ioapic.h +2 -4
index 554157b..674a388 100644
@@ -96,9 +96,7 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
 		struct kvm_lapic_irq *irq, unsigned long *dest_map);
 int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state);
 int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state);
-void kvm_ioapic_make_eoibitmap_request(struct kvm *kvm);
-void kvm_ioapic_calculate_eoi_exitmap(struct kvm_vcpu *vcpu,
-					u64 *eoi_exit_bitmap);
-
+void kvm_vcpu_request_scan_ioapic(struct kvm *kvm);
+void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
 
 #endif
virt/kvm/irq_comm.c +2 -2
index 8efb580..25ab480 100644
@@ -285,7 +285,7 @@ void kvm_register_irq_ack_notifier(struct kvm *kvm,
 	mutex_lock(&kvm->irq_lock);
 	hlist_add_head_rcu(&kian->link, &kvm->irq_ack_notifier_list);
 	mutex_unlock(&kvm->irq_lock);
-	kvm_ioapic_make_eoibitmap_request(kvm);
+	kvm_vcpu_request_scan_ioapic(kvm);
 }
 
 void kvm_unregister_irq_ack_notifier(struct kvm *kvm,
@@ -295,7 +295,7 @@ void kvm_unregister_irq_ack_notifier(struct kvm *kvm,
 	hlist_del_init_rcu(&kian->link);
 	mutex_unlock(&kvm->irq_lock);
 	synchronize_rcu();
-	kvm_ioapic_make_eoibitmap_request(kvm);
+	kvm_vcpu_request_scan_ioapic(kvm);
 }
 
 int kvm_request_irq_source_id(struct kvm *kvm)
virt/kvm/kvm_main.c +2 -2
index 6c4842a..8b5c6a8 100644
@@ -217,9 +217,9 @@ void kvm_make_mclock_inprogress_request(struct kvm *kvm)
 	make_all_cpus_request(kvm, KVM_REQ_MCLOCK_INPROGRESS);
 }
 
-void kvm_make_update_eoibitmap_request(struct kvm *kvm)
+void kvm_make_scan_ioapic_request(struct kvm *kvm)
 {
-	make_all_cpus_request(kvm, KVM_REQ_EOIBITMAP);
+	make_all_cpus_request(kvm, KVM_REQ_SCAN_IOAPIC);
 }
 
 int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
Signature · 1 line
1.7.1
author
#5 lore raw

PATCH v10 5/7 KVM: Set TMR when programming ioapic entry

In reply to Yang Zhang

From: Yang Zhang <[email protected]>

We already know the trigger mode of a given interrupt when programming the ioapice entry. So it's not necessary to set it in each interrupt delivery.

---
 arch/x86/kvm/lapic.c |   15 +++++++++------
 arch/x86/kvm/lapic.h |    1 +
 arch/x86/kvm/x86.c   |    5 ++++-
 virt/kvm/ioapic.c    |   12 +++++++++---
 virt/kvm/ioapic.h    |    3 ++-
 5 files changed, 25 insertions(+), 11 deletions(-)
arch/x86/kvm/lapic.c +9 -6
index 34a8ca8..d197579 100644
@@ -468,6 +468,15 @@ static inline int apic_find_highest_isr(struct kvm_lapic *apic)
 	return result;
 }
 
+void kvm_apic_update_tmr(struct kvm_vcpu *vcpu, u32 *tmr)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+	int i;
+
+	for (i = 0; i < 8; i++)
+		apic_set_reg(apic, APIC_TMR + 0x10 * i, tmr[i]);
+}
+
 static void apic_update_ppr(struct kvm_lapic *apic)
 {
 	u32 tpr, isrv, ppr, old_ppr;
@@ -661,12 +670,6 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
 		if (dest_map)
 			__set_bit(vcpu->vcpu_id, dest_map);
 
-		if (trig_mode) {
-			apic_debug("level trig mode for vector %d", vector);
-			apic_set_vector(vector, apic->regs + APIC_TMR);
-		} else
-			apic_clear_vector(vector, apic->regs + APIC_TMR);
-
 		result = !apic_test_and_set_irr(vector, apic);
 		trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
 					  trig_mode, vector, !result);
arch/x86/kvm/lapic.h +1 -0
index 16304b1..7fe0c91 100644
@@ -53,6 +53,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value);
 u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);
 void kvm_apic_set_version(struct kvm_vcpu *vcpu);
 
+void kvm_apic_update_tmr(struct kvm_vcpu *vcpu, u32 *tmr);
 int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
 int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
 int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq,
arch/x86/kvm/x86.c +4 -1
index d8e9a32..6147d24 100644
@@ -5652,14 +5652,17 @@ static void kvm_gen_update_masterclock(struct kvm *kvm)
 static void vcpu_scan_ioapic(struct kvm_vcpu *vcpu)
 {
 	u64 eoi_exit_bitmap[4];
+	u32 tmr[8];
 
 	if (!kvm_apic_hw_enabled(vcpu->arch.apic))
 		return;
 
 	memset(eoi_exit_bitmap, 0, 32);
+	memset(tmr, 0, 32);
 
-	kvm_ioapic_scan_entry(vcpu, eoi_exit_bitmap);
+	kvm_ioapic_scan_entry(vcpu, eoi_exit_bitmap, tmr);
 	kvm_x86_ops->load_eoi_exitmap(vcpu, eoi_exit_bitmap);
+	kvm_apic_update_tmr(vcpu, tmr);
 }
 
 static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
virt/kvm/ioapic.c +9 -3
index f2157a9..2d68297 100644
@@ -193,7 +193,8 @@ static void update_handled_vectors(struct kvm_ioapic *ioapic)
 	smp_wmb();
 }
 
-void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
+void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap,
+			u32 *tmr)
 {
 	struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic;
 	union kvm_ioapic_redirect_entry *e;
@@ -207,8 +208,13 @@ void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
 			 kvm_irq_has_notifier(ioapic->kvm, KVM_IRQCHIP_IOAPIC,
 				 index) || index == RTC_GSI)) {
 			if (kvm_apic_match_dest(vcpu, NULL, 0,
-				e->fields.dest_id, e->fields.dest_mode))
-				__set_bit(e->fields.vector, (unsigned long *)eoi_exit_bitmap);
+				e->fields.dest_id, e->fields.dest_mode)) {
+				__set_bit(e->fields.vector,
+					(unsigned long *)eoi_exit_bitmap);
+				if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG)
+					__set_bit(e->fields.vector,
+						(unsigned long *)tmr);
+			}
 		}
 	}
 	spin_unlock(&ioapic->lock);
virt/kvm/ioapic.h +2 -1
index 674a388..615d8c9 100644
@@ -97,6 +97,7 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
 int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state);
 int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state);
 void kvm_vcpu_request_scan_ioapic(struct kvm *kvm);
-void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
+void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap,
+			u32 *tmr);
 
 #endif
Signature · 1 line
1.7.1
author
#6 lore raw

PATCH v10 6/7 KVM: VMX: Add the algorithm of deliver posted interrupt

In reply to Yang Zhang

From: Yang Zhang <[email protected]>

Only deliver the posted interrupt when target vcpu is running and there is no previous interrupt pending in pir.

---
 arch/x86/include/asm/kvm_host.h |    2 +
 arch/x86/kvm/lapic.c            |   13 ++++++++
 arch/x86/kvm/lapic.h            |    1 +
 arch/x86/kvm/svm.c              |    6 ++++
 arch/x86/kvm/vmx.c              |   64 ++++++++++++++++++++++++++++++++++++++-
 virt/kvm/kvm_main.c             |    1 +
 6 files changed, 86 insertions(+), 1 deletions(-)
arch/x86/include/asm/kvm_host.h +2 -0
index 8e95512..842ea5a 100644
@@ -704,6 +704,8 @@ struct kvm_x86_ops {
 	void (*hwapic_isr_update)(struct kvm *kvm, int isr);
 	void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
 	void (*set_virtual_x2apic_mode)(struct kvm_vcpu *vcpu, bool set);
+	void (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector);
+	void (*sync_pir_to_irr)(struct kvm_vcpu *vcpu);
 	int (*set_tss_addr)(struct kvm *kvm, unsigned int addr);
 	int (*get_tdp_level)(void);
 	u64 (*get_mt_mask)(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio);
arch/x86/kvm/lapic.c +13 -0
index d197579..dbf74c9 100644
@@ -318,6 +318,19 @@ static u8 count_vectors(void *bitmap)
 	return count;
 }
 
+void kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir)
+{
+	u32 i, pir_val;
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	for (i = 0; i <= 7; i++) {
+		pir_val = xchg(&pir[i], 0);
+		if (pir_val)
+			*((u32 *)(apic->regs + APIC_IRR + i * 0x10)) |= pir_val;
+	}
+}
+EXPORT_SYMBOL_GPL(kvm_apic_update_irr);
+
 static inline int apic_test_and_set_irr(int vec, struct kvm_lapic *apic)
 {
 	apic->irr_pending = true;
arch/x86/kvm/lapic.h +1 -0
index 7fe0c91..c730ac9 100644
@@ -54,6 +54,7 @@ u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);
 void kvm_apic_set_version(struct kvm_vcpu *vcpu);
 
 void kvm_apic_update_tmr(struct kvm_vcpu *vcpu, u32 *tmr);
+void kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir);
 int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
 int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
 int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq,
arch/x86/kvm/svm.c +6 -0
index 2f8fe3f..d6713e1 100644
@@ -3577,6 +3577,11 @@ static void svm_hwapic_isr_update(struct kvm *kvm, int isr)
 	return;
 }
 
+static void svm_sync_pir_to_irr(struct kvm_vcpu *vcpu)
+{
+	return;
+}
+
 static int svm_nmi_allowed(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
@@ -4305,6 +4310,7 @@ static struct kvm_x86_ops svm_x86_ops = {
 	.vm_has_apicv = svm_vm_has_apicv,
 	.load_eoi_exitmap = svm_load_eoi_exitmap,
 	.hwapic_isr_update = svm_hwapic_isr_update,
+	.sync_pir_to_irr = svm_sync_pir_to_irr,
 
 	.set_tss_addr = svm_set_tss_addr,
 	.get_tdp_level = get_npt_level,
arch/x86/kvm/vmx.c +63 -1

95 lines not on this page · raw message

virt/kvm/kvm_main.c +1 -0
index 8b5c6a8..97c2264 100644
@@ -1671,6 +1671,7 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
 			smp_send_reschedule(cpu);
 	put_cpu();
 }
+EXPORT_SYMBOL_GPL(kvm_vcpu_kick);
 #endif /* !CONFIG_S390 */
 
 void kvm_resched(struct kvm_vcpu *vcpu)
Signature · 1 line
1.7.1
author
#7 lore raw

PATCH v10 7/7 KVM: VMX: Use posted interrupt to deliver virtual interrupt

In reply to Yang Zhang

From: Yang Zhang <[email protected]>

If posted interrupt is avaliable, then uses it to inject virtual interrupt to guest.

---
 arch/x86/kvm/lapic.c |   30 +++++++++++++++++++-----------
 arch/x86/kvm/vmx.c   |    2 +-
 arch/x86/kvm/x86.c   |    1 +
 3 files changed, 21 insertions(+), 12 deletions(-)
arch/x86/kvm/lapic.c +19 -11
index dbf74c9..e29883c 100644
@@ -353,6 +353,7 @@ static inline int apic_find_highest_irr(struct kvm_lapic *apic)
 	if (!apic->irr_pending)
 		return -1;
 
+	kvm_x86_ops->sync_pir_to_irr(apic->vcpu);
 	result = apic_search_irr(apic);
 	ASSERT(result == -1 || result >= 16);
 
@@ -683,18 +684,25 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
 		if (dest_map)
 			__set_bit(vcpu->vcpu_id, dest_map);
 
-		result = !apic_test_and_set_irr(vector, apic);
-		trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
-					  trig_mode, vector, !result);
-		if (!result) {
-			if (trig_mode)
-				apic_debug("level trig mode repeatedly for "
-						"vector %d", vector);
-			break;
-		}
+		if (kvm_x86_ops->deliver_posted_interrupt) {
+			result = 1;
+			kvm_x86_ops->deliver_posted_interrupt(vcpu, vector);
+		} else {
+			result = !apic_test_and_set_irr(vector, apic);
 
-		kvm_make_request(KVM_REQ_EVENT, vcpu);
-		kvm_vcpu_kick(vcpu);
+			if (!result) {
+				if (trig_mode)
+					apic_debug("level trig mode repeatedly "
+						"for vector %d", vector);
+				goto out;
+			}
+
+			kvm_make_request(KVM_REQ_EVENT, vcpu);
+			kvm_vcpu_kick(vcpu);
+		}
+out:
+		trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
+				trig_mode, vector, !result);
 		break;
 
 	case APIC_DM_REMRD:
arch/x86/kvm/vmx.c +1 -1
index 314b2ed..52b21da 100644
@@ -84,7 +84,7 @@ module_param(vmm_exclusive, bool, S_IRUGO);
 static bool __read_mostly fasteoi = 1;
 module_param(fasteoi, bool, S_IRUGO);
 
-static bool __read_mostly enable_apicv;
+static bool __read_mostly enable_apicv = 1;
 module_param(enable_apicv, bool, S_IRUGO);
 
 /*
arch/x86/kvm/x86.c +1 -0
index 6147d24..628582f 100644
@@ -2685,6 +2685,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
 				    struct kvm_lapic_state *s)
 {
+	kvm_x86_ops->sync_pir_to_irr(vcpu);
 	memcpy(s->regs, vcpu->arch.apic->regs, sizeof *s);
 
 	return 0;
Signature · 1 line
1.7.1
#8 lore raw

RE: [PATCH v10 7/7] KVM: VMX: Use posted interrupt to deliver virtual interrupt

Hi Yang Zhang,

Could you please let me know your CPU model or the CPU models which supports apic-v which your patch requires()? So that I could try you patches.

Intel Software Developer's Manualm, Volume 3C,
System Programming Guide, Part 3. Ch29,
APIC VIRTUALIZATION AND VIRTUAL INTERRUPTS

Or how can I know whether my hardware support those features listed in the manual above?

Thanks,
Steven

Quoted 105 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Yang Zhang
Sent: Thursday, April 11, 2013 7:25 PM
To: [email protected]
Cc: [email protected]; [email protected]; [email protected]; [email protected]; Yang Zhang
Subject: [PATCH v10 7/7] KVM: VMX: Use posted interrupt to deliver virtual interrupt

From: Yang Zhang <[email protected]>

If posted interrupt is avaliable, then uses it to inject virtual interrupt to guest.

---
 arch/x86/kvm/lapic.c |   30 +++++++++++++++++++-----------
 arch/x86/kvm/vmx.c   |    2 +-
 arch/x86/kvm/x86.c   |    1 +
 3 files changed, 21 insertions(+), 12 deletions(-)
arch/x86/kvm/lapic.c +19 -11
index dbf74c9..e29883c 100644
@@ -353,6 +353,7 @@ static inline int apic_find_highest_irr(struct kvm_lapic
 *apic)
 	if (!apic->irr_pending)
 		return -1;
 
+	kvm_x86_ops->sync_pir_to_irr(apic->vcpu);
 	result = apic_search_irr(apic);
 	ASSERT(result == -1 || result >= 16);
@@ -683,18 +684,25 @@ static int __apic_accept_irq(struct kvm_lapic *apic,
 int delivery_mode,
 		if (dest_map)
 			__set_bit(vcpu->vcpu_id, dest_map);
 
-		result = !apic_test_and_set_irr(vector, apic);
-		trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
-					  trig_mode, vector, !result);
-		if (!result) {
-			if (trig_mode)
-				apic_debug("level trig mode repeatedly for "
-						"vector %d", vector);
-			break;
-		}
+		if (kvm_x86_ops->deliver_posted_interrupt) {
+			result = 1;
+			kvm_x86_ops->deliver_posted_interrupt(vcpu, vector);
+		} else {
+			result = !apic_test_and_set_irr(vector, apic);
 
-		kvm_make_request(KVM_REQ_EVENT, vcpu);
-		kvm_vcpu_kick(vcpu);
+			if (!result) {
+				if (trig_mode)
+					apic_debug("level trig mode repeatedly "
+						"for vector %d", vector);
+				goto out;
+			}
+
+			kvm_make_request(KVM_REQ_EVENT, vcpu);
+			kvm_vcpu_kick(vcpu);
+		}
+out:
+		trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
+				trig_mode, vector, !result);
 		break;
 
arch/x86/kvm/lapic.c +0 -0
 	case APIC_DM_REMRD:
arch/x86/kvm/vmx.c +1 -1
index 314b2ed..52b21da 100644
@@ -84,7 +84,7 @@ module_param(vmm_exclusive, bool, S_IRUGO);
 static bool __read_mostly fasteoi = 1;
 module_param(fasteoi, bool, S_IRUGO);
 
-static bool __read_mostly enable_apicv;
+static bool __read_mostly enable_apicv = 1;
 module_param(enable_apicv, bool, S_IRUGO);
 
 /*
arch/x86/kvm/x86.c +1 -1
index 6147d24..628582f 100644
@@ -2685,6 +2685,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
 				    struct kvm_lapic_state *s)
 {
+	kvm_x86_ops->sync_pir_to_irr(vcpu);
 	memcpy(s->regs, vcpu->arch.apic->regs, sizeof *s);
 
 	return 0;
--

1.7.1

--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#9 lore raw

RE: [PATCH v10 7/7] KVM: VMX: Use posted interrupt to deliver virtual interrupt

Yangminqiang wrote on 2013-04-26:

Quoted 11 lines

Hi Yang Zhang,

Could you please let me know your CPU model or the CPU models which supports apic-v which your patch requires()? So that I could try you patches.

Intel Software Developer's Manualm, Volume 3C,
System Programming Guide, Part 3. Ch29,
APIC VIRTUALIZATION AND VIRTUAL INTERRUPTS
Or how can I know whether my hardware support those features listed in the manual above?

Ivytown or newer platform supported it.

Quoted 87 lines

Thanks,
Steven

[email protected] wrote on 2013-04-11:

Quoted 83 lines

Subject: [PATCH v10 7/7] KVM: VMX: Use posted interrupt to deliver virtual interrupt

From: Yang Zhang <[email protected]>

If posted interrupt is avaliable, then uses it to inject virtual interrupt to guest.

---
 arch/x86/kvm/lapic.c |   30 +++++++++++++++++++-----------
 arch/x86/kvm/vmx.c   |    2 +-
 arch/x86/kvm/x86.c   |    1 +
 3 files changed, 21 insertions(+), 12 deletions(-)
arch/x86/kvm/lapic.c +19 -11
index dbf74c9..e29883c 100644
@@ -353,6 +353,7 @@ static inline int apic_find_highest_irr(struct kvm_lapic
 *apic)
 	if (!apic->irr_pending)
 		return -1;
+	kvm_x86_ops->sync_pir_to_irr(apic->vcpu);
 	result = apic_search_irr(apic);
 	ASSERT(result == -1 || result >= 16);
@@ -683,18 +684,25 @@ static int __apic_accept_irq(struct kvm_lapic *apic,
 int delivery_mode,
 		if (dest_map)
 			__set_bit(vcpu->vcpu_id, dest_map);
-		result = !apic_test_and_set_irr(vector, apic);
-		trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
-					  trig_mode, vector, !result);
-		if (!result) {
-			if (trig_mode)
-				apic_debug("level trig mode repeatedly for "
-						"vector %d", vector);
-			break;
-		}
+		if (kvm_x86_ops->deliver_posted_interrupt) {
+			result = 1;
+			kvm_x86_ops->deliver_posted_interrupt(vcpu, vector);
+		} else {
+			result = !apic_test_and_set_irr(vector, apic);
 
-		kvm_make_request(KVM_REQ_EVENT, vcpu);
-		kvm_vcpu_kick(vcpu);
+			if (!result) {
+				if (trig_mode)
+					apic_debug("level trig mode repeatedly "
+						"for vector %d", vector);
+				goto out;
+			}
+
+			kvm_make_request(KVM_REQ_EVENT, vcpu);
+			kvm_vcpu_kick(vcpu);
+		}
+out:
+		trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
+				trig_mode, vector, !result);
 		break;
 
 	case APIC_DM_REMRD:
arch/x86/kvm/vmx.c +1 -1
index 314b2ed..52b21da 100644
@@ -84,7 +84,7 @@ module_param(vmm_exclusive, bool, S_IRUGO);
 static bool __read_mostly fasteoi = 1;
 module_param(fasteoi, bool, S_IRUGO);
-static bool __read_mostly enable_apicv;
+static bool __read_mostly enable_apicv = 1;
 module_param(enable_apicv, bool, S_IRUGO);
 
 /*
arch/x86/kvm/x86.c +0 -0
index 6147d24..628582f 100644
@@ -2685,6 +2685,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu, 				   
 struct kvm_lapic_state *s) { +	kvm_x86_ops->sync_pir_to_irr(vcpu);
 	memcpy(s->regs, vcpu->arch.apic->regs, sizeof *s);
 
Quoted 8 lines
Quoted 8 lines
arch/x86/kvm/x86.c +0 -1
 	return 0;
--

1.7.1

--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

Best regards,
Yang

#10 lore raw

RE: [PATCH v10 7/7] KVM: VMX: Use posted interrupt to deliver virtual interrupt

Quoted 18 lines

-----Original Message-----
From: Zhang, Yang Z [mailto:[email protected]]
Sent: Friday, April 26, 2013 1:10 PM
To: Yangminqiang; [email protected]
Cc: [email protected]; [email protected]; Zhang, Xiantao; Nakajima, Jun; Luohao (brian); Haofeng
Subject: RE: [PATCH v10 7/7] KVM: VMX: Use posted interrupt to deliver virtual interrupt

Yangminqiang wrote on 2013-04-26:

Quoted 6 lines

Hi Yang Zhang,

Could you please let me know your CPU model or the CPU models which supports apic-v which your patch requires()? So that I could try you patches.

Quoted 6 lines
Quoted 5 lines

Intel Software Developer's Manualm, Volume 3C,
System Programming Guide, Part 3. Ch29,
APIC VIRTUALIZATION AND VIRTUAL INTERRUPTS
Or how can I know whether my hardware support those features listed in the manual above?

Ivytown or newer platform supported it.

Ivytown? Do you mean Ivy Bridge?

Quoted 104 lines
Quoted 13 lines

Thanks,
Steven

[email protected] wrote on 2013-04-11:

Quoted 8 lines

Subject: [PATCH v10 7/7] KVM: VMX: Use posted interrupt to deliver virtual interrupt

From: Yang Zhang <[email protected]>

If posted interrupt is avaliable, then uses it to inject virtual interrupt to guest.

Quoted 11 lines

arch/x86/kvm/lapic.c static inline int apic_find_highest_irr(struct

Quoted 11 lines
---
 arch/x86/kvm/lapic.c |   30 +++++++++++++++++++-----------
 arch/x86/kvm/vmx.c   |    2 +-
 arch/x86/kvm/x86.c   |    1 +
 3 files changed, 21 insertions(+), 12 deletions(-)
arch/x86/kvm/lapic.c +0 -0
index dbf74c9..e29883c 100644
@@ -353,6 +353,7 @@ static inline int apic_find_highest_irr(struct

kvm_lapic

Quoted 7 lines

arch/x86/kvm/lapic.c static int __apic_accept_irq(struct kvm_lapic

Quoted 7 lines
arch/x86/kvm/lapic.c +1 -0
 *apic)
 	if (!apic->irr_pending)
 		return -1;
+	kvm_x86_ops->sync_pir_to_irr(apic->vcpu);
 	result = apic_search_irr(apic);
 	ASSERT(result == -1 || result >= 16);
@@ -683,18 +684,25 @@ static int __apic_accept_irq(struct kvm_lapic

*apic,

Quoted 58 lines
Quoted 58 lines
arch/x86/kvm/lapic.c +18 -11
 int delivery_mode,
 		if (dest_map)
 			__set_bit(vcpu->vcpu_id, dest_map);
-		result = !apic_test_and_set_irr(vector, apic);
-		trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
-					  trig_mode, vector, !result);
-		if (!result) {
-			if (trig_mode)
-				apic_debug("level trig mode repeatedly for "
-						"vector %d", vector);
-			break;
-		}
+		if (kvm_x86_ops->deliver_posted_interrupt) {
+			result = 1;
+			kvm_x86_ops->deliver_posted_interrupt(vcpu, vector);
+		} else {
+			result = !apic_test_and_set_irr(vector, apic);
 
-		kvm_make_request(KVM_REQ_EVENT, vcpu);
-		kvm_vcpu_kick(vcpu);
+			if (!result) {
+				if (trig_mode)
+					apic_debug("level trig mode repeatedly "
+						"for vector %d", vector);
+				goto out;
+			}
+
+			kvm_make_request(KVM_REQ_EVENT, vcpu);
+			kvm_vcpu_kick(vcpu);
+		}
+out:
+		trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
+				trig_mode, vector, !result);
 		break;
 
 	case APIC_DM_REMRD:
arch/x86/kvm/vmx.c +1 -1
index 314b2ed..52b21da 100644
@@ -84,7 +84,7 @@ module_param(vmm_exclusive, bool, S_IRUGO);
 static bool __read_mostly fasteoi = 1;
 module_param(fasteoi, bool, S_IRUGO);
-static bool __read_mostly enable_apicv;
+static bool __read_mostly enable_apicv = 1;
 module_param(enable_apicv, bool, S_IRUGO);
 
 /*
arch/x86/kvm/x86.c +0 -0
index 6147d24..628582f 100644
@@ -2685,6 +2685,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
 
 struct kvm_lapic_state *s) { +	kvm_x86_ops->sync_pir_to_irr(vcpu);
 	memcpy(s->regs, vcpu->arch.apic->regs, sizeof *s);
 
Quoted 8 lines
Quoted 8 lines
arch/x86/kvm/x86.c +0 -1
 	return 0;
--

1.7.1

--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

Best regards,
Yang

#11 lore raw

Re: [PATCH v10 7/7] KVM: VMX: Use posted interrupt to deliver virtual interrupt

Quoted 4 lines · Yangminqiang
Quoted 1 line

Ivytown or newer platform supported it.

Ivytown? Do you mean Ivy Bridge?

Ivy Town is the codename of "Ivy Bridge-based servers".

--
Jun
Intel Open Source Technology Center

#12 lore raw

RE: [PATCH v10 7/7] KVM: VMX: Use posted interrupt to deliver virtual interrupt

Quoted 12 lines

-----Original Message-----
From: Nakajima, Jun [mailto:[email protected]]
Sent: Friday, April 26, 2013 9:46 PM
To: Yangminqiang
Cc: Zhang, Yang Z; [email protected]; [email protected]; [email protected]; Zhang, Xiantao; Luohao (brian); Haofeng
Subject: Re: [PATCH v10 7/7] KVM: VMX: Use posted interrupt to deliver virtual interrupt

On Fri, Apr 26, 2013 at 2:29 AM, Yangminqiang <[email protected]> wrote:

Quoted 6 lines
Quoted 4 lines
Quoted 1 line

Ivytown or newer platform supported it.

Ivytown? Do you mean Ivy Bridge?

Ivy Town is the codename of "Ivy Bridge-based servers".

One more question, what is the relationship between x2APIC and APIC virtualization? APIC-v requires x2APIC or APIC-v includes x2APIC?

Regards,
Steven

#13 lore raw

RE: [PATCH v10 7/7] KVM: VMX: Use posted interrupt to deliver virtual interrupt

Yangminqiang wrote on 2013-05-03:

Quoted 9 lines

Nakajima, Jun wrote on 2013-04-26:

Quoted 8 lines

Subject: Re: [PATCH v10 7/7] KVM: VMX: Use posted interrupt to deliver virtual interrupt

Quoted 2 lines · Yangminqiang
Quoted 1 line

Ivytown or newer platform supported it.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

Ivytown? Do you mean Ivy Bridge?

Ivy Town is the codename of "Ivy Bridge-based servers".

One more question, what is the relationship between x2APIC and APIC virtualization? APIC-v requires x2APIC or APIC-v includes x2APIC?

If you are using x2apic way(MSR base access)inside guest and want to benefit from apic virtualization technology, then you should set virtual x2apic bit in Secondary Processor-Based VM-Execution Controls.

Best regards,
Yang

Reviewed-by on the v10 series
#14 lore raw
In reply to Yang Zhang
Quoted 10 lines · Yang Zhang

From: Yang Zhang <[email protected]>

The follwoing patches are adding the Posted Interrupt supporting to KVM:
The first patch enables the feature 'acknowledge interrupt on vmexit'.Since it is required by Posted interrupt, we need to enable it firstly.

And the subsequent patches are adding the posted interrupt supporting:
Posted Interrupt allows APIC interrupts to inject into guest directly without any vmexit.

Quoted 9 lines

- When delivering a interrupt to guest, if target vcpu is running, update Posted-interrupt requests bitmap and send a notification event to the vcpu. Then the vcpu will handle this interrupt automatically, without any software involvemnt.

- If target vcpu is not running or there already a notification event pending in the vcpu, do nothing. The interrupt will be handled by next vm entry

Quoted 38 lines

Changes from v9 to v10:
* Only check kvm_apic_hw_enable() in vcpu_sacn_ioapic().
* Remove repeated tracing in __apic_accept_irq().
* Rebase on top of KVM upstream + RTC eoi tracking patch.

Changes from v8 to v9:
* Add tracing in PI case when deliver interrupt.
* Scan ioapic when updating SPIV register.
* Rebase on top of KVM upstream + RTC eoi tracking patch.

Changes from v7 to v8:
* Remove unused memeber 'on' from struct pi_desc.
* Register a dummy function to sync_pir_to_irr is apicv is disabled.
* Minor fixup.
* Rebase on top of KVM upstream + RTC eoi tracking patch.

Yang Zhang (7):
KVM: VMX: Enable acknowledge interupt on vmexit
KVM: VMX: Register a new IPI for posted interrupt
KVM: VMX: Check the posted interrupt capability
KVM: Call common update function when ioapic entry changed.
KVM: Set TMR when programming ioapic entry
KVM: VMX: Add the algorithm of deliver posted interrupt
KVM: VMX: Use posted interrupt to deliver virtual interrupt

 arch/ia64/kvm/lapic.h              |    6 -
 arch/x86/include/asm/entry_arch.h  |    4 +
 arch/x86/include/asm/hardirq.h     |    3 +
 arch/x86/include/asm/hw_irq.h      |    1 +
 arch/x86/include/asm/irq_vectors.h |    5 +
 arch/x86/include/asm/kvm_host.h    |    3 +
 arch/x86/include/asm/vmx.h         |    4 +
 arch/x86/kernel/entry_64.S         |    5 +
 arch/x86/kernel/irq.c              |   22 ++++
 arch/x86/kernel/irqinit.c          |    4 +
 arch/x86/kvm/lapic.c               |   58 +++++++---
 arch/x86/kvm/lapic.h               |    2 +
 arch/x86/kvm/svm.c                 |   12 ++
Quoted 8 lines
 arch/x86/kvm/vmx.c                 |  207 +++++++++++++++++++++++++++++++-----
 arch/x86/kvm/x86.c                 |   19 +++-
 include/linux/kvm_host.h           |    4 +-
 virt/kvm/ioapic.c                  |   32 ++++--
 virt/kvm/ioapic.h                  |    7 +-
 virt/kvm/irq_comm.c                |    4 +-
 virt/kvm/kvm_main.c                |    5 +-
 20 files changed, 333 insertions(+), 74 deletions(-)

--
Gleb.

#15 lore raw
Quoted 16 lines · Gleb Natapov
Quoted 15 lines · Yang Zhang

From: Yang Zhang <[email protected]>

The follwoing patches are adding the Posted Interrupt supporting to KVM:
The first patch enables the feature 'acknowledge interrupt on vmexit'.Since it is required by Posted interrupt, we need to enable it firstly.

And the subsequent patches are adding the posted interrupt supporting:
Posted Interrupt allows APIC interrupts to inject into guest directly without any vmexit.

- When delivering a interrupt to guest, if target vcpu is running, update Posted-interrupt requests bitmap and send a notification event to the vcpu. Then the vcpu will handle this interrupt automatically, without any software involvemnt.

Quoted 5 lines
Quoted 4 lines

- If target vcpu is not running or there already a notification event pending in the vcpu, do nothing. The interrupt will be handled by next vm entry

Applied, thanks.