[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-arm] [v2] nvic: set pending status for not active interrupts
From: |
marcin.krzeminski |
Subject: |
[Qemu-arm] [v2] nvic: set pending status for not active interrupts |
Date: |
Tue, 18 Oct 2016 08:14:45 +0200 |
From: Marcin Krzeminski <address@hidden>
According to ARM DUI 0552A 4.2.10. NVIC set pending status
also for disabled interrupts. This patch adds possibility
to emulate this in Qemu.
Signed-off-by: Marcin Krzeminski <address@hidden>
---
Changes for v2:
- add a dedicated unction for nvic
- update complete_irq
hw/intc/arm_gic.c | 27 +++++++++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index b30cc91..72e4c01 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -156,6 +156,21 @@ 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);
+ if (GIC_TEST_EDGE_TRIGGER(irq) || GIC_TEST_ENABLED(irq, cm)
+ || !GIC_TEST_ACTIVE(irq, cm)) {
+ DPRINTF("Set %d pending mask %x\n", irq, target);
+ 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 +216,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 +585,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 +593,12 @@ 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_ENABLED(irq, cm) && GIC_TEST_LEVEL(irq, cm)
+ && (GIC_TARGET(irq) & cm) != 0) {
+ 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
- [Qemu-arm] [v2] nvic: set pending status for not active interrupts,
marcin.krzeminski <=