diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2022-04-08 15:15:37 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2022-04-22 14:44:53 +0100 |
commit | 99ba56d25beb3962c2f876690fe429d817cb7b06 (patch) | |
tree | 8bfe728de35c74fa1c2de2c5b00db96318abbaa8 /hw | |
parent | e97be73c97b246e5e4c2582fafcaea0384e14964 (diff) |
hw/intc/arm_gicv3_redist: Factor out "update hpplpi for all LPIs" logic
Factor out the common part of gicv3_redist_update_lpi_only() into
a new function update_for_all_lpis(), which does a full rescan
of an LPI Pending table and sets the specified PendingIrq struct
with the highest priority pending enabled LPI it finds.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20220408141550.1271295-29-peter.maydell@linaro.org
Diffstat (limited to 'hw')
-rw-r--r-- | hw/intc/arm_gicv3_redist.c | 66 |
1 files changed, 46 insertions, 20 deletions
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c index 571e0fa830..2379389d14 100644 --- a/hw/intc/arm_gicv3_redist.c +++ b/hw/intc/arm_gicv3_redist.c @@ -103,6 +103,48 @@ static void update_for_one_lpi(GICv3CPUState *cs, int irq, } } +/** + * update_for_all_lpis: Fully scan LPI tables and find best pending LPI + * + * @cs: GICv3CPUState + * @ptbase: physical address of LPI Pending table + * @ctbase: physical address of LPI Configuration table + * @ptsizebits: size of tables, specified as number of interrupt ID bits minus 1 + * @ds: true if priority value should not be shifted + * @hpp: points to pending information to set + * + * Recalculate the highest priority pending enabled LPI from scratch, + * and set @hpp accordingly. + * + * We scan the LPI pending table @ptbase; for each pending LPI, we read the + * corresponding entry in the LPI configuration table @ctbase to extract + * the priority and enabled information. + * + * We take @ptsizebits in the form idbits-1 because this is the way that + * LPI table sizes are architecturally specified in GICR_PROPBASER.IDBits + * and in the VMAPP command's VPT_size field. + */ +static void update_for_all_lpis(GICv3CPUState *cs, uint64_t ptbase, + uint64_t ctbase, unsigned ptsizebits, + bool ds, PendingIrq *hpp) +{ + AddressSpace *as = &cs->gic->dma_as; + uint8_t pend; + uint32_t pendt_size = (1ULL << (ptsizebits + 1)); + int i, bit; + + hpp->prio = 0xff; + + for (i = GICV3_LPI_INTID_START / 8; i < pendt_size / 8; i++) { + address_space_read(as, ptbase + i, MEMTXATTRS_UNSPECIFIED, &pend, 1); + while (pend) { + bit = ctz32(pend); + update_for_one_lpi(cs, i * 8 + bit, ctbase, ds, hpp); + pend &= ~(1 << bit); + } + } +} + static uint8_t gicr_read_ipriorityr(GICv3CPUState *cs, MemTxAttrs attrs, int irq) { @@ -657,11 +699,7 @@ void gicv3_redist_update_lpi_only(GICv3CPUState *cs) * priority is lower than the last computed high priority lpi interrupt. * If yes, replace current LPI as the new high priority lpi interrupt. */ - AddressSpace *as = &cs->gic->dma_as; - uint64_t lpipt_baddr; - uint32_t pendt_size = 0; - uint8_t pend; - int i, bit; + uint64_t lpipt_baddr, lpict_baddr; uint64_t idbits; idbits = MIN(FIELD_EX64(cs->gicr_propbaser, GICR_PROPBASER, IDBITS), @@ -671,23 +709,11 @@ void gicv3_redist_update_lpi_only(GICv3CPUState *cs) return; } - cs->hpplpi.prio = 0xff; - lpipt_baddr = cs->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK; + lpict_baddr = cs->gicr_propbaser & R_GICR_PROPBASER_PHYADDR_MASK; - /* Determine the highest priority pending interrupt among LPIs */ - pendt_size = (1ULL << (idbits + 1)); - - for (i = GICV3_LPI_INTID_START / 8; i < pendt_size / 8; i++) { - address_space_read(as, lpipt_baddr + i, MEMTXATTRS_UNSPECIFIED, &pend, - sizeof(pend)); - - while (pend) { - bit = ctz32(pend); - gicv3_redist_check_lpi_priority(cs, i * 8 + bit); - pend &= ~(1 << bit); - } - } + update_for_all_lpis(cs, lpipt_baddr, lpict_baddr, idbits, + cs->gic->gicd_ctlr & GICD_CTLR_DS, &cs->hpplpi); } void gicv3_redist_update_lpi(GICv3CPUState *cs) |