Skip to content

Commit

Permalink
hw/intc/arm_gicv3: Implement GICv4's new redistributor frame
Browse files Browse the repository at this point in the history
The GICv4 extends the redistributor register map -- where GICv3
had two 64KB frames per CPU, GICv4 has four frames. Add support
for the extra frame by using a new gicv3_redist_size() function
in the places in the GIC implementation which currently use
a fixed constant size for the redistributor register block.
(Until we implement the extra registers they will RAZ/WI.)

Any board that wants to use a GICv4 will need to also adjust
to handle the different sized redistributor register block;
that will be done separately.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20220408141550.1271295-23-peter.maydell@linaro.org
  • Loading branch information
pm215 committed Apr 22, 2022
1 parent c6dd2f9 commit ae3b3ba
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 5 deletions.
2 changes: 1 addition & 1 deletion hw/intc/arm_gicv3_common.c
Expand Up @@ -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);
}
Expand Down
8 changes: 4 additions & 4 deletions hw/intc/arm_gicv3_redist.c
Expand Up @@ -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];

Expand Down Expand Up @@ -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];

Expand Down
21 changes: 21 additions & 0 deletions hw/intc/gicv3_internal.h
Expand Up @@ -489,6 +489,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
Expand Down
5 changes: 5 additions & 0 deletions include/hw/intc/arm_gicv3_common.h
Expand Up @@ -38,7 +38,12 @@

#define GICV3_LPI_INTID_START 8192

/*
* The redistributor in GICv3 has two 64KB frames per CPU; in
* GICv4 it has four 64KB frames per CPU.
*/
#define GICV3_REDIST_SIZE 0x20000
#define GICV4_REDIST_SIZE 0x40000

/* Number of SGI target-list bits */
#define GICV3_TARGETLIST_BITS 16
Expand Down

0 comments on commit ae3b3ba

Please sign in to comment.