aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2022-04-08 15:15:14 +0100
committerPeter Maydell <peter.maydell@linaro.org>2022-04-22 09:19:24 +0100
commit9acd2d3373b899b342bfaa84107c613a75b65735 (patch)
tree39f24b6e7cd2b1f43fca0ea5b55b8c5c90f4aa3f
parent50a3a309e12789e28a3c4e260348ed7305c28b99 (diff)
downloadqemu-9acd2d3373b899b342bfaa84107c613a75b65735.zip
qemu-9acd2d3373b899b342bfaa84107c613a75b65735.tar.gz
qemu-9acd2d3373b899b342bfaa84107c613a75b65735.tar.bz2
target/arm/cpu.c: ignore VIRQ and VFIQ if no EL2
In a GICv3, it is impossible for the GIC to deliver a VIRQ or VFIQ to the CPU unless the CPU has EL2, because VIRQ and VFIQ are only configurable via EL2-only system registers. Moreover, in our implementation we were only calculating and updating the state of the VIRQ and VFIQ lines in gicv3_cpuif_virt_irq_fiq_update() when those EL2 system registers changed. We were therefore able to assert in arm_cpu_set_irq() that we didn't see a VIRQ or VFIQ line update if EL2 wasn't present. This assumption no longer holds with GICv4: * even if the CPU does not have EL2 the guest is able to cause the GIC to deliver a virtual LPI by programming the ITS (which is a silly thing for it to do, but possible) * because we now need to recalculate the state of the VIRQ and VFIQ lines in more cases than just "some EL2 GIC sysreg was written", we will see calls to arm_cpu_set_irq() for "VIRQ is 0, VFIQ is 0" even if the guest is not using the virtual LPI parts of the ITS Remove the assertions, and instead simply ignore the state of the VIRQ and VFIQ lines if the CPU does not have EL2. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20220408141550.1271295-6-peter.maydell@linaro.org
-rw-r--r--target/arm/cpu.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 3609de0..fa13fce 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -694,6 +694,16 @@ static void arm_cpu_set_irq(void *opaque, int irq, int level)
[ARM_CPU_VFIQ] = CPU_INTERRUPT_VFIQ
};
+ if (!arm_feature(env, ARM_FEATURE_EL2) &&
+ (irq == ARM_CPU_VIRQ || irq == ARM_CPU_VFIQ)) {
+ /*
+ * The GIC might tell us about VIRQ and VFIQ state, but if we don't
+ * have EL2 support we don't care. (Unless the guest is doing something
+ * silly this will only be calls saying "level is still 0".)
+ */
+ return;
+ }
+
if (level) {
env->irq_line_state |= mask[irq];
} else {
@@ -702,11 +712,9 @@ static void arm_cpu_set_irq(void *opaque, int irq, int level)
switch (irq) {
case ARM_CPU_VIRQ:
- assert(arm_feature(env, ARM_FEATURE_EL2));
arm_cpu_update_virq(cpu);
break;
case ARM_CPU_VFIQ:
- assert(arm_feature(env, ARM_FEATURE_EL2));
arm_cpu_update_vfiq(cpu);
break;
case ARM_CPU_IRQ: