diff options
author | Feng Wu <feng.wu@intel.com> | 2015-05-19 05:07:16 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2015-05-19 09:51:17 -0400 |
commit | f6b3c72c23661e5534cd2eede16e9bac7ebb761c (patch) | |
tree | 9a4033e16059ae731bd8fc5420a942b9dcecaadc | |
parent | a2f1c8bdc02bfcaa5a658283b883fdb54e328b36 (diff) |
x86/irq: Define a global vector for VT-d Posted-Interrupts
Currently, we use a global vector as the Posted-Interrupts
Notification Event for all the vCPUs in the system. We need
to introduce another global vector for VT-d Posted-Interrtups,
which will be used to wakeup the sleep vCPU when an external
interrupt from a direct-assigned device happens for that vCPU.
[ tglx: Removed a gazillion of extra newlines ]
Signed-off-by: Feng Wu <feng.wu@intel.com>
Cc: jiang.liu@linux.intel.com
Link: http://lkml.kernel.org/r/1432026437-16560-4-git-send-email-feng.wu@intel.com
Suggested-by: Yang Zhang <yang.z.zhang@intel.com>
Acked-by: H. Peter Anvin <hpa@linux.intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | arch/x86/include/asm/entry_arch.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/hardirq.h | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/hw_irq.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/irq.h | 4 | ||||
-rw-r--r-- | arch/x86/include/asm/irq_vectors.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/entry_64.S | 2 | ||||
-rw-r--r-- | arch/x86/kernel/irq.c | 26 | ||||
-rw-r--r-- | arch/x86/kernel/irqinit.c | 2 |
8 files changed, 40 insertions, 0 deletions
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h index dc5fa661465f..27ca0afcccd7 100644 --- a/arch/x86/include/asm/entry_arch.h +++ b/arch/x86/include/asm/entry_arch.h | |||
@@ -23,6 +23,8 @@ BUILD_INTERRUPT(x86_platform_ipi, X86_PLATFORM_IPI_VECTOR) | |||
23 | #ifdef CONFIG_HAVE_KVM | 23 | #ifdef CONFIG_HAVE_KVM |
24 | BUILD_INTERRUPT3(kvm_posted_intr_ipi, POSTED_INTR_VECTOR, | 24 | BUILD_INTERRUPT3(kvm_posted_intr_ipi, POSTED_INTR_VECTOR, |
25 | smp_kvm_posted_intr_ipi) | 25 | smp_kvm_posted_intr_ipi) |
26 | BUILD_INTERRUPT3(kvm_posted_intr_wakeup_ipi, POSTED_INTR_WAKEUP_VECTOR, | ||
27 | smp_kvm_posted_intr_wakeup_ipi) | ||
26 | #endif | 28 | #endif |
27 | 29 | ||
28 | /* | 30 | /* |
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h index 0f5fb6b6567e..986606539395 100644 --- a/arch/x86/include/asm/hardirq.h +++ b/arch/x86/include/asm/hardirq.h | |||
@@ -14,6 +14,7 @@ typedef struct { | |||
14 | #endif | 14 | #endif |
15 | #ifdef CONFIG_HAVE_KVM | 15 | #ifdef CONFIG_HAVE_KVM |
16 | unsigned int kvm_posted_intr_ipis; | 16 | unsigned int kvm_posted_intr_ipis; |
17 | unsigned int kvm_posted_intr_wakeup_ipis; | ||
17 | #endif | 18 | #endif |
18 | unsigned int x86_platform_ipis; /* arch dependent */ | 19 | unsigned int x86_platform_ipis; /* arch dependent */ |
19 | unsigned int apic_perf_irqs; | 20 | unsigned int apic_perf_irqs; |
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 9ec5d37d8da3..10c80d4f8386 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h | |||
@@ -29,6 +29,7 @@ | |||
29 | extern asmlinkage void apic_timer_interrupt(void); | 29 | extern asmlinkage void apic_timer_interrupt(void); |
30 | extern asmlinkage void x86_platform_ipi(void); | 30 | extern asmlinkage void x86_platform_ipi(void); |
31 | extern asmlinkage void kvm_posted_intr_ipi(void); | 31 | extern asmlinkage void kvm_posted_intr_ipi(void); |
32 | extern asmlinkage void kvm_posted_intr_wakeup_ipi(void); | ||
32 | extern asmlinkage void error_interrupt(void); | 33 | extern asmlinkage void error_interrupt(void); |
33 | extern asmlinkage void irq_work_interrupt(void); | 34 | extern asmlinkage void irq_work_interrupt(void); |
34 | 35 | ||
@@ -58,6 +59,7 @@ extern void trace_call_function_single_interrupt(void); | |||
58 | #define trace_irq_move_cleanup_interrupt irq_move_cleanup_interrupt | 59 | #define trace_irq_move_cleanup_interrupt irq_move_cleanup_interrupt |
59 | #define trace_reboot_interrupt reboot_interrupt | 60 | #define trace_reboot_interrupt reboot_interrupt |
60 | #define trace_kvm_posted_intr_ipi kvm_posted_intr_ipi | 61 | #define trace_kvm_posted_intr_ipi kvm_posted_intr_ipi |
62 | #define trace_kvm_posted_intr_wakeup_ipi kvm_posted_intr_wakeup_ipi | ||
61 | #endif /* CONFIG_TRACING */ | 63 | #endif /* CONFIG_TRACING */ |
62 | 64 | ||
63 | #ifdef CONFIG_X86_LOCAL_APIC | 65 | #ifdef CONFIG_X86_LOCAL_APIC |
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index a80cbb88ea91..8008d06581c7 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h | |||
@@ -30,6 +30,10 @@ extern void fixup_irqs(void); | |||
30 | extern void irq_force_complete_move(int); | 30 | extern void irq_force_complete_move(int); |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | #ifdef CONFIG_HAVE_KVM | ||
34 | extern void kvm_set_posted_intr_wakeup_handler(void (*handler)(void)); | ||
35 | #endif | ||
36 | |||
33 | extern void (*x86_platform_ipi_callback)(void); | 37 | extern void (*x86_platform_ipi_callback)(void); |
34 | extern void native_init_IRQ(void); | 38 | extern void native_init_IRQ(void); |
35 | extern bool handle_irq(unsigned irq, struct pt_regs *regs); | 39 | extern bool handle_irq(unsigned irq, struct pt_regs *regs); |
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index bf55235d7772..0ed29ac13a9d 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h | |||
@@ -86,6 +86,7 @@ | |||
86 | /* Vector for KVM to deliver posted interrupt IPI */ | 86 | /* Vector for KVM to deliver posted interrupt IPI */ |
87 | #ifdef CONFIG_HAVE_KVM | 87 | #ifdef CONFIG_HAVE_KVM |
88 | #define POSTED_INTR_VECTOR 0xf2 | 88 | #define POSTED_INTR_VECTOR 0xf2 |
89 | #define POSTED_INTR_WAKEUP_VECTOR 0xf1 | ||
89 | #endif | 90 | #endif |
90 | 91 | ||
91 | /* | 92 | /* |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 47b95813dc37..22aadc917868 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -916,6 +916,8 @@ apicinterrupt X86_PLATFORM_IPI_VECTOR \ | |||
916 | #ifdef CONFIG_HAVE_KVM | 916 | #ifdef CONFIG_HAVE_KVM |
917 | apicinterrupt3 POSTED_INTR_VECTOR \ | 917 | apicinterrupt3 POSTED_INTR_VECTOR \ |
918 | kvm_posted_intr_ipi smp_kvm_posted_intr_ipi | 918 | kvm_posted_intr_ipi smp_kvm_posted_intr_ipi |
919 | apicinterrupt3 POSTED_INTR_WAKEUP_VECTOR \ | ||
920 | kvm_posted_intr_wakeup_ipi smp_kvm_posted_intr_wakeup_ipi | ||
919 | #endif | 921 | #endif |
920 | 922 | ||
921 | #ifdef CONFIG_X86_MCE_THRESHOLD | 923 | #ifdef CONFIG_X86_MCE_THRESHOLD |
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index be3894512820..90b2f7052f5b 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
@@ -242,6 +242,18 @@ __visible void smp_x86_platform_ipi(struct pt_regs *regs) | |||
242 | } | 242 | } |
243 | 243 | ||
244 | #ifdef CONFIG_HAVE_KVM | 244 | #ifdef CONFIG_HAVE_KVM |
245 | static void dummy_handler(void) {} | ||
246 | static void (*kvm_posted_intr_wakeup_handler)(void) = dummy_handler; | ||
247 | |||
248 | void kvm_set_posted_intr_wakeup_handler(void (*handler)(void)) | ||
249 | { | ||
250 | if (handler) | ||
251 | kvm_posted_intr_wakeup_handler = handler; | ||
252 | else | ||
253 | kvm_posted_intr_wakeup_handler = dummy_handler; | ||
254 | } | ||
255 | EXPORT_SYMBOL_GPL(kvm_set_posted_intr_wakeup_handler); | ||
256 | |||
245 | /* | 257 | /* |
246 | * Handler for POSTED_INTERRUPT_VECTOR. | 258 | * Handler for POSTED_INTERRUPT_VECTOR. |
247 | */ | 259 | */ |
@@ -254,6 +266,20 @@ __visible void smp_kvm_posted_intr_ipi(struct pt_regs *regs) | |||
254 | exiting_irq(); | 266 | exiting_irq(); |
255 | set_irq_regs(old_regs); | 267 | set_irq_regs(old_regs); |
256 | } | 268 | } |
269 | |||
270 | /* | ||
271 | * Handler for POSTED_INTERRUPT_WAKEUP_VECTOR. | ||
272 | */ | ||
273 | __visible void smp_kvm_posted_intr_wakeup_ipi(struct pt_regs *regs) | ||
274 | { | ||
275 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
276 | |||
277 | entering_ack_irq(); | ||
278 | inc_irq_stat(kvm_posted_intr_wakeup_ipis); | ||
279 | kvm_posted_intr_wakeup_handler(); | ||
280 | exiting_irq(); | ||
281 | set_irq_regs(old_regs); | ||
282 | } | ||
257 | #endif | 283 | #endif |
258 | 284 | ||
259 | __visible void smp_trace_x86_platform_ipi(struct pt_regs *regs) | 285 | __visible void smp_trace_x86_platform_ipi(struct pt_regs *regs) |
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index dc1e08d23552..680723a8e4b6 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c | |||
@@ -144,6 +144,8 @@ static void __init apic_intr_init(void) | |||
144 | #ifdef CONFIG_HAVE_KVM | 144 | #ifdef CONFIG_HAVE_KVM |
145 | /* IPI for KVM to deliver posted interrupt */ | 145 | /* IPI for KVM to deliver posted interrupt */ |
146 | alloc_intr_gate(POSTED_INTR_VECTOR, kvm_posted_intr_ipi); | 146 | alloc_intr_gate(POSTED_INTR_VECTOR, kvm_posted_intr_ipi); |
147 | /* IPI for KVM to deliver interrupt to wake up tasks */ | ||
148 | alloc_intr_gate(POSTED_INTR_WAKEUP_VECTOR, kvm_posted_intr_wakeup_ipi); | ||
147 | #endif | 149 | #endif |
148 | 150 | ||
149 | /* IPI vectors for APIC spurious and error interrupts */ | 151 | /* IPI vectors for APIC spurious and error interrupts */ |