hw/riscv/riscv-iommu.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
We need to throw an MSI_MISCONFIGURED error when any of the reserved PTE
bits (first doubleword only) are set.
Fixes: Fixes: 0c54acb8243d ("hw/riscv: add RISC-V IOMMU base emulation")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3563
Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
---
hw/riscv/riscv-iommu.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
index c9687e01a8..6828349fe3 100644
--- a/hw/riscv/riscv-iommu.c
+++ b/hw/riscv/riscv-iommu.c
@@ -648,6 +648,27 @@ static MemTxResult riscv_iommu_msi_write(RISCVIOMMUState *s,
switch (get_field(pte[0], RISCV_IOMMU_MSI_PTE_M)) {
case RISCV_IOMMU_MSI_PTE_M_BASIC:
+ /*
+ * riscv-iommu spec MSI PTE basic translate mode:
+ * "When an MSI PTE has fields V = 1, C = 0, and M = 3
+ * (basic translate mode), the PTE's complete format is:
+ * First doubleword: bit 63 C, = 0
+ * bits 53:10 PPN
+ * bits 2:1 M, = 3
+ * bit 0 V, = 1
+ * All other bits of the first doubleword are reserved
+ * and must be set to zeros by software. The second
+ * doubleword is ignored by an IOMMU so is free for
+ * software to use."
+ *
+ * In other words, bits 62:54 and 9:3 of pte[0] are reserved.
+ */
+ if (pte[0] & (GENMASK_ULL(62, 54) | GENMASK_ULL(9, 3))) {
+ res = MEMTX_DECODE_ERROR;
+ cause = RISCV_IOMMU_FQ_CAUSE_MSI_MISCONFIGURED;
+ goto err;
+ }
+
/* MSI Pass-through mode */
addr = PPN_PHYS(get_field(pte[0], RISCV_IOMMU_MSI_PTE_PPN));
--
2.43.0
On Mon, Jun 29, 2026 at 10:58 PM Daniel Henrique Barboza
<daniel.barboza@oss.qualcomm.com> wrote:
>
> We need to throw an MSI_MISCONFIGURED error when any of the reserved PTE
> bits (first doubleword only) are set.
>
> Fixes: Fixes: 0c54acb8243d ("hw/riscv: add RISC-V IOMMU base emulation")
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3563
> Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Thanks!
Applied to riscv-to-apply.next
Alistair
> ---
> hw/riscv/riscv-iommu.c | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
> index c9687e01a8..6828349fe3 100644
> --- a/hw/riscv/riscv-iommu.c
> +++ b/hw/riscv/riscv-iommu.c
> @@ -648,6 +648,27 @@ static MemTxResult riscv_iommu_msi_write(RISCVIOMMUState *s,
>
> switch (get_field(pte[0], RISCV_IOMMU_MSI_PTE_M)) {
> case RISCV_IOMMU_MSI_PTE_M_BASIC:
> + /*
> + * riscv-iommu spec MSI PTE basic translate mode:
> + * "When an MSI PTE has fields V = 1, C = 0, and M = 3
> + * (basic translate mode), the PTE's complete format is:
> + * First doubleword: bit 63 C, = 0
> + * bits 53:10 PPN
> + * bits 2:1 M, = 3
> + * bit 0 V, = 1
> + * All other bits of the first doubleword are reserved
> + * and must be set to zeros by software. The second
> + * doubleword is ignored by an IOMMU so is free for
> + * software to use."
> + *
> + * In other words, bits 62:54 and 9:3 of pte[0] are reserved.
> + */
> + if (pte[0] & (GENMASK_ULL(62, 54) | GENMASK_ULL(9, 3))) {
> + res = MEMTX_DECODE_ERROR;
> + cause = RISCV_IOMMU_FQ_CAUSE_MSI_MISCONFIGURED;
> + goto err;
> + }
> +
> /* MSI Pass-through mode */
> addr = PPN_PHYS(get_field(pte[0], RISCV_IOMMU_MSI_PTE_PPN));
>
> --
> 2.43.0
>
>
On 6/29/2026 8:57 PM, Daniel Henrique Barboza wrote:
> We need to throw an MSI_MISCONFIGURED error when any of the reserved PTE
> bits (first doubleword only) are set.
>
> Fixes: Fixes: 0c54acb8243d ("hw/riscv: add RISC-V IOMMU base emulation")
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3563
> Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Nutty Liu <nutty.liu@hotmail.com>
Thanks,
Nutty
> ---
> hw/riscv/riscv-iommu.c | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
> index c9687e01a8..6828349fe3 100644
> --- a/hw/riscv/riscv-iommu.c
> +++ b/hw/riscv/riscv-iommu.c
> @@ -648,6 +648,27 @@ static MemTxResult riscv_iommu_msi_write(RISCVIOMMUState *s,
>
> switch (get_field(pte[0], RISCV_IOMMU_MSI_PTE_M)) {
> case RISCV_IOMMU_MSI_PTE_M_BASIC:
> + /*
> + * riscv-iommu spec MSI PTE basic translate mode:
> + * "When an MSI PTE has fields V = 1, C = 0, and M = 3
> + * (basic translate mode), the PTE's complete format is:
> + * First doubleword: bit 63 C, = 0
> + * bits 53:10 PPN
> + * bits 2:1 M, = 3
> + * bit 0 V, = 1
> + * All other bits of the first doubleword are reserved
> + * and must be set to zeros by software. The second
> + * doubleword is ignored by an IOMMU so is free for
> + * software to use."
> + *
> + * In other words, bits 62:54 and 9:3 of pte[0] are reserved.
> + */
> + if (pte[0] & (GENMASK_ULL(62, 54) | GENMASK_ULL(9, 3))) {
> + res = MEMTX_DECODE_ERROR;
> + cause = RISCV_IOMMU_FQ_CAUSE_MSI_MISCONFIGURED;
> + goto err;
> + }
> +
> /* MSI Pass-through mode */
> addr = PPN_PHYS(get_field(pte[0], RISCV_IOMMU_MSI_PTE_PPN));
>
© 2016 - 2026 Red Hat, Inc.