diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2022-04-08 15:15:36 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2022-04-22 14:44:53 +0100 |
commit | e97be73c97b246e5e4c2582fafcaea0384e14964 (patch) | |
tree | c99830f8f67620b5271067e1858d1ebde92d1a10 /hw/intc | |
parent | 189d1d9d5704dfb4fca4d2ccad087bf0e4615898 (diff) | |
download | qemu-e97be73c97b246e5e4c2582fafcaea0384e14964.zip qemu-e97be73c97b246e5e4c2582fafcaea0384e14964.tar.gz qemu-e97be73c97b246e5e4c2582fafcaea0384e14964.tar.bz2 |
hw/intc/arm_gicv3_redist: Factor out "update hpplpi for one LPI" logic
Currently the functions which update the highest priority pending LPI
information by looking at the LPI Pending and Configuration tables
are hard-coded to use the physical LPI tables addressed by
GICR_PENDBASER and GICR_PROPBASER. To support virtual LPIs we will
need to do essentially the same job, but looking at the current
virtual LPI Pending and Configuration tables and updating cs->hppvlpi
instead of cs->hpplpi.
Factor out the common part of the gicv3_redist_check_lpi_priority()
function into a new update_for_one_lpi() function, which updates
a PendingIrq struct if the specified LPI is higher priority than
what is currently recorded there.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20220408141550.1271295-28-peter.maydell@linaro.org
Diffstat (limited to 'hw/intc')
-rw-r--r-- | hw/intc/arm_gicv3_redist.c | 74 |
1 files changed, 47 insertions, 27 deletions
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c index 3464972..571e0fa 100644 --- a/hw/intc/arm_gicv3_redist.c +++ b/hw/intc/arm_gicv3_redist.c @@ -60,6 +60,49 @@ static uint32_t gicr_read_bitmap_reg(GICv3CPUState *cs, MemTxAttrs attrs, return reg; } +/** + * update_for_one_lpi: Update pending information if this LPI is better + * + * @cs: GICv3CPUState + * @irq: interrupt to look up in the LPI Configuration table + * @ctbase: physical address of the LPI Configuration table to use + * @ds: true if priority value should not be shifted + * @hpp: points to pending information to update + * + * Look up @irq in the Configuration table specified by @ctbase + * to see if it is enabled and what its priority is. If it is an + * enabled interrupt with a higher priority than that currently + * recorded in @hpp, update @hpp. + */ +static void update_for_one_lpi(GICv3CPUState *cs, int irq, + uint64_t ctbase, bool ds, PendingIrq *hpp) +{ + uint8_t lpite; + uint8_t prio; + + address_space_read(&cs->gic->dma_as, + ctbase + ((irq - GICV3_LPI_INTID_START) * sizeof(lpite)), + MEMTXATTRS_UNSPECIFIED, &lpite, sizeof(lpite)); + + if (!(lpite & LPI_CTE_ENABLED)) { + return; + } + + if (ds) { + prio = lpite & LPI_PRIORITY_MASK; + } else { + prio = ((lpite & LPI_PRIORITY_MASK) >> 1) | 0x80; + } + + if ((prio < hpp->prio) || + ((prio == hpp->prio) && (irq <= hpp->irq))) { + hpp->irq = irq; + hpp->prio = prio; + /* LPIs and vLPIs are always non-secure Grp1 interrupts */ + hpp->grp = GICV3_G1NS; + } +} + static uint8_t gicr_read_ipriorityr(GICv3CPUState *cs, MemTxAttrs attrs, int irq) { @@ -598,34 +641,11 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data, static void gicv3_redist_check_lpi_priority(GICv3CPUState *cs, int irq) { - AddressSpace *as = &cs->gic->dma_as; - uint64_t lpict_baddr; - uint8_t lpite; - uint8_t prio; + uint64_t lpict_baddr = cs->gicr_propbaser & R_GICR_PROPBASER_PHYADDR_MASK; - lpict_baddr = cs->gicr_propbaser & R_GICR_PROPBASER_PHYADDR_MASK; - - address_space_read(as, lpict_baddr + ((irq - GICV3_LPI_INTID_START) * - sizeof(lpite)), MEMTXATTRS_UNSPECIFIED, &lpite, - sizeof(lpite)); - - if (!(lpite & LPI_CTE_ENABLED)) { - return; - } - - if (cs->gic->gicd_ctlr & GICD_CTLR_DS) { - prio = lpite & LPI_PRIORITY_MASK; - } else { - prio = ((lpite & LPI_PRIORITY_MASK) >> 1) | 0x80; - } - - if ((prio < cs->hpplpi.prio) || - ((prio == cs->hpplpi.prio) && (irq <= cs->hpplpi.irq))) { - cs->hpplpi.irq = irq; - cs->hpplpi.prio = prio; - /* LPIs are always non-secure Grp1 interrupts */ - cs->hpplpi.grp = GICV3_G1NS; - } + update_for_one_lpi(cs, irq, lpict_baddr, + cs->gic->gicd_ctlr & GICD_CTLR_DS, + &cs->hpplpi); } void gicv3_redist_update_lpi_only(GICv3CPUState *cs) |