aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2012-05-02 16:49:40 +0000
committerPeter Maydell <peter.maydell@linaro.org>2012-06-19 13:24:44 +0000
commit6b9680bb5826dcf0ead42bafb62946f472466d63 (patch)
tree8ca295252fa148d6222adef9592e778a2d3d94e4
parent306a571a2d75e32cd2eae5486c2714b7b7792a63 (diff)
downloadqemu-6b9680bb5826dcf0ead42bafb62946f472466d63.zip
qemu-6b9680bb5826dcf0ead42bafb62946f472466d63.tar.gz
qemu-6b9680bb5826dcf0ead42bafb62946f472466d63.tar.bz2
hw/arm_gic: Make CPU target registers RAZ/WI on uniprocessor
The GIC spec says that the CPU target registers should RAZ/WI for uniprocessor implementations. Implement this, which also conveniently lets us drop an NVIC ifdef. Annoyingly, the 11MPCore's GIC is the odd one out, since it always has these registers, even in uniprocessor configs. Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/arm_gic.c56
1 files changed, 33 insertions, 23 deletions
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index ad72ac6..a6e2431 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -86,11 +86,7 @@ typedef struct gic_irq_state
#define GIC_GET_PRIORITY(irq, cpu) (((irq) < GIC_INTERNAL) ? \
s->priority1[irq][cpu] : \
s->priority2[(irq) - GIC_INTERNAL])
-#ifdef NVIC
-#define GIC_TARGET(irq) 1
-#else
#define GIC_TARGET(irq) s->irq_target[irq]
-#endif
typedef struct gic_state
{
@@ -377,18 +373,22 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
if (irq >= s->num_irq)
goto bad_reg;
res = GIC_GET_PRIORITY(irq, cpu);
-#ifndef NVIC
} else if (offset < 0xc00) {
/* Interrupt CPU Target. */
- irq = (offset - 0x800) + GIC_BASE_IRQ;
- if (irq >= s->num_irq)
- goto bad_reg;
- if (irq >= 29 && irq <= 31) {
- res = cm;
+ if (s->num_cpu == 1 && s->revision != REV_11MPCORE) {
+ /* For uniprocessor GICs these RAZ/WI */
+ res = 0;
} else {
- res = GIC_TARGET(irq);
+ irq = (offset - 0x800) + GIC_BASE_IRQ;
+ if (irq >= s->num_irq) {
+ goto bad_reg;
+ }
+ if (irq >= 29 && irq <= 31) {
+ res = cm;
+ } else {
+ res = GIC_TARGET(irq);
+ }
}
-#endif
} else if (offset < 0xf00) {
/* Interrupt Configuration. */
irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
@@ -533,18 +533,22 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
} else {
s->priority2[irq - GIC_INTERNAL] = value;
}
-#ifndef NVIC
} else if (offset < 0xc00) {
- /* Interrupt CPU Target. */
- irq = (offset - 0x800) + GIC_BASE_IRQ;
- if (irq >= s->num_irq)
- goto bad_reg;
- if (irq < 29)
- value = 0;
- else if (irq < GIC_INTERNAL)
- value = ALL_CPU_MASK;
- s->irq_target[irq] = value & ALL_CPU_MASK;
-#endif
+ /* Interrupt CPU Target. RAZ/WI on uniprocessor GICs, with the
+ * annoying exception of the 11MPCore's GIC.
+ */
+ if (s->num_cpu != 1 || s->revision == REV_11MPCORE) {
+ irq = (offset - 0x800) + GIC_BASE_IRQ;
+ if (irq >= s->num_irq) {
+ goto bad_reg;
+ }
+ if (irq < 29) {
+ value = 0;
+ } else if (irq < GIC_INTERNAL) {
+ value = ALL_CPU_MASK;
+ }
+ s->irq_target[irq] = value & ALL_CPU_MASK;
+ }
} else if (offset < 0xf00) {
/* Interrupt Configuration. */
irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
@@ -733,6 +737,12 @@ static void gic_reset(DeviceState *dev)
GIC_SET_ENABLED(i, ALL_CPU_MASK);
GIC_SET_TRIGGER(i);
}
+ if (s->num_cpu == 1) {
+ /* For uniprocessor GICs all interrupts always target the sole CPU */
+ for (i = 0; i < GIC_MAXIRQ; i++) {
+ s->irq_target[i] = 1;
+ }
+ }
s->enabled = 0;
}