Message ID | 1414707132-24588-12-git-send-email-greg.bellows@linaro.org |
---|---|
State | New |
Headers | show |
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 --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)