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

Reply via email to