On Fri, May 01, 2015 at 06:50:38PM +0100, Peter Maydell wrote: > From: Fabian Aggeler <aggel...@ethz.ch> > > Grouping (GICv2) and Security Extensions change the behavior of EOIR > writes. Completing Group0 interrupts is only allowed from Secure state. > > Signed-off-by: Fabian Aggeler <aggel...@ethz.ch> > Signed-off-by: Greg Bellows <greg.bell...@linaro.org> > Message-id: 1429113742-8371-13-git-send-email-greg.bell...@linaro.org > [PMM: Rather than go to great lengths to ignore the UNPREDICTABLE case > of a Secure EOI of a Group1 (NS) irq with AckCtl == 0, we just let > it fall through; add a comment about it.] > Signed-off-by: Peter Maydell <peter.mayd...@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.igles...@xilinx.com> > --- > hw/intc/arm_gic.c | 14 ++++++++++++-- > hw/intc/armv7m_nvic.c | 2 +- > hw/intc/gic_internal.h | 2 +- > 3 files changed, 14 insertions(+), 4 deletions(-) > > diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c > index 75c69b3..4ad80e7 100644 > --- a/hw/intc/arm_gic.c > +++ b/hw/intc/arm_gic.c > @@ -382,7 +382,7 @@ static uint8_t gic_get_running_priority(GICState *s, int > cpu, MemTxAttrs attrs) > } > } > > -void gic_complete_irq(GICState *s, int cpu, int irq) > +void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs) > { > int update = 0; > int cm = 1 << cpu; > @@ -412,6 +412,16 @@ void gic_complete_irq(GICState *s, int cpu, int irq) > } > } > > + if (s->security_extn && !attrs.secure && !GIC_TEST_GROUP(irq, cm)) { > + DPRINTF("Non-secure EOI for Group0 interrupt %d ignored\n", irq); > + return; > + } > + > + /* Secure EOI with GICC_CTLR.AckCtl == 0 when the IRQ is a Group 1 > + * interrupt is UNPREDICTABLE. We choose to handle it as if AckCtl == 1, > + * i.e. go ahead and complete the irq anyway. > + */ > + > if (irq != s->running_irq[cpu]) { > /* Complete an IRQ that is not currently running. */ > int tmp = s->running_irq[cpu]; > @@ -959,7 +969,7 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, > int offset, > } > break; > case 0x10: /* End Of Interrupt */ > - gic_complete_irq(s, cpu, value & 0x3ff); > + gic_complete_irq(s, cpu, value & 0x3ff, attrs); > return MEMTX_OK; > case 0x1c: /* Aliased Binary Point */ > if (!gic_has_groups(s) || (s->security_extn && !attrs.secure)) { > diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c > index c226daf..dd06ceb 100644 > --- a/hw/intc/armv7m_nvic.c > +++ b/hw/intc/armv7m_nvic.c > @@ -135,7 +135,7 @@ void armv7m_nvic_complete_irq(void *opaque, int irq) > nvic_state *s = (nvic_state *)opaque; > if (irq >= 16) > irq += 16; > - gic_complete_irq(&s->gic, 0, irq); > + gic_complete_irq(&s->gic, 0, irq, MEMTXATTRS_UNSPECIFIED); > } > > static uint32_t nvic_readl(nvic_state *s, uint32_t offset) > diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h > index 119fb81..d3cebef 100644 > --- a/hw/intc/gic_internal.h > +++ b/hw/intc/gic_internal.h > @@ -79,7 +79,7 @@ > > void gic_set_pending_private(GICState *s, int cpu, int irq); > uint32_t gic_acknowledge_irq(GICState *s, int cpu); > -void gic_complete_irq(GICState *s, int cpu, int irq); > +void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs); > void gic_update(GICState *s); > void gic_init_irqs_and_distributor(GICState *s); > void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val, > -- > 1.9.1 >