From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35062) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1c3hSs-0007Eq-0M for qemu-devel@nongnu.org; Mon, 07 Nov 2016 05:47:50 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1c3hSr-0004kH-3G for qemu-devel@nongnu.org; Mon, 07 Nov 2016 05:47:46 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:47500) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1c3hSq-0004hx-SB for qemu-devel@nongnu.org; Mon, 07 Nov 2016 05:47:45 -0500 From: Peter Maydell Date: Mon, 7 Nov 2016 10:47:31 +0000 Message-Id: <1478515653-6361-3-git-send-email-peter.maydell@linaro.org> In-Reply-To: <1478515653-6361-1-git-send-email-peter.maydell@linaro.org> References: <1478515653-6361-1-git-send-email-peter.maydell@linaro.org> Subject: [Qemu-devel] [PULL 2/4] nvic: set pending status for not active interrupts List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Stefan Hajnoczi From: Marcin Krzeminski According to ARM DUI 0552A 4.2.10. NVIC set pending status also for disabled interrupts. Correct the logic for when interrupts are marked pending both on input level transition and when interrupts are dismissed, to match the NVIC behaviour rather than the 11MPCore GIC. Signed-off-by: Marcin Krzeminski Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/intc/arm_gic.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index b30cc91..521aac3 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -156,6 +156,17 @@ static void gic_set_irq_11mpcore(GICState *s, int irq, int level, } } +static void gic_set_irq_nvic(GICState *s, int irq, int level, + int cm, int target) +{ + if (level) { + GIC_SET_LEVEL(irq, cm); + GIC_SET_PENDING(irq, target); + } else { + GIC_CLEAR_LEVEL(irq, cm); + } +} + static void gic_set_irq_generic(GICState *s, int irq, int level, int cm, int target) { @@ -201,8 +212,10 @@ static void gic_set_irq(void *opaque, int irq, int level) return; } - if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) { + if (s->revision == REV_11MPCORE) { gic_set_irq_11mpcore(s, irq, level, cm, target); + } else if (s->revision == REV_NVIC) { + gic_set_irq_nvic(s, irq, level, cm, target); } else { gic_set_irq_generic(s, irq, level, cm, target); } @@ -568,7 +581,7 @@ void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs) return; /* No active IRQ. */ } - if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) { + if (s->revision == REV_11MPCORE) { /* Mark level triggered interrupts as pending if they are still raised. */ if (!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm) @@ -576,6 +589,11 @@ void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs) DPRINTF("Set %d pending mask %x\n", irq, cm); GIC_SET_PENDING(irq, cm); } + } else if (s->revision == REV_NVIC) { + if (GIC_TEST_LEVEL(irq, cm)) { + DPRINTF("Set nvic %d pending mask %x\n", irq, cm); + GIC_SET_PENDING(irq, cm); + } } group = gic_has_groups(s) && GIC_TEST_GROUP(irq, cm); -- 2.7.4