diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2022-02-14 12:51:52 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2022-02-21 10:55:28 +0000 |
commit | 8c332954f06af724a9d7ef7e6dcfcb4f62d2cdb4 (patch) | |
tree | 8f58caf16b655c77a51a5437d7b6d498d30ed4e4 | |
parent | 47c85c088019ed4c8ee50a828bfee4804f3c1339 (diff) |
hw/intc/arm_gicv3_redist: Factor out "update bit in pending table" code
Factor out the code which sets a single bit in an LPI pending table.
We're going to need this for handling vLPI tables, not just the
physical LPI table.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | hw/intc/arm_gicv3_redist.c | 43 |
1 files changed, 24 insertions, 19 deletions
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c index 600b080d79..9f8854b372 100644 --- a/hw/intc/arm_gicv3_redist.c +++ b/hw/intc/arm_gicv3_redist.c @@ -725,36 +725,41 @@ void gicv3_redist_update_lpi(GICv3CPUState *cs) gicv3_redist_update(cs); } -void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level) +static bool set_pending_table_bit(GICv3CPUState *cs, uint64_t addr, + int irq, int level) { /* - * This function updates the pending bit in lpi pending table for - * the irq being activated or deactivated. + * Set the pending bit for LPI @irq to @level in the LPI pending table + * at guest address @addr. Returns true if we needed to do something, + * false if the bit was already at @level. */ AddressSpace *as = &cs->gic->dma_as; - uint64_t lpipt_baddr; - bool ispend = false; uint8_t pend; + addr += irq / 8; + address_space_read(as, addr, MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend)); + if (extract32(pend, irq % 8, 1) == level) { + /* Bit already at requested state, no action required */ + return false; + } + pend = deposit32(pend, irq % 8, 1, level ? 1 : 0); + address_space_write(as, addr, MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend)); + return true; +} + +void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level) +{ /* - * get the bit value corresponding to this irq in the - * lpi pending table + * This function updates the pending bit in lpi pending table for + * the irq being activated or deactivated. */ - lpipt_baddr = cs->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK; - - address_space_read(as, lpipt_baddr + ((irq / 8) * sizeof(pend)), - MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend)); - - ispend = extract32(pend, irq % 8, 1); + uint64_t lpipt_baddr; - /* no change in the value of pending bit, return */ - if (ispend == level) { + lpipt_baddr = cs->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK; + if (!set_pending_table_bit(cs, lpipt_baddr, irq, level)) { + /* no change in the value of pending bit, return */ return; } - pend = deposit32(pend, irq % 8, 1, level ? 1 : 0); - - address_space_write(as, lpipt_baddr + ((irq / 8) * sizeof(pend)), - MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend)); /* * check if this LPI is better than the current hpplpi, if yes |