Implement the redirection of the ICC_CR0_EL1 encoding to the
hypervisor guest's view ICV_CR0_EL1.  This has only one bit in it,
the enable (EN) bit, which is stored in ICH_VMCR_EL2.EN at the
same bit location (0).

Signed-off-by: Peter Maydell <[email protected]>
---
 target/arm/tcg/gicv5-cpuif.c | 41 +++++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/target/arm/tcg/gicv5-cpuif.c b/target/arm/tcg/gicv5-cpuif.c
index b183c8a6e79..247cefd9e68 100644
--- a/target/arm/tcg/gicv5-cpuif.c
+++ b/target/arm/tcg/gicv5-cpuif.c
@@ -67,6 +67,9 @@ FIELD(ICC_HPPIR_EL1, ID, 0, 24)
 FIELD(ICC_HPPIR_EL1, TYPE, 29, 3)
 FIELD(ICC_HPPIR_EL1, HPPIV, 32, 1)
 
+FIELD(ICH_VMCR_EL2, EN, 0, 1)
+FIELD(ICH_VMCR_EL2, VMPR, 27, 5)
+
 /*
  * We implement 24 bits of interrupt ID, the mandated 5 bits of priority,
  * and no legacy GICv3.3 vcpu interface (yet)
@@ -564,24 +567,38 @@ static void gic_icc_apr_el1_reset(CPUARMState *env, const 
ARMCPRegInfo *ri)
 /* ICC_CR0_EL1 is also banked */
 static uint64_t gic_icc_cr0_el1_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
-    GICv5Domain domain = gicv5_logical_domain(env);
-    return env->gicv5_cpuif.icc_cr0[domain];
+    if (gicv5_icv_access(env)) {
+        /* ICV_CR0_EL1 has only an EN bit, stored in ICH_VMCR_EL2.EN */
+        return FIELD_EX64(env->gicv5_cpuif.ich_vmcr_el2, ICH_VMCR_EL2, EN);
+    } else {
+        GICv5Domain domain = gicv5_logical_domain(env);
+        return env->gicv5_cpuif.icc_cr0[domain];
+    }
 }
 
 static void gic_icc_cr0_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                   uint64_t value)
 {
-    /*
-     * For our implementation the link to the IRI is always connected,
-     * so LINK and LINK_IDLE are always 1. Without EL3, PID and IPPT
-     * are RAZ/WI, so the only writeable bit is the main enable bit EN.
-     */
-    GICv5Domain domain = gicv5_logical_domain(env);
-    value &= R_ICC_CR0_EN_MASK;
-    value |= R_ICC_CR0_LINK_MASK | R_ICC_CR0_LINK_IDLE_MASK;
+    if (gicv5_icv_access(env)) {
+        /* Only the EN bit is writeable, and it lives in ICH_VMCR_EL2 */
+        uint64_t vmcr = env->gicv5_cpuif.ich_vmcr_el2;
 
-    env->gicv5_cpuif.icc_cr0[domain] = value;
-    gicv5_update_irq_fiq(env);
+        vmcr = FIELD_DP64(vmcr, ICH_VMCR_EL2, EN,
+                          FIELD_EX64(value, ICC_CR0, EN));
+        env->gicv5_cpuif.ich_vmcr_el2 = vmcr;
+    } else {
+        /*
+         * For our implementation the link to the IRI is always connected,
+         * so LINK and LINK_IDLE are always 1. Without EL3, PID and IPPT
+         * are RAZ/WI, so the only writeable bit is the main enable bit EN.
+         */
+        GICv5Domain domain = gicv5_logical_domain(env);
+        value &= R_ICC_CR0_EN_MASK;
+        value |= R_ICC_CR0_LINK_MASK | R_ICC_CR0_LINK_IDLE_MASK;
+
+        env->gicv5_cpuif.icc_cr0[domain] = value;
+        gicv5_update_irq_fiq(env);
+    }
 }
 
 static void gic_icc_cr0_el1_reset(CPUARMState *env, const ARMCPRegInfo *ri)
-- 
2.43.0


Reply via email to