@samitouri / QOSamiQemu / commits / 8c12118f7b

vfio/iommufd: Create nesting parent hwpt with IOMMU_HWPT_ALLOC_PASID flag

When both device and vIOMMU have PASID enabled, then guest may setup 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 <zhenzhong.duan@intel.com> Reviewed-by: Yi Liu <yi.l.liu@intel.com> Tested-by: Xudong Hao <xudong.hao@intel.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Message-Id: <20260527054658.1021096-4-zhenzhong.duan@intel.com> Reviewed-by: Shameer Kolothum <skolothumtho@nvidia.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

Zhenzhong Duan committed May 27, 2026 at 01:46 UTC 8c12118f7bad41cd544803f23da323d2cb61dae7
4 files changed +30 -1
hw/vfio/device.c
+11
@@ -543,6 +543,17 @@ bool vfio_device_get_viommu_flags_want_nesting(VFIODevice *vbasedev)
543 return false;
544 }
545
546 +bool vfio_device_get_viommu_flags_want_pasid_attach(VFIODevice *vbasedev)
547 +{
548 + VFIOPCIDevice *vdev = vfio_pci_from_vfio_device(vbasedev);
549 +
550 + if (vdev) {
551 + return !!(pci_device_get_viommu_flags(PCI_DEVICE(vdev)) &
552 + VIOMMU_FLAG_WANT_PASID_ATTACH);
553 + }
554 + return false;
555 +}
556 +
557 bool vfio_device_get_host_iommu_quirk_bypass_ro(VFIODevice *vbasedev,
558 uint32_t type, void *caps,
559 uint32_t size)
hw/vfio/iommufd.c
+7 -1
@@ -364,6 +364,7 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev,
364 VendorCaps caps;
365 VFIOIOASHwpt *hwpt;
366 uint32_t hwpt_id;
367 + uint8_t max_pasid_log2 = 0;
368 int ret;
369
370 /* Try to find a domain */
@@ -409,7 +410,7 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev,
410 */
411 if (!iommufd_backend_get_device_info(vbasedev->iommufd, vbasedev->devid,
412 &type, &caps, sizeof(caps), &hw_caps,
412 - NULL, errp)) {
413 + &max_pasid_log2, errp)) {
414 return false;
415 }
416
@@ -437,6 +438,11 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev,
438 }
439 }
440
441 + if (max_pasid_log2 &&
442 + vfio_device_get_viommu_flags_want_pasid_attach(vbasedev)) {
443 + flags |= IOMMU_HWPT_ALLOC_PASID;
444 + }
445 +
446 if (cpr_is_incoming()) {
447 hwpt_id = vbasedev->cpr.hwpt_id;
448 goto skip_alloc;
include/hw/core/iommu.h
+11
@@ -20,9 +20,20 @@
20 enum viommu_flags {
21 /* vIOMMU needs nesting parent HWPT to create nested HWPT */
22 VIOMMU_FLAG_WANT_NESTING_PARENT = BIT_ULL(0),
23 + /*
24 + * vIOMMU supports PASID capability, VFIO checks this flag and synthesize
25 + * a PASID capability.
26 + */
27 VIOMMU_FLAG_PASID_SUPPORTED = BIT_ULL(1),
28 /* vIOMMU needs dirty tracking on the nesting parent HWPT for nested use */
29 VIOMMU_FLAG_WANT_NESTING_DIRTY_TRACKING = BIT_ULL(2),
30 + /*
31 + * vIOMMU requests other sub-system like VFIO to create a HWPT that can be
32 + * used with PASID attachment. VIOMMU_FLAG_PASID_SUPPORTED can't be used
33 + * for this purpose as PASID attachment is needed by VTD IOMMU but not ARM
34 + * SMMU.
35 + */
36 + VIOMMU_FLAG_WANT_PASID_ATTACH = BIT_ULL(3),
37 };
38
39 /* Host IOMMU quirks. Extracted from host IOMMU capabilities */
include/hw/vfio/vfio-device.h
+1
@@ -282,6 +282,7 @@ void vfio_device_unprepare(VFIODevice *vbasedev);
282
283 bool vfio_device_get_viommu_flags_want_nesting(VFIODevice *vbasedev);
284 bool vfio_device_get_viommu_flags_want_nesting_dirty(VFIODevice *vbasedev);
285 +bool vfio_device_get_viommu_flags_want_pasid_attach(VFIODevice *vbasedev);
286 bool vfio_device_get_host_iommu_quirk_bypass_ro(VFIODevice *vbasedev,
287 uint32_t type, void *caps,
288 uint32_t size);