[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 08/19] hw/intc/arm_gic: Make ICDDCR/GICD_CTLR banked
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PULL 08/19] hw/intc/arm_gic: Make ICDDCR/GICD_CTLR banked |
Date: |
Mon, 11 May 2015 14:40:27 +0100 |
From: Fabian Aggeler <address@hidden>
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 <address@hidden>
Signed-off-by: Greg Bellows <address@hidden>
Reviewed-by: Edgar E. Iglesias <address@hidden>
Signed-off-by: Peter Maydell <address@hidden>
Message-id: address@hidden
Message-id: address@hidden
[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 <address@hidden>
---
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 ca19157..16f0dca2 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 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
- [Qemu-devel] [PULL 00/19] target-arm queue, Peter Maydell, 2015/05/11
- [Qemu-devel] [PULL 03/19] hw/intc/arm_gic: Create outbound FIQ lines, Peter Maydell, 2015/05/11
- [Qemu-devel] [PULL 09/19] hw/intc/arm_gic: Make ICCBPR/GICC_BPR banked, Peter Maydell, 2015/05/11
- [Qemu-devel] [PULL 06/19] hw/intc/arm_gic: Add Interrupt Group Registers, Peter Maydell, 2015/05/11
- [Qemu-devel] [PULL 04/19] hw/intc/arm_gic: Add Security Extensions property, Peter Maydell, 2015/05/11
- [Qemu-devel] [PULL 08/19] hw/intc/arm_gic: Make ICDDCR/GICD_CTLR banked,
Peter Maydell <=
- [Qemu-devel] [PULL 19/19] hw/arm/highbank.c: Wire FIQ between CPU <> GIC, Peter Maydell, 2015/05/11
- [Qemu-devel] [PULL 10/19] hw/intc/arm_gic: Make ICCICR/GICC_CTLR banked, Peter Maydell, 2015/05/11
- [Qemu-devel] [PULL 17/19] hw/arm/virt.c: Wire FIQ between CPU <> GIC, Peter Maydell, 2015/05/11
- [Qemu-devel] [PULL 16/19] hw/intc/arm_gic: Add grouping support to gic_update(), Peter Maydell, 2015/05/11
- [Qemu-devel] [PULL 11/19] hw/intc/arm_gic: Implement Non-secure view of RPR, Peter Maydell, 2015/05/11
- [Qemu-devel] [PULL 15/19] hw/intc/arm_gic: Change behavior of IAR writes, Peter Maydell, 2015/05/11
- [Qemu-devel] [PULL 07/19] hw/intc/arm_gic_kvm.c: Save and restore GICD_IGROUPRn state, Peter Maydell, 2015/05/11
- [Qemu-devel] [PULL 14/19] hw/intc/arm_gic: Change behavior of EOIR writes, Peter Maydell, 2015/05/11
- [Qemu-devel] [PULL 01/19] armv7m_nvic: systick: Reload the RELOAD value and count down only if ENABLE bit is set, Peter Maydell, 2015/05/11
- [Qemu-devel] [PULL 13/19] hw/intc/arm_gic: Handle grouping for GICC_HPPIR, Peter Maydell, 2015/05/11