qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 2/5] hw/intc/arm_gic: Running priority is group prio


From: Peter Maydell
Subject: [Qemu-devel] [PATCH 2/5] hw/intc/arm_gic: Running priority is group priority, not full priority
Date: Tue, 28 Jul 2015 14:22:25 +0100

Priority values for the GIC are divided into a "group priority"
and a "subpriority" (with the division being determined by the
binary point register). The running priority is only determined
by the group priority of the active interrupts, not the
subpriority. In particular, this means that there can't be more
than one active interrupt at any particular group priority.

Signed-off-by: Peter Maydell <address@hidden>
---
 hw/intc/arm_gic.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 454bfd7..9814bb9 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -219,13 +219,39 @@ static uint16_t gic_get_current_pending_irq(GICState *s, 
int cpu,
     return pending_irq;
 }
 
+static int gic_get_group_priority(GICState *s, int cpu, int irq)
+{
+    /* Return the group priority of the specified interrupt
+     * (which is the top bits of its priority, with the number
+     * of bits masked determined by the applicable binary point register).
+     */
+    int bpr;
+    uint32_t mask;
+
+    if (gic_has_groups(s) &&
+        !(s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) &&
+        GIC_TEST_GROUP(irq, (1 << cpu))) {
+        bpr = s->abpr[cpu];
+    } else {
+        bpr = s->bpr[cpu];
+    }
+
+    /* a BPR of 0 means the group priority bits are [7:1];
+     * a BPR of 1 means they are [7:2], and so on down to
+     * a BPR of 7 meaning no group priority bits at all.
+     */
+    mask = ~0U << ((bpr & 7) + 1);
+
+    return GIC_GET_PRIORITY(irq, cpu) & mask;
+}
+
 static void gic_set_running_irq(GICState *s, int cpu, int irq)
 {
     s->running_irq[cpu] = irq;
     if (irq == 1023) {
         s->running_priority[cpu] = 0x100;
     } else {
-        s->running_priority[cpu] = GIC_GET_PRIORITY(irq, cpu);
+        s->running_priority[cpu] = gic_get_group_priority(s, cpu, irq);
     }
     gic_update(s);
 }
-- 
1.9.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]