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
