From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752695AbbJORm2 (ORCPT ); Thu, 15 Oct 2015 13:42:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:33854 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751395AbbJORm0 (ORCPT ); Thu, 15 Oct 2015 13:42:26 -0400 From: Vitaly Kuznetsov To: x86@kernel.org Cc: linux-kernel@vger.kernel.org, Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , Jiang Liu , Yinghai Lu , "K. Y. Srinivasan" Subject: [PATCH] x86/ioapic: Disable interrupts when re-routing legacy IRQs Date: Thu, 15 Oct 2015 19:42:23 +0200 Message-Id: <1444930943-19336-1-git-send-email-vkuznets@redhat.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org A sporadic hang with consequent crash is observed when booting Hyper-V Gen1 guests: Call Trace: [] ? trace_hardirqs_off+0xd/0x10 [] queue_work_on+0x46/0x90 [] ? add_interrupt_randomness+0x176/0x1d0 ... [] ? _raw_spin_unlock_irqrestore+0x3b/0x60 [] __irq_put_desc_unlock+0x1e/0x40 [] irq_modify_status+0xb5/0xd0 [] mp_register_handler+0x4b/0x70 [] mp_irqdomain_alloc+0x1ea/0x2a0 [] irq_domain_alloc_irqs_recursive+0x40/0xa0 [] __irq_domain_alloc_irqs+0x13c/0x2b0 [] alloc_isa_irq_from_domain.isra.1+0xc0/0xe0 [] mp_map_pin_to_irq+0x165/0x2d0 [] pin_2_irq+0x47/0x80 [] setup_IO_APIC+0xfe/0x802 ... [] ? 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. Decorate manipulations with legacy IRQs with local_irq_save()/ local_irq_restore(). Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: Jiang Liu Cc: Yinghai Lu Cc: K. Y. Srinivasan Signed-off-by: Vitaly Kuznetsov --- It may make sense to have interrupts disabled for non-legacy IRQs as well but I'm unaware of any bugs with them at this moment. --- arch/x86/kernel/apic/io_apic.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 5c60bb1..9aac777 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -2907,6 +2907,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 = 0; if (!info || nr_irqs > 1) return -EINVAL; @@ -2939,11 +2940,16 @@ 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); + + if (virq < nr_legacy_irqs()) + 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()) + 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", -- 2.4.3