The ICC_PPI_HMR<n>_EL1 and ICV_PPI_HMR<n>_EL1 registers are both
read-only and report whether PPIs have the edge or level handling
mode.  This doesn't change under virtualization and there is no
mechanism for the hypervisor to report a different value to the
guest.  However, we do need to honour the ICH_PPI_HVI bits that
make the PPI behave as if it was unimplemented (bit is RAZ/WI).

Add a readfn for these registers so we can mask them when they are
read by the hypervisor guest.

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

diff --git a/target/arm/tcg/gicv5-cpuif.c b/target/arm/tcg/gicv5-cpuif.c
index e1d3ffb7b1e..b55fe4991ba 100644
--- a/target/arm/tcg/gicv5-cpuif.c
+++ b/target/arm/tcg/gicv5-cpuif.c
@@ -425,6 +425,23 @@ static void gic_cdhm_write(CPUARMState *env, const 
ARMCPRegInfo *ri,
     gicv5_set_handling(gic, id, hm, domain, type, virtual);
 }
 
+static uint64_t gic_ppi_hmr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    uint64_t value = raw_read(env, ri);
+
+    if (gicv5_icv_access(env)) {
+        /*
+         * The spec defines ICV_PPI_HMR<n>_EL1 virtual versions of these
+         * registers, but they are read-only and can only ever report the
+         * same value as the physical ICC_ versions. However we do need
+         * to make sure the bits RAZ/WI if the hypervisor has made the
+         * PPI appear disabled to the guest via ICH_PPI_HVIR<n>_EL2.
+         */
+        value &= ~env->gicv5_cpuif.ich_ppi_hvi[ri->opc2 & 1];
+    }
+    return value;
+}
+
 static void gic_ppi_cactive_write(CPUARMState *env, const ARMCPRegInfo *ri,
                                   uint64_t value)
 {
@@ -1054,6 +1071,7 @@ static const ARMCPRegInfo gicv5_cpuif_reginfo[] = {
         .access = PL1_R, .type = ARM_CP_IO | ARM_CP_NO_RAW,
         .fgt = FGT_ICC_PPI_HMRN_EL1,
         .fieldoffset = offsetof(CPUARMState, gicv5_cpuif.ppi_hm[0]),
+        .readfn = gic_ppi_hmr_read,
         .resetvalue = PPI_HMR0_RESET,
     },
     {   .name = "ICC_PPI_HMR1_EL1", .state = ARM_CP_STATE_AA64,
@@ -1061,6 +1079,7 @@ static const ARMCPRegInfo gicv5_cpuif_reginfo[] = {
         .access = PL1_R, .type = ARM_CP_IO | ARM_CP_NO_RAW,
         .fgt = FGT_ICC_PPI_HMRN_EL1,
         .fieldoffset = offsetof(CPUARMState, gicv5_cpuif.ppi_hm[1]),
+        .readfn = gic_ppi_hmr_read,
         .resetvalue = PPI_HMR1_RESET,
     },
     {   .name = "ICC_HPPIR_EL1", .state = ARM_CP_STATE_AA64,
-- 
2.43.0


Reply via email to