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
