From nobody Thu Apr 9 11:15:05 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3D93399032; Mon, 9 Mar 2026 11:17:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773055053; cv=none; b=UfglHdRhI5zuuWR1e6dFrBIx7q9warDNeQA4eGs9SspKAyGHJAWfNMSPu/heDRWnVDPsdskK8AgMI3+l6bm4t5A71A3YmpOmrVZ3eJWPWrOamMgFXow+XKSIKRhDjEebRxDElLyh30scyxyrhGmgyxTYTHxogQxhV3vMiRq3RW4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773055053; c=relaxed/simple; bh=F5Zm0UVICZbWezI1fp8Hz+Q6fqxqJVOmYIbu8pPJtcE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kQVEmCwjDK0oDGwvdoBFLkICu0RgDPyo6CsxZWj52VW3r8wub7IOVrXAHPXs7aagMSFqLa/afRdy47C0cQZoECieNBZjhIOGWK/O7yoq28U2JGR1l/6ubWXA1mrmdS6/ZfCkT9y2tUmehvlDD9pIMtW1Bf2ijsKErILvdqoKLvI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KThGJ7eq; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KThGJ7eq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 41BE2C2BCAF; Mon, 9 Mar 2026 11:17:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773055053; bh=F5Zm0UVICZbWezI1fp8Hz+Q6fqxqJVOmYIbu8pPJtcE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KThGJ7eqNHRweBH21oVCx0yy4L4ILEJTW5ln+J9ETxSGvIy9XH75fDwkOVPSClCH5 jhWBbXPc7RVfHIUk0/bbZDBwvFkhvjx1uKastEbT0iEltR2L2LXglSrIywcvASGZlg dFO1lyklF+SFLv/M07dAfaGHPbOVY9Zv4SEcNdWS0SqJJKgMl8TQRUOyQ78y/qg+vR PgRdsHenEV2o1zUtzlWETntx5eiBi2Aa02r/LIL0J9FIijyAj9L7+arvDhFUqP5EfE GVThSMmy3K3nSY40o9P5c6j84WHrFipPaadPfWqNSpzkFaVfrsOYQuDrXbFwlUNdv3 4Cp3Dl+1wceYg== From: "Aneesh Kumar K.V (Arm)" To: iommu@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Kevin Tian , Joerg Roedel , Will Deacon , Bjorn Helgaas , Jonathan Cameron , Dan Williams , Alexey Kardashevskiy , Samuel Ortiz , Xu Yilun , Jason Gunthorpe , Suzuki K Poulose , Steven Price Subject: [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU Date: Mon, 9 Mar 2026 16:47:02 +0530 Message-ID: <20260309111704.2330479-2-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260309111704.2330479-1-aneesh.kumar@kernel.org> References: <20260309111704.2330479-1-aneesh.kumar@kernel.org> 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" Add optional KVM association to IOMMU_VIOMMU_ALLOC by introducing IOMMU_VIOMMU_KVM_FD and iommu_viommu_alloc::kvm_vm_fd. When the flag is set, iommufd validates that kvm_vm_fd refers to a KVM VM file and stores a referenced struct file in the vIOMMU object, so later iommufd operations can safely resolve the owning VM. This is preparatory plumbing for subsequent patches that bind TDI state to the associated KVM VM. The patch also switch file_is_kvm from EXPORT_SYMBOL_FOR_KVM_INTERNAL to EXPORT_SYMBOL_GPL so that iommu module can use that. Cc: Kevin Tian Cc: Joerg Roedel Cc: Will Deacon Cc: Bjorn Helgaas Cc: Jonathan Cameron Cc: Dan Williams Cc: Alexey Kardashevskiy Cc: Samuel Ortiz Cc: Xu Yilun Cc: Jason Gunthorpe Cc: Suzuki K Poulose Cc: Steven Price Signed-off-by: Aneesh Kumar K.V (Arm) --- drivers/iommu/iommufd/viommu.c | 54 +++++++++++++++++++++++++++++++++- include/linux/iommufd.h | 3 ++ include/uapi/linux/iommufd.h | 13 +++++++- virt/kvm/kvm_main.c | 2 +- 4 files changed, 69 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/iommufd/viommu.c b/drivers/iommu/iommufd/viommu.c index 4081deda9b33..08f8930c86da 100644 --- a/drivers/iommu/iommufd/viommu.c +++ b/drivers/iommu/iommufd/viommu.c @@ -2,6 +2,45 @@ /* Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES */ #include "iommufd_private.h" +#include + +#if IS_ENABLED(CONFIG_KVM) +#include + +static int viommu_get_kvm(struct iommufd_viommu *viommu, int kvm_vm_fd) +{ + int rc =3D -EBADF; + struct file *filp __free(fput) =3D fget(kvm_vm_fd); + + if (!file_is_kvm(filp)) + return rc; + + /* hold the kvm reference via file descriptor */ + viommu->kvm_filp =3D no_free_ptr(filp); + return 0; +} + +static void viommu_put_kvm(struct iommufd_viommu *viommu) +{ + if (!viommu->kvm_filp) + return; + + fput(viommu->kvm_filp); + viommu->kvm_filp =3D NULL; +} + +#else + +static inline int viommu_get_kvm(struct iommufd_viommu *viommu, int kvm_vm= _fd) +{ + return -EOPNOTSUPP; +} + +static inline void viommu_put_kvm(struct iommufd_viommu *viommu) +{ +} + +#endif =20 void iommufd_viommu_destroy(struct iommufd_object *obj) { @@ -12,6 +51,8 @@ void iommufd_viommu_destroy(struct iommufd_object *obj) viommu->ops->destroy(viommu); refcount_dec(&viommu->hwpt->common.obj.users); xa_destroy(&viommu->vdevs); + + viommu_put_kvm(viommu); } =20 int iommufd_viommu_alloc_ioctl(struct iommufd_ucmd *ucmd) @@ -29,7 +70,9 @@ int iommufd_viommu_alloc_ioctl(struct iommufd_ucmd *ucmd) size_t viommu_size; int rc; =20 - if (cmd->flags || cmd->type =3D=3D IOMMU_VIOMMU_TYPE_DEFAULT) + if (cmd->flags & ~IOMMU_VIOMMU_KVM_FD) + return -EOPNOTSUPP; + if (cmd->type =3D=3D IOMMU_VIOMMU_TYPE_DEFAULT) return -EOPNOTSUPP; =20 idev =3D iommufd_get_device(ucmd, cmd->dev_id); @@ -100,8 +143,17 @@ int iommufd_viommu_alloc_ioctl(struct iommufd_ucmd *uc= md) goto out_put_hwpt; } =20 + /* get the kvm details if specified. */ + if (cmd->flags & IOMMU_VIOMMU_KVM_FD) { + rc =3D viommu_get_kvm(viommu, cmd->kvm_vm_fd); + if (rc) + goto out_put_hwpt; + } + cmd->out_viommu_id =3D viommu->obj.id; rc =3D iommufd_ucmd_respond(ucmd, sizeof(*cmd)); + if (rc) + viommu_put_kvm(viommu); =20 out_put_hwpt: iommufd_put_object(ucmd->ictx, &hwpt_paging->common.obj); diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h index 6e7efe83bc5d..7c515d3c52db 100644 --- a/include/linux/iommufd.h +++ b/include/linux/iommufd.h @@ -12,6 +12,7 @@ #include #include #include +#include #include =20 struct device; @@ -58,6 +59,7 @@ struct iommufd_object { unsigned int id; }; =20 +struct kvm; struct iommufd_device *iommufd_device_bind(struct iommufd_ctx *ictx, struct device *dev, u32 *id); void iommufd_device_unbind(struct iommufd_device *idev); @@ -101,6 +103,7 @@ struct iommufd_viommu { struct iommufd_ctx *ictx; struct iommu_device *iommu_dev; struct iommufd_hwpt_paging *hwpt; + struct file *kvm_filp; =20 const struct iommufd_viommu_ops *ops; =20 diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h index 1dafbc552d37..b862c3e57133 100644 --- a/include/uapi/linux/iommufd.h +++ b/include/uapi/linux/iommufd.h @@ -1071,10 +1071,19 @@ struct iommu_viommu_tegra241_cmdqv { __aligned_u64 out_vintf_mmap_length; }; =20 +/** + * define IOMMU_VIOMMU_KVM_FD - Flag indicating a valid KVM VM file descri= ptor + * + * Set this flag when allocating a viommu instance that should be associat= ed + * with a specific KVM VM. If this flag is not provided, + * @iommu_viommu_alloc::kvm_vm_fd is ignored. + */ +#define IOMMU_VIOMMU_KVM_FD BIT(0) + /** * struct iommu_viommu_alloc - ioctl(IOMMU_VIOMMU_ALLOC) * @size: sizeof(struct iommu_viommu_alloc) - * @flags: Must be 0 + * @flags: Supported flags (IOMMU_VIOMMU_KVM_FD) * @type: Type of the virtual IOMMU. Must be defined in enum iommu_viommu_= type * @dev_id: The device's physical IOMMU will be used to back the virtual I= OMMU * @hwpt_id: ID of a nesting parent HWPT to associate to @@ -1082,6 +1091,7 @@ struct iommu_viommu_tegra241_cmdqv { * @data_len: Length of the type specific data * @__reserved: Must be 0 * @data_uptr: User pointer to a driver-specific virtual IOMMU data + * @kvm_vm_fd: KVM VM file descriptor when IOMMU_VIOMMU_KVM_FD is set * * Allocate a virtual IOMMU object, representing the underlying physical I= OMMU's * virtualization support that is a security-isolated slice of the real IO= MMU HW @@ -1105,6 +1115,7 @@ struct iommu_viommu_alloc { __u32 data_len; __u32 __reserved; __aligned_u64 data_uptr; + __s32 kvm_vm_fd; }; #define IOMMU_VIOMMU_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_VIOMMU_ALLOC) =20 diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 1bc1da66b4b0..f076c5a7a290 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -5481,7 +5481,7 @@ bool file_is_kvm(struct file *file) { return file && file->f_op =3D=3D &kvm_vm_fops; } -EXPORT_SYMBOL_FOR_KVM_INTERNAL(file_is_kvm); +EXPORT_SYMBOL_GPL(file_is_kvm); =20 static int kvm_dev_ioctl_create_vm(unsigned long type) { --=20 2.43.0 From nobody Thu Apr 9 11:15:05 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2C15D3A1D1F; Mon, 9 Mar 2026 11:17:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773055059; cv=none; b=ue9GbiDgHYhUCQ6DEZ9POQvWBhCDmRTtKppSNBeo+VX5c9jRJpEmGF0qvREFe3PsRsO2JI3v5OOcqBLyovZrgabJeF2pMRclJ3GISUdfjmQAJiwAmA6W+6AqlxCb3/IPo/kBf/EQEoaud9GZ0f9ntb1jTWWLVvyhxMyLC2FP6LY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773055059; c=relaxed/simple; bh=FXOwjOtb0lik0JoRc6nz9TJV7sakxmBgRJTv/CV2Al0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=e48NP+K4LEYbhAnksbA5PJgyfA7m/IgriSdb/Tsq2NNG4XA+yYETklsTqo0NdwOTHBSTE9/W4pc+ESLzO+BxW7gDhcm3b7tyXKumxYPIHIlTJcYgHl8XmTupX05oLP5pd/GiwfjPVEvhRScb7rAEzMsqigbFGOJqYsRL1nuiSf4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=eZm8CLQM; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="eZm8CLQM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B40F4C4CEF7; Mon, 9 Mar 2026 11:17:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773055058; bh=FXOwjOtb0lik0JoRc6nz9TJV7sakxmBgRJTv/CV2Al0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eZm8CLQMQwSuaSi2fIn8FCx4Fm8UFjpb4+EmGP2N2QpqmxPXn1OT87DMFJnUCLiRg 37bdD30hy6m7FEd+VVat2QOdoOOTR4gZSBnqdFzvfMhhkhXQsptDRTSAEoNsXjhI0v JxYVOiYvV/8L1yNl1oJiPZ4zFICe5sz611jsxUMqARUJBK8BK4R3BLYauorqa1qOn7 9hBlK9Nx0o/TaBGOUAe5+Ab2CbjTjmdjMKdlu1RUrNpIeHAf2mKX1m6ueJPK6GZM31 ti0IY+MN/50JfhxOkIgz0p6faEmWt5g9KbFn9FVBN940DkTKECqvG2sewwWqI6eOJS o6a/mDFSxslUw== From: "Aneesh Kumar K.V (Arm)" To: iommu@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Kevin Tian , Joerg Roedel , Will Deacon , Bjorn Helgaas , Jonathan Cameron , Dan Williams , Alexey Kardashevskiy , Samuel Ortiz , Xu Yilun , Jason Gunthorpe , Suzuki K Poulose , Steven Price Subject: [PATCH v2 2/3] iommufd/tsm: add vdevice TSM bind/unbind ioctl Date: Mon, 9 Mar 2026 16:47:03 +0530 Message-ID: <20260309111704.2330479-3-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260309111704.2330479-1-aneesh.kumar@kernel.org> References: <20260309111704.2330479-1-aneesh.kumar@kernel.org> 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" Introduce IOMMU_VDEVICE_TSM_OP to allow userspace to issue TSM bind/unbind operations for an iommufd vdevice. The new ioctl: - looks up the vdevice object from vdevice_id - resolves the associated KVM VM from the vIOMMU KVM file reference - dispatches bind/unbind via tsm_bind()/tsm_unbind() Also add common TSM helpers in tsm-core and wire vdevice teardown to unbind the device from TSM state. This provides iommufd plumbing to bind a TDI to a confidential guest through the TSM layer. Cc: Kevin Tian Cc: Joerg Roedel Cc: Will Deacon Cc: Bjorn Helgaas Cc: Jonathan Cameron Cc: Dan Williams Cc: Alexey Kardashevskiy Cc: Samuel Ortiz Cc: Xu Yilun Cc: Jason Gunthorpe Cc: Suzuki K Poulose Cc: Steven Price Signed-off-by: Aneesh Kumar K.V (Arm) --- drivers/iommu/iommufd/Makefile | 2 + drivers/iommu/iommufd/iommufd_private.h | 8 +++ drivers/iommu/iommufd/main.c | 3 ++ drivers/iommu/iommufd/tsm.c | 67 +++++++++++++++++++++++++ drivers/iommu/iommufd/viommu.c | 3 ++ drivers/virt/coco/tsm-core.c | 19 +++++++ include/linux/tsm.h | 18 +++++++ include/uapi/linux/iommufd.h | 18 +++++++ 8 files changed, 138 insertions(+) create mode 100644 drivers/iommu/iommufd/tsm.c diff --git a/drivers/iommu/iommufd/Makefile b/drivers/iommu/iommufd/Makefile index 71d692c9a8f4..431089089ee9 100644 --- a/drivers/iommu/iommufd/Makefile +++ b/drivers/iommu/iommufd/Makefile @@ -10,6 +10,8 @@ iommufd-y :=3D \ vfio_compat.o \ viommu.o =20 +iommufd-$(CONFIG_TSM) +=3D tsm.o + iommufd-$(CONFIG_IOMMUFD_TEST) +=3D selftest.o =20 obj-$(CONFIG_IOMMUFD) +=3D iommufd.o diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommuf= d/iommufd_private.h index 6ac1965199e9..aa1ceed924c2 100644 --- a/drivers/iommu/iommufd/iommufd_private.h +++ b/drivers/iommu/iommufd/iommufd_private.h @@ -697,6 +697,14 @@ void iommufd_vdevice_destroy(struct iommufd_object *ob= j); void iommufd_vdevice_abort(struct iommufd_object *obj); int iommufd_hw_queue_alloc_ioctl(struct iommufd_ucmd *ucmd); void iommufd_hw_queue_destroy(struct iommufd_object *obj); +#ifdef CONFIG_TSM +int iommufd_vdevice_tsm_op_ioctl(struct iommufd_ucmd *ucmd); +#else +static inline int iommufd_vdevice_tsm_op_ioctl(struct iommufd_ucmd *ucmd) +{ + return -EOPNOTSUPP; +} +#endif =20 static inline struct iommufd_vdevice * iommufd_get_vdevice(struct iommufd_ctx *ictx, u32 id) diff --git a/drivers/iommu/iommufd/main.c b/drivers/iommu/iommufd/main.c index 8c6d43601afb..d73e6b391c6f 100644 --- a/drivers/iommu/iommufd/main.c +++ b/drivers/iommu/iommufd/main.c @@ -432,6 +432,7 @@ union ucmd_buffer { struct iommu_veventq_alloc veventq; struct iommu_vfio_ioas vfio_ioas; struct iommu_viommu_alloc viommu; + struct iommu_vdevice_tsm_op tsm_op; #ifdef CONFIG_IOMMUFD_TEST struct iommu_test_cmd test; #endif @@ -493,6 +494,8 @@ static const struct iommufd_ioctl_op iommufd_ioctl_ops[= ] =3D { __reserved), IOCTL_OP(IOMMU_VIOMMU_ALLOC, iommufd_viommu_alloc_ioctl, struct iommu_viommu_alloc, out_viommu_id), + IOCTL_OP(IOMMU_VDEVICE_TSM_OP, iommufd_vdevice_tsm_op_ioctl, + struct iommu_vdevice_tsm_op, vdevice_id), #ifdef CONFIG_IOMMUFD_TEST IOCTL_OP(IOMMU_TEST_CMD, iommufd_test, struct iommu_test_cmd, last), #endif diff --git a/drivers/iommu/iommufd/tsm.c b/drivers/iommu/iommufd/tsm.c new file mode 100644 index 000000000000..401469110752 --- /dev/null +++ b/drivers/iommu/iommufd/tsm.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026 ARM Ltd. + */ + +#include "iommufd_private.h" +#include + +/** + * iommufd_vdevice_tsm_op_ioctl - Handle vdevice TSM operations + * @ucmd: user command data for IOMMU_VDEVICE_TSM_OP + * + * Currently only supports TSM bind/unbind operations + * Resolve @iommu_vdevice_tsm_op::vdevice_id to a vdevice and dispatch the + * requested bind/unbind operation through the TSM core. + * + * Return: 0 on success, or a negative error code on failure. + */ +int iommufd_vdevice_tsm_op_ioctl(struct iommufd_ucmd *ucmd) +{ + int rc; + struct kvm *kvm; + struct iommufd_vdevice *vdev; + struct iommu_vdevice_tsm_op *cmd =3D ucmd->cmd; + + if (cmd->flags) + return -EOPNOTSUPP; + + vdev =3D container_of(iommufd_get_object(ucmd->ictx, cmd->vdevice_id, + IOMMUFD_OBJ_VDEVICE), + struct iommufd_vdevice, obj); + if (IS_ERR(vdev)) + return PTR_ERR(vdev); + + if (!vdev->viommu->kvm_filp) { + rc =3D -ENODEV; + goto out_put_vdev; + } + + kvm =3D vdev->viommu->kvm_filp->private_data; + if (!kvm) { + rc =3D -ENODEV; + goto out_put_vdev; + } + + /* tsm layer will take care of parallel calls to tsm_bind/unbind */ + switch (cmd->op) { + case IOMMU_VDEVICE_TSM_BIND: + rc =3D tsm_bind(vdev->idev->dev, kvm, vdev->virt_id); + break; + case IOMMU_VDEVICE_TSM_UNBIND: + rc =3D tsm_unbind(vdev->idev->dev); + break; + default: + rc =3D -EINVAL; + goto out_put_vdev; + } + + if (rc) + goto out_put_vdev; + + rc =3D iommufd_ucmd_respond(ucmd, sizeof(*cmd)); + +out_put_vdev: + iommufd_put_object(ucmd->ictx, &vdev->obj); + return rc; +} diff --git a/drivers/iommu/iommufd/viommu.c b/drivers/iommu/iommufd/viommu.c index 08f8930c86da..8eb7a3441a61 100644 --- a/drivers/iommu/iommufd/viommu.c +++ b/drivers/iommu/iommufd/viommu.c @@ -3,6 +3,7 @@ */ #include "iommufd_private.h" #include +#include =20 #if IS_ENABLED(CONFIG_KVM) #include @@ -171,6 +172,8 @@ void iommufd_vdevice_abort(struct iommufd_object *obj) =20 lockdep_assert_held(&idev->igroup->lock); =20 + tsm_unbind(idev->dev); + if (vdev->destroy) vdev->destroy(vdev); /* xa_cmpxchg is okay to fail if alloc failed xa_cmpxchg previously */ diff --git a/drivers/virt/coco/tsm-core.c b/drivers/virt/coco/tsm-core.c index ae3617abd2ac..f0e35fc38776 100644 --- a/drivers/virt/coco/tsm-core.c +++ b/drivers/virt/coco/tsm-core.c @@ -240,6 +240,25 @@ void tsm_ide_stream_unregister(struct pci_ide *ide) } EXPORT_SYMBOL_GPL(tsm_ide_stream_unregister); =20 +int tsm_bind(struct device *dev, struct kvm *kvm, u64 tdi_id) +{ + if (!dev_is_pci(dev)) + return -EINVAL; + + return pci_tsm_bind(to_pci_dev(dev), kvm, tdi_id); +} +EXPORT_SYMBOL_GPL(tsm_bind); + +int tsm_unbind(struct device *dev) +{ + if (!dev_is_pci(dev)) + return -EINVAL; + + pci_tsm_unbind(to_pci_dev(dev)); + return 0; +} +EXPORT_SYMBOL_GPL(tsm_unbind); + static void tsm_release(struct device *dev) { struct tsm_dev *tsm_dev =3D container_of(dev, typeof(*tsm_dev), dev); diff --git a/include/linux/tsm.h b/include/linux/tsm.h index 7f72a154b6b2..9f2a7868021a 100644 --- a/include/linux/tsm.h +++ b/include/linux/tsm.h @@ -124,6 +124,24 @@ struct tsm_dev *tsm_register(struct device *parent, st= ruct pci_tsm_ops *ops); void tsm_unregister(struct tsm_dev *tsm_dev); struct tsm_dev *find_tsm_dev(int id); struct pci_ide; +struct kvm; int tsm_ide_stream_register(struct pci_ide *ide); void tsm_ide_stream_unregister(struct pci_ide *ide); +#ifdef CONFIG_TSM +int tsm_bind(struct device *dev, struct kvm *kvm, u64 tdi_id); +int tsm_unbind(struct device *dev); + +#else + +static inline int tsm_bind(struct device *dev, struct kvm *kvm, u64 tdi_id) +{ + return -EINVAL; +} + +static inline int tsm_unbind(struct device *dev) +{ + return 0; +} +#endif + #endif /* __TSM_H */ diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h index b862c3e57133..653402e7048a 100644 --- a/include/uapi/linux/iommufd.h +++ b/include/uapi/linux/iommufd.h @@ -57,6 +57,7 @@ enum { IOMMUFD_CMD_IOAS_CHANGE_PROCESS =3D 0x92, IOMMUFD_CMD_VEVENTQ_ALLOC =3D 0x93, IOMMUFD_CMD_HW_QUEUE_ALLOC =3D 0x94, + IOMMUFD_CMD_VDEVICE_TSM_OP =3D 0x95, }; =20 /** @@ -1174,6 +1175,23 @@ enum iommu_veventq_flag { IOMMU_VEVENTQ_FLAG_LOST_EVENTS =3D (1U << 0), }; =20 +/** + * struct iommu_vdevice_tsm_op - ioctl(IOMMU_VDEVICE_TSM_OP) + * @size: sizeof(struct iommu_vdevice_tsm_op) + * @op: Either TSM_BIND or TSM_UNBIND + * @flags: Must be 0 + * @vdevice_id: Object handle for the vDevice. Returned from IOMMU_VDEVICE= _ALLOC + */ +struct iommu_vdevice_tsm_op { + __u32 size; + __u32 op; + __u32 flags; + __u32 vdevice_id; +}; +#define IOMMU_VDEVICE_TSM_OP _IO(IOMMUFD_TYPE, IOMMUFD_CMD_VDEVICE_TSM_OP) +#define IOMMU_VDEVICE_TSM_BIND 0x1 +#define IOMMU_VDEVICE_TSM_UNBIND 0x2 + /** * struct iommufd_vevent_header - Virtual Event Header for a vEVENTQ Status * @flags: Combination of enum iommu_veventq_flag --=20 2.43.0 From nobody Thu Apr 9 11:15:05 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4B0A73A1A4D; Mon, 9 Mar 2026 11:17:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773055064; cv=none; b=LEewX/pW0qI6N3TpcF/s4JESMvRp0M4RZoRVNaEmaE8CC9Mv6L78v8Rwo8/4HqO6+kIYnSy6vOjjwRJePSlXsV972l7RTtvRDZT1MiiH+knJHY50tmcia1VLoL/1vq/k4WaQEM/KhTc7qs6jdDjZJlWqlpG2kQmZR43EX6mPcc0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773055064; c=relaxed/simple; bh=OtGshxzVApu9OGSwfjeOY5QHAt1HWmJXqthR23/nz0s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oLSMYTFYv6T0n64xMvWfCiJfLPipkxAegm5kd7AOehCeorKPLclr/TC1x+FlvkdnOg0Ea81V5KZx5BUIm+t/szEvqwhKFA3m3ieownTj6wluMxei4aQv1uMmcfCwKhZxQB0E+GYCUUgxPizeJhqqi47Pta/18jkX7hqAqjJAnZU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uc2eixKr; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="uc2eixKr" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2EE39C2BCAF; Mon, 9 Mar 2026 11:17:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773055064; bh=OtGshxzVApu9OGSwfjeOY5QHAt1HWmJXqthR23/nz0s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uc2eixKrtDMbfFAXjIrfoSv/n/itUKbdR0cZhd/Qn8caO1xEjexj6Nkiib+g9XtZc hdMMmoMJh9ZZjINoWj97F0f9w3aROOZfqjR4h3EqZU2KbpJwy6i+hhSnRr64TQcmod OrJCeITA0NDg8Wddphk2cg2PkE9vzAwUOWg25zl82WQytZ6vQISKLJi1u/8An7kobL GE7iwQeReCYfHMvKx0onHaeeTLBVKnV5uJbMEihU64Ns9CEDpdrOAFRlTWl6cLdGQ3 p1HxRxOHMY1W4B3Y5c2bWhb4HJNtQirWHwv+8oN7U0HG6kDTamzS6Se+FjD4OxNrbS GiwqRmmV4R3YQ== From: "Aneesh Kumar K.V (Arm)" To: iommu@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Kevin Tian , Joerg Roedel , Will Deacon , Bjorn Helgaas , Jonathan Cameron , Dan Williams , Alexey Kardashevskiy , Samuel Ortiz , Xu Yilun , Jason Gunthorpe , Suzuki K Poulose , Steven Price Subject: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl Date: Mon, 9 Mar 2026 16:47:04 +0530 Message-ID: <20260309111704.2330479-4-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260309111704.2330479-1-aneesh.kumar@kernel.org> References: <20260309111704.2330479-1-aneesh.kumar@kernel.org> 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" Add IOMMU_VDEVICE_TSM_GUEST_REQUEST for issuing TSM guest request/response transactions against an iommufd vdevice. The ioctl takes a vdevice_id plus request/response user buffers and length fields, and forwards the request through tsm_guest_req() to the PCI TSM backend. This provides the host-side passthrough path used by CoCo guests for TSM device attestation and acceptance flows after the device has been bound to TSM. Also add the supporting tsm_guest_req() helper and associated TSM core interface definitions. Based on changes from: Alexey Kardashevskiy Cc: Kevin Tian Cc: Joerg Roedel Cc: Will Deacon Cc: Bjorn Helgaas Cc: Jonathan Cameron Cc: Dan Williams Cc: Alexey Kardashevskiy Cc: Samuel Ortiz Cc: Xu Yilun Cc: Jason Gunthorpe Cc: Suzuki K Poulose Cc: Steven Price Signed-off-by: Aneesh Kumar K.V (Arm) --- drivers/iommu/iommufd/iommufd_private.h | 7 ++++ drivers/iommu/iommufd/main.c | 3 ++ drivers/iommu/iommufd/tsm.c | 48 +++++++++++++++++++++++++ drivers/virt/coco/tsm-core.c | 14 ++++++++ include/linux/tsm.h | 26 ++++++++++++++ include/uapi/linux/iommufd.h | 23 ++++++++++++ 6 files changed, 121 insertions(+) diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommuf= d/iommufd_private.h index aa1ceed924c2..7042993913dd 100644 --- a/drivers/iommu/iommufd/iommufd_private.h +++ b/drivers/iommu/iommufd/iommufd_private.h @@ -699,11 +699,18 @@ int iommufd_hw_queue_alloc_ioctl(struct iommufd_ucmd = *ucmd); void iommufd_hw_queue_destroy(struct iommufd_object *obj); #ifdef CONFIG_TSM int iommufd_vdevice_tsm_op_ioctl(struct iommufd_ucmd *ucmd); +int iommufd_vdevice_tsm_guest_request_ioctl(struct iommufd_ucmd *ucmd); #else static inline int iommufd_vdevice_tsm_op_ioctl(struct iommufd_ucmd *ucmd) { return -EOPNOTSUPP; } + +static inline int +iommufd_vdevice_tsm_guest_request_ioctl(struct iommufd_ucmd *ucmd) +{ + return -EOPNOTSUPP; +} #endif =20 static inline struct iommufd_vdevice * diff --git a/drivers/iommu/iommufd/main.c b/drivers/iommu/iommufd/main.c index d73e6b391c6f..7f4bbdd0bda5 100644 --- a/drivers/iommu/iommufd/main.c +++ b/drivers/iommu/iommufd/main.c @@ -433,6 +433,7 @@ union ucmd_buffer { struct iommu_vfio_ioas vfio_ioas; struct iommu_viommu_alloc viommu; struct iommu_vdevice_tsm_op tsm_op; + struct iommu_vdevice_tsm_guest_request gr; #ifdef CONFIG_IOMMUFD_TEST struct iommu_test_cmd test; #endif @@ -496,6 +497,8 @@ static const struct iommufd_ioctl_op iommufd_ioctl_ops[= ] =3D { struct iommu_viommu_alloc, out_viommu_id), IOCTL_OP(IOMMU_VDEVICE_TSM_OP, iommufd_vdevice_tsm_op_ioctl, struct iommu_vdevice_tsm_op, vdevice_id), + IOCTL_OP(IOMMU_VDEVICE_TSM_GUEST_REQUEST, iommufd_vdevice_tsm_guest_reque= st_ioctl, + struct iommu_vdevice_tsm_guest_request, resp_uptr), #ifdef CONFIG_IOMMUFD_TEST IOCTL_OP(IOMMU_TEST_CMD, iommufd_test, struct iommu_test_cmd, last), #endif diff --git a/drivers/iommu/iommufd/tsm.c b/drivers/iommu/iommufd/tsm.c index 401469110752..6b96d0aef25f 100644 --- a/drivers/iommu/iommufd/tsm.c +++ b/drivers/iommu/iommufd/tsm.c @@ -65,3 +65,51 @@ int iommufd_vdevice_tsm_op_ioctl(struct iommufd_ucmd *uc= md) iommufd_put_object(ucmd->ictx, &vdev->obj); return rc; } + +/** + * iommufd_vdevice_tsm_guest_request_ioctl - Forward guest TSM requests + * @ucmd: user command data for IOMMU_VDEVICE_TSM_GUEST_REQUEST + * + * Resolve @iommu_vdevice_tsm_guest_request::vdevice_id to a vdevice and p= ass + * the request/response buffers to the TSM core. + * + * Return: + * -errno on error. + * positive residue if response/request bytes were left unconsumed. + * if response buffer is provided, residue indicates the number of bytes + * not used in response buffer + * if there is no response buffer, residue indicates the number of bytes + * not consumed in req buffer + * 0 otherwise. + */ +int iommufd_vdevice_tsm_guest_request_ioctl(struct iommufd_ucmd *ucmd) +{ + int rc; + struct iommufd_vdevice *vdev; + struct iommu_vdevice_tsm_guest_request *cmd =3D ucmd->cmd; + struct tsm_guest_req_info info =3D { + .scope =3D cmd->scope, + .req =3D { + .user =3D u64_to_user_ptr(cmd->req_uptr), + .is_kernel =3D false, + }, + .req_len =3D cmd->req_len, + .resp =3D { + .user =3D u64_to_user_ptr(cmd->resp_uptr), + .is_kernel =3D false, + }, + .resp_len =3D cmd->resp_len, + }; + + vdev =3D container_of(iommufd_get_object(ucmd->ictx, cmd->vdevice_id, + IOMMUFD_OBJ_VDEVICE), + struct iommufd_vdevice, obj); + if (IS_ERR(vdev)) + return PTR_ERR(vdev); + + rc =3D tsm_guest_req(vdev->idev->dev, &info); + + /* No inline response, hence we don't need to copy the response */ + iommufd_put_object(ucmd->ictx, &vdev->obj); + return rc; +} diff --git a/drivers/virt/coco/tsm-core.c b/drivers/virt/coco/tsm-core.c index f0e35fc38776..317fcb53e4bf 100644 --- a/drivers/virt/coco/tsm-core.c +++ b/drivers/virt/coco/tsm-core.c @@ -259,6 +259,20 @@ int tsm_unbind(struct device *dev) } EXPORT_SYMBOL_GPL(tsm_unbind); =20 +ssize_t tsm_guest_req(struct device *dev, struct tsm_guest_req_info *info) +{ + ssize_t ret; + + if (!dev_is_pci(dev)) + return -EINVAL; + + ret =3D pci_tsm_guest_req(to_pci_dev(dev), info->scope, + info->req, info->req_len, + info->resp, info->resp_len, NULL); + return ret; +} +EXPORT_SYMBOL_GPL(tsm_guest_req); + static void tsm_release(struct device *dev) { struct tsm_dev *tsm_dev =3D container_of(dev, typeof(*tsm_dev), dev); diff --git a/include/linux/tsm.h b/include/linux/tsm.h index 9f2a7868021a..5231d5abf84d 100644 --- a/include/linux/tsm.h +++ b/include/linux/tsm.h @@ -6,6 +6,7 @@ #include #include #include +#include =20 #define TSM_REPORT_INBLOB_MAX 64 #define TSM_REPORT_OUTBLOB_MAX SZ_16M @@ -131,6 +132,24 @@ void tsm_ide_stream_unregister(struct pci_ide *ide); int tsm_bind(struct device *dev, struct kvm *kvm, u64 tdi_id); int tsm_unbind(struct device *dev); =20 +/** + * struct tsm_guest_req_info - parameter for tsm_guest_req() + * @scope: scope for tsm guest request + * @req: request data buffer filled by guest + * @req_len: the size of @req filled by guest + * @resp: response data buffer filled by host + * @resp_len: for input, the size of @resp buffer filled by guest + * for output, the size of actual response data filled by host + */ +struct tsm_guest_req_info { + u32 scope; + sockptr_t req; + size_t req_len; + sockptr_t resp; + size_t resp_len; +}; +ssize_t tsm_guest_req(struct device *dev, struct tsm_guest_req_info *info); + #else =20 static inline int tsm_bind(struct device *dev, struct kvm *kvm, u64 tdi_id) @@ -142,6 +161,13 @@ static inline int tsm_unbind(struct device *dev) { return 0; } + +struct tsm_guest_req_info; +static inline ssize_t tsm_guest_req(struct device *dev, + struct tsm_guest_req_info *info) +{ + return -EINVAL; +} #endif =20 #endif /* __TSM_H */ diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h index 653402e7048a..b0d1ecd81638 100644 --- a/include/uapi/linux/iommufd.h +++ b/include/uapi/linux/iommufd.h @@ -58,6 +58,7 @@ enum { IOMMUFD_CMD_VEVENTQ_ALLOC =3D 0x93, IOMMUFD_CMD_HW_QUEUE_ALLOC =3D 0x94, IOMMUFD_CMD_VDEVICE_TSM_OP =3D 0x95, + IOMMUFD_CMD_VDEVICE_TSM_GUEST_REQUEST =3D 0x96, }; =20 /** @@ -1367,4 +1368,26 @@ struct iommu_hw_queue_alloc { __aligned_u64 length; }; #define IOMMU_HW_QUEUE_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HW_QUEUE_ALLOC) + +/** + * struct iommu_vdevice_tsm_guest_request - ioctl(IOMMU_VDEVICE_TSM_GUEST_= REQUEST) + * @size: sizeof(struct iommu_vdevice_tsm_guest_request) + * @vdevice_id: vDevice ID the guest request is for + * @scope: scope of tsm guest request + * @req_len: the blob size for @req_uptr, filled by guest + * @resp_len: the blob size for @resp_uptr, filled by guest + * @req_uptr: request data buffer filled by guest + * @resp_uptr: response data buffer + */ +struct iommu_vdevice_tsm_guest_request { + __u32 size; + __u32 vdevice_id; + __u32 scope; + __u32 req_len; + __u32 resp_len; + __aligned_u64 req_uptr; + __aligned_u64 resp_uptr; +}; +#define IOMMU_VDEVICE_TSM_GUEST_REQUEST _IO(IOMMUFD_TYPE, IOMMUFD_CMD_VDEV= ICE_TSM_GUEST_REQUEST) + #endif --=20 2.43.0