aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2022-04-08 15:15:37 +0100
committerPeter Maydell <peter.maydell@linaro.org>2022-04-22 14:44:53 +0100
commit99ba56d25beb3962c2f876690fe429d817cb7b06 (patch)
tree8bfe728de35c74fa1c2de2c5b00db96318abbaa8 /hw
parente97be73c97b246e5e4c2582fafcaea0384e14964 (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.c66
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)