[{"id":3670417,"web_url":"http://patchwork.ozlabs.org/comment/3670417/","msgid":"<87y0jdgu2d.fsf@suse.de>","list_archive_url":null,"date":"2026-03-27T15:39:54","subject":"Re: [PATCH v3 1/2] tests/qtest/libqos: Add Intel IOMMU helper library","submitter":{"id":85343,"url":"http://patchwork.ozlabs.org/api/people/85343/","name":"Fabiano Rosas","email":"farosas@suse.de"},"content":"Fengyuan Yu <15fengyuan@gmail.com> writes:\n\n> Introduce a libqos helper module for Intel IOMMU (VT-d) bare-metal\n> testing via iommu-testdev. The helper provides routines to:\n>\n> - Build Legacy-mode structures: Root Entry Tables, Context Entry Tables,\n>   and 4-level page tables for 48-bit address translation\n> - Build Scalable-mode structures: Scalable Context Entries, PASID\n>   Directory Entries, PASID Table Entries, and 4-level page tables for\n>   both second-level and first-level translation\n> - Program VT-d registers (Root Table Address, Invalidation Queue,\n>   Fault Event MSI, Global Command) following the VT-d specification,\n>   with GSTS read-back verification for each step\n> - Execute DMA translations through iommu-testdev and verify results\n>   by reading back guest memory\n>\n> The module supports all major VT-d translation modes through the\n> QVTDTransMode enum:\n> - Legacy pass-through\n> - Legacy translated with 4-level paging\n> - Scalable pass-through\n> - Scalable Second-Level Translation\n> - Scalable First-Level Translation\n>\n> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>\n> Signed-off-by: Fengyuan Yu <15fengyuan@gmail.com>\n> ---\n>  MAINTAINERS                          |   1 +\n>  tests/qtest/libqos/meson.build       |   3 +\n>  tests/qtest/libqos/qos-intel-iommu.c | 454 +++++++++++++++++++++++++++\n>  tests/qtest/libqos/qos-intel-iommu.h | 185 +++++++++++\n>  4 files changed, 643 insertions(+)\n>  create mode 100644 tests/qtest/libqos/qos-intel-iommu.c\n>  create mode 100644 tests/qtest/libqos/qos-intel-iommu.h\n>\n> diff --git a/MAINTAINERS b/MAINTAINERS\n> index cd8ba14450..ba0901bf4f 100644\n> --- a/MAINTAINERS\n> +++ b/MAINTAINERS\n> @@ -3606,6 +3606,7 @@ S: Maintained\n>  F: tests/qtest/libqos/qos-iommu*\n>  F: tests/qtest/libqos/qos-smmuv3*\n>  F: tests/qtest/libqos/qos-riscv-iommu*\n> +F: tests/qtest/libqos/qos-intel-iommu*\n>  \n>  Device Fuzzing\n>  M: Alexander Bulekov <alxndr@bu.edu>\n> diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build\n> index 4a69acad0d..96f2fc48b4 100644\n> --- a/tests/qtest/libqos/meson.build\n> +++ b/tests/qtest/libqos/meson.build\n> @@ -73,6 +73,9 @@ endif\n>  if config_all_devices.has_key('CONFIG_RISCV_IOMMU')\n>    libqos_srcs += files('riscv-iommu.c', 'qos-riscv-iommu.c')\n>  endif\n> +if config_all_devices.has_key('CONFIG_VTD')\n> +  libqos_srcs += files('qos-intel-iommu.c')\n> +endif\n>  if config_all_devices.has_key('CONFIG_TPCI200')\n>    libqos_srcs += files('tpci200.c')\n>  endif\n> diff --git a/tests/qtest/libqos/qos-intel-iommu.c b/tests/qtest/libqos/qos-intel-iommu.c\n> new file mode 100644\n> index 0000000000..f8ca4c871b\n> --- /dev/null\n> +++ b/tests/qtest/libqos/qos-intel-iommu.c\n> @@ -0,0 +1,454 @@\n> +/*\n> + * QOS Intel IOMMU (VT-d) Module Implementation\n> + *\n> + * This module provides Intel IOMMU-specific helper functions for libqos tests.\n> + *\n> + * Copyright (c) 2026 Fengyuan Yu <15fengyuan@gmail.com>\n> + *\n> + * SPDX-License-Identifier: GPL-2.0-or-later\n> + */\n> +\n> +#include \"qemu/osdep.h\"\n> +#include \"hw/i386/intel_iommu_internal.h\"\n> +#include \"tests/qtest/libqos/pci.h\"\n> +#include \"qos-iommu-testdev.h\"\n> +#include \"qos-intel-iommu.h\"\n> +\n> +#define QVTD_AW_48BIT_ENCODING    2\n> +\n> +uint32_t qvtd_expected_dma_result(QVTDTestContext *ctx)\n> +{\n> +    return ctx->config.expected_result;\n> +}\n> +\n> +uint32_t qvtd_build_dma_attrs(void)\n> +{\n> +    /*\n> +     * VT-d obtains the Requester ID (Source ID) from PCI bus/devfn routing\n> +     * via pci_device_iommu_address_space(), not from DMA attributes.\n> +     *\n> +     * For scalable mode, iommu-testdev does not set MemTxAttrs.pid,\n> +     * so the device's VTDAddressSpace has pasid=PCI_NO_PASID.\n> +     * vtd_do_iommu_translate() remaps PCI_NO_PASID to PASID_0\n> +     * when root_scalable is set, which matches the PASID=0 entry\n> +     * we configure in qvtd_build_pasid_table_entry().\n> +     */\n> +    return 0;\n> +}\n> +\n> +static void qvtd_build_root_entry(QTestState *qts, uint8_t bus,\n> +                                  uint64_t context_table_ptr,\n> +                                  QVTDTransMode mode)\n> +{\n> +    uint64_t root_entry_addr = QVTD_ROOT_TABLE_BASE +\n> +                               (bus * sizeof(VTDRootEntry));\n> +    uint64_t lo, hi;\n> +\n> +    if (qvtd_is_scalable(mode)) {\n> +        /*\n> +         * Scalable-mode Root Entry (Section 9.2):\n> +         * lo = Lower Context Table Pointer + LP (Lower Present)\n> +         * hi = Upper Context Table Pointer + UP (Upper Present)\n> +         *\n> +         * Lower table covers devfn 0-127, Upper covers devfn 128-255.\n> +         * Only lower half is needed for test device (devfn < 128).\n> +         */\n> +        lo = (context_table_ptr & VTD_ROOT_ENTRY_CTP) | VTD_ROOT_ENTRY_P;\n> +        hi = 0;  /* UP=0: upper context table not present */\n> +    } else {\n> +        /*\n> +         * Legacy Root Entry (Section 9.1):\n> +         * lo = Context Table Pointer + Present\n> +         * hi = Reserved\n> +         */\n> +        lo = (context_table_ptr & VTD_ROOT_ENTRY_CTP) | VTD_ROOT_ENTRY_P;\n> +        hi = 0;\n> +    }\n> +\n> +    qtest_writeq(qts, root_entry_addr, lo);\n> +    qtest_writeq(qts, root_entry_addr + 8, hi);\n> +}\n> +\n> +static void qvtd_build_context_entry(QTestState *qts, uint16_t sid,\n> +                                     QVTDTransMode mode, uint64_t ssptptr)\n> +{\n> +    uint8_t devfn = sid & 0xff;\n> +    uint64_t context_entry_addr = QVTD_CONTEXT_TABLE_BASE +\n> +                                 (devfn * VTD_CTX_ENTRY_LEGACY_SIZE);\n> +    uint64_t lo, hi;\n> +\n> +    if (mode == QVTD_TM_LEGACY_PT) {\n> +        /*\n> +         * Pass-through mode (Section 9.3):\n> +         * lo: P + FPD(=0, fault enabled) + TT(=Pass-through)\n> +         * hi: DID + AW\n> +         */\n> +        lo = VTD_CONTEXT_ENTRY_P | VTD_CONTEXT_TT_PASS_THROUGH;\n> +        hi = ((uint64_t)QVTD_DOMAIN_ID << 8) | QVTD_AW_48BIT_ENCODING;\n> +    } else {\n> +        /*\n> +         * Translated mode (Section 9.3):\n> +         * lo: P + FPD(=0, fault enabled) + TT(=Multi-level) + SSPTPTR\n> +         * hi: DID + AW(=48-bit, 4-level)\n> +         */\n> +        lo = VTD_CONTEXT_ENTRY_P | VTD_CONTEXT_TT_MULTI_LEVEL |\n> +             (ssptptr & VTD_CONTEXT_ENTRY_SSPTPTR);\n> +        hi = ((uint64_t)QVTD_DOMAIN_ID << 8) | QVTD_AW_48BIT_ENCODING;\n> +    }\n> +\n> +    qtest_writeq(qts, context_entry_addr, lo);\n> +    qtest_writeq(qts, context_entry_addr + 8, hi);\n> +}\n> +\n> +static void qvtd_build_scalable_context_entry(QTestState *qts, uint16_t sid)\n> +{\n> +    uint8_t devfn = sid & 0xff;\n> +    uint64_t ce_addr = QVTD_CONTEXT_TABLE_BASE +\n> +                       (devfn * VTD_CTX_ENTRY_SCALABLE_SIZE);\n> +\n> +    /*\n> +     * Scalable-Mode Context Entry (Section 9.4), 32 bytes = 4 qwords:\n> +     *\n> +     * val[0]: P + FPD(=0) + DTE(=0) + PASIDE(=0) + PRE(=0) + HPTE(=0)\n> +     *         + EPTR(=0) + PDTS(=0) + PASIDDIRPTR\n> +     * val[1]: RID_PASID(=0) + PDTTE(=0) + PRE(=0) + RID_CG(=0)\n> +     * val[2]: Reserved (must be 0)\n> +     * val[3]: Reserved (must be 0)\n> +     */\n> +    qtest_writeq(qts, ce_addr,\n> +                 (QVTD_PASID_DIR_BASE & VTD_PASID_DIR_BASE_ADDR_MASK) |\n> +                 VTD_CONTEXT_ENTRY_P);\n> +    qtest_writeq(qts, ce_addr + 8, 0);\n> +    qtest_writeq(qts, ce_addr + 16, 0);\n> +    qtest_writeq(qts, ce_addr + 24, 0);\n> +}\n> +\n> +static void qvtd_build_pasid_dir_entry(QTestState *qts)\n> +{\n> +    uint64_t addr = QVTD_PASID_DIR_BASE +\n> +                    VTD_PASID_DIR_INDEX(0) * VTD_PASID_DIR_ENTRY_SIZE;\n> +\n> +    /*\n> +     * PASID Directory Entry (Section 9.5):\n> +     * P + FPD(=0, fault enabled) + SMPTBLPTR\n> +     */\n> +    qtest_writeq(qts, addr,\n> +                 (QVTD_PASID_TABLE_BASE & VTD_PASID_TABLE_BASE_ADDR_MASK) |\n> +                 VTD_PASID_ENTRY_P);\n> +}\n> +\n> +static void qvtd_build_pasid_table_entry(QTestState *qts, QVTDTransMode mode,\n> +                                         uint64_t ptptr)\n> +{\n> +    uint64_t addr = QVTD_PASID_TABLE_BASE +\n> +                    VTD_PASID_TABLE_INDEX(0) * VTD_PASID_ENTRY_SIZE;\n> +    uint64_t val0, val1, val2;\n> +\n> +    /*\n> +     * Scalable-Mode PASID Table Entry (Section 9.6), 64 bytes = 8 qwords:\n> +     *\n> +     * val[0]: P + FPD(=0) + AW + PGTT + SSADE(=0) + SSPTPTR\n> +     * val[1]: DID + PWSNP(=0) + PGSNP(=0)\n> +     *         + CD(=0) + EMTE(=0) + PAT(=0): Memory Type,\n> +     *           all Reserved(0) since QEMU ECAP.MTS=0\n> +     * val[2]: SRE(=0) + FSPM(=0, 4-level) + WPE(=0) + IGN + EAFE(=0) + FSPTPTR\n> +     * val[3]: Reserved (must be 0)\n> +     * val[4]: HPT fields, Reserved(0) since QEMU ECAP.HPTS=0\n> +     * val[5]: HPT fields, Reserved(0) since QEMU ECAP.HPTS=0\n> +     * val[6]: Reserved (must be 0)\n> +     * val[7]: Reserved (must be 0)\n> +     */\n> +    switch (mode) {\n> +    case QVTD_TM_SCALABLE_PT:\n> +        val0 = VTD_PASID_ENTRY_P |\n> +               ((uint64_t)VTD_SM_PASID_ENTRY_PT << 6);\n> +        val1 = (uint64_t)QVTD_DOMAIN_ID;\n> +        val2 = 0;\n> +        break;\n> +    case QVTD_TM_SCALABLE_SLT:\n> +        val0 = VTD_PASID_ENTRY_P |\n> +               ((uint64_t)VTD_SM_PASID_ENTRY_SST << 6) |\n> +               ((uint64_t)QVTD_AW_48BIT_ENCODING << 2) |\n> +               (ptptr & VTD_SM_PASID_ENTRY_SSPTPTR);\n> +        val1 = (uint64_t)QVTD_DOMAIN_ID;\n> +        val2 = 0;\n> +        break;\n> +    case QVTD_TM_SCALABLE_FLT:\n> +        /*\n> +         * val[2] fields for FLT (Section 9.6):\n> +         * SRE(=0, user-level DMA only) + FSPM(=0, 4-level) +\n> +         * WPE(=0, no supervisor write-protect) + IGN + EAFE(=0) + FSPTPTR\n> +         */\n> +        val0 = VTD_PASID_ENTRY_P |\n> +               ((uint64_t)VTD_SM_PASID_ENTRY_FST << 6);\n> +        val1 = (uint64_t)QVTD_DOMAIN_ID;\n> +        val2 = ptptr & QVTD_SM_PASID_ENTRY_FSPTPTR;\n> +        break;\n> +    default:\n> +        g_assert_not_reached();\n> +    }\n> +\n> +    qtest_writeq(qts, addr, val0);\n> +    qtest_writeq(qts, addr + 8, val1);\n> +    qtest_writeq(qts, addr + 16, val2);\n> +    qtest_writeq(qts, addr + 24, 0);\n> +    qtest_writeq(qts, addr + 32, 0);\n> +    qtest_writeq(qts, addr + 40, 0);\n> +    qtest_writeq(qts, addr + 48, 0);\n> +    qtest_writeq(qts, addr + 56, 0);\n> +}\n> +\n> +/*\n> + * VT-d second-level paging helpers.\n> + * 4-level, 48-bit address space, 9 bits per level index.\n> + */\n> +static uint32_t qvtd_get_table_index(uint64_t iova, int level)\n> +{\n> +    int shift = VTD_PAGE_SHIFT + VTD_LEVEL_BITS * (level - 1);\n> +\n> +    return (iova >> shift) & ((1u << VTD_LEVEL_BITS) - 1);\n> +}\n> +\n> +static uint64_t qvtd_get_table_addr(uint64_t base, int level, uint64_t iova)\n> +{\n> +    return base + (qvtd_get_table_index(iova, level) * QVTD_PTE_SIZE);\n> +}\n> +\n> +static uint64_t qvtd_get_pte_attrs(void)\n> +{\n> +    /* Second-level: R/W in every paging entry (Section 3.7.1) */\n> +    return VTD_SS_R | VTD_SS_W;\n> +}\n> +\n> +static uint64_t qvtd_get_fl_pte_attrs(bool is_leaf)\n> +{\n> +    /* First-level: x86 page table format (VT-d spec Section 9.9) */\n> +    uint64_t attrs = VTD_FS_P | VTD_FS_RW | VTD_FS_US | VTD_FS_A;\n> +\n> +    if (is_leaf) {\n> +        attrs |= VTD_FS_D;\n> +    }\n> +    return attrs;\n> +}\n> +\n> +void qvtd_setup_translation_tables(QTestState *qts, uint64_t iova,\n> +                                   QVTDTransMode mode)\n> +{\n> +    bool is_fl = (mode == QVTD_TM_SCALABLE_FLT);\n> +    uint64_t non_leaf_attrs, leaf_attrs;\n> +\n> +    if (is_fl) {\n> +        non_leaf_attrs = qvtd_get_fl_pte_attrs(false);\n> +        leaf_attrs = qvtd_get_fl_pte_attrs(true);\n> +    } else {\n> +        /* Second-level: all levels use identical R/W attrs (spec 3.7.1) */\n> +        non_leaf_attrs = qvtd_get_pte_attrs();\n> +        leaf_attrs = non_leaf_attrs;\n> +    }\n> +\n> +    g_test_message(\"Page table setup: IOVA=0x%\" PRIx64\n> +                   \" PA=0x%\" PRIx64 \" %s\",\n> +                   (uint64_t)iova, (uint64_t)QVTD_PT_VAL,\n> +                   is_fl ? \"first-level\" : \"second-level\");\n> +\n> +    /* PML4 (L4) -> PDPT (L3) -> PD (L2) -> PT (L1) -> PA */\n> +    qtest_writeq(qts, qvtd_get_table_addr(QVTD_PT_L4_BASE, 4, iova),\n> +                 QVTD_PT_L3_BASE | non_leaf_attrs);\n> +    qtest_writeq(qts, qvtd_get_table_addr(QVTD_PT_L3_BASE, 3, iova),\n> +                 QVTD_PT_L2_BASE | non_leaf_attrs);\n> +    qtest_writeq(qts, qvtd_get_table_addr(QVTD_PT_L2_BASE, 2, iova),\n> +                 QVTD_PT_L1_BASE | non_leaf_attrs);\n> +    qtest_writeq(qts, qvtd_get_table_addr(QVTD_PT_L1_BASE, 1, iova),\n> +                 (QVTD_PT_VAL & VTD_PAGE_MASK_4K) | leaf_attrs);\n> +}\n> +\n> +void qvtd_program_regs(QTestState *qts, uint64_t iommu_base,\n> +                       QVTDTransMode mode)\n> +{\n> +    uint32_t gcmd = 0;\n> +    uint64_t rtaddr = QVTD_ROOT_TABLE_BASE;\n> +\n> +    /* Set SMT bit for scalable mode (VT-d spec Section 9.1) */\n> +    if (qvtd_is_scalable(mode)) {\n> +        rtaddr |= VTD_RTADDR_SMT;\n> +    }\n> +\n> +    /* Set Root Table Address */\n> +    qtest_writeq(qts, iommu_base + DMAR_RTADDR_REG, rtaddr);\n> +\n> +    /* Set Root Table Pointer and verify */\n> +    gcmd |= VTD_GCMD_SRTP;\n> +    qtest_writel(qts, iommu_base + DMAR_GCMD_REG, gcmd);\n> +    g_assert(qtest_readl(qts, iommu_base + DMAR_GSTS_REG) & VTD_GSTS_RTPS);\n> +\n> +    /* Setup Invalidation Queue */\n> +    qtest_writeq(qts, iommu_base + DMAR_IQA_REG,\n> +                 QVTD_IQ_BASE | QVTD_IQ_QS);\n> +    qtest_writeq(qts, iommu_base + DMAR_IQH_REG, 0);\n> +    qtest_writeq(qts, iommu_base + DMAR_IQT_REG, 0);\n> +\n> +    /* Enable Queued Invalidation and verify */\n> +    gcmd |= VTD_GCMD_QIE;\n> +    qtest_writel(qts, iommu_base + DMAR_GCMD_REG, gcmd);\n> +    g_assert(qtest_readl(qts, iommu_base + DMAR_GSTS_REG) & VTD_GSTS_QIES);\n> +\n> +    /* Setup Fault Event MSI */\n> +    qtest_writel(qts, iommu_base + DMAR_FECTL_REG, 0x0);\n> +    qtest_writel(qts, iommu_base + DMAR_FEDATA_REG, QVTD_FAULT_IRQ_DATA);\n> +    qtest_writel(qts, iommu_base + DMAR_FEADDR_REG, QVTD_FAULT_IRQ_ADDR);\n> +\n> +    /* Enable translation and verify */\n> +    gcmd |= VTD_GCMD_TE;\n> +    qtest_writel(qts, iommu_base + DMAR_GCMD_REG, gcmd);\n> +    g_assert(qtest_readl(qts, iommu_base + DMAR_GSTS_REG) & VTD_GSTS_TES);\n> +}\n> +\n> +uint32_t qvtd_build_translation(QTestState *qts, QVTDTransMode mode,\n> +                                uint16_t sid)\n> +{\n> +    uint8_t bus = (sid >> 8) & 0xff;\n> +\n> +    g_test_message(\"Build translation: IOVA=0x%\" PRIx64 \" PA=0x%\" PRIx64\n> +                   \" mode=%d\",\n> +                   (uint64_t)QVTD_IOVA, (uint64_t)QVTD_PT_VAL, mode);\n> +\n> +    /* Clear IOMMU structure regions to avoid stale entries */\n> +    qtest_memset(qts, QVTD_ROOT_TABLE_BASE, 0, 0x1000);\n> +    qtest_memset(qts, QVTD_PT_L4_BASE, 0, 0x4000);\n> +\n> +    if (qvtd_is_scalable(mode)) {\n> +        /* Scalable: 32B context entries need 8KB */\n> +        qtest_memset(qts, QVTD_CONTEXT_TABLE_BASE, 0, 0x2000);\n> +        qtest_memset(qts, QVTD_PASID_DIR_BASE, 0, 0x1000);\n> +        qtest_memset(qts, QVTD_PASID_TABLE_BASE, 0, 0x1000);\n> +    } else {\n> +        qtest_memset(qts, QVTD_CONTEXT_TABLE_BASE, 0, 0x1000);\n> +    }\n> +\n> +    qvtd_build_root_entry(qts, bus, QVTD_CONTEXT_TABLE_BASE, mode);\n> +\n> +    if (qvtd_is_scalable(mode)) {\n> +        /* Scalable path: context -> PASID dir -> PASID entry -> page tables */\n> +        qvtd_build_scalable_context_entry(qts, sid);\n> +        qvtd_build_pasid_dir_entry(qts);\n> +\n> +        if (mode == QVTD_TM_SCALABLE_PT) {\n> +            qvtd_build_pasid_table_entry(qts, mode, 0);\n> +        } else {\n> +            qvtd_setup_translation_tables(qts, QVTD_IOVA, mode);\n> +            qvtd_build_pasid_table_entry(qts, mode, QVTD_PT_L4_BASE);\n> +        }\n> +    } else {\n> +        /* Legacy path */\n> +        if (mode == QVTD_TM_LEGACY_PT) {\n> +            qvtd_build_context_entry(qts, sid, mode, 0);\n> +        } else {\n> +            qvtd_setup_translation_tables(qts, QVTD_IOVA, mode);\n> +            qvtd_build_context_entry(qts, sid, mode, QVTD_PT_L4_BASE);\n> +        }\n> +    }\n> +\n> +    return 0;\n> +}\n> +\n> +uint32_t qvtd_setup_and_enable_translation(QVTDTestContext *ctx)\n> +{\n> +    uint32_t build_result;\n> +\n> +    /* Build translation structures first */\n> +    build_result = qvtd_build_translation(ctx->qts, ctx->config.trans_mode,\n> +                                          ctx->sid);\n> +    if (build_result != 0) {\n> +        g_test_message(\"Build failed: mode=%u sid=%u status=0x%x\",\n> +                       ctx->config.trans_mode, ctx->sid, build_result);\n> +        ctx->trans_status = build_result;\n> +        return ctx->trans_status;\n> +    }\n> +\n> +    /* Program IOMMU registers (sets root table pointer, enables translation) */\n> +    qvtd_program_regs(ctx->qts, ctx->iommu_base, ctx->config.trans_mode);\n> +\n> +    ctx->trans_status = 0;\n> +    return ctx->trans_status;\n> +}\n> +\n> +static bool qvtd_validate_test_result(QVTDTestContext *ctx)\n> +{\n> +    uint32_t expected = qvtd_expected_dma_result(ctx);\n> +\n> +    g_test_message(\"-> Validating result: expected=0x%x actual=0x%x\",\n> +                   expected, ctx->dma_result);\n> +    return (ctx->dma_result == expected);\n> +}\n> +\n> +static uint32_t qvtd_single_translation_setup(void *opaque)\n> +{\n> +    return qvtd_setup_and_enable_translation(opaque);\n> +}\n> +\n> +static uint32_t qvtd_single_translation_attrs(void *opaque)\n> +{\n> +    return qvtd_build_dma_attrs();\n> +}\n> +\n> +static bool qvtd_single_translation_validate(void *opaque)\n> +{\n> +    return qvtd_validate_test_result(opaque);\n> +}\n> +\n> +static void qvtd_single_translation_report(void *opaque, uint32_t dma_result)\n> +{\n> +    QVTDTestContext *ctx = opaque;\n> +\n> +    if (dma_result != 0) {\n> +        g_test_message(\"DMA failed: mode=%u result=0x%x\",\n> +                       ctx->config.trans_mode, dma_result);\n> +    } else {\n> +        g_test_message(\"-> DMA succeeded: mode=%u\",\n> +                       ctx->config.trans_mode);\n> +    }\n> +}\n> +\n> +void qvtd_run_translation_case(QTestState *qts, QPCIDevice *dev,\n> +                               QPCIBar bar, uint64_t iommu_base,\n> +                               const QVTDTestConfig *cfg)\n> +{\n> +    QVTDTestContext ctx = {\n> +        .qts = qts,\n> +        .dev = dev,\n> +        .bar = bar,\n> +        .iommu_base = iommu_base,\n> +        .config = *cfg,\n> +        .sid = dev->devfn,\n> +    };\n> +\n> +    QOSIOMMUTestdevDmaCfg dma = {\n> +        .dev = dev,\n> +        .bar = bar,\n> +        .iova = QVTD_IOVA,\n> +        .gpa = cfg->dma_gpa,\n> +        .len = cfg->dma_len,\n> +    };\n> +\n> +    qtest_memset(qts, cfg->dma_gpa, 0x00, cfg->dma_len);\n> +    qos_iommu_testdev_single_translation(&dma, &ctx,\n> +                                         qvtd_single_translation_setup,\n> +                                         qvtd_single_translation_attrs,\n> +                                         qvtd_single_translation_validate,\n> +                                         qvtd_single_translation_report,\n> +                                         &ctx.dma_result);\n> +\n> +    if (ctx.dma_result == 0 && ctx.config.expected_result == 0) {\n> +        g_autofree uint8_t *buf = NULL;\n> +\n> +        buf = g_malloc(ctx.config.dma_len);\n> +        qtest_memread(ctx.qts, ctx.config.dma_gpa, buf, ctx.config.dma_len);\n> +\n> +        for (int i = 0; i < ctx.config.dma_len; i++) {\n> +            uint8_t expected;\n> +\n> +            expected = (ITD_DMA_WRITE_VAL >> ((i % 4) * 8)) & 0xff;\n> +            g_assert_cmpuint(buf[i], ==, expected);\n> +        }\n> +    }\n> +}\n> diff --git a/tests/qtest/libqos/qos-intel-iommu.h b/tests/qtest/libqos/qos-intel-iommu.h\n> new file mode 100644\n> index 0000000000..c6cacc5c3f\n> --- /dev/null\n> +++ b/tests/qtest/libqos/qos-intel-iommu.h\n> @@ -0,0 +1,185 @@\n> +/*\n> + * QOS Intel IOMMU (VT-d) Module\n> + *\n> + * This module provides Intel IOMMU-specific helper functions for libqos tests,\n> + * encapsulating VT-d setup, assertion, and cleanup operations.\n> + *\n> + * Copyright (c) 2026 Fengyuan Yu <15fengyuan@gmail.com>\n> + *\n> + * SPDX-License-Identifier: GPL-2.0-or-later\n> + */\n> +\n> +#ifndef QTEST_LIBQOS_INTEL_IOMMU_H\n> +#define QTEST_LIBQOS_INTEL_IOMMU_H\n> +\n> +#include \"hw/misc/iommu-testdev.h\"\n> +#include \"hw/i386/intel_iommu_internal.h\"\n> +\n> +/*\n> + * Guest memory layout for IOMMU structures.\n> + * All structures are placed in guest physical memory inside the 512MB RAM.\n> + * Using 256MB mark (0x10000000) as base to ensure all structures fit in RAM.\n> + */\n> +#define QVTD_MEM_BASE             0x10000000ULL\n> +\n> +/* Root Entry Table: 256 entries * 16 bytes = 4KB */\n> +#define QVTD_ROOT_TABLE_BASE      (QVTD_MEM_BASE + 0x00000000)\n> +\n> +/* Context Entry Table: 256 entries, 16B (legacy) or 32B (scalable) per entry */\n> +#define QVTD_CONTEXT_TABLE_BASE   (QVTD_MEM_BASE + 0x00001000)\n> +\n> +/* Page Tables: 4-level hierarchy for 48-bit address translation */\n> +#define QVTD_PT_L4_BASE           (QVTD_MEM_BASE + 0x00010000)  /* PML4 */\n> +#define QVTD_PT_L3_BASE           (QVTD_MEM_BASE + 0x00011000)  /* PDPT */\n> +#define QVTD_PT_L2_BASE           (QVTD_MEM_BASE + 0x00012000)  /* PD */\n> +#define QVTD_PT_L1_BASE           (QVTD_MEM_BASE + 0x00013000)  /* PT */\n> +\n> +/*\n> + * Invalidation Queue.\n> + * IQA_REG bits[2:0] = QS, entries = 1 << (QS + 8), each entry 16 bytes.\n> + */\n> +#define QVTD_IQ_BASE              (QVTD_MEM_BASE + 0x00020000)\n> +#define QVTD_IQ_QS                0    /* QS=0 → 256 entries */\n> +\n> +/*\n> + * Fault Event MSI configuration.\n> + */\n> +#define QVTD_FAULT_IRQ_ADDR       0xfee00000   /* APIC base */\n> +#define QVTD_FAULT_IRQ_DATA       0x0\n> +\n> +/* Scalable mode PASID structures */\n> +#define QVTD_PASID_DIR_BASE        (QVTD_MEM_BASE + 0x00030000)\n> +#define QVTD_PASID_TABLE_BASE      (QVTD_MEM_BASE + 0x00031000)\n> +\n> +/* Page table entry size (8 bytes per PTE) */\n> +#define QVTD_PTE_SIZE             sizeof(uint64_t)\n> +\n> +/* FSPTPTR mask: same as VTD_SM_PASID_ENTRY_SSPTPTR, bits[63:12] */\n> +#define QVTD_SM_PASID_ENTRY_FSPTPTR   VTD_SM_PASID_ENTRY_SSPTPTR\n> +\n> +/* Default Domain ID for single-domain tests */\n> +#define QVTD_DOMAIN_ID            0\n> +\n> +/* Test IOVA and target physical address */\n> +#define QVTD_IOVA                 0x0000000010200567ull\n> +#define QVTD_PT_VAL               (QVTD_MEM_BASE + 0x00100000)\n> +\n> +/*\n> + * Translation modes supported by Intel IOMMU\n> + */\n> +typedef enum QVTDTransMode {\n> +    QVTD_TM_LEGACY_PT,          /* Legacy pass-through mode */\n> +    QVTD_TM_LEGACY_TRANS,       /* Legacy translated mode (4-level paging) */\n> +    QVTD_TM_SCALABLE_PT,        /* Scalable pass-through mode */\n> +    QVTD_TM_SCALABLE_SLT,       /* Scalable Second Level Translation */\n> +    QVTD_TM_SCALABLE_FLT,       /* Scalable First Level Translation */\n> +} QVTDTransMode;\n> +\n> +static inline bool qvtd_is_scalable(QVTDTransMode mode)\n> +{\n> +    return mode == QVTD_TM_SCALABLE_PT ||\n> +           mode == QVTD_TM_SCALABLE_SLT ||\n> +           mode == QVTD_TM_SCALABLE_FLT;\n> +}\n> +\n> +typedef struct QVTDTestConfig {\n> +    QVTDTransMode trans_mode;     /* Translation mode */\n> +    uint64_t dma_gpa;             /* GPA for readback validation */\n> +    uint32_t dma_len;             /* DMA length for testing */\n> +    uint32_t expected_result;     /* Expected DMA result */\n> +} QVTDTestConfig;\n> +\n> +typedef struct QVTDTestContext {\n> +    QTestState *qts;              /* QTest state handle */\n> +    QPCIDevice *dev;              /* PCI device handle */\n> +    QPCIBar bar;                  /* PCI BAR for MMIO access */\n> +    QVTDTestConfig config;        /* Test configuration */\n> +    uint64_t iommu_base;          /* Intel IOMMU base address */\n> +    uint32_t trans_status;        /* Translation configuration status */\n> +    uint32_t dma_result;          /* DMA operation result */\n> +    uint16_t sid;                 /* Source ID (bus:devfn) */\n> +} QVTDTestContext;\n> +\n> +/*\n> + * qvtd_setup_and_enable_translation - Complete translation setup and enable\n> + *\n> + * @ctx: Test context containing configuration and device handles\n> + *\n> + * Returns: Translation status (0 = success, non-zero = error)\n> + *\n> + * This function performs the complete translation setup sequence:\n> + * 1. Builds VT-d structures (root/context entry, page tables)\n> + * 2. Programs IOMMU registers and enables translation\n> + * 3. Returns configuration status\n> + */\n> +uint32_t qvtd_setup_and_enable_translation(QVTDTestContext *ctx);\n> +\n> +/*\n> + * qvtd_build_translation - Build Intel IOMMU translation structures\n> + *\n> + * @qts: QTest state handle\n> + * @mode: Translation mode (pass-through or translated)\n> + * @sid: Source ID (bus:devfn)\n> + *\n> + * Returns: Build status (0 = success, non-zero = error)\n> + *\n> + * Constructs all necessary VT-d translation structures in guest memory:\n> + * - Root Entry for the device's bus\n> + * - Context Entry for the device\n> + * - Complete 4-level page table hierarchy (if translated mode)\n> + */\n> +uint32_t qvtd_build_translation(QTestState *qts, QVTDTransMode mode,\n> +                                uint16_t sid);\n> +\n> +/*\n> + * qvtd_program_regs - Program Intel IOMMU registers and enable translation\n> + *\n> + * @qts: QTest state handle\n> + * @iommu_base: IOMMU base address\n> + * @mode: Translation mode (scalable modes set RTADDR SMT bit)\n> + *\n> + * Programs IOMMU registers with the following sequence:\n> + * 1. Set root table pointer (SRTP), with SMT bit for scalable mode\n> + * 2. Setup invalidation queue (QIE)\n> + * 3. Configure fault event MSI\n> + * 4. Enable translation (TE)\n> + *\n> + * Each step verifies completion via GSTS register read-back.\n> + */\n> +void qvtd_program_regs(QTestState *qts, uint64_t iommu_base,\n> +                       QVTDTransMode mode);\n> +\n> +/*\n> + * qvtd_setup_translation_tables - Setup complete VT-d page table hierarchy\n> + *\n> + * @qts: QTest state handle\n> + * @iova: Input Virtual Address to translate\n> + * @mode: Translation mode\n> + *\n> + * This builds the 4-level page table structure for translating\n> + * the given IOVA to PA through Intel VT-d. The structure is:\n> + * - PML4 (Level 4): IOVA bits [47:39]\n> + * - PDPT (Level 3): IOVA bits [38:30]\n> + * - PD (Level 2): IOVA bits [29:21]\n> + * - PT (Level 1): IOVA bits [20:12]\n> + * - Page offset: IOVA bits [11:0]\n> + *\n> + * The function writes all necessary Page Table Entries (PTEs) to guest\n> + * memory using qtest_writeq(), setting up the complete translation path\n> + * that the VT-d hardware will traverse during DMA operations.\n> + */\n> +void qvtd_setup_translation_tables(QTestState *qts, uint64_t iova,\n> +                                   QVTDTransMode mode);\n> +\n> +/* Calculate expected DMA result */\n> +uint32_t qvtd_expected_dma_result(QVTDTestContext *ctx);\n> +\n> +/* Build DMA attributes for Intel VT-d */\n> +uint32_t qvtd_build_dma_attrs(void);\n> +\n> +/* High-level test execution helpers */\n> +void qvtd_run_translation_case(QTestState *qts, QPCIDevice *dev,\n> +                               QPCIBar bar, uint64_t iommu_base,\n> +                               const QVTDTestConfig *cfg);\n> +\n> +#endif /* QTEST_LIBQOS_INTEL_IOMMU_H */\n\nReviewed-by: Fabiano Rosas <farosas@suse.de>","headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=suse.de header.i=@suse.de header.a=rsa-sha256\n header.s=susede2_rsa header.b=IUv21nko;\n\tdkim=pass header.d=suse.de header.i=@suse.de header.a=ed25519-sha256\n header.s=susede2_ed25519 header.b=h/0J+Pn2;\n\tdkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de\n header.a=rsa-sha256 header.s=susede2_rsa header.b=IUv21nko;\n\tdkim=neutral header.d=suse.de header.i=@suse.de header.a=ed25519-sha256\n header.s=susede2_ed25519 header.b=h/0J+Pn2;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)","smtp-out2.suse.de;\n dkim=pass header.d=suse.de header.s=susede2_rsa header.b=IUv21nko;\n dkim=pass header.d=suse.de header.s=susede2_ed25519 header.b=\"h/0J+Pn2\""],"Received":["from lists.gnu.org (lists.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fj4br3qsqz1y1x\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 28 Mar 2026 02:40:40 +1100 (AEDT)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1w69I4-0001Bs-PZ; Fri, 27 Mar 2026 11:40:04 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <farosas@suse.de>) id 1w69I3-0001Af-5g\n for qemu-devel@nongnu.org; Fri, 27 Mar 2026 11:40:03 -0400","from smtp-out2.suse.de ([195.135.223.131])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.90_1) (envelope-from <farosas@suse.de>) id 1w69Hz-0000zY-Or\n for qemu-devel@nongnu.org; Fri, 27 Mar 2026 11:40:02 -0400","from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org\n [IPv6:2a07:de40:b281:104:10:150:64:97])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest\n SHA256)\n (No client certificate requested)\n by smtp-out2.suse.de (Postfix) with ESMTPS id AC6D05BD9A;\n Fri, 27 Mar 2026 15:39:57 +0000 (UTC)","from imap1.dmz-prg2.suse.org (localhost [127.0.0.1])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest\n SHA256)\n (No client certificate requested)\n by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 1751F4A0A2;\n Fri, 27 Mar 2026 15:39:56 +0000 (UTC)","from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167])\n by imap1.dmz-prg2.suse.org with ESMTPSA id zk/yNcykxmlwGwAAD6G6ig\n (envelope-from <farosas@suse.de>); Fri, 27 Mar 2026 15:39:56 +0000"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de;\n s=susede2_rsa;\n t=1774625997;\n h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc:\n mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=mf7cU7TgraW1UzFcjlNKkoITFv+WT3LUEhXuLD9ppto=;\n b=IUv21nkokQjxM0Do2Cvm4N9xc5laDupQ9WIe5WyD/TmO+X1F2mc/ZutKSD89TO998l1irF\n apFbnGBc5QsSfpOtKjIhNI6W74kqaXZ8l1PCJNXyQOzbCL+Il8Rx05RsncK6BXMeND8xkm\n 8MvdXEKZVVeBunUjjlso7FEhFJkc32Y=","v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de;\n s=susede2_ed25519; t=1774625997;\n h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc:\n mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=mf7cU7TgraW1UzFcjlNKkoITFv+WT3LUEhXuLD9ppto=;\n b=h/0J+Pn2zPXyiURpQrRgCCS4egQx5yUIdBgahavwn1Qp1yDh7u4PQCpcjNQNSVRkp5Ew/d\n XBylqhJt0wNTQhDQ==","v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de;\n s=susede2_rsa;\n t=1774625997;\n h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc:\n mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=mf7cU7TgraW1UzFcjlNKkoITFv+WT3LUEhXuLD9ppto=;\n b=IUv21nkokQjxM0Do2Cvm4N9xc5laDupQ9WIe5WyD/TmO+X1F2mc/ZutKSD89TO998l1irF\n apFbnGBc5QsSfpOtKjIhNI6W74kqaXZ8l1PCJNXyQOzbCL+Il8Rx05RsncK6BXMeND8xkm\n 8MvdXEKZVVeBunUjjlso7FEhFJkc32Y=","v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de;\n s=susede2_ed25519; t=1774625997;\n h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc:\n mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=mf7cU7TgraW1UzFcjlNKkoITFv+WT3LUEhXuLD9ppto=;\n b=h/0J+Pn2zPXyiURpQrRgCCS4egQx5yUIdBgahavwn1Qp1yDh7u4PQCpcjNQNSVRkp5Ew/d\n XBylqhJt0wNTQhDQ=="],"From":"Fabiano Rosas <farosas@suse.de>","To":"Fengyuan Yu <15fengyuan@gmail.com>, \"Michael S. Tsirkin\" <mst@redhat.com>,\n Jason Wang <jasowang@redhat.com>, Yi Liu <yi.l.liu@intel.com>, =?utf-8?q?Cl?=\n\t=?utf-8?q?=C3=A9ment?= Mathieu--Drif <clement.mathieu--drif@bull.com>,\n Laurent Vivier <lvivier@redhat.com>, Paolo Bonzini <pbonzini@redhat.com>,\n Tao Tang <tangtao1634@phytium.com.cn>","Cc":"qemu-devel@nongnu.org, Chao Liu <chao.liu.zevorn@gmail.com>, Fengyuan Yu\n <15fengyuan@gmail.com>","Subject":"Re: [PATCH v3 1/2] tests/qtest/libqos: Add Intel IOMMU helper library","In-Reply-To":"\n <c4f7bf5d7985891a2db291193669ebe15dd2ba15.1774421649.git.15fengyuan@gmail.com>","References":"<cover.1774421649.git.15fengyuan@gmail.com>\n <c4f7bf5d7985891a2db291193669ebe15dd2ba15.1774421649.git.15fengyuan@gmail.com>","Date":"Fri, 27 Mar 2026 12:39:54 -0300","Message-ID":"<87y0jdgu2d.fsf@suse.de>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Transfer-Encoding":"quoted-printable","X-Spamd-Result":"default: False [-3.01 / 50.00]; BAYES_HAM(-3.00)[100.00%];\n SUSPICIOUS_RECIPS(1.50)[]; NEURAL_HAM_LONG(-1.00)[-1.000];\n R_DKIM_ALLOW(-0.20)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519];\n NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain];\n MX_GOOD(-0.01)[]; TO_MATCH_ENVRCPT_ALL(0.00)[];\n DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519];\n RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[2a07:de40:b281:104:10:150:64:97:from];\n FUZZY_RATELIMITED(0.00)[rspamd.com]; TO_DN_SOME(0.00)[];\n FREEMAIL_TO(0.00)[gmail.com,redhat.com,intel.com,bull.com,phytium.com.cn];\n MIME_TRACE(0.00)[0:+]; ARC_NA(0.00)[];\n FREEMAIL_ENVRCPT(0.00)[gmail.com]; RCVD_TLS_ALL(0.00)[];\n SPAMHAUS_XBL(0.00)[2a07:de40:b281:104:10:150:64:97:from];\n RCVD_COUNT_TWO(0.00)[2]; MID_RHS_MATCH_FROM(0.00)[];\n FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[];\n FREEMAIL_CC(0.00)[nongnu.org,gmail.com];\n RCPT_COUNT_SEVEN(0.00)[11]; TAGGED_RCPT(0.00)[];\n DKIM_TRACE(0.00)[suse.de:+];\n RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[2a07:de40:b281:106:10:150:64:167:received];\n MISSING_XM_UA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[];\n DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:mid, suse.de:dkim, suse.de:email,\n imap1.dmz-prg2.suse.org:helo, imap1.dmz-prg2.suse.org:rdns]","X-Rspamd-Action":"no action","X-Spam-Score":"-3.01","X-Rspamd-Server":"rspamd1.dmz-prg2.suse.org","X-Rspamd-Queue-Id":"AC6D05BD9A","Received-SPF":"pass client-ip=195.135.223.131; envelope-from=farosas@suse.de;\n helo=smtp-out2.suse.de","X-Spam_score_int":"-43","X-Spam_score":"-4.4","X-Spam_bar":"----","X-Spam_report":"(-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001,\n RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001,\n SPF_PASS=-0.001 autolearn=ham autolearn_force=no","X-Spam_action":"no action","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"qemu development <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"}},{"id":3670962,"web_url":"http://patchwork.ozlabs.org/comment/3670962/","msgid":"<7440519b-bc64-49f7-aa35-32b607817739@phytium.com.cn>","list_archive_url":null,"date":"2026-03-30T09:09:18","subject":"Re: [PATCH v3 1/2] tests/qtest/libqos: Add Intel IOMMU helper library","submitter":{"id":91412,"url":"http://patchwork.ozlabs.org/api/people/91412/","name":"Tao Tang","email":"tangtao1634@phytium.com.cn"},"content":"Hi Fengyuan,\n\nOn 2026/3/25 15:09, Fengyuan Yu wrote:\n> Introduce a libqos helper module for Intel IOMMU (VT-d) bare-metal\n> testing via iommu-testdev. The helper provides routines to:\n>\n> - Build Legacy-mode structures: Root Entry Tables, Context Entry Tables,\n>    and 4-level page tables for 48-bit address translation\n> - Build Scalable-mode structures: Scalable Context Entries, PASID\n>    Directory Entries, PASID Table Entries, and 4-level page tables for\n>    both second-level and first-level translation\n> - Program VT-d registers (Root Table Address, Invalidation Queue,\n>    Fault Event MSI, Global Command) following the VT-d specification,\n>    with GSTS read-back verification for each step\n> - Execute DMA translations through iommu-testdev and verify results\n>    by reading back guest memory\n>\n> The module supports all major VT-d translation modes through the\n> QVTDTransMode enum:\n> - Legacy pass-through\n> - Legacy translated with 4-level paging\n> - Scalable pass-through\n> - Scalable Second-Level Translation\n> - Scalable First-Level Translation\n>\n> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>\n> Signed-off-by: Fengyuan Yu <15fengyuan@gmail.com>\n\nReviewed-by: Tao Tang <tangtao1634@phytium.com.cn>","headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)","hzbj-icmmx-6; spf=neutral smtp.mail=tangtao163\n 4@phytium.com.cn;"],"Received":["from lists.gnu.org (lists.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fklnX04sBz1yGH\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 30 Mar 2026 20:09:52 +1100 (AEDT)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1w78cy-0004w8-9i; Mon, 30 Mar 2026 05:09:44 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <tangtao1634@phytium.com.cn>)\n id 1w78cv-0004oo-Dn\n for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:09:41 -0400","from zg8tmtyylji0my4xnjqumte4.icoremail.net ([162.243.164.118])\n by eggs.gnu.org with esmtp (Exim 4.90_1)\n (envelope-from <tangtao1634@phytium.com.cn>) id 1w78cr-000088-R3\n for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:09:41 -0400","from prodtpl.icoremail.net (unknown [10.12.1.20])\n by hzbj-icmmx-6 (Coremail) with SMTP id AQAAfwDXj2fDPcppGOw3AA--.22250S2;\n Mon, 30 Mar 2026 17:09:23 +0800 (CST)","from [10.31.91.158] (unknown [218.76.62.144])\n by mail (Coremail) with SMTP id AQAAf8DwwJO+PcppYm0HAA--.17633S2;\n Mon, 30 Mar 2026 17:09:18 +0800 (CST)"],"Message-ID":"<7440519b-bc64-49f7-aa35-32b607817739@phytium.com.cn>","Date":"Mon, 30 Mar 2026 17:09:18 +0800","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v3 1/2] tests/qtest/libqos: Add Intel IOMMU helper library","To":"Fengyuan Yu <15fengyuan@gmail.com>, \"Michael S. Tsirkin\" <mst@redhat.com>,\n Jason Wang <jasowang@redhat.com>, Yi Liu <yi.l.liu@intel.com>, =?utf-8?q?Cl?=\n\t=?utf-8?q?=C3=A9ment_Mathieu--Drif?= <clement.mathieu--drif@bull.com>,\n Fabiano Rosas <farosas@suse.de>, Laurent Vivier <lvivier@redhat.com>,\n Paolo Bonzini <pbonzini@redhat.com>","Cc":"qemu-devel@nongnu.org, Chao Liu <chao.liu.zevorn@gmail.com>","References":"<cover.1774421649.git.15fengyuan@gmail.com>\n <c4f7bf5d7985891a2db291193669ebe15dd2ba15.1774421649.git.15fengyuan@gmail.com>","From":"Tao Tang <tangtao1634@phytium.com.cn>","In-Reply-To":"\n <c4f7bf5d7985891a2db291193669ebe15dd2ba15.1774421649.git.15fengyuan@gmail.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","X-CM-TRANSID":"AQAAf8DwwJO+PcppYm0HAA--.17633S2","X-CM-SenderInfo":"pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQAKBWnJfH8DswAAsd","X-Coremail-Antispam":"1Uk129KBjvJXoW7JFWxZF15XFWUKw43uFW8tFb_yoW8JrW8pa\n y8Gryrtayvyr12kr1kWw40qFyrKay8Ka17Zw4UGwnxAwn3KrW0yr1Uta4qgayrur4rXF15\n Xa1qyr47XayktrDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj\n DUYxn0WfASr-VFAU7a7-sFnT9fnUUIcSsGvfJ3UbIYCTnIWIevJa73UjIFyTuYvj4RJUUU\n UUUUU","Received-SPF":"pass client-ip=162.243.164.118;\n envelope-from=tangtao1634@phytium.com.cn;\n helo=zg8tmtyylji0my4xnjqumte4.icoremail.net","X-Spam_score_int":"-5","X-Spam_score":"-0.6","X-Spam_bar":"/","X-Spam_report":"(-0.6 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7,\n RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=1, RCVD_IN_VALIDITY_RPBL_BLOCKED=1,\n SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no","X-Spam_action":"no action","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"qemu development <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"}}]