@samitouri / QOSamiQemu / commits / 3cee183ff9

hw/riscv/riscv-iommu.c: fix MSI MRIF interrupt-pending offset

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 <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260626220529.3800372-1-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

Daniel Henrique Barboza committed Jun 26, 2026 at 19:05 UTC 3cee183ff9a1a644fcc027ce2751276a5525b123
1 file changed +20 -1
hw/riscv/riscv-iommu.c
+20 -1
@@ -686,7 +686,26 @@ static MemTxResult riscv_iommu_msi_write(RISCVIOMMUState *s,
686
687 /* MRIF pending bit address */
688 addr = get_field(pte[0], RISCV_IOMMU_MSI_PTE_MRIF_ADDR) << 9;
689 - addr = addr | ((data & 0x7c0) >> 3);
689 + /*
690 + * AIA spec section "Format of a memory-resident interrupt file":
691 + * address offset 0x000 contains interrupt-pending bits for
692 + * identities 1-63, offfset 0x010 for identities 64-127, and
693 + * so it goes up to 0x1F0 for identities 1984-2047.
694 + *
695 + * Hence each batch of identities advances offset by 16 (0x010)
696 + * for every interrupt-pending bits. This means that doing
697 + * (data & 0x7c0) will filter out the first 6 bits, then
698 + * a >> 2 will turn the result in the 0x10 steps we need.
699 + *
700 + * E.g:
701 + *
702 + * - (1-63 & 0x7c0) = 0, 0 >> 2 = 0, offset 0x000
703 + * - (64-127 & 0x7c0) = 64, 64 >> 2 = 16, offset 0x010
704 + * - (128-191 & 0x7c0) = 128, 128 >> 2 = 32, offset 0x020
705 + *
706 + * and so on.
707 + */
708 + addr = addr | ((data & 0x7c0) >> 2);
709
710 trace_riscv_iommu_msi(s->parent_obj.id, PCI_BUS_NUM(ctx->devid),
711 PCI_SLOT(ctx->devid), PCI_FUNC(ctx->devid),