From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45041) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xstt5-0000Lp-DA for qemu-devel@nongnu.org; Mon, 24 Nov 2014 08:41:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Xstsy-0008I3-5H for qemu-devel@nongnu.org; Mon, 24 Nov 2014 08:41:07 -0500 Received: from mail-wi0-x22c.google.com ([2a00:1450:400c:c05::22c]:41792) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xstsx-0008Hl-V2 for qemu-devel@nongnu.org; Mon, 24 Nov 2014 08:41:00 -0500 Received: by mail-wi0-f172.google.com with SMTP id n3so5692953wiv.5 for ; Mon, 24 Nov 2014 05:40:59 -0800 (PST) Received: from playground.station (net-93-146-133-240.cust.vodafonedsl.it. [93.146.133.240]) by mx.google.com with ESMTPSA id j8sm12093033wib.10.2014.11.24.05.40.57 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 24 Nov 2014 05:40:58 -0800 (PST) Sender: Paolo Bonzini From: Paolo Bonzini Date: Mon, 24 Nov 2014 14:40:48 +0100 Message-Id: <1416836449-2599-3-git-send-email-pbonzini@redhat.com> In-Reply-To: <1416836449-2599-1-git-send-email-pbonzini@redhat.com> References: <1416836449-2599-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PULL 2/3] apic: fix loss of IPI due to masked ExtINT List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org This patch fixes an obscure failure of the QNX kernel on QEMU x86 SMP. In QNX, all hardware interrupts come via the PIC, and are delivered by the cpu 0 LAPIC in ExtINT mode, while IPIs are delivered by the LAPIC in fixed mode. This bug happens as follows: - cpu 0 masks a particular PIC interrupt - IPI sent to cpu 0 (CPU_INTERRUPT_HARD is set) - before the IPI is accepted, the masked interrupt line is asserted by the device Since the interrupt is masked, apic_deliver_pic_intr will clear CPU_INTERRUPT_HARD. The IPI will still be set in the APIC irr, but since CPU_INTERRUPT_HARD is not set the cpu will not notice. Depending on the scenario this can cause a system hang, i.e. if cpu 0 is expected to unmask the interrupt. In order to fix this, do a full check of the APIC before an EXTINT is acknowledged. This can result in clearing CPU_INTERRUPT_HARD, but can also result in delivering the lost IPI. Reported-by: Richard Bilson Tested-by: Richard Bilson Signed-off-by: Paolo Bonzini --- hw/intc/apic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 0653409..6ec5861 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -188,7 +188,7 @@ void apic_deliver_pic_intr(DeviceState *dev, int level) apic_reset_bit(s->irr, lvt & 0xff); /* fall through */ case APIC_DM_EXTINT: - cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_HARD); + apic_update_irq(s); break; } } @@ -376,6 +376,8 @@ static void apic_update_irq(APICCommonState *s) cpu_interrupt(cpu, CPU_INTERRUPT_POLL); } else if (apic_irq_pending(s) > 0) { cpu_interrupt(cpu, CPU_INTERRUPT_HARD); + } else if (!apic_accept_pic_intr(&s->busdev.qdev) || !pic_get_output(isa_pic)) { + cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD); } } -- 1.8.3.1