From: Daniel Henrique Barboza <[email protected]>
We're doing a wrong shift when calculating the offset for the
interrupt-pending bits, off by one right shift order.
This went undercover for awhile because the calculation works for
interrupt entities 1 to 63. The math goes wrong when using interrupt
entities 64 or greater.
Instead of fixing the issue and running we're also adding some notes
on where this calc comes from.
Fixes: 0c54acb8243d ("hw/riscv: add RISC-V IOMMU base emulation")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3561
Signed-off-by: Daniel Henrique Barboza <[email protected]>
Acked-by: Alistair Francis <[email protected]>
Message-ID: <[email protected]>
Signed-off-by: Alistair Francis <[email protected]>
---
hw/riscv/riscv-iommu.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
index c65e273dbb..01f5634f04 100644
--- a/hw/riscv/riscv-iommu.c
+++ b/hw/riscv/riscv-iommu.c
@@ -686,7 +686,26 @@ static MemTxResult riscv_iommu_msi_write(RISCVIOMMUState
*s,
/* MRIF pending bit address */
addr = get_field(pte[0], RISCV_IOMMU_MSI_PTE_MRIF_ADDR) << 9;
- addr = addr | ((data & 0x7c0) >> 3);
+ /*
+ * AIA spec section "Format of a memory-resident interrupt file":
+ * address offset 0x000 contains interrupt-pending bits for
+ * identities 1-63, offfset 0x010 for identities 64-127, and
+ * so it goes up to 0x1F0 for identities 1984-2047.
+ *
+ * Hence each batch of identities advances offset by 16 (0x010)
+ * for every interrupt-pending bits. This means that doing
+ * (data & 0x7c0) will filter out the first 6 bits, then
+ * a >> 2 will turn the result in the 0x10 steps we need.
+ *
+ * E.g:
+ *
+ * - (1-63 & 0x7c0) = 0, 0 >> 2 = 0, offset 0x000
+ * - (64-127 & 0x7c0) = 64, 64 >> 2 = 16, offset 0x010
+ * - (128-191 & 0x7c0) = 128, 128 >> 2 = 32, offset 0x020
+ *
+ * and so on.
+ */
+ addr = addr | ((data & 0x7c0) >> 2);
trace_riscv_iommu_msi(s->parent_obj.id, PCI_BUS_NUM(ctx->devid),
PCI_SLOT(ctx->devid), PCI_FUNC(ctx->devid),
--
2.54.0