diff mbox

[v2,11/16] hw/intc/arm_gic: Handle grouping for GICC_HPPIR

Message ID 1414707132-24588-12-git-send-email-greg.bellows@linaro.org
State New
Headers show

Commit Message

Greg Bellows Oct. 30, 2014, 10:12 p.m. UTC
From: Fabian Aggeler <aggelerf@ethz.ch>

Grouping (GICv2) and Security Extensions change the behaviour of reads
of the highest priority pending interrupt register (ICCHPIR/GICC_HPPIR).

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
---
 hw/intc/arm_gic.c      | 29 ++++++++++++++++++++++++++++-
 hw/intc/gic_internal.h |  1 +
 2 files changed, 29 insertions(+), 1 deletion(-)

Comments

Peter Maydell April 14, 2015, 7:25 p.m. UTC | #1
On 30 October 2014 at 22:12, Greg Bellows <greg.bellows@linaro.org> wrote:
> From: Fabian Aggeler <aggelerf@ethz.ch>
>
> Grouping (GICv2) and Security Extensions change the behaviour of reads
> of the highest priority pending interrupt register (ICCHPIR/GICC_HPPIR).
>
> Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
> ---
>  hw/intc/arm_gic.c      | 29 ++++++++++++++++++++++++++++-
>  hw/intc/gic_internal.h |  1 +
>  2 files changed, 29 insertions(+), 1 deletion(-)
>
> diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
> index 9b021d7..15fd660 100644
> --- a/hw/intc/arm_gic.c
> +++ b/hw/intc/arm_gic.c
> @@ -329,6 +329,33 @@ uint8_t gic_get_running_priority(GICState *s, int cpu)
>      }
>  }
>
> +uint16_t gic_get_current_pending_irq(GICState *s, int cpu)
> +{
> +    bool isGrp0;
> +    uint16_t pendingId = s->current_pending[cpu];
> +
> +    if (pendingId < GIC_MAXIRQ && (s->revision >= 2 || s->security_extn)) {
> +        isGrp0 = GIC_TEST_GROUP0(pendingId, (1 << cpu));
> +        if ((isGrp0 && !s->enabled_grp[0])
> +                || (!isGrp0 && !s->enabled_grp[1])) {
> +            return 1023;
> +        }
> +        if (s->security_extn) {
> +            if (isGrp0 && ns_access()) {
> +                /* Group0 interrupts hidden from Non-secure access */
> +                return 1023;
> +            }
> +            if (!isGrp0 && !ns_access()
> +                    && !(s->cpu_control[cpu][0] & GICC_CTLR_S_ACK_CTL)) {
> +                /* Group1 interrupts only seen by Secure access if
> +                 * AckCtl bit set. */
> +                return 1022;
> +            }
> +        }
> +    }
> +    return pendingId;
> +}

Some coding style nits about var name capitalisation and
multiline comment style, but otherwise OK.

-- PMM
diff mbox

Patch

diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 9b021d7..15fd660 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -329,6 +329,33 @@  uint8_t gic_get_running_priority(GICState *s, int cpu)
     }
 }
 
+uint16_t gic_get_current_pending_irq(GICState *s, int cpu)
+{
+    bool isGrp0;
+    uint16_t pendingId = s->current_pending[cpu];
+
+    if (pendingId < GIC_MAXIRQ && (s->revision >= 2 || s->security_extn)) {
+        isGrp0 = GIC_TEST_GROUP0(pendingId, (1 << cpu));
+        if ((isGrp0 && !s->enabled_grp[0])
+                || (!isGrp0 && !s->enabled_grp[1])) {
+            return 1023;
+        }
+        if (s->security_extn) {
+            if (isGrp0 && ns_access()) {
+                /* Group0 interrupts hidden from Non-secure access */
+                return 1023;
+            }
+            if (!isGrp0 && !ns_access()
+                    && !(s->cpu_control[cpu][0] & GICC_CTLR_S_ACK_CTL)) {
+                /* Group1 interrupts only seen by Secure access if
+                 * AckCtl bit set. */
+                return 1022;
+            }
+        }
+    }
+    return pendingId;
+}
+
 void gic_complete_irq(GICState *s, int cpu, int irq)
 {
     int update = 0;
@@ -866,7 +893,7 @@  static uint32_t gic_cpu_read(GICState *s, int cpu, int offset)
     case 0x14: /* Running Priority */
         return gic_get_running_priority(s, cpu);
     case 0x18: /* Highest Pending Interrupt */
-        return s->current_pending[cpu];
+        return gic_get_current_pending_irq(s, cpu);
     case 0x1c: /* Aliased Binary Point */
         if (!s->security_extn || (s->security_extn && ns_access())) {
             /* If Security Extensions are present ABPR is a secure register,
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
index 821ce16..fbb1f66 100644
--- a/hw/intc/gic_internal.h
+++ b/hw/intc/gic_internal.h
@@ -79,6 +79,7 @@  void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val);
 uint32_t gic_get_cpu_control(GICState *s, int cpu);
 void gic_set_cpu_control(GICState *s, int cpu, uint32_t value);
 uint8_t gic_get_running_priority(GICState *s, int cpu);
+uint16_t gic_get_current_pending_irq(GICState *s, int cpu);
 
 
 static inline bool gic_test_pending(GICState *s, int irq, int cm)