Message ID | 6d7e52f46daa71df5e4c05a6fbfb661bf0eb6ba6.1447867806.git.joseph.salisbury@canonical.com |
---|---|
State | New |
Headers | show |
Looks safe, clean cherry pick
On Fri, Nov 20, 2015 at 03:32:18PM -0500, Joseph Salisbury wrote: > From: Vitaly Kuznetsov <vkuznets@redhat.com> > > BugLink: http://bugs.launchpad.net/bugs/1508593 > > A sporadic hang with consequent crash is observed when booting Hyper-V Gen1 > guests: > > Call Trace: > <IRQ> > [<ffffffff810ab68d>] ? trace_hardirqs_off+0xd/0x10 > [<ffffffff8107b616>] queue_work_on+0x46/0x90 > [<ffffffff81365696>] ? add_interrupt_randomness+0x176/0x1d0 > ... > <EOI> > [<ffffffff81471ddb>] ? _raw_spin_unlock_irqrestore+0x3b/0x60 > [<ffffffff810c295e>] __irq_put_desc_unlock+0x1e/0x40 > [<ffffffff810c5c35>] irq_modify_status+0xb5/0xd0 > [<ffffffff8104adbb>] mp_register_handler+0x4b/0x70 > [<ffffffff8104c55a>] mp_irqdomain_alloc+0x1ea/0x2a0 > [<ffffffff810c7f10>] irq_domain_alloc_irqs_recursive+0x40/0xa0 > [<ffffffff810c860c>] __irq_domain_alloc_irqs+0x13c/0x2b0 > [<ffffffff8104b070>] alloc_isa_irq_from_domain.isra.1+0xc0/0xe0 > [<ffffffff8104bfa5>] mp_map_pin_to_irq+0x165/0x2d0 > [<ffffffff8104c157>] pin_2_irq+0x47/0x80 > [<ffffffff81744253>] setup_IO_APIC+0xfe/0x802 > ... > [<ffffffff814631c0>] ? rest_init+0x140/0x140 > > The issue is easily reproducible with a simple instrumentation: if > mdelay(10) is put between mp_setup_entry() and mp_register_handler() calls > in mp_irqdomain_alloc() Hyper-V guest always fails to boot when re-routing > IRQ0. The issue seems to be caused by the fact that we don't disable > interrupts while doing IOPIC programming for legacy IRQs and IRQ0 actually > happens. > > Protect the setup sequence against concurrent interrupts. > > [ tglx: Make the protection unconditional and not only for legacy > interrupts ] > > Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> > Cc: Jiang Liu <jiang.liu@linux.intel.com> > Cc: Yinghai Lu <yinghai@kernel.org> > Cc: K. Y. Srinivasan <kys@microsoft.com> > Link: http://lkml.kernel.org/r/1444930943-19336-1-git-send-email-vkuznets@redhat.com > Signed-off-by: Thomas Gleixner <tglx@linutronix.de> > (cherry picked from commit c0ff971ef9acacd4d2caa508e444edad958dead9) > Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com> > --- > arch/x86/kernel/apic/io_apic.c | 4 ++++ > 1 file changed, 4 insertions(+) > > diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c > index 206052e..b15b924 100644 > --- a/arch/x86/kernel/apic/io_apic.c > +++ b/arch/x86/kernel/apic/io_apic.c > @@ -2906,6 +2906,7 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq, > struct irq_data *irq_data; > struct mp_chip_data *data; > struct irq_alloc_info *info = arg; > + unsigned long flags; > > if (!info || nr_irqs > 1) > return -EINVAL; > @@ -2938,11 +2939,14 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq, > > cfg = irqd_cfg(irq_data); > add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin); > + > + local_irq_save(flags); > if (info->ioapic_entry) > mp_setup_entry(cfg, data, info->ioapic_entry); > mp_register_handler(virq, data->trigger); > if (virq < nr_legacy_irqs()) > legacy_pic->mask(virq); > + local_irq_restore(flags); > > apic_printk(APIC_VERBOSE, KERN_DEBUG > "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i Dest:%d)\n", Look to do what is claimed, clean cherry pick. Acked-by: Andy Whitcroft <apw@canonical.com> -apw
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 206052e..b15b924 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -2906,6 +2906,7 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq, struct irq_data *irq_data; struct mp_chip_data *data; struct irq_alloc_info *info = arg; + unsigned long flags; if (!info || nr_irqs > 1) return -EINVAL; @@ -2938,11 +2939,14 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq, cfg = irqd_cfg(irq_data); add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin); + + local_irq_save(flags); if (info->ioapic_entry) mp_setup_entry(cfg, data, info->ioapic_entry); mp_register_handler(virq, data->trigger); if (virq < nr_legacy_irqs()) legacy_pic->mask(virq); + local_irq_restore(flags); apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i Dest:%d)\n",