KVM: VMX: Register a new IPI for posted interrupt
authorYang Zhang <yang.z.zhang@Intel.com>
Thu, 11 Apr 2013 11:25:11 +0000 (19:25 +0800)
committerMarcelo Tosatti <mtosatti@redhat.com>
Tue, 16 Apr 2013 19:32:39 +0000 (16:32 -0300)
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.

Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com>
Acked-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
arch/x86/include/asm/entry_arch.h
arch/x86/include/asm/hardirq.h
arch/x86/include/asm/hw_irq.h
arch/x86/include/asm/irq_vectors.h
arch/x86/kernel/entry_64.S
arch/x86/kernel/irq.c
arch/x86/kernel/irqinit.c

index 40afa0005c6905ae1e2826f0c7151b7740f73b80..9bd4ecac72be33f4366e08d5a98ac687cf4a6fe7 100644 (file)
@@ -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
index 81f04cee5f741226b6e23e45bcab7874bff29e62..ab0ae1aa6d0af1c5d64edcd313e5283aa099c04f 100644 (file)
@@ -11,6 +11,9 @@ typedef struct {
        unsigned int apic_timer_irqs;   /* arch dependent */
        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;
index 10a78c3d3d5a771d8581a13e402eb69e462e1dae..1da97efad08ae3c79f73827be832ed5618dd0372 100644 (file)
@@ -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);
 
index aac5fa62a86caf91c82873712543017f89df1756..5702d7e3111db94facc17423b882d46617bd64fe 100644 (file)
  */
 #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:
  */
index c1d01e6ca790299611a2ada8eb0e163e4fd8336b..727208941030943370fde4160b6f9ad54e62b68b 100644 (file)
@@ -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 \
index e4595f10591071c4af181bc0a16a2bf2d901a30f..6ae6ea1d27d931ab656ee5671e21dc33cd3ff24a 100644 (file)
@@ -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
index 7dc4e459c2b389c2126d679d1692856ea4caddb0..a2a1fbc594ff906d0727e9f44e7db6f02c876570 100644 (file)
@@ -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);