Re: [PATCH v2 3/3] tests/qtest: add RISC-V IOMMU MRIF notice tests
Chao Liu <[email protected]> Mon, 27 Jul 2026 14:23:44 +0800
| Newsgroups | org.nongnu.qemu-riscv,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
On Sun, Jul 26, 2026 at 05:22:00AM +0800, [email protected] wrote: > 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