Alexey Kardashevskiy <aik@xxxxxxx> writes: .... > +int iommufd_vdevice_tsm_bind_ioctl(struct iommufd_ucmd *ucmd) > +{ > + struct iommu_vdevice_tsm_bind *cmd = ucmd->cmd; > + struct iommufd_viommu *viommu; > + struct iommufd_vdevice *vdev; > + struct iommufd_device *idev; > + struct tsm_tdi *tdi; > + int rc = 0; > + > + viommu = iommufd_get_viommu(ucmd, cmd->viommu_id); > + if (IS_ERR(viommu)) > + return PTR_ERR(viommu); > Would this require an IOMMU_HWPT_ALLOC_NEST_PARENT page table allocation? How would this work in cases where there's no need to set up Stage 1 IOMMU tables? Alternatively, should we allocate an IOMMU_HWPT_ALLOC_NEST_PARENT with a Stage 1 disabled translation config? (In the ARM case, this could mean marking STE entries as Stage 1 bypass and Stage 2 translate.) Also, if a particular setup doesn't require creating IOMMU entries because the entire guest RAM is identity-mapped in the IOMMU, do we still need to make tsm_tdi_bind use this abstraction in iommufd? > + > + idev = iommufd_get_device(ucmd, cmd->dev_id); > + if (IS_ERR(idev)) { > + rc = PTR_ERR(idev); > + goto out_put_viommu; > + } > + > + vdev = container_of(iommufd_get_object(ucmd->ictx, cmd->vdevice_id, > + IOMMUFD_OBJ_VDEVICE), > + struct iommufd_vdevice, obj); > + if (IS_ERR(idev)) { > + rc = PTR_ERR(idev); > + goto out_put_dev; > + } > + > + tdi = tsm_tdi_get(idev->dev); > + if (!tdi) { > + rc = -ENODEV; > + goto out_put_vdev; > + } > + > + rc = tsm_tdi_bind(tdi, vdev->id, cmd->kvmfd); > + if (rc) > + goto out_put_tdi; > + > + vdev->tsm_bound = true; > + > + rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd)); > +out_put_tdi: > + tsm_tdi_put(tdi); > +out_put_vdev: > + iommufd_put_object(ucmd->ictx, &vdev->obj); > +out_put_dev: > + iommufd_put_object(ucmd->ictx, &idev->obj); > +out_put_viommu: > + iommufd_put_object(ucmd->ictx, &viommu->obj); > + return rc; > +} -aneesh