From patchwork Mon Feb 7 14:14:44 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gleb Natapov X-Patchwork-Id: 82162 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id D88A4B7109 for ; Tue, 8 Feb 2011 08:53:10 +1100 (EST) Received: from localhost ([127.0.0.1]:51562 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PmS1g-0005Xv-Tp for incoming@patchwork.ozlabs.org; Mon, 07 Feb 2011 09:25:13 -0500 Received: from [140.186.70.92] (port=36332 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PmRrc-0000tM-I6 for qemu-devel@nongnu.org; Mon, 07 Feb 2011 09:14:49 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PmRrb-0006J4-6P for qemu-devel@nongnu.org; Mon, 07 Feb 2011 09:14:48 -0500 Received: from mx1.redhat.com ([209.132.183.28]:6663) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PmRra-0006Is-SQ for qemu-devel@nongnu.org; Mon, 07 Feb 2011 09:14:47 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p17EEkNU025834 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 7 Feb 2011 09:14:46 -0500 Received: from dhcp-1-237.tlv.redhat.com (dhcp-1-237.tlv.redhat.com [10.35.1.237]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p17EEjYw028847 for ; Mon, 7 Feb 2011 09:14:45 -0500 Received: by dhcp-1-237.tlv.redhat.com (Postfix, from userid 13519) id D69B718D3E9; Mon, 7 Feb 2011 16:14:44 +0200 (IST) Date: Mon, 7 Feb 2011 16:14:44 +0200 From: Gleb Natapov To: qemu-devel@nongnu.org Message-ID: <20110207141444.GH14984@redhat.com> MIME-Version: 1.0 Content-Disposition: inline X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH stable] correctly check ppr priority during interrupt injection] X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org TPR blocks all interrupts in a priority class, so simple "less or equal" check is not enough. Signed-off-by: Gleb Natapov Reviewed-by: Jan Kiszka --- Gleb. diff --git a/hw/apic.c b/hw/apic.c index 2f8376a..218d1bb 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -372,19 +372,36 @@ static int apic_get_arb_pri(APICState *s) return 0; } -/* signal the CPU if an irq is pending */ -static void apic_update_irq(APICState *s) + +/* + * <0 - low prio interrupt, + * 0 - no interrupt, + * >0 - interrupt number + */ +static int apic_irq_pending(APICState *s) { int irrv, ppr; - if (!(s->spurious_vec & APIC_SV_ENABLE)) - return; irrv = get_highest_priority_int(s->irr); - if (irrv < 0) - return; + if (irrv < 0) { + return 0; + } ppr = apic_get_ppr(s); - if (ppr && (irrv & 0xf0) <= (ppr & 0xf0)) + if (ppr && (irrv & 0xf0) <= (ppr & 0xf0)) { + return -1; + } + + return irrv; +} + +/* signal the CPU if an irq is pending */ +static void apic_update_irq(APICState *s) +{ + if (!(s->spurious_vec & APIC_SV_ENABLE)) { return; - cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD); + } + if (apic_irq_pending(s) > 0) { + cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD); + } } void apic_reset_irq_delivered(void) @@ -590,12 +607,13 @@ int apic_get_interrupt(DeviceState *d) if (!(s->spurious_vec & APIC_SV_ENABLE)) return -1; - /* XXX: spurious IRQ handling */ - intno = get_highest_priority_int(s->irr); - if (intno < 0) + intno = apic_irq_pending(s); + + if (intno == 0) { return -1; - if (s->tpr && intno <= s->tpr) + } else if (intno < 0) { return s->spurious_vec & 0xff; + } reset_bit(s->irr, intno); set_bit(s->isr, intno); apic_update_irq(s);