aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir@xen.org>2010-12-01 20:14:56 +0000
committerKeir Fraser <keir@xen.org>2010-12-01 20:14:56 +0000
commit1d632a04aef8a261a3dc06d8410641029fcb7d53 (patch)
tree0648da1478411f6a9be27d6db7127286ba274255
parent8d4f58459ccd828a0dc58a47bb95503fd9381836 (diff)
downloadxen-1d632a04aef8a261a3dc06d8410641029fcb7d53.tar.gz
xen-1d632a04aef8a261a3dc06d8410641029fcb7d53.tar.bz2
xen-1d632a04aef8a261a3dc06d8410641029fcb7d53.zip
x86: fix IRQ migration when using directed EOI (broken with c/s 20465)
In directed-EOI mode, there is no chance to do the migration in mask_and_ack_level_ioapic_irq(), as the remote IRR bit can't possibly be clear after issuing the EOI to the LAPIC. Consequently, there's no point to even try. Instead, migration must be done in end_level_ioapic_irq(), and it requires masking the interrupt source prior to issuing the EOI to the IO-APIC. Signed-off-by: Jan Beulich <jbeulich@novell.com> xen-unstable changeset: 22452:62bf12040b0f xen-unstable date: Wed Dec 01 20:10:27 2010 +0000
-rw-r--r--xen/arch/x86/io_apic.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c
index 99a78da847..1f653510c5 100644
--- a/xen/arch/x86/io_apic.c
+++ b/xen/arch/x86/io_apic.c
@@ -1634,11 +1634,14 @@ static void mask_and_ack_level_ioapic_irq (unsigned int irq)
ack_APIC_irq();
+ if ( directed_eoi_enabled )
+ return;
+
if ((irq_desc[irq].status & IRQ_MOVE_PENDING) &&
!io_apic_level_ack_pending(irq))
- move_native_irq(irq);
+ move_masked_irq(irq);
- if (!directed_eoi_enabled && !(v & (1 << (i & 0x1f)))) {
+ if ( !(v & (1 << (i & 0x1f))) ) {
atomic_inc(&irq_mis_count);
spin_lock(&ioapic_lock);
__edge_IO_APIC_irq(irq);
@@ -1654,12 +1657,22 @@ static void end_level_ioapic_irq (unsigned int irq)
if ( !ioapic_ack_new )
{
- if ( irq_desc[irq].status & IRQ_DISABLED )
- return;
-
if ( directed_eoi_enabled )
+ {
+ if ( !(irq_desc[irq].status & (IRQ_DISABLED|IRQ_MOVE_PENDING)) )
+ {
+ eoi_IO_APIC_irq(irq);
+ return;
+ }
+
+ mask_IO_APIC_irq(irq);
eoi_IO_APIC_irq(irq);
- else
+ if ( (irq_desc[irq].status & IRQ_MOVE_PENDING) &&
+ !io_apic_level_ack_pending(irq) )
+ move_masked_irq(irq);
+ }
+
+ if ( !(irq_desc[irq].status & IRQ_DISABLED) )
unmask_IO_APIC_irq(irq);
return;