diff options
author | Keir Fraser <keir@xen.org> | 2010-12-01 20:14:56 +0000 |
---|---|---|
committer | Keir Fraser <keir@xen.org> | 2010-12-01 20:14:56 +0000 |
commit | 1d632a04aef8a261a3dc06d8410641029fcb7d53 (patch) | |
tree | 0648da1478411f6a9be27d6db7127286ba274255 | |
parent | 8d4f58459ccd828a0dc58a47bb95503fd9381836 (diff) | |
download | xen-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.c | 25 |
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; |