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;