From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=42062 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Pm0w3-0005ij-V3 for qemu-devel@nongnu.org; Sun, 06 Feb 2011 04:29:40 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Pm0vt-0000cE-0V for qemu-devel@nongnu.org; Sun, 06 Feb 2011 04:29:25 -0500 Received: from mx1.redhat.com ([209.132.183.28]:18605) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Pm0vs-0000cA-Q5 for qemu-devel@nongnu.org; Sun, 06 Feb 2011 04:29:24 -0500 Date: Sun, 6 Feb 2011 11:29:20 +0200 From: Gleb Natapov Message-ID: <20110206092920.GZ14984@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Subject: [Qemu-devel] [PATCH] correctly check ppr priority during interrupt injection List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Jan Kiszka TPR blocks all interrupts in a priority class, so simple "less or equal" check is not enough. Signed-off-by: Gleb Natapov diff --git a/hw/apic.c b/hw/apic.c index 2f8376a..cbac75d 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -372,19 +372,33 @@ 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; + return 0; ppr = apic_get_ppr(s); 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 +604,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); -- Gleb.