On 4/30/26 15:12, Zhenzhong Duan wrote:
When both device and vIOMMU have PASID enabled, then guest may setup
pasid attached translation.

s/pasid attached translation/pasid usages such as SVM/

VFIO needs to be aware of potential pasid usage and should attach the
non-pasid part of pasid-capable device to hwpt flagged with
IOMMU_HWPT_ALLOC_PASID.

ARM SMMU doesn't support IOMMU_HWPT_ALLOC_PASID, only VTD need it. So
we can't check the existing vIOMMU flag VIOMMU_FLAG_PASID_SUPPORTED to
determine if set flag IOMMU_HWPT_ALLOC_PASID. Instead, introduce a new
flag VIOMMU_FLAG_WANT_PASID_ATTACH which will only be exposed by VTD.

Opportunistically add documentation for VIOMMU_FLAG_PASID_SUPPORTED
and explain the difference with VIOMMU_FLAG_WANT_PASID_ATTACH.

Signed-off-by: Zhenzhong Duan <[email protected]>
Reviewed-by: Yi Liu <[email protected]>
Tested-by: Xudong Hao <[email protected]>
---
  include/hw/core/iommu.h       | 11 +++++++++++
  include/hw/vfio/vfio-device.h |  1 +
  hw/vfio/device.c              | 11 +++++++++++
  hw/vfio/iommufd.c             |  8 +++++++-
  4 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/include/hw/core/iommu.h b/include/hw/core/iommu.h
index 77739d4214..20d6d79062 100644
--- a/include/hw/core/iommu.h
+++ b/include/hw/core/iommu.h
@@ -20,9 +20,20 @@
  enum viommu_flags {
      /* vIOMMU needs nesting parent HWPT to create nested HWPT */
      VIOMMU_FLAG_WANT_NESTING_PARENT = BIT_ULL(0),
+    /*
+     * vIOMMU supports PASID capability, VFIO checks this flag and synthesize
+     * a PASID capability.
+     */
      VIOMMU_FLAG_PASID_SUPPORTED = BIT_ULL(1),
      /* vIOMMU needs dirty tracking on the nesting parent HWPT for nested use 
*/
      VIOMMU_FLAG_WANT_NESTING_DIRTY_TRACKING = BIT_ULL(2),
+    /*
+     * vIOMMU requests other sub-system like VFIO to create a HWPT that can be
+     * used with PASID attachment. VIOMMU_FLAG_PASID_SUPPORTED can't be used
+     * for this purpose as PASID attachment is needed by VTD IOMMU but not ARM
+     * SMMU.
+     */
+    VIOMMU_FLAG_WANT_PASID_ATTACH = BIT_ULL(3),

instead of having a flag, is there any chance to let vfio check the
struct iommu_hw_info::type? It appears that only
IOMMU_HW_INFO_TYPE_INTEL_VTD has explicit pasid attach.

  };
/* Host IOMMU quirks. Extracted from host IOMMU capabilities */
diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
index 380a55d6e5..8472420d3f 100644
--- a/include/hw/vfio/vfio-device.h
+++ b/include/hw/vfio/vfio-device.h
@@ -282,6 +282,7 @@ void vfio_device_unprepare(VFIODevice *vbasedev);
bool vfio_device_get_viommu_flags_want_nesting(VFIODevice *vbasedev);
  bool vfio_device_get_viommu_flags_want_nesting_dirty(VFIODevice *vbasedev);
+bool vfio_device_get_viommu_flags_want_pasid_attach(VFIODevice *vbasedev);
  bool vfio_device_get_host_iommu_quirk_bypass_ro(VFIODevice *vbasedev,
                                                  uint32_t type, void *caps,
                                                  uint32_t size);
diff --git a/hw/vfio/device.c b/hw/vfio/device.c
index 3ffd69a579..b954b44d31 100644
--- a/hw/vfio/device.c
+++ b/hw/vfio/device.c
@@ -544,6 +544,17 @@ bool vfio_device_get_viommu_flags_want_nesting(VFIODevice 
*vbasedev)
      return false;
  }
+bool vfio_device_get_viommu_flags_want_pasid_attach(VFIODevice *vbasedev)
+{
+    VFIOPCIDevice *vdev = vfio_pci_from_vfio_device(vbasedev);
+
+    if (vdev) {
+        return !!(pci_device_get_viommu_flags(PCI_DEVICE(vdev)) &
+                  VIOMMU_FLAG_WANT_PASID_ATTACH);
+    }
+    return false;
+}
+
  bool vfio_device_get_host_iommu_quirk_bypass_ro(VFIODevice *vbasedev,
                                                  uint32_t type, void *caps,
                                                  uint32_t size)
diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c
index 78e7b6a045..0718f029ca 100644
--- a/hw/vfio/iommufd.c
+++ b/hw/vfio/iommufd.c
@@ -364,6 +364,7 @@ static bool iommufd_cdev_autodomains_get(VFIODevice 
*vbasedev,
      VendorCaps caps;
      VFIOIOASHwpt *hwpt;
      uint32_t hwpt_id;
+    uint8_t max_pasid_log2 = 0;
      int ret;
/* Try to find a domain */
@@ -409,7 +410,7 @@ static bool iommufd_cdev_autodomains_get(VFIODevice 
*vbasedev,
       */
      if (!iommufd_backend_get_device_info(vbasedev->iommufd, vbasedev->devid,
                                           &type, &caps, sizeof(caps), &hw_caps,
-                                         NULL, errp)) {
+                                         &max_pasid_log2, errp)) {
          return false;
      }
@@ -437,6 +438,11 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev,
          }
      }
+ if (max_pasid_log2 &&
+        vfio_device_get_viommu_flags_want_pasid_attach(vbasedev)) {
+        flags |= IOMMU_HWPT_ALLOC_PASID;
+    }
+
      if (cpr_is_incoming()) {
          hwpt_id = vbasedev->cpr.hwpt_id;
          goto skip_alloc;


Reply via email to