summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2022-04-08 15:15:46 +0100
committerPeter Maydell <peter.maydell@linaro.org>2022-04-22 14:44:53 +0100
commite2d5e189aa51f7ab1891c17b3808fbac7c1ab6ef (patch)
tree5b98ed5f67a9d15cddc92290f23adad85c076c1b
parent1b19ccfa3845393fee9ecc9af99700ebf97ad277 (diff)
hw/intc/arm_gicv3: Update ID and feature registers for GICv4
Update the various GIC ID and feature registers for GICv4: * PIDR2 [7:4] is the GIC architecture revision * GICD_TYPER.DVIS is 1 to indicate direct vLPI injection support * GICR_TYPER.VLPIS is 1 to indicate redistributor support for vLPIs * GITS_TYPER.VIRTUAL is 1 to indicate vLPI support * GITS_TYPER.VMOVP is 1 to indicate that our VMOVP implementation handles cross-ITS synchronization for the guest * ICH_VTR_EL2.nV4 is 0 to indicate direct vLPI injection support Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20220408141550.1271295-38-peter.maydell@linaro.org
-rw-r--r--hw/intc/arm_gicv3_common.c7
-rw-r--r--hw/intc/arm_gicv3_cpuif.c6
-rw-r--r--hw/intc/arm_gicv3_dist.c7
-rw-r--r--hw/intc/arm_gicv3_its.c7
-rw-r--r--hw/intc/arm_gicv3_redist.c2
-rw-r--r--hw/intc/gicv3_internal.h15
6 files changed, 32 insertions, 12 deletions
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index 3f47b3501f..181f342f32 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -406,8 +406,8 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
* Last == 1 if this is the last redistributor in a series of
* contiguous redistributor pages
* DirectLPI == 0 (direct injection of LPIs not supported)
- * VLPIS == 0 (virtual LPIs not supported)
- * PLPIS == 0 (physical LPIs not supported)
+ * VLPIS == 1 if vLPIs supported (GICv4 and up)
+ * PLPIS == 1 if LPIs supported
*/
cpu_affid = object_property_get_uint(OBJECT(cpu), "mp-affinity", NULL);
@@ -422,6 +422,9 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
if (s->lpi_enable) {
s->cpu[i].gicr_typer |= GICR_TYPER_PLPIS;
+ if (s->revision > 3) {
+ s->cpu[i].gicr_typer |= GICR_TYPER_VLPIS;
+ }
}
}
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index d627ddac90..8404f46ee0 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -2578,11 +2578,15 @@ static uint64_t ich_vtr_read(CPUARMState *env, const ARMCPRegInfo *ri)
uint64_t value;
value = ((cs->num_list_regs - 1) << ICH_VTR_EL2_LISTREGS_SHIFT)
- | ICH_VTR_EL2_TDS | ICH_VTR_EL2_NV4 | ICH_VTR_EL2_A3V
+ | ICH_VTR_EL2_TDS | ICH_VTR_EL2_A3V
| (1 << ICH_VTR_EL2_IDBITS_SHIFT)
| ((cs->vprebits - 1) << ICH_VTR_EL2_PREBITS_SHIFT)
| ((cs->vpribits - 1) << ICH_VTR_EL2_PRIBITS_SHIFT);
+ if (cs->gic->revision < 4) {
+ value |= ICH_VTR_EL2_NV4;
+ }
+
trace_gicv3_ich_vtr_read(gicv3_redist_affid(cs), value);
return value;
}
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
index 7f6275363e..b9ed955e36 100644
--- a/hw/intc/arm_gicv3_dist.c
+++ b/hw/intc/arm_gicv3_dist.c
@@ -383,7 +383,7 @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
* No1N == 1 (1-of-N SPI interrupts not supported)
* A3V == 1 (non-zero values of Affinity level 3 supported)
* IDbits == 0xf (we support 16-bit interrupt identifiers)
- * DVIS == 0 (Direct virtual LPI injection not supported)
+ * DVIS == 1 (Direct virtual LPI injection supported) if GICv4
* LPIS == 1 (LPIs are supported if affinity routing is enabled)
* num_LPIs == 0b00000 (bits [15:11],Number of LPIs as indicated
* by GICD_TYPER.IDbits)
@@ -399,8 +399,9 @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
* so we only need to check the DS bit.
*/
bool sec_extn = !(s->gicd_ctlr & GICD_CTLR_DS);
+ bool dvis = s->revision >= 4;
- *data = (1 << 25) | (1 << 24) | (sec_extn << 10) |
+ *data = (1 << 25) | (1 << 24) | (dvis << 18) | (sec_extn << 10) |
(s->lpi_enable << GICD_TYPER_LPIS_SHIFT) |
(0xf << 19) | itlinesnumber;
return true;
@@ -557,7 +558,7 @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
}
case GICD_IDREGS ... GICD_IDREGS + 0x2f:
/* ID registers */
- *data = gicv3_idreg(offset - GICD_IDREGS, GICV3_PIDR0_DIST);
+ *data = gicv3_idreg(s, offset - GICD_IDREGS, GICV3_PIDR0_DIST);
return true;
case GICD_SGIR:
/* WO registers, return unknown value */
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 0670aca4d4..2ff21ed6bb 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -1699,7 +1699,7 @@ static bool its_readl(GICv3ITSState *s, hwaddr offset,
break;
case GITS_IDREGS ... GITS_IDREGS + 0x2f:
/* ID registers */
- *data = gicv3_idreg(offset - GITS_IDREGS, GICV3_PIDR0_ITS);
+ *data = gicv3_idreg(s->gicv3, offset - GITS_IDREGS, GICV3_PIDR0_ITS);
break;
case GITS_TYPER:
*data = extract64(s->typer, 0, 32);
@@ -1946,6 +1946,11 @@ static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
s->typer = FIELD_DP64(s->typer, GITS_TYPER, DEVBITS, ITS_DEVBITS);
s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIL, 1);
s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIDBITS, ITS_CIDBITS);
+ if (s->gicv3->revision >= 4) {
+ /* Our VMOVP handles cross-ITS synchronization itself */
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, VMOVP, 1);
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, VIRTUAL, 1);
+ }
}
static void gicv3_its_reset(DeviceState *dev)
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
index bcb54bef76..c3d4cdd66b 100644
--- a/hw/intc/arm_gicv3_redist.c
+++ b/hw/intc/arm_gicv3_redist.c
@@ -441,7 +441,7 @@ static MemTxResult gicr_readl(GICv3CPUState *cs, hwaddr offset,
*data = cs->gicr_nsacr;
return MEMTX_OK;
case GICR_IDREGS ... GICR_IDREGS + 0x2f:
- *data = gicv3_idreg(offset - GICR_IDREGS, GICV3_PIDR0_REDIST);
+ *data = gicv3_idreg(cs->gic, offset - GICR_IDREGS, GICV3_PIDR0_REDIST);
return MEMTX_OK;
/*
* VLPI frame registers. We don't need a version check for
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index 2a9d3cf974..29d5cdc1b6 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -309,6 +309,7 @@ FIELD(GITS_TYPER, SEIS, 18, 1)
FIELD(GITS_TYPER, PTA, 19, 1)
FIELD(GITS_TYPER, CIDBITS, 32, 4)
FIELD(GITS_TYPER, CIL, 36, 1)
+FIELD(GITS_TYPER, VMOVP, 37, 1)
#define GITS_IDREGS 0xFFD0
@@ -747,23 +748,29 @@ static inline uint32_t gicv3_iidr(void)
#define GICV3_PIDR0_REDIST 0x93
#define GICV3_PIDR0_ITS 0x94
-static inline uint32_t gicv3_idreg(int regoffset, uint8_t pidr0)
+static inline uint32_t gicv3_idreg(GICv3State *s, int regoffset, uint8_t pidr0)
{
/* Return the value of the CoreSight ID register at the specified
* offset from the first ID register (as found in the distributor
* and redistributor register banks).
- * These values indicate an ARM implementation of a GICv3.
+ * These values indicate an ARM implementation of a GICv3 or v4.
*/
static const uint8_t gicd_ids[] = {
- 0x44, 0x00, 0x00, 0x00, 0x92, 0xB4, 0x3B, 0x00, 0x0D, 0xF0, 0x05, 0xB1
+ 0x44, 0x00, 0x00, 0x00, 0x92, 0xB4, 0x0B, 0x00, 0x0D, 0xF0, 0x05, 0xB1
};
+ uint32_t id;
regoffset /= 4;
if (regoffset == 4) {
return pidr0;
}
- return gicd_ids[regoffset];
+ id = gicd_ids[regoffset];
+ if (regoffset == 6) {
+ /* PIDR2 bits [7:4] are the GIC architecture revision */
+ id |= s->revision << 4;
+ }
+ return id;
}
/**