diff options
author | Fabian Aggeler <aggelerf@ethz.ch> | 2015-05-12 11:57:17 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-05-12 11:57:17 +0100 |
commit | 679aa175e84f5f80b32b307fce5a6b92729e0e61 (patch) | |
tree | 55aefc4eb7ed961e5dcfedc990521b2d5a08e756 | |
parent | eb8b9530b0c618d4f2e728eae10d89239d35b0c0 (diff) |
hw/intc/arm_gic: Make ICDDCR/GICD_CTLR banked
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 <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1430502643-25909-7-git-send-email-peter.maydell@linaro.org
Message-id: 1429113742-8371-8-git-send-email-greg.bellows@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.maydell@linaro.org>
-rw-r--r-- | hw/intc/arm_gic.c | 28 | ||||
-rw-r--r-- | hw/intc/arm_gic_common.c | 8 | ||||
-rw-r--r-- | hw/intc/arm_gic_kvm.c | 8 | ||||
-rw-r--r-- | hw/intc/armv7m_nvic.c | 2 | ||||
-rw-r--r-- | hw/intc/gic_internal.h | 2 | ||||
-rw-r--r-- | include/hw/intc/arm_gic_common.h | 5 |
6 files changed, 38 insertions, 15 deletions
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 1aa45209ce..4f13ff2c90 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 b5a85e5673..bef76fc474 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/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c index 3591ca7d5d..4260fd8f04 100644 --- a/hw/intc/arm_gic_kvm.c +++ b/hw/intc/arm_gic_kvm.c @@ -353,8 +353,8 @@ static void kvm_arm_gic_put(GICState *s) * Distributor State */ - /* s->enabled -> GICD_CTLR */ - reg = s->enabled; + /* s->ctlr -> GICD_CTLR */ + reg = s->ctlr; kvm_gicd_access(s, 0x0, 0, ®, true); /* Sanity checking on GICD_TYPER and s->num_irq, s->num_cpu */ @@ -453,9 +453,9 @@ static void kvm_arm_gic_get(GICState *s) * Distributor State */ - /* GICD_CTLR -> s->enabled */ + /* GICD_CTLR -> s->ctlr */ kvm_gicd_access(s, 0x0, 0, ®, false); - s->enabled = reg & 1; + s->ctlr = reg; /* Sanity checking on GICD_TYPER -> s->num_irq, s->num_cpu */ kvm_gicd_access(s, 0x4, 0, ®, false); diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index ca19157c1e..16f0dca2d4 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -477,7 +477,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 e8cf773e73..3b4b3fbc0e 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 b78981ed58..d5d38772c2 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]; |