On Fri, May 01, 2015 at 06:50:32PM +0100, Peter Maydell wrote: > From: Fabian Aggeler <aggel...@ethz.ch> > > ICDDCR/GICD_CTLR is banked if the GIC has the security extensions, > and the S (or only) copy has separate enable bits for Group0 and > Group1 enable if the GIC implements interrupt groups. > > EnableGroup0 (Bit [1]) in GICv1 is architecturally IMPDEF. Since this > bit (Enable Non-secure) is present in the integrated GIC of the Cortex-A9 > MPCore, we support this bit in our GICv1 implementation too. > > Signed-off-by: Fabian Aggeler <aggel...@ethz.ch> > Signed-off-by: Greg Bellows <greg.bell...@linaro.org> > Message-id: 1429113742-8371-8-git-send-email-greg.bell...@linaro.org > [PMM: rewritten to store the state in a single s->ctlr uint32, > with the NS register handled as an alias of bit 1 in that value; > added vmstate version bump] > Signed-off-by: Peter Maydell <peter.mayd...@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.igles...@xilinx.com> > --- > hw/intc/arm_gic.c | 28 +++++++++++++++++++++++----- > hw/intc/arm_gic_common.c | 8 ++++---- > hw/intc/armv7m_nvic.c | 2 +- > hw/intc/gic_internal.h | 2 ++ > include/hw/intc/arm_gic_common.h | 5 ++++- > 5 files changed, 34 insertions(+), 11 deletions(-) > > diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c > index 1aa4520..4f13ff2 100644 > --- a/hw/intc/arm_gic.c > +++ b/hw/intc/arm_gic.c > @@ -67,7 +67,8 @@ void gic_update(GICState *s) > for (cpu = 0; cpu < NUM_CPU(s); cpu++) { > cm = 1 << cpu; > s->current_pending[cpu] = 1023; > - if (!s->enabled || !s->cpu_enabled[cpu]) { > + if (!(s->ctlr & (GICD_CTLR_EN_GRP0 | GICD_CTLR_EN_GRP1)) > + || !s->cpu_enabled[cpu]) { > qemu_irq_lower(s->parent_irq[cpu]); > return; > } > @@ -303,8 +304,16 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr > offset, MemTxAttrs attrs) > cpu = gic_get_current_cpu(s); > cm = 1 << cpu; > if (offset < 0x100) { > - if (offset == 0) > - return s->enabled; > + if (offset == 0) { /* GICD_CTLR */ > + if (s->security_extn && !attrs.secure) { > + /* The NS bank of this register is just an alias of the > + * EnableGrp1 bit in the S bank version. > + */ > + return extract32(s->ctlr, 1, 1); > + } else { > + return s->ctlr; > + } > + } > if (offset == 4) > /* Interrupt Controller Type Register */ > return ((s->num_irq / 32) - 1) > @@ -475,8 +484,17 @@ static void gic_dist_writeb(void *opaque, hwaddr offset, > cpu = gic_get_current_cpu(s); > if (offset < 0x100) { > if (offset == 0) { > - s->enabled = (value & 1); > - DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis"); > + if (s->security_extn && !attrs.secure) { > + /* NS version is just an alias of the S version's bit 1 */ > + s->ctlr = deposit32(s->ctlr, 1, 1, value); > + } else if (gic_has_groups(s)) { > + s->ctlr = value & (GICD_CTLR_EN_GRP0 | GICD_CTLR_EN_GRP1); > + } else { > + s->ctlr = value & GICD_CTLR_EN_GRP0; > + } > + DPRINTF("Distributor: Group0 %sabled; Group 1 %sabled\n", > + s->ctlr & GICD_CTLR_EN_GRP0 ? "En" : "Dis", > + s->ctlr & GICD_CTLR_EN_GRP1 ? "En" : "Dis"); > } else if (offset < 4) { > /* ignored. */ > } else if (offset >= 0x80) { > diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c > index b5a85e5..bef76fc 100644 > --- a/hw/intc/arm_gic_common.c > +++ b/hw/intc/arm_gic_common.c > @@ -59,12 +59,12 @@ static const VMStateDescription vmstate_gic_irq_state = { > > static const VMStateDescription vmstate_gic = { > .name = "arm_gic", > - .version_id = 8, > - .minimum_version_id = 8, > + .version_id = 9, > + .minimum_version_id = 9, > .pre_save = gic_pre_save, > .post_load = gic_post_load, > .fields = (VMStateField[]) { > - VMSTATE_BOOL(enabled, GICState), > + VMSTATE_UINT32(ctlr, GICState), > VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, GIC_NCPU), > VMSTATE_STRUCT_ARRAY(irq_state, GICState, GIC_MAXIRQ, 1, > vmstate_gic_irq_state, gic_irq_state), > @@ -146,7 +146,7 @@ static void arm_gic_common_reset(DeviceState *dev) > s->irq_target[i] = 1; > } > } > - s->enabled = false; > + s->ctlr = 0; > } > > static Property arm_gic_common_properties[] = { > diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c > index 6ff6c7f..4e6456e 100644 > --- a/hw/intc/armv7m_nvic.c > +++ b/hw/intc/armv7m_nvic.c > @@ -468,7 +468,7 @@ static void armv7m_nvic_reset(DeviceState *dev) > s->gic.cpu_enabled[0] = true; > s->gic.priority_mask[0] = 0x100; > /* The NVIC as a whole is always enabled. */ > - s->gic.enabled = true; > + s->gic.ctlr = 1; > systick_reset(s); > } > > diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h > index e8cf773..3b4b3fb 100644 > --- a/hw/intc/gic_internal.h > +++ b/hw/intc/gic_internal.h > @@ -54,6 +54,8 @@ > #define GIC_SET_GROUP(irq, cm) (s->irq_state[irq].group |= (cm)) > #define GIC_TEST_GROUP(irq, cm) ((s->irq_state[irq].group & (cm)) != 0) > > +#define GICD_CTLR_EN_GRP0 (1U << 0) > +#define GICD_CTLR_EN_GRP1 (1U << 1) > > /* The special cases for the revision property: */ > #define REV_11MPCORE 0 > diff --git a/include/hw/intc/arm_gic_common.h > b/include/hw/intc/arm_gic_common.h > index b78981e..d5d3877 100644 > --- a/include/hw/intc/arm_gic_common.h > +++ b/include/hw/intc/arm_gic_common.h > @@ -52,7 +52,10 @@ typedef struct GICState { > > qemu_irq parent_irq[GIC_NCPU]; > qemu_irq parent_fiq[GIC_NCPU]; > - bool enabled; > + /* GICD_CTLR; for a GIC with the security extensions the NS banked > version > + * of this register is just an alias of bit 1 of the S banked version. > + */ > + uint32_t ctlr; > bool cpu_enabled[GIC_NCPU]; > > gic_irq_state irq_state[GIC_MAXIRQ]; > -- > 1.9.1 >