From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45047) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xstt6-0000Ls-CC for qemu-devel@nongnu.org; Mon, 24 Nov 2014 08:41:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Xstt0-0008Ik-7u for qemu-devel@nongnu.org; Mon, 24 Nov 2014 08:41:08 -0500 Received: from mail-wg0-x235.google.com ([2a00:1450:400c:c00::235]:45752) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xstt0-0008Ib-1w for qemu-devel@nongnu.org; Mon, 24 Nov 2014 08:41:02 -0500 Received: by mail-wg0-f53.google.com with SMTP id l18so12367439wgh.12 for ; Mon, 24 Nov 2014 05:41:01 -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.59 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 24 Nov 2014 05:41:00 -0800 (PST) Sender: Paolo Bonzini From: Paolo Bonzini Date: Mon, 24 Nov 2014 14:40:49 +0100 Message-Id: <1416836449-2599-4-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 3/3] apic: fix incorrect handling of ExtINT interrupts wrt processor priority List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org This fixes another failure with ExtINT, demonstrated by QNX. The failure mode is as follows: - IPI sent to cpu 0 (bit set in APIC irr) - IPI accepted by cpu 0 (bit cleared in irr, set in isr) - IPI sent to cpu 0 (bit set in both irr and isr) - PIC interrupt sent to cpu 0 The PIC interrupt causes CPU_INTERRUPT_HARD to be set, but apic_irq_pending observes that the highest pending APIC interrupt priority (the IPI) is the same as the processor priority (since the IPI is still being handled), so apic_get_interrupt returns a spurious interrupt rather than the pending PIC interrupt. The result is an endless sequence of spurious interrupts, since nothing will clear CPU_INTERRUPT_HARD. Instead, ExtINT interrupts should have ignored the processor priority. Calling apic_check_pic early in apic_get_interrupt ensures that apic_deliver_pic_intr is called instead of delivering the spurious interrupt. apic_deliver_pic_intr then clears CPU_INTERRUPT_HARD if needed. Reported-by: Richard Bilson Tested-by: Richard Bilson Signed-off-by: Paolo Bonzini --- hw/intc/apic.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 6ec5861..0f97b47 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -571,7 +571,10 @@ int apic_get_interrupt(DeviceState *dev) apic_sync_vapic(s, SYNC_FROM_VAPIC); intno = apic_irq_pending(s); - if (intno == 0) { + /* if there is an interrupt from the 8259, let the caller handle + * that first since ExtINT interrupts ignore the priority. + */ + if (intno == 0 || apic_check_pic(s)) { apic_sync_vapic(s, SYNC_TO_VAPIC); return -1; } else if (intno < 0) { @@ -582,9 +585,6 @@ int apic_get_interrupt(DeviceState *dev) apic_set_bit(s->isr, intno); apic_sync_vapic(s, SYNC_TO_VAPIC); - /* re-inject if there is still a pending PIC interrupt */ - apic_check_pic(s); - apic_update_irq(s); return intno; -- 1.8.3.1