From nobody Tue Apr 7 16:13:28 2026 Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 57D123F0AB1 for ; Thu, 12 Mar 2026 15:56:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=13.77.154.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773331008; cv=none; b=GsdUoZTajrXAkHQCgLDvXbFchSfGLmcrygNXneaVVwo4sFi9x/PWEoVDNg3euOQ2V3ZW6BEoZstbk6tTs3tMQ1rtGo65Roqsq4tVFnlzhtrB8eQGVDGj3wV+OFppq3Q08u9sWRl/onkOBx/I8OtD3Wgize5PFSH1yqaf92U0x50= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773331008; c=relaxed/simple; bh=/6zjW23pvLpPHPAOXtukezbhsq5kWKQr6msf/ZPV7UE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=tHzS4h2rFFcMfSQ5OBiMpT69C9hsH3d6AIOAQpOyLLUzoTfutDVtYHP1CHg2EXylEZ5Vkn2LAVIEExpPV+e6/VlySqon0WJLk+Lz5I0+xu/Eu1fLPp2MOb/WAEn0eZfD+iE4+wu4K6zCKNfY75Z5YxegY+7hZGcjspXYFVveWsM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.microsoft.com; spf=pass smtp.mailfrom=linux.microsoft.com; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b=j/JEJtGA; arc=none smtp.client-ip=13.77.154.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.microsoft.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.microsoft.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="j/JEJtGA" Received: from DESKTOP-0403QTC.corp.microsoft.com (unknown [52.148.138.235]) by linux.microsoft.com (Postfix) with ESMTPSA id 254F420B6F12; Thu, 12 Mar 2026 08:56:41 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 254F420B6F12 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1773331001; bh=tz2IbcvQXBLS4zfZdPH/7krrGF/PbgxjGvCMudQfOGc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=j/JEJtGAhV3Y+rlBFbFBTmj7KENyrSIbrZMGCWAej7D6GKTHxS8kdfR8fLluPA/me NwJ685no08HraNRiKAC3kaABnsT+1uR8z6pTAGZcgLq3Xhda2uy2hn6wEh2rTdO1Sd /vO1n4ko/dNAe5GG8yF0R+dPTI53OLs8CxFxOwbk= From: Jacob Pan To: linux-kernel@vger.kernel.org, "iommu@lists.linux.dev" , Jason Gunthorpe , Alex Williamson , Joerg Roedel , David Matlack , Robin Murphy , Nicolin Chen , "Tian, Kevin" , Yi Liu Cc: skhawaja@google.com, pasha.tatashin@soleen.com, Will Deacon , Jacob Pan , Baolu Lu Subject: [PATCH V2 03/11] iommufd: Allow binding to a noiommu device Date: Thu, 12 Mar 2026 08:56:29 -0700 Message-Id: <20260312155637.376854-4-jacob.pan@linux.microsoft.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260312155637.376854-1-jacob.pan@linux.microsoft.com> References: <20260312155637.376854-1-jacob.pan@linux.microsoft.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Jason Gunthorpe Allow iommufd to bind devices without an IOMMU (noiommu mode) by creating a dummy IOMMU group for such devices and skipping hwpt operations. This enables noiommu devices to operate through the same iommufd API as IOM= MU- capable devices. Signed-off-by: Jason Gunthorpe Signed-off-by: Jacob Pan --- drivers/iommu/iommufd/device.c | 113 ++++++++++++++++++++++----------- 1 file changed, 76 insertions(+), 37 deletions(-) diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c index 54d73016468f..c38d3efa3d6f 100644 --- a/drivers/iommu/iommufd/device.c +++ b/drivers/iommu/iommufd/device.c @@ -23,6 +23,11 @@ struct iommufd_attach { struct xarray device_array; }; =20 +static bool is_vfio_noiommu(struct iommufd_device *idev) +{ + return !device_iommu_mapped(idev->dev) || !idev->dev->iommu; +} + static void iommufd_group_release(struct kref *kref) { struct iommufd_group *igroup =3D @@ -205,32 +210,17 @@ void iommufd_device_destroy(struct iommufd_object *ob= j) struct iommufd_device *idev =3D container_of(obj, struct iommufd_device, obj); =20 - iommu_device_release_dma_owner(idev->dev); + if (!is_vfio_noiommu(idev)) + iommu_device_release_dma_owner(idev->dev); iommufd_put_group(idev->igroup); if (!iommufd_selftest_is_mock_dev(idev->dev)) iommufd_ctx_put(idev->ictx); } =20 -/** - * iommufd_device_bind - Bind a physical device to an iommu fd - * @ictx: iommufd file descriptor - * @dev: Pointer to a physical device struct - * @id: Output ID number to return to userspace for this device - * - * A successful bind establishes an ownership over the device and returns - * struct iommufd_device pointer, otherwise returns error pointer. - * - * A driver using this API must set driver_managed_dma and must not touch - * the device until this routine succeeds and establishes ownership. - * - * Binding a PCI device places the entire RID under iommufd control. - * - * The caller must undo this with iommufd_device_unbind() - */ -struct iommufd_device *iommufd_device_bind(struct iommufd_ctx *ictx, - struct device *dev, u32 *id) +static int iommufd_bind_iommu(struct iommufd_device *idev) { - struct iommufd_device *idev; + struct iommufd_ctx *ictx =3D idev->ictx; + struct device *dev =3D idev->dev; struct iommufd_group *igroup; int rc; =20 @@ -239,11 +229,11 @@ struct iommufd_device *iommufd_device_bind(struct iom= mufd_ctx *ictx, * to restore cache coherency. */ if (!device_iommu_capable(dev, IOMMU_CAP_CACHE_COHERENCY)) - return ERR_PTR(-EINVAL); + return -EINVAL; =20 - igroup =3D iommufd_get_group(ictx, dev); + igroup =3D iommufd_get_group(idev->ictx, dev); if (IS_ERR(igroup)) - return ERR_CAST(igroup); + return PTR_ERR(igroup); =20 /* * For historical compat with VFIO the insecure interrupt path is @@ -269,21 +259,66 @@ struct iommufd_device *iommufd_device_bind(struct iom= mufd_ctx *ictx, if (rc) goto out_group_put; =20 + /* igroup refcount moves into iommufd_device */ + idev->igroup =3D igroup; + return 0; + +out_group_put: + iommufd_put_group(igroup); + return rc; +} + +/** + * iommufd_device_bind - Bind a physical device to an iommu fd + * @ictx: iommufd file descriptor + * @dev: Pointer to a physical device struct + * @id: Output ID number to return to userspace for this device + * + * A successful bind establishes an ownership over the device and returns + * struct iommufd_device pointer, otherwise returns error pointer. + * + * A driver using this API must set driver_managed_dma and must not touch + * the device until this routine succeeds and establishes ownership. + * + * Binding a PCI device places the entire RID under iommufd control. + * + * The caller must undo this with iommufd_device_unbind() + */ +struct iommufd_device *iommufd_device_bind(struct iommufd_ctx *ictx, + struct device *dev, u32 *id) +{ + struct iommufd_device *idev; + int rc; + idev =3D iommufd_object_alloc(ictx, idev, IOMMUFD_OBJ_DEVICE); - if (IS_ERR(idev)) { - rc =3D PTR_ERR(idev); - goto out_release_owner; - } + if (IS_ERR(idev)) + return idev; idev->ictx =3D ictx; - if (!iommufd_selftest_is_mock_dev(dev)) - iommufd_ctx_get(ictx); idev->dev =3D dev; idev->enforce_cache_coherency =3D device_iommu_capable(dev, IOMMU_CAP_ENFORCE_CACHE_COHERENCY); + + if (!is_vfio_noiommu(idev)) { + rc =3D iommufd_bind_iommu(idev); + if (rc) + return ERR_PTR(rc); + } else { + struct iommufd_group *igroup; + + /* + * Create a dummy igroup, lots of stuff expects ths igroup to be + * present, but a NULL igroup->group is OK + */ + igroup =3D iommufd_alloc_group(ictx, NULL); + if (IS_ERR(igroup)) + return ERR_CAST(igroup); + idev->igroup =3D igroup; + } + + if (!iommufd_selftest_is_mock_dev(dev)) + iommufd_ctx_get(ictx); /* The calling driver is a user until iommufd_device_unbind() */ refcount_inc(&idev->obj.users); - /* igroup refcount moves into iommufd_device */ - idev->igroup =3D igroup; =20 /* * If the caller fails after this success it must call @@ -295,11 +330,6 @@ struct iommufd_device *iommufd_device_bind(struct iomm= ufd_ctx *ictx, *id =3D idev->obj.id; return idev; =20 -out_release_owner: - iommu_device_release_dma_owner(dev); -out_group_put: - iommufd_put_group(igroup); - return ERR_PTR(rc); } EXPORT_SYMBOL_NS_GPL(iommufd_device_bind, "IOMMUFD"); =20 @@ -513,6 +543,9 @@ static int iommufd_hwpt_attach_device(struct iommufd_hw= _pagetable *hwpt, struct iommufd_attach_handle *handle; int rc; =20 + if (is_vfio_noiommu(idev)) + return 0; + if (!iommufd_hwpt_compatible_device(hwpt, idev)) return -EINVAL; =20 @@ -560,6 +593,9 @@ static void iommufd_hwpt_detach_device(struct iommufd_h= w_pagetable *hwpt, { struct iommufd_attach_handle *handle; =20 + if (is_vfio_noiommu(idev)) + return; + handle =3D iommufd_device_get_attach_handle(idev, pasid); if (pasid =3D=3D IOMMU_NO_PASID) iommu_detach_group_handle(hwpt->domain, idev->igroup->group); @@ -578,6 +614,9 @@ static int iommufd_hwpt_replace_device(struct iommufd_d= evice *idev, struct iommufd_attach_handle *handle, *old_handle; int rc; =20 + if (is_vfio_noiommu(idev)) + return 0; + if (!iommufd_hwpt_compatible_device(hwpt, idev)) return -EINVAL; =20 @@ -653,7 +692,7 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_paget= able *hwpt, goto err_release_devid; } =20 - if (attach_resv) { + if (attach_resv && !is_vfio_noiommu(idev)) { rc =3D iommufd_device_attach_reserved_iova(idev, hwpt_paging); if (rc) goto err_release_devid; --=20 2.34.1