The GICv5 IRS must support virtualization if any CPU in the system has EL2 (by spec rule R_KDSPG). Add a has_virt field to the GICv5Common struct to track this, and automatically set it if any connected CPU has EL2.
We get the CPU to tell us whether it needs virtualization in the return value of gicv5_set_gicv5state(); this allows us to maintain the arm's-length relationship between the IRS and the CPU (and in particular we don't need to include cpu.h in arm_gicv5_common.c, as we would if we directly called arm_feature() there). We could alternatively have provided a has-virtualization QOM property, but then the board code would need to take care to explicitly configure the IRS to match the CPUs. (The GICv3 doesn't have an equivalent to this, because in the GICv3 design virtualization is handled entirely by the CPU interface and software; in GICv5 the IRS has hardware support, to reduce the work software needs to do.) None of the code we are about to add in future commits that tests the has_virt flag will be accessible until we remove the check in virt.c that prevents creation of a machine with the GICv5 and an EL2 CPU, so no behaviour will change until we have completed the entire virtualization support feature and allow the user to select it. Signed-off-by: Peter Maydell <[email protected]> --- hw/intc/arm_gicv5_common.c | 9 ++++++++- include/hw/intc/arm_gicv5_common.h | 2 ++ include/hw/intc/arm_gicv5_stream.h | 15 +++++++++++---- target/arm/cpu.c | 17 +++++++++++------ 4 files changed, 32 insertions(+), 11 deletions(-) diff --git a/hw/intc/arm_gicv5_common.c b/hw/intc/arm_gicv5_common.c index cfadfee4f05..17fd67b5ccd 100644 --- a/hw/intc/arm_gicv5_common.c +++ b/hw/intc/arm_gicv5_common.c @@ -176,11 +176,18 @@ static void gicv5_common_realize(DeviceState *dev, Error **errp) } for (int i = 0; i < cs->num_cpus; i++) { - if (!gicv5_set_gicv5state(cs->cpus[i], cs, cs->cpu_iaffids[i], i)) { + switch (gicv5_set_gicv5state(cs->cpus[i], cs, cs->cpu_iaffids[i], i)) { + case GICV5_CPUIF_MISSING: error_setg(errp, "CPU %d (IAFFID 0x%x) does not implement GICv5 CPU interface", i, cs->cpu_iaffids[i]); return; + case GICV5_CPUIF_PRESENT: + break; + case GICV5_CPUIF_NEEDS_VIRT: + /* R_KDSPG: IRS must implement virtualization if any CPU has EL2 */ + cs->has_virt = true; + break; } } diff --git a/include/hw/intc/arm_gicv5_common.h b/include/hw/intc/arm_gicv5_common.h index a47f639e84c..d8f6f5d5db9 100644 --- a/include/hw/intc/arm_gicv5_common.h +++ b/include/hw/intc/arm_gicv5_common.h @@ -127,6 +127,8 @@ struct GICv5Common { uint32_t spi_base; uint32_t spi_irs_range; uint32_t spi_range; + + bool has_virt; }; struct GICv5CommonClass { diff --git a/include/hw/intc/arm_gicv5_stream.h b/include/hw/intc/arm_gicv5_stream.h index f6d32c6beca..ea27d6aec0f 100644 --- a/include/hw/intc/arm_gicv5_stream.h +++ b/include/hw/intc/arm_gicv5_stream.h @@ -16,6 +16,12 @@ typedef struct GICv5Common GICv5Common; +typedef enum GICv5CPUIFStatus { + GICV5_CPUIF_MISSING, /* CPU does not have GICv5 cpuif support */ + GICV5_CPUIF_PRESENT, /* CPU has GICv5 cpuif */ + GICV5_CPUIF_NEEDS_VIRT, /* CPU has GICv5, and needs virt support in IRS */ +} GICv5CPUIFStatus; + /** * gicv5_set_gicv5state * @cpu: CPU object to tell about its IRS @@ -27,11 +33,12 @@ typedef struct GICv5Common GICv5Common; * IRS must call this when it is realized, for each CPU it is * connected to. * - * Returns true on success, false if the CPU doesn't implement the - * GICv5 CPU interface. + * The return value indicates whether the CPU has a GICv5 CPU + * interface, and if it does whether it needs virtualization support + * from the IRS. */ -bool gicv5_set_gicv5state(ARMCPU *cpu, GICv5Common *cs, uint32_t iaffid, - uint32_t cpuidx); +GICv5CPUIFStatus gicv5_set_gicv5state(ARMCPU *cpu, GICv5Common *cs, + uint32_t iaffid, uint32_t cpuidx); /* * The architected Stream Protocol is asynchronous; commands can be diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 4731d1cc7c4..62262d742a2 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -1215,20 +1215,25 @@ static void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags) } #ifndef CONFIG_USER_ONLY -bool gicv5_set_gicv5state(ARMCPU *cpu, GICv5Common *cs, uint32_t iaffid, - uint32_t cpuidx) +GICv5CPUIFStatus gicv5_set_gicv5state(ARMCPU *cpu, GICv5Common *cs, + uint32_t iaffid, uint32_t cpuidx) { /* - * Set this CPU's gicv5state pointer to point to the GIC that we are - * connected to, and record our IAFFID and CPU index. + * Set this CPU's gicv5state pointer to point to the GIC that we + * are connected to, record our IAFFID and cpuidx, and let the IRS + * know if it needs to implement virtualization support. */ if (!cpu_isar_feature(aa64_gcie, cpu)) { - return false; + return GICV5_CPUIF_MISSING; } cpu->env.gicv5.gicv5state = cs; cpu->env.gicv5.iaffid = iaffid; cpu->env.gicv5.cpuidx = cpuidx; - return true; + if (arm_feature(&cpu->env, ARM_FEATURE_EL2)) { + return GICV5_CPUIF_NEEDS_VIRT; + } else { + return GICV5_CPUIF_PRESENT; + } } #endif -- 2.43.0
