Now we are calculating and storing the vHPPI for each VPE, we can
implement IRS_VPE_HPPIR, which allows the guest to read the current
vHPPI for the VPE it has selected using IRS_VPE_SELR.

The specification allows the IRS to return the current vHPPI on
reads, rather than having to sample and hold the vHPPI at the point
when a VPE is selected by writing to IRS_VPE_SELR.  We choose to do
this.

Signed-off-by: Peter Maydell <[email protected]>
---
 hw/intc/arm_gicv5.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/hw/intc/arm_gicv5.c b/hw/intc/arm_gicv5.c
index ab0cd1d80e5..b3ce8a87e81 100644
--- a/hw/intc/arm_gicv5.c
+++ b/hw/intc/arm_gicv5.c
@@ -2319,6 +2319,21 @@ static void irs_vpe_selr_write(GICv5 *s, GICv5Domain 
domain, uint64_t value)
     cs->irs_vpe_statusr[domain] = status;
 }
 
+static uint64_t irs_vpe_hppir_read(GICv5 *s, GICv5Domain domain)
+{
+    /*
+     * The spec allows the IRS to update IRS_VPE_HPPIR as the VPE's
+     * vHPPI changes, rather than sampling it when IRS_VPE_SELR
+     * is written like e.g. IRS_VPE_DBR. That's what we choose to do.
+     */
+    VPE *vpe = vpe_from_selr(s, domain);
+
+    if (vpe && vpe->vhppi.prio != PRIO_IDLE) {
+        return vpe->vhppi.intid | R_IRS_VPE_HPPIR_HPPIV_MASK;
+    }
+    return 0;
+}
+
 static void irs_vpe_dbr_write(GICv5 *s, GICv5Domain domain, uint64_t value)
 {
     GICv5Common *cs = ARM_GICV5_COMMON(s);
@@ -2617,6 +2632,22 @@ static bool config_readl(GICv5 *s, GICv5Domain domain, 
hwaddr offset,
             *data = 0;
         }
         return true;
+    case A_IRS_VPE_HPPIR:
+        if (gicv5_domain_has_virt(cs, domain)) {
+            *data = extract64(irs_vpe_hppir_read(s, domain), 0, 32);
+        } else {
+            /* RAZ if no virt */
+            *data = 0;
+        }
+        return true;
+    case A_IRS_VPE_HPPIR + 4:
+        if (gicv5_domain_has_virt(cs, domain)) {
+            *data = extract64(irs_vpe_hppir_read(s, domain), 32, 32);
+        } else {
+            /* RAZ if no virt */
+            *data = 0;
+        }
+        return true;
     case A_IRS_VPE_CR0:
         /* RES0 when VIRT_ONE_N is not implemented */
         *data = 0;
@@ -2962,6 +2993,14 @@ static bool config_readll(GICv5 *s, GICv5Domain domain, 
hwaddr offset,
             *data = 0;
         }
         return true;
+    case A_IRS_VPE_HPPIR:
+        if (gicv5_domain_has_virt(cs, domain)) {
+            *data = irs_vpe_hppir_read(s, domain);
+        } else {
+            /* RAZ if no virt */
+            *data = 0;
+        }
+        return true;
     }
 
     return false;
-- 
2.43.0


Reply via email to