summaryrefslogtreecommitdiffstats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/intc/arm_gicv3_common.c2
-rw-r--r--hw/intc/arm_gicv3_redist.c8
-rw-r--r--hw/intc/gicv3_internal.h21
3 files changed, 26 insertions, 5 deletions
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index dcc5ce28c6..18999e3c8b 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -295,7 +295,7 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
memory_region_init_io(&region->iomem, OBJECT(s),
ops ? &ops[1] : NULL, region, name,
- s->redist_region_count[i] * GICV3_REDIST_SIZE);
+ s->redist_region_count[i] * gicv3_redist_size(s));
sysbus_init_mmio(sbd, &region->iomem);
g_free(name);
}
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
index 7c75dd6f07..9f1fe09a78 100644
--- a/hw/intc/arm_gicv3_redist.c
+++ b/hw/intc/arm_gicv3_redist.c
@@ -442,8 +442,8 @@ MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data,
* in the memory map); if so then the GIC has multiple MemoryRegions
* for the redistributors.
*/
- cpuidx = region->cpuidx + offset / GICV3_REDIST_SIZE;
- offset %= GICV3_REDIST_SIZE;
+ cpuidx = region->cpuidx + offset / gicv3_redist_size(s);
+ offset %= gicv3_redist_size(s);
cs = &s->cpu[cpuidx];
@@ -501,8 +501,8 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
* in the memory map); if so then the GIC has multiple MemoryRegions
* for the redistributors.
*/
- cpuidx = region->cpuidx + offset / GICV3_REDIST_SIZE;
- offset %= GICV3_REDIST_SIZE;
+ cpuidx = region->cpuidx + offset / gicv3_redist_size(s);
+ offset %= gicv3_redist_size(s);
cs = &s->cpu[cpuidx];
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index a46d1378a9..9fff1cd52a 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -490,6 +490,27 @@ FIELD(VTE, RDBASE, 42, RDBASE_PROCNUM_LENGTH)
/* Functions internal to the emulated GICv3 */
/**
+ * gicv3_redist_size:
+ * @s: GICv3State
+ *
+ * Return the size of the redistributor register frame in bytes
+ * (which depends on what GIC version this is)
+ */
+static inline int gicv3_redist_size(GICv3State *s)
+{
+ /*
+ * Redistributor size is controlled by the redistributor GICR_TYPER.VLPIS.
+ * It's the same for every redistributor in the GIC, so arbitrarily
+ * use the register field in the first one.
+ */
+ if (s->cpu[0].gicr_typer & GICR_TYPER_VLPIS) {
+ return GICV4_REDIST_SIZE;
+ } else {
+ return GICV3_REDIST_SIZE;
+ }
+}
+
+/**
* gicv3_intid_is_special:
* @intid: interrupt ID
*