On Sun, Jul 26, 2026 at 07:28:27PM +0800, [email protected] wrote:
> From a13bfa64b84ac70c9e257253616ce650fc3e794b Mon Sep 17 00:00:00 2001
> From: Flavien Solt <[email protected]>
> Date: Sun, 26 Jul 2026 17:54:04 +0800
> Subject: [PATCH v3 3/3] tests/qtest: add RISC-V IOMMU MRIF notice tests
>
> Exercise MRIF-mode MSI writes through iommu-testdev with the destination
> interrupt-enable bit both clear and set. Each case requires the pending
> bit to be stored plus the configured notice ID to reach guest memory.
>
> The enable-clear case regresses the notice suppression fixed by the
> previous patch. The enable-set case provides a control for the existing
> path.
>
> Signed-off-by: Flavien Solt <[email protected]>
Reviewed-by: Chao Liu <[email protected]>
Thanks,
Chao
> ---
> tests/qtest/iommu-riscv-test.c | 102 +++++++++++++++++++++++++++++++++
> 1 file changed, 102 insertions(+)
>
> diff --git a/tests/qtest/iommu-riscv-test.c b/tests/qtest/iommu-riscv-test.c
> index 2638024..85f79ea 100644
> --- a/tests/qtest/iommu-riscv-test.c
> +++ b/tests/qtest/iommu-riscv-test.c
> @@ -14,6 +14,7 @@
> #include "hw/pci/pci_regs.h"
> #include "hw/misc/iommu-testdev.h"
> #include "hw/riscv/riscv-iommu-bits.h"
> +#include "libqos/qos-iommu-testdev.h"
> #include "libqos/qos-riscv-iommu.h"
> #include "libqos/riscv-iommu.h"
>
> @@ -26,6 +27,13 @@
> #define RISCV_BUS_MMIO_LIMIT 0x80000000
> #define RISCV_ECAM_ALLOC_PTR 0x30000000
>
> +#define RISCV_MRIF_MSI_IOVA 0x00000000fee00000ull
> +#define RISCV_MRIF_MSI_PT_GPA (QRIOMMU_SPACE_OFFS + 0x00030000ull)
> +#define RISCV_MRIF_BASE_GPA (QRIOMMU_SPACE_OFFS + 0x00031000ull)
> +#define RISCV_MRIF_NOTICE_GPA (QRIOMMU_SPACE_OFFS + 0x00032000ull)
> +#define RISCV_MRIF_INTID 5u
> +#define RISCV_MRIF_NOTICE_ID 0x12du
> +
> typedef struct RiscvIommuTestState {
> QTestState *qts;
> QGenericPCIBus gbus;
> @@ -264,6 +272,96 @@ static void test_riscv_iommu_nested(void)
> run_riscv_iommu_translation(&cfg);
> }
>
> +static void riscv_iommu_setup_mrif_context(RiscvIommuTestState *state)
> +{
> + uint64_t dc_addr;
> + uint64_t msiptp;
> + uint64_t pte0;
> + uint64_t pte1;
> +
> + qtest_memset(state->qts, QRIOMMU_SPACE_OFFS + QRIOMMU_DDT_BASE, 0,
> + 0x1000);
> + qtest_memset(state->qts, RISCV_MRIF_MSI_PT_GPA, 0, 0x1000);
> + qtest_memset(state->qts, RISCV_MRIF_BASE_GPA, 0, 0x1000);
> + qtest_memset(state->qts, RISCV_MRIF_NOTICE_GPA, 0, 4);
> +
> + dc_addr = QRIOMMU_SPACE_OFFS + QRIOMMU_DDT_BASE +
> + state->testdev->devfn * sizeof(struct riscv_iommu_dc);
> +
> + msiptp = (RISCV_MRIF_MSI_PT_GPA >> 12) |
> + ((uint64_t)RISCV_IOMMU_DC_MSIPTP_MODE_FLAT << 60);
> +
> + qtest_writeq(state->qts, dc_addr + 0, RISCV_IOMMU_DC_TC_V);
> + qtest_writeq(state->qts, dc_addr + 8, 0);
> + qtest_writeq(state->qts, dc_addr + 16, 0);
> + qtest_writeq(state->qts, dc_addr + 24, 0);
> + qtest_writeq(state->qts, dc_addr + 32, msiptp);
> + qtest_writeq(state->qts, dc_addr + 40, 0);
> + qtest_writeq(state->qts, dc_addr + 48, RISCV_MRIF_MSI_IOVA >> 12);
> + qtest_writeq(state->qts, dc_addr + 56, 0);
> +
> + pte0 = RISCV_IOMMU_MSI_PTE_V |
> + ((uint64_t)RISCV_IOMMU_MSI_PTE_M_MRIF << 1) |
> + ((RISCV_MRIF_BASE_GPA >> 9) << 7);
> + pte1 = ((RISCV_MRIF_NOTICE_GPA >> 12) << 10) | RISCV_MRIF_NOTICE_ID;
> +
> + qtest_writeq(state->qts, RISCV_MRIF_MSI_PT_GPA, pte0);
> + qtest_writeq(state->qts, RISCV_MRIF_MSI_PT_GPA + 8, pte1);
> +
> + qriommu_program_regs(state->qts, state->iommu_base);
> +}
> +
> +static void run_riscv_iommu_mrif_notice(bool enable_bit)
> +{
> + RiscvIommuTestState state = { 0 };
> + uint64_t pending;
> + uint64_t enabled;
> + uint32_t notice;
> + uint32_t dma_result;
> +
> + if (!riscv_iommu_test_setup(&state)) {
> + return;
> + }
> +
> + riscv_iommu_check(state.qts, state.iommu_base, QRIOMMU_TM_BARE);
> + riscv_iommu_setup_mrif_context(&state);
> +
> + enabled = enable_bit ? (1ull << RISCV_MRIF_INTID) : 0;
> + qtest_writeq(state.qts, RISCV_MRIF_BASE_GPA + 8, enabled);
> + qpci_io_writel(state.testdev, state.testdev_bar, ITD_REG_DMA_WRITE_VAL,
> + RISCV_MRIF_INTID);
> +
> + dma_result = qos_iommu_testdev_trigger_dma(
> + state.testdev, state.testdev_bar, RISCV_MRIF_MSI_IOVA,
> + RISCV_MRIF_NOTICE_GPA, DMA_LEN, qriommu_build_dma_attrs());
> +
> + pending = qtest_readq(state.qts, RISCV_MRIF_BASE_GPA);
> + notice = qtest_readl(state.qts, RISCV_MRIF_NOTICE_GPA);
> +
> + g_test_message("MRIF notice: enable=%u pending=0x%" PRIx64
> + " notice=0x%x", enable_bit, pending, notice);
> +
> + /*
> + * Interrupt remapping consumes the original DMA write; the generic
> + * test device cannot read it back from the supplied physical address.
> + */
> + g_assert_cmpuint(dma_result, ==, ITD_DMA_ERR_MISMATCH);
> + g_assert_cmpuint(pending & (1ull << RISCV_MRIF_INTID), !=, 0);
> + g_assert_cmpuint(notice, ==, RISCV_MRIF_NOTICE_ID);
> +
> + riscv_iommu_test_teardown(&state);
> +}
> +
> +static void test_riscv_iommu_mrif_notice_enable_clear(void)
> +{
> + run_riscv_iommu_mrif_notice(false);
> +}
> +
> +static void test_riscv_iommu_mrif_notice_enable_set(void)
> +{
> + run_riscv_iommu_mrif_notice(true);
> +}
> +
> int main(int argc, char **argv)
> {
> g_test_init(&argc, &argv, NULL);
> @@ -275,5 +373,9 @@ int main(int argc, char **argv)
> test_riscv_iommu_g_stage_only);
> qtest_add_func("/iommu-testdev/translation/ns-nested",
> test_riscv_iommu_nested);
> + qtest_add_func("/iommu-testdev/mrif-notice/enable-clear",
> + test_riscv_iommu_mrif_notice_enable_clear);
> + qtest_add_func("/iommu-testdev/mrif-notice/enable-set",
> + test_riscv_iommu_mrif_notice_enable_set);
> return g_test_run();
> }
> --
> 2.54.0