[PATCH v3 03/14] vfio/iommufd: Create nesting parent hwpt with IOMMU_HWPT_ALLOC_PASID flag

Zhenzhong Duan posted 14 patches 1 week, 1 day ago
[PATCH v3 03/14] vfio/iommufd: Create nesting parent hwpt with IOMMU_HWPT_ALLOC_PASID flag
Posted by Zhenzhong Duan 1 week, 1 day ago
When both device and vIOMMU have PASID enabled, then guest may setup
pasid attached translation.

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.

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>
---
 include/hw/core/iommu.h       |  1 +
 include/hw/vfio/vfio-device.h |  1 +
 hw/vfio/device.c              | 11 +++++++++++
 hw/vfio/iommufd.c             |  8 +++++++-
 4 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/include/hw/core/iommu.h b/include/hw/core/iommu.h
index bfcd511013..67c575b08c 100644
--- a/include/hw/core/iommu.h
+++ b/include/hw/core/iommu.h
@@ -21,6 +21,7 @@ enum viommu_flags {
     /* vIOMMU needs nesting parent HWPT to create nested HWPT */
     VIOMMU_FLAG_WANT_NESTING_PARENT = BIT_ULL(0),
     VIOMMU_FLAG_PASID_SUPPORTED = BIT_ULL(1),
+    VIOMMU_FLAG_WANT_PASID_ATTACH = BIT_ULL(2),
 };
 
 /* 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 828a31c006..d6e522f8b8 100644
--- a/include/hw/vfio/vfio-device.h
+++ b/include/hw/vfio/vfio-device.h
@@ -268,6 +268,7 @@ void vfio_device_prepare(VFIODevice *vbasedev, VFIOContainer *bcontainer,
 void vfio_device_unprepare(VFIODevice *vbasedev);
 
 bool vfio_device_get_viommu_flags_want_nesting(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 973fc35b59..bc1d37e776 100644
--- a/hw/vfio/device.c
+++ b/hw/vfio/device.c
@@ -533,6 +533,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 ecabc33064..ead40b6617 100644
--- a/hw/vfio/iommufd.c
+++ b/hw/vfio/iommufd.c
@@ -363,6 +363,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 */
@@ -408,7 +409,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;
     }
 
@@ -430,6 +431,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;
-- 
2.47.3
Re: [PATCH v3 03/14] vfio/iommufd: Create nesting parent hwpt with IOMMU_HWPT_ALLOC_PASID flag
Posted by Cédric Le Goater 1 week, 1 day ago
Hello Zhenzhong

On 4/3/26 05:55, Zhenzhong Duan wrote:
> When both device and vIOMMU have PASID enabled, then guest may setup
> pasid attached translation.
> 
> 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.
> 
> 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>
> ---
>   include/hw/core/iommu.h       |  1 +
>   include/hw/vfio/vfio-device.h |  1 +
>   hw/vfio/device.c              | 11 +++++++++++
>   hw/vfio/iommufd.c             |  8 +++++++-
>   4 files changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/include/hw/core/iommu.h b/include/hw/core/iommu.h
> index bfcd511013..67c575b08c 100644
> --- a/include/hw/core/iommu.h
> +++ b/include/hw/core/iommu.h
> @@ -21,6 +21,7 @@ enum viommu_flags {
>       /* vIOMMU needs nesting parent HWPT to create nested HWPT */
>       VIOMMU_FLAG_WANT_NESTING_PARENT = BIT_ULL(0),
>       VIOMMU_FLAG_PASID_SUPPORTED = BIT_ULL(1),
> +    VIOMMU_FLAG_WANT_PASID_ATTACH = BIT_ULL(2),

VIOMMU_FLAG_WANT_NESTING_DIRTY_TRACKING was introduced since. The change
is on vfio-next.

You will need to rebase. While at it, I think the documentation of each
of these VIOMMU_FLAGs can be improved.

Thanks,

C.


>   };
>   
>   /* 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 828a31c006..d6e522f8b8 100644
> --- a/include/hw/vfio/vfio-device.h
> +++ b/include/hw/vfio/vfio-device.h
> @@ -268,6 +268,7 @@ void vfio_device_prepare(VFIODevice *vbasedev, VFIOContainer *bcontainer,
>   void vfio_device_unprepare(VFIODevice *vbasedev);
>   
>   bool vfio_device_get_viommu_flags_want_nesting(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 973fc35b59..bc1d37e776 100644
> --- a/hw/vfio/device.c
> +++ b/hw/vfio/device.c
> @@ -533,6 +533,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 ecabc33064..ead40b6617 100644
> --- a/hw/vfio/iommufd.c
> +++ b/hw/vfio/iommufd.c
> @@ -363,6 +363,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 */
> @@ -408,7 +409,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;
>       }
>   
> @@ -430,6 +431,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;
RE: [PATCH v3 03/14] vfio/iommufd: Create nesting parent hwpt with IOMMU_HWPT_ALLOC_PASID flag
Posted by Duan, Zhenzhong 4 days, 16 hours ago
Hello Cédric,

>-----Original Message-----
>From: Cédric Le Goater <clg@redhat.com>

>Subject: Re: [PATCH v3 03/14] vfio/iommufd: Create nesting parent hwpt with
>IOMMU_HWPT_ALLOC_PASID flag
>
>Hello Zhenzhong
>
>On 4/3/26 05:55, Zhenzhong Duan wrote:
>> When both device and vIOMMU have PASID enabled, then guest may setup
>> pasid attached translation.
>>
>> 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.
>>
>> 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>
>> ---
>>   include/hw/core/iommu.h       |  1 +
>>   include/hw/vfio/vfio-device.h |  1 +
>>   hw/vfio/device.c              | 11 +++++++++++
>>   hw/vfio/iommufd.c             |  8 +++++++-
>>   4 files changed, 20 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/hw/core/iommu.h b/include/hw/core/iommu.h
>> index bfcd511013..67c575b08c 100644
>> --- a/include/hw/core/iommu.h
>> +++ b/include/hw/core/iommu.h
>> @@ -21,6 +21,7 @@ enum viommu_flags {
>>       /* vIOMMU needs nesting parent HWPT to create nested HWPT */
>>       VIOMMU_FLAG_WANT_NESTING_PARENT = BIT_ULL(0),
>>       VIOMMU_FLAG_PASID_SUPPORTED = BIT_ULL(1),
>> +    VIOMMU_FLAG_WANT_PASID_ATTACH = BIT_ULL(2),
>
>VIOMMU_FLAG_WANT_NESTING_DIRTY_TRACKING was introduced since. The
>change
>is on vfio-next.
>
>You will need to rebase. While at it, I think the documentation of each
>of these VIOMMU_FLAGs can be improved.

Sure, will do.

BRs,
Zhenzhong