Hi Eric,

On 2026/1/17 18:02, Eric Auger wrote:
Hi Tao,

On 12/24/25 4:46 AM, Tao Tang wrote:
Introduce qos-smmuv3, a reusable library for SMMUv3-related qtest
operations. This module encapsulates common tasks like:

- SMMUv3 initialization (enabling, configuring command/event queues)
- Stream Table Entry (STE) and Context Descriptor (CD) setup
- Multi-level page table construction (L0-L3 for 4KB granules)
- Support for Stage 1, Stage 2, and nested translation modes
- Could be easily extended to support multi-space testing infrastructure
     (Non-Secure, Secure, Root, Realm)

The library provides high-level abstractions that allow test code to
focus on IOMMU behavior validation rather than low-level register
manipulation and page table encoding. Key features include:

- Provide memory allocation for translation structures with proper
     alignment
- Helper functions to build valid STEs/CDs for different translation
     scenarios
- Page table walkers that handle address offset calculations per
     security space

This infrastructure is designed to be used by iommu-testdev-based tests
and future SMMUv3 test suites, reducing code duplication and improving
test maintainability.

Signed-off-by: Tao Tang<[email protected]>
Reviewed-by: Pierrick Bouvier<[email protected]>
Reviewed-by: Fabiano Rosas<[email protected]>
---
  MAINTAINERS                     |   6 +
  tests/qtest/libqos/meson.build  |   3 +
  tests/qtest/libqos/qos-smmuv3.c | 633 ++++++++++++++++++++++++++++++++
  tests/qtest/libqos/qos-smmuv3.h | 256 +++++++++++++
  4 files changed, 898 insertions(+)
  create mode 100644 tests/qtest/libqos/qos-smmuv3.c
  create mode 100644 tests/qtest/libqos/qos-smmuv3.h

------------------------------<snip>------------------------------



------------------------------<snip>------------------------------
+
+uint32_t qsmmu_trigger_dma(QSMMUTestContext *ctx)
qsmmu_trigger_dma and  qsmmu_single_translation  helpers which do not really 
relate to SMMU but rather relate to the pci
test dev. put them in a specific section of this file or move them in a
separate file. They could be reused by other non SMMU specific tests


Agreed — that’s a better separation. I’ll move these two helpers out of qos-smmuv3 into a generic libqos helper (something like qos-iommu-testdev.[ch]).


+{
+    uint32_t result, attrs_val;
+
+    /* Program DMA parameters */
+    qpci_io_writel(ctx->dev, ctx->bar, ITD_REG_DMA_GVA_LO,
+                   (uint32_t)ctx->config.dma_iova);
+    qpci_io_writel(ctx->dev, ctx->bar, ITD_REG_DMA_GVA_HI,
+                   (uint32_t)(ctx->config.dma_iova >> 32));
+    qpci_io_writel(ctx->dev, ctx->bar, ITD_REG_DMA_LEN,
+                   ctx->config.dma_len);
+
+    /* Build and write DMA attributes based on device security state. */
+    attrs_val = qsmmu_build_dma_attrs(QSMMU_SPACE_NONSECURE);
+    qpci_io_writel(ctx->dev, ctx->bar, ITD_REG_DMA_ATTRS, attrs_val);
+
+    /* Flip status */
+    /* Arm iommu-testdev so the next read triggers DMA */
+    qpci_io_writel(ctx->dev, ctx->bar, ITD_REG_DMA_DBELL, ITD_DMA_DBELL_ARM);
+
+    /* Trigger DMA */
+    qpci_io_readl(ctx->dev, ctx->bar, ITD_REG_DMA_TRIGGERING);
+
+    /* Poll for DMA completion */
+    for (int i = 0; i < 1000; i++) {
+        result = qpci_io_readl(ctx->dev, ctx->bar, ITD_REG_DMA_RESULT);
+        if (result != ITD_DMA_RESULT_BUSY) {
+            ctx->dma_result = result;
+            break;
+        }
+        g_usleep(1000);
+    }
+
+    /* Fallback for timeout */
+    if (ctx->dma_result == ITD_DMA_RESULT_BUSY) {
+        ctx->dma_result = ITD_DMA_ERR_TX_FAIL;
+    }
+
+    return ctx->dma_result;
+}
+
+bool qsmmu_validate_test_result(QSMMUTestContext *ctx)
+{
+    uint32_t expected = qsmmu_expected_dma_result(ctx);
+    g_test_message("-> Validating result: expected=0x%x actual=0x%x",
+                   expected, ctx->dma_result);
+    return (ctx->dma_result == expected);
+}
+
+QSMMUSpace qsmmu_sec_sid_to_space(QSMMUSecSID sec_sid)
+{
+    switch (sec_sid) {
+    case QSMMU_SEC_SID_NONSECURE:
+        return QSMMU_SPACE_NONSECURE;
+    default:
+        g_assert_not_reached();
+    }
+}
+
+uint64_t qsmmu_space_offset(QSMMUSpace sp)
+{
+    switch (sp) {
+    case QSMMU_SPACE_NONSECURE:
+        return QSMMU_SPACE_OFFS_NS;
+    default:
+        g_assert_not_reached();
+    }
+}
+
+void qsmmu_single_translation(QSMMUTestContext *ctx)
+{
+    uint32_t config_result;
+    uint32_t dma_result;
+
+    /* Configure SMMU translation */
+    config_result = qsmmu_setup_and_enable_translation(ctx);
+    g_assert_cmpuint(config_result, ==, 0);
+
+    /* Trigger DMA operation */
+    dma_result = qsmmu_trigger_dma(ctx);
+    if (dma_result != 0) {
+        g_test_message("DMA failed: mode=%u result=0x%x",
+                       ctx->config.trans_mode, dma_result);
+    } else {
+        g_test_message("-> DMA succeeded: mode=%u", ctx->config.trans_mode);
+    }
+
+    /* Validate test result */
+    g_assert_true(qsmmu_validate_test_result(ctx));
+}
+
------------------------------<snip>------------------------------



------------------------------<snip>------------------------------
diff --git a/tests/qtest/libqos/qos-smmuv3.h b/tests/qtest/libqos/qos-smmuv3.h
new file mode 100644
index 0000000000..375778517f
--- /dev/null
+++ b/tests/qtest/libqos/qos-smmuv3.h
@@ -0,0 +1,256 @@
+/*
+ * QOS SMMUv3 Module
+ *
+ * This module provides SMMUv3-specific helper functions for libqos tests,
+ * encapsulating SMMUv3 setup, and assertions.
+ *
+ * Copyright (c) 2025 Phytium Technology
+ *
+ * Author:
+ *  Tao Tang<[email protected]>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef QTEST_LIBQOS_SMMUV3_H
+#define QTEST_LIBQOS_SMMUV3_H
+
+#include "hw/misc/iommu-testdev.h"
+
+/*
+ * SMMU MMIO register base. We hardcode this as base_memmap is 'static const'
+ * in hw/arm/virt.c and not directly accessible here.
+ */
+#define VIRT_SMMU_BASE            0x0000000009050000ull
+
+/* SMMU queue and table base addresses */
+#define QSMMU_CMDQ_BASE_ADDR      0x000000000e16b000ull
+#define QSMMU_EVENTQ_BASE_ADDR    0x000000000e170000ull
+
+/*
+ * Translation tables and descriptors for a mapping of
+ *   - IOVA(Stage 1 only)
you mentionned you also support S1 + S2

Yes there should be `- IOVA(Stage 1 and nested translation stage)`.


+ *   - IPA (Stage 2 only)
+ * to GPA.
+ *
+ * The translation is based on the Arm architecture with the following
+ * prerequisites:
+ * - Granule size: 4KB pages.
would be nice to support 64kB as well in the future. Can be done later
though.
+ * - Page table levels: 4 levels (L0, L1, L2, L3), starting at level 0.
+ * - IOVA size: The walk resolves a IOVA: 0x8080604567
well this is passed as a test config parameter and this is does not
sound relevant to hardcode it.


I initially wanted dma_iova to be configurable and have the page-table builder follow it, but I didn’t find a clean way to keep the table construction in sync.

So for now I’ll likely drop QSMMUTestConfig.dma_iova and consistently use the fixed QSMMU_IOVA for both table setup and DMA, to avoid a misleading knob. We can revisit later to make IOVA + tables configurable, and potentially add 64KB granule support as well.


Thanks,
Tao


Reply via email to