[PATCH v4 10/27] hw/arm/smmuv3-accel: Allocate a vDEVICE object for device

Shameer Kolothum posted 27 patches 1 month, 2 weeks ago
There is a newer version of this series
[PATCH v4 10/27] hw/arm/smmuv3-accel: Allocate a vDEVICE object for device
Posted by Shameer Kolothum 1 month, 2 weeks ago
From: Nicolin Chen <nicolinc@nvidia.com>

Allocate and associate a vDEVICE object for the Guest device with the
vIOMMU. This will help the host kernel to make a virtual SID --> physical
SID mapping. Since we pass the raw invalidation commands(eg: CMD_CFGI_CD)
from Guest directly to host kernel, this provides a way to retrieve the
correct physical SID.

Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com>
---
 hw/arm/smmuv3-accel.c | 41 +++++++++++++++++++++++++++++++++++++++++
 hw/arm/smmuv3-accel.h |  1 +
 2 files changed, 42 insertions(+)

diff --git a/hw/arm/smmuv3-accel.c b/hw/arm/smmuv3-accel.c
index 5c3825cecd..790887ac31 100644
--- a/hw/arm/smmuv3-accel.c
+++ b/hw/arm/smmuv3-accel.c
@@ -39,6 +39,35 @@
 #define STE1_MASK     (STE1_ETS | STE1_S1STALLD | STE1_S1CSH | STE1_S1COR | \
                        STE1_S1CIR | STE1_S1DSS)
 
+static bool
+smmuv3_accel_alloc_vdev(SMMUv3AccelDevice *accel_dev, int sid, Error **errp)
+{
+    SMMUViommu *viommu = accel_dev->viommu;
+    IOMMUFDVdev *vdev;
+    uint32_t vdev_id;
+
+    if (!accel_dev->idev || accel_dev->vdev) {
+        return true;
+    }
+
+    if (!iommufd_backend_alloc_vdev(viommu->iommufd, accel_dev->idev->devid,
+                                   viommu->core.viommu_id, sid,
+                                   &vdev_id, errp)) {
+            return false;
+    }
+    if (!host_iommu_device_iommufd_attach_hwpt(accel_dev->idev,
+                                               viommu->bypass_hwpt_id, errp)) {
+        iommufd_backend_free_id(viommu->iommufd, vdev_id);
+        return false;
+    }
+
+    vdev = g_new(IOMMUFDVdev, 1);
+    vdev->vdev_id = vdev_id;
+    vdev->dev_id = sid;
+    accel_dev->vdev = vdev;
+    return true;
+}
+
 static bool
 smmuv3_accel_dev_uninstall_nested_ste(SMMUv3AccelDevice *accel_dev, bool abort,
                                       Error **errp)
@@ -127,6 +156,10 @@ smmuv3_accel_install_nested_ste(SMMUv3State *s, SMMUDevice *sdev, int sid,
         return true;
     }
 
+    if (!smmuv3_accel_alloc_vdev(accel_dev, sid, errp)) {
+        return false;
+    }
+
     ret = smmu_find_ste(sdev->smmu, sid, &ste, &event);
     if (ret) {
         error_setg(errp, "Failed to find STE for Device 0x%x", sid);
@@ -311,6 +344,7 @@ static void smmuv3_accel_unset_iommu_device(PCIBus *bus, void *opaque,
     SMMUPciBus *sbus = g_hash_table_lookup(bs->smmu_pcibus_by_busptr, bus);
     SMMUv3AccelDevice *accel_dev;
     SMMUViommu *viommu;
+    IOMMUFDVdev *vdev;
     SMMUDevice *sdev;
     uint16_t sid;
 
@@ -337,6 +371,13 @@ static void smmuv3_accel_unset_iommu_device(PCIBus *bus, void *opaque,
     trace_smmuv3_accel_unset_iommu_device(devfn, sid);
 
     viommu = s->s_accel->viommu;
+    vdev = accel_dev->vdev;
+    if (vdev) {
+        iommufd_backend_free_id(viommu->iommufd, vdev->vdev_id);
+        g_free(vdev);
+        accel_dev->vdev = NULL;
+    }
+
     if (QLIST_EMPTY(&viommu->device_list)) {
         iommufd_backend_free_id(viommu->iommufd, viommu->bypass_hwpt_id);
         iommufd_backend_free_id(viommu->iommufd, viommu->abort_hwpt_id);
diff --git a/hw/arm/smmuv3-accel.h b/hw/arm/smmuv3-accel.h
index f631443b09..6242614c00 100644
--- a/hw/arm/smmuv3-accel.h
+++ b/hw/arm/smmuv3-accel.h
@@ -31,6 +31,7 @@ typedef struct SMMUv3AccelDevice {
     SMMUDevice  sdev;
     HostIOMMUDeviceIOMMUFD *idev;
     SMMUS1Hwpt *s1_hwpt;
+    IOMMUFDVdev *vdev;
     SMMUViommu *viommu;
     QLIST_ENTRY(SMMUv3AccelDevice) next;
 } SMMUv3AccelDevice;
-- 
2.43.0
Re: [PATCH v4 10/27] hw/arm/smmuv3-accel: Allocate a vDEVICE object for device
Posted by Eric Auger 4 weeks ago
Hi Shameer,

On 9/29/25 3:36 PM, Shameer Kolothum wrote:
> From: Nicolin Chen <nicolinc@nvidia.com>
>
> Allocate and associate a vDEVICE object for the Guest device with the
> vIOMMU. This will help the host kernel to make a virtual SID --> physical
> SID mapping. Since we pass the raw invalidation commands(eg: CMD_CFGI_CD)
> from Guest directly to host kernel, this provides a way to retrieve the
> correct physical SID.
>
> Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
> Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com>
> ---
>  hw/arm/smmuv3-accel.c | 41 +++++++++++++++++++++++++++++++++++++++++
>  hw/arm/smmuv3-accel.h |  1 +
>  2 files changed, 42 insertions(+)
>
> diff --git a/hw/arm/smmuv3-accel.c b/hw/arm/smmuv3-accel.c
> index 5c3825cecd..790887ac31 100644
> --- a/hw/arm/smmuv3-accel.c
> +++ b/hw/arm/smmuv3-accel.c
> @@ -39,6 +39,35 @@
>  #define STE1_MASK     (STE1_ETS | STE1_S1STALLD | STE1_S1CSH | STE1_S1COR | \
>                         STE1_S1CIR | STE1_S1DSS)
>  
> +static bool
> +smmuv3_accel_alloc_vdev(SMMUv3AccelDevice *accel_dev, int sid, Error **errp)
> +{
> +    SMMUViommu *viommu = accel_dev->viommu;
> +    IOMMUFDVdev *vdev;
> +    uint32_t vdev_id;
> +
> +    if (!accel_dev->idev || accel_dev->vdev) {
> +        return true;
> +    }
> +
> +    if (!iommufd_backend_alloc_vdev(viommu->iommufd, accel_dev->idev->devid,
> +                                   viommu->core.viommu_id, sid,
> +                                   &vdev_id, errp)) {
> +            return false;
> +    }
> +    if (!host_iommu_device_iommufd_attach_hwpt(accel_dev->idev,
> +                                               viommu->bypass_hwpt_id, errp)) {
> +        iommufd_backend_free_id(viommu->iommufd, vdev_id);
> +        return false;
> +    }
> +
> +    vdev = g_new(IOMMUFDVdev, 1);
> +    vdev->vdev_id = vdev_id;
> +    vdev->dev_id = sid;
That's confusing to me it should be virt_id and not dev_id which usually
refers to an iommu object id.

Would be nice in general to stick to the kernel uapi terminology. For
instance vdev_id shall rather vdevice_id although in that case it is
understandable.

+bool iommufd_backend_alloc_vdev(IOMMUFDBackend *be, uint32_t dev_id,
+                                uint32_t viommu_id, uint64_t virt_id,
+                                uint32_t *out_vdev_id, Error **errp)

 * struct iommu_vdevice_alloc - ioctl(IOMMU_VDEVICE_ALLOC)
 * @size: sizeof(struct iommu_vdevice_alloc)
 * @viommu_id: vIOMMU ID to associate with the virtual device
 * @dev_id: The physical device to allocate a virtual instance on the vIOMMU
 * @out_vdevice_id: Object handle for the vDevice. Pass to IOMMU_DESTORY
 * @virt_id: Virtual device ID per vIOMMU, e.g. vSID of ARM SMMUv3,
vDeviceID
 *           of AMD IOMMU, and vRID of Intel VT-d



> +    accel_dev->vdev = vdev;
> +    return true;
> +}
> +
>  static bool
>  smmuv3_accel_dev_uninstall_nested_ste(SMMUv3AccelDevice *accel_dev, bool abort,
>                                        Error **errp)
> @@ -127,6 +156,10 @@ smmuv3_accel_install_nested_ste(SMMUv3State *s, SMMUDevice *sdev, int sid,
>          return true;
>      }
>  
> +    if (!smmuv3_accel_alloc_vdev(accel_dev, sid, errp)) {
> +        return false;
> +    }
> +
>      ret = smmu_find_ste(sdev->smmu, sid, &ste, &event);
>      if (ret) {
>          error_setg(errp, "Failed to find STE for Device 0x%x", sid);
> @@ -311,6 +344,7 @@ static void smmuv3_accel_unset_iommu_device(PCIBus *bus, void *opaque,
>      SMMUPciBus *sbus = g_hash_table_lookup(bs->smmu_pcibus_by_busptr, bus);
>      SMMUv3AccelDevice *accel_dev;
>      SMMUViommu *viommu;
> +    IOMMUFDVdev *vdev;
>      SMMUDevice *sdev;
>      uint16_t sid;
>  
> @@ -337,6 +371,13 @@ static void smmuv3_accel_unset_iommu_device(PCIBus *bus, void *opaque,
>      trace_smmuv3_accel_unset_iommu_device(devfn, sid);
>  
>      viommu = s->s_accel->viommu;
> +    vdev = accel_dev->vdev;
> +    if (vdev) {
> +        iommufd_backend_free_id(viommu->iommufd, vdev->vdev_id);
> +        g_free(vdev);
> +        accel_dev->vdev = NULL;
> +    }
> +
>      if (QLIST_EMPTY(&viommu->device_list)) {
>          iommufd_backend_free_id(viommu->iommufd, viommu->bypass_hwpt_id);
>          iommufd_backend_free_id(viommu->iommufd, viommu->abort_hwpt_id);
> diff --git a/hw/arm/smmuv3-accel.h b/hw/arm/smmuv3-accel.h
> index f631443b09..6242614c00 100644
> --- a/hw/arm/smmuv3-accel.h
> +++ b/hw/arm/smmuv3-accel.h
> @@ -31,6 +31,7 @@ typedef struct SMMUv3AccelDevice {
>      SMMUDevice  sdev;
>      HostIOMMUDeviceIOMMUFD *idev;
>      SMMUS1Hwpt *s1_hwpt;
> +    IOMMUFDVdev *vdev;
>      SMMUViommu *viommu;
>      QLIST_ENTRY(SMMUv3AccelDevice) next;
>  } SMMUv3AccelDevice;
Thanks

Eric


Re: [PATCH v4 10/27] hw/arm/smmuv3-accel: Allocate a vDEVICE object for device
Posted by Jonathan Cameron via 1 month, 2 weeks ago
On Mon, 29 Sep 2025 14:36:26 +0100
Shameer Kolothum <skolothumtho@nvidia.com> wrote:

> From: Nicolin Chen <nicolinc@nvidia.com>
> 
> Allocate and associate a vDEVICE object for the Guest device with the
> vIOMMU. This will help the host kernel to make a virtual SID --> physical
> SID mapping. Since we pass the raw invalidation commands(eg: CMD_CFGI_CD)
> from Guest directly to host kernel, this provides a way to retrieve the
> correct physical SID.
> 
> Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
> Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com>

Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>