aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2022-02-14 12:51:52 +0000
committerPeter Maydell <peter.maydell@linaro.org>2022-02-21 10:55:28 +0000
commit8c332954f06af724a9d7ef7e6dcfcb4f62d2cdb4 (patch)
tree8f58caf16b655c77a51a5437d7b6d498d30ed4e4
parent47c85c088019ed4c8ee50a828bfee4804f3c1339 (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.c43
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