[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-4.0-testing] IRQ: manually EOI migrating line interrupts
# HG changeset patch # User Andrew Cooper <andrew.cooper3@xxxxxxxxxx> # Date 1314801477 -3600 # Node ID 0383662ea34cb24314ff614a6abed8294e6c14c3 # Parent 4b7b75ace86391ca337198857be65491adf08756 IRQ: manually EOI migrating line interrupts When migrating IO-APIC line level interrupts between PCPUs, the migration code rewrites the IO-APIC entry to point to the new CPU/Vector before EOI'ing it. The EOI process says that EOI'ing the Local APIC will cause a broadcast with the vector number, which the IO-APIC must listen to to clear the IRR and Status bits. In the case of migrating, the IO-APIC has already been reprogrammed so the EOI broadcast with the old vector fails to match the new vector, leaving the IO-APIC with an outstanding vector, preventing any more use of that line interrupt. This causes a lockup especially when your root device is using PCI INTA (megaraid_sas driver *ehem*) However, the problem is mostly hidden because send_cleanup_vector() causes a cleanup of all moving vectors on the current PCPU in such a way which does not cause the problem, and if the problem has occured, the writes it makes to the IO-APIC clears the IRR and Status bits which unlocks the problem. This fix is distinctly a temporary hack, waiting on a cleanup of the irq code. It checks for the edge case where we have moved the irq, and manually EOI's the old vector with the IO-APIC which correctly clears the IRR and Status bits. Also, it protects the code which updates irq_cfg by disabling interrupts. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> xen-unstable changeset: 23805:7048810180de xen-unstable date: Wed Aug 31 15:19:24 2011 +0100 --- diff -r 4b7b75ace863 -r 0383662ea34c xen/arch/x86/hpet.c --- a/xen/arch/x86/hpet.c Thu Aug 25 15:36:50 2011 +0100 +++ b/xen/arch/x86/hpet.c Wed Aug 31 15:37:57 2011 +0100 @@ -297,7 +297,7 @@ ack_APIC_irq(); } -static void hpet_msi_end(unsigned int irq) +static void hpet_msi_end(unsigned int irq, u8 vector) { } diff -r 4b7b75ace863 -r 0383662ea34c xen/arch/x86/hvm/vmx/vpmu_core2.c --- a/xen/arch/x86/hvm/vmx/vpmu_core2.c Thu Aug 25 15:36:50 2011 +0100 +++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c Wed Aug 31 15:37:57 2011 +0100 @@ -55,7 +55,8 @@ is_pmc_quirk = 0; if ( family == 6 ) { - if ( cpu_model == 46 || cpu_model == 26 ) + if ( cpu_model == 47 || cpu_model == 46 || cpu_model == 42 || + cpu_model == 26 ) is_pmc_quirk = 1; } } diff -r 4b7b75ace863 -r 0383662ea34c xen/arch/x86/i8259.c --- a/xen/arch/x86/i8259.c Thu Aug 25 15:36:50 2011 +0100 +++ b/xen/arch/x86/i8259.c Wed Aug 31 15:37:57 2011 +0100 @@ -91,7 +91,7 @@ return 0; /* never anything pending */ } -static void end_8259A_irq(unsigned int irq) +static void end_8259A_irq(unsigned int irq, u8 vector) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) enable_8259A_irq(irq); diff -r 4b7b75ace863 -r 0383662ea34c xen/arch/x86/io_apic.c --- a/xen/arch/x86/io_apic.c Thu Aug 25 15:36:50 2011 +0100 +++ b/xen/arch/x86/io_apic.c Wed Aug 31 15:37:57 2011 +0100 @@ -1651,7 +1651,7 @@ } } -static void end_level_ioapic_irq (unsigned int irq) +static void end_level_ioapic_irq (unsigned int irq, u8 vector) { unsigned long v; int i; @@ -1700,6 +1700,14 @@ */ i = IO_APIC_VECTOR(irq); + /* Manually EOI the old vector if we are moving to the new */ + if ( vector && i != vector ) + { + int ioapic; + for (ioapic = 0; ioapic < nr_ioapics; ioapic++) + io_apic_eoi(ioapic, i); + } + v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1)); ack_APIC_irq(); @@ -1724,9 +1732,9 @@ { } -static void end_edge_ioapic_irq(unsigned int irq) - { - } +static void end_edge_ioapic_irq(unsigned int irq, u8 vector) +{ +} /* * Level and edge triggered IO-APIC interrupts need different handling, @@ -1775,7 +1783,7 @@ ack_APIC_irq(); /* ACKTYPE_NONE */ } -static void end_msi_irq(unsigned int irq) +static void end_msi_irq(unsigned int irq, u8 vector) { if ( !msi_maskable_irq(irq_desc[irq].msi_desc) ) ack_APIC_irq(); /* ACKTYPE_EOI */ @@ -1828,7 +1836,7 @@ ack_APIC_irq(); } -static void end_lapic_irq(unsigned int irq) { /* nothing */ } +#define end_lapic_irq end_edge_ioapic_irq static hw_irq_controller lapic_irq_type = { .typename = "local-APIC-edge", diff -r 4b7b75ace863 -r 0383662ea34c xen/arch/x86/irq.c --- a/xen/arch/x86/irq.c Thu Aug 25 15:36:50 2011 +0100 +++ b/xen/arch/x86/irq.c Wed Aug 31 15:37:57 2011 +0100 @@ -307,6 +307,7 @@ void no_action(int cpl, void *dev_id, struct cpu_user_regs *regs) { } static void enable_none(unsigned int vector) { } +static void end_none(unsigned int irq, u8 vector) { } static unsigned int startup_none(unsigned int vector) { return 0; } static void disable_none(unsigned int vector) { } static void ack_none(unsigned int irq) @@ -315,7 +316,6 @@ } #define shutdown_none disable_none -#define end_none enable_none hw_irq_controller no_irq_type = { "none", @@ -345,6 +345,7 @@ static int current_vector = FIRST_DYNAMIC_VECTOR, current_offset = 0; unsigned int old_vector; int cpu, err; + unsigned long flags; cpumask_t tmp_mask; if ((cfg->move_in_progress) || cfg->move_cleanup_count) @@ -392,6 +393,7 @@ /* Found one! */ current_vector = vector; current_offset = offset; + local_irq_save(flags); if (old_vector) { cfg->move_in_progress = 1; cpus_copy(cfg->old_domain, cfg->domain); @@ -405,6 +407,7 @@ if (IO_APIC_IRQ(irq)) irq_vector[irq] = vector; err = 0; + local_irq_restore(flags); break; } return err; @@ -599,7 +602,7 @@ desc->status &= ~IRQ_INPROGRESS; out: - desc->handler->end(irq); + desc->handler->end(irq, regs->entry_vector); out_no_end: spin_unlock(&desc->lock); irq_exit(); @@ -815,7 +818,7 @@ switch ( action->ack_type ) { case ACKTYPE_UNMASK: - desc->handler->end(irq); + desc->handler->end(irq, 0); break; case ACKTYPE_EOI: cpu_eoi_map = action->cpu_eoi_map; @@ -846,7 +849,7 @@ /* An interrupt may slip through while freeing an ACKTYPE_EOI irq. */ ASSERT(action->ack_type == ACKTYPE_EOI); ASSERT(desc->status & IRQ_DISABLED); - desc->handler->end(irq); + desc->handler->end(irq, vector); return; } @@ -957,7 +960,7 @@ ASSERT(irq > 0); desc = irq_to_desc(irq); spin_lock(&desc->lock); - desc->handler->end(irq); + desc->handler->end(irq, peoi[sp].vector); spin_unlock(&desc->lock); } @@ -1038,7 +1041,7 @@ if ( action->ack_type == ACKTYPE_UNMASK ) { ASSERT(cpus_empty(action->cpu_eoi_map)); - desc->handler->end(irq); + desc->handler->end(irq, 0); spin_unlock_irq(&desc->lock); return; } @@ -1298,7 +1301,7 @@ case ACKTYPE_UNMASK: if ( test_and_clear_bit(pirq, d->pirq_mask) && (--action->in_flight == 0) ) - desc->handler->end(irq); + desc->handler->end(irq, 0); break; case ACKTYPE_EOI: /* NB. If #guests == 0 then we clear the eoi_map later on. */ diff -r 4b7b75ace863 -r 0383662ea34c xen/drivers/passthrough/amd/iommu_init.c --- a/xen/drivers/passthrough/amd/iommu_init.c Thu Aug 25 15:36:50 2011 +0100 +++ b/xen/drivers/passthrough/amd/iommu_init.c Wed Aug 31 15:37:57 2011 +0100 @@ -437,7 +437,7 @@ return 0; } -static void iommu_msi_end(unsigned int irq) +static void iommu_msi_end(unsigned int irq, u8 vector) { iommu_msi_unmask(irq); ack_APIC_irq(); diff -r 4b7b75ace863 -r 0383662ea34c xen/drivers/passthrough/vtd/iommu.c --- a/xen/drivers/passthrough/vtd/iommu.c Thu Aug 25 15:36:50 2011 +0100 +++ b/xen/drivers/passthrough/vtd/iommu.c Wed Aug 31 15:37:57 2011 +0100 @@ -967,7 +967,7 @@ return 0; } -static void dma_msi_end(unsigned int irq) +static void dma_msi_end(unsigned int irq, u8 vector) { dma_msi_unmask(irq); ack_APIC_irq(); diff -r 4b7b75ace863 -r 0383662ea34c xen/include/xen/irq.h --- a/xen/include/xen/irq.h Thu Aug 25 15:36:50 2011 +0100 +++ b/xen/include/xen/irq.h Wed Aug 31 15:37:57 2011 +0100 @@ -43,7 +43,7 @@ void (*enable)(unsigned int irq); void (*disable)(unsigned int irq); void (*ack)(unsigned int irq); - void (*end)(unsigned int irq); + void (*end)(unsigned int irq, u8 vector); void (*set_affinity)(unsigned int irq, cpumask_t mask); }; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog |
Lists.xenproject.org is hosted with RackSpace, monitoring our |