From: Nicolin Chen <[email protected]>

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 <[email protected]>
Signed-off-by: Shameer Kolothum <[email protected]>
Signed-off-by: Shameer Kolothum <[email protected]>
---
 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


Reply via email to