* [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU
2026-03-09 11:17 [PATCH v2 0/3] Add iommufd ioctls to support TSM operations Aneesh Kumar K.V (Arm)
@ 2026-03-09 11:17 ` Aneesh Kumar K.V (Arm)
2026-03-11 21:18 ` Jonathan Cameron
` (2 more replies)
2026-03-09 11:17 ` [PATCH v2 2/3] iommufd/tsm: add vdevice TSM bind/unbind ioctl Aneesh Kumar K.V (Arm)
2026-03-09 11:17 ` [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl Aneesh Kumar K.V (Arm)
2 siblings, 3 replies; 23+ messages in thread
From: Aneesh Kumar K.V (Arm) @ 2026-03-09 11:17 UTC (permalink / raw)
To: iommu, linux-kernel, kvm
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
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 <kevin.tian@intel.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will@kernel.org>
Cc: Bjorn Helgaas <helgaas@kernel.org>
Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Alexey Kardashevskiy <aik@amd.com>
Cc: Samuel Ortiz <sameo@rivosinc.com>
Cc: Xu Yilun <yilun.xu@linux.intel.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Suzuki K Poulose <Suzuki.Poulose@arm.com>
Cc: Steven Price <steven.price@arm.com>
Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
---
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 <linux/cleanup.h>
+
+#if IS_ENABLED(CONFIG_KVM)
+#include <linux/kvm_host.h>
+
+static int viommu_get_kvm(struct iommufd_viommu *viommu, int kvm_vm_fd)
+{
+ int rc = -EBADF;
+ struct file *filp __free(fput) = fget(kvm_vm_fd);
+
+ if (!file_is_kvm(filp))
+ return rc;
+
+ /* hold the kvm reference via file descriptor */
+ viommu->kvm_filp = 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 = 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
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);
}
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;
- if (cmd->flags || cmd->type == IOMMU_VIOMMU_TYPE_DEFAULT)
+ if (cmd->flags & ~IOMMU_VIOMMU_KVM_FD)
+ return -EOPNOTSUPP;
+ if (cmd->type == IOMMU_VIOMMU_TYPE_DEFAULT)
return -EOPNOTSUPP;
idev = iommufd_get_device(ucmd, cmd->dev_id);
@@ -100,8 +143,17 @@ int iommufd_viommu_alloc_ioctl(struct iommufd_ucmd *ucmd)
goto out_put_hwpt;
}
+ /* get the kvm details if specified. */
+ if (cmd->flags & IOMMU_VIOMMU_KVM_FD) {
+ rc = viommu_get_kvm(viommu, cmd->kvm_vm_fd);
+ if (rc)
+ goto out_put_hwpt;
+ }
+
cmd->out_viommu_id = viommu->obj.id;
rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
+ if (rc)
+ viommu_put_kvm(viommu);
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 <linux/refcount.h>
#include <linux/types.h>
#include <linux/xarray.h>
+#include <linux/file.h>
#include <uapi/linux/iommufd.h>
struct device;
@@ -58,6 +59,7 @@ struct iommufd_object {
unsigned int id;
};
+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;
const struct iommufd_viommu_ops *ops;
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;
};
+/**
+ * define IOMMU_VIOMMU_KVM_FD - Flag indicating a valid KVM VM file descriptor
+ *
+ * Set this flag when allocating a viommu instance that should be associated
+ * 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 IOMMU
* @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 IOMMU's
* virtualization support that is a security-isolated slice of the real IOMMU 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)
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 == &kvm_vm_fops;
}
-EXPORT_SYMBOL_FOR_KVM_INTERNAL(file_is_kvm);
+EXPORT_SYMBOL_GPL(file_is_kvm);
static int kvm_dev_ioctl_create_vm(unsigned long type)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU
2026-03-09 11:17 ` [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU Aneesh Kumar K.V (Arm)
@ 2026-03-11 21:18 ` Jonathan Cameron
2026-03-13 18:27 ` Jason Gunthorpe
2026-03-13 6:15 ` Nicolin Chen
2026-03-13 18:31 ` Jason Gunthorpe
2 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2026-03-11 21:18 UTC (permalink / raw)
To: Aneesh Kumar K.V (Arm)
Cc: iommu, linux-kernel, kvm, Kevin Tian, Joerg Roedel, Will Deacon,
Bjorn Helgaas, Dan Williams, Alexey Kardashevskiy, Samuel Ortiz,
Xu Yilun, Jason Gunthorpe, Suzuki K Poulose, Steven Price
On Mon, 9 Mar 2026 16:47:02 +0530
"Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org> wrote:
> 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 <kevin.tian@intel.com>
> Cc: Joerg Roedel <joro@8bytes.org>
> Cc: Will Deacon <will@kernel.org>
> Cc: Bjorn Helgaas <helgaas@kernel.org>
> Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: Alexey Kardashevskiy <aik@amd.com>
> Cc: Samuel Ortiz <sameo@rivosinc.com>
> Cc: Xu Yilun <yilun.xu@linux.intel.com>
> Cc: Jason Gunthorpe <jgg@ziepe.ca>
> Cc: Suzuki K Poulose <Suzuki.Poulose@arm.com>
> Cc: Steven Price <steven.price@arm.com>
Hi Aneesh,
Given we don't generally want a massive cc list in the git log,
move them below ---
If you are tracking them in your git tree, just add a --- after your sign off
and put them under that.
Also good to +CC everyone in the CC for patches on the cover letter.
I happened not be subscribed to any of the lists that went to so have to
pull it down by hand from lore.
Fairly minor stuff inline.
Thanks,
Jonathan
> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
> ---
> 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 <linux/cleanup.h>
Usually put linux includes before the local ones (though I haven't
checked local conventions in iommufd).
> +
> +#if IS_ENABLED(CONFIG_KVM)
Hmm. Really a question for Jason / Kevin, but so far this file is ifdef free.
Should we keep it that way by spinning this stuff off to a separate .c file,
or maybe use if (IS_ENABLED()) the implementation which I think means
we need a stub for file_is_kvm()?
> +#include <linux/kvm_host.h>
> +
> +static int viommu_get_kvm(struct iommufd_viommu *viommu, int kvm_vm_fd)
> +{
> + int rc = -EBADF;
> + struct file *filp __free(fput) = fget(kvm_vm_fd);
> +
> + if (!file_is_kvm(filp))
> + return rc;
return -EBADF;
and drop the local variable.
> +
> + /* hold the kvm reference via file descriptor */
> + viommu->kvm_filp = 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 = 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
> 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 <linux/refcount.h>
> #include <linux/types.h>
> #include <linux/xarray.h>
> +#include <linux/file.h>
Just based on context in this patch, this smells alphabetical.
I checked it is, so this belongs between errno.h and iommu.h
> #include <uapi/linux/iommufd.h>
>
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU
2026-03-11 21:18 ` Jonathan Cameron
@ 2026-03-13 18:27 ` Jason Gunthorpe
0 siblings, 0 replies; 23+ messages in thread
From: Jason Gunthorpe @ 2026-03-13 18:27 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Aneesh Kumar K.V (Arm), iommu, linux-kernel, kvm, Kevin Tian,
Joerg Roedel, Will Deacon, Bjorn Helgaas, Dan Williams,
Alexey Kardashevskiy, Samuel Ortiz, Xu Yilun, Suzuki K Poulose,
Steven Price
On Wed, Mar 11, 2026 at 09:18:07PM +0000, Jonathan Cameron wrote:
> > +#if IS_ENABLED(CONFIG_KVM)
>
> Hmm. Really a question for Jason / Kevin, but so far this file is ifdef free.
> Should we keep it that way by spinning this stuff off to a separate .c file,
> or maybe use if (IS_ENABLED()) the implementation which I think means
> we need a stub for file_is_kvm()?
I'd prefer we add the stub, then you don't need any of these ifdefs
either..
Jason
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU
2026-03-09 11:17 ` [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU Aneesh Kumar K.V (Arm)
2026-03-11 21:18 ` Jonathan Cameron
@ 2026-03-13 6:15 ` Nicolin Chen
2026-03-13 18:34 ` Jason Gunthorpe
2026-03-16 5:49 ` Aneesh Kumar K.V
2026-03-13 18:31 ` Jason Gunthorpe
2 siblings, 2 replies; 23+ messages in thread
From: Nicolin Chen @ 2026-03-13 6:15 UTC (permalink / raw)
To: Aneesh Kumar K.V (Arm)
Cc: iommu, linux-kernel, kvm, 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
On Mon, Mar 09, 2026 at 04:47:02PM +0530, Aneesh Kumar K.V (Arm) wrote:
> 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.
struct vfio_device has the kvm pointer already. So, I think it
could be forwarded from VFIO side v.s. via userspace ioctl.
Shammer had two patches before and Jason partially reviewed. I
took those for a side project but haven't sent anywhere. Would
you please check if they for you?
https://github.com/nicolinc/iommufd/commits/wip/viommu_kvm
Nicolin
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU
2026-03-13 6:15 ` Nicolin Chen
@ 2026-03-13 18:34 ` Jason Gunthorpe
2026-03-16 5:49 ` Aneesh Kumar K.V
1 sibling, 0 replies; 23+ messages in thread
From: Jason Gunthorpe @ 2026-03-13 18:34 UTC (permalink / raw)
To: Nicolin Chen
Cc: Aneesh Kumar K.V (Arm), iommu, linux-kernel, kvm, Kevin Tian,
Joerg Roedel, Will Deacon, Bjorn Helgaas, Jonathan Cameron,
Dan Williams, Alexey Kardashevskiy, Samuel Ortiz, Xu Yilun,
Suzuki K Poulose, Steven Price
On Thu, Mar 12, 2026 at 11:15:16PM -0700, Nicolin Chen wrote:
> On Mon, Mar 09, 2026 at 04:47:02PM +0530, Aneesh Kumar K.V (Arm) wrote:
> > 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.
>
> struct vfio_device has the kvm pointer already. So, I think it
> could be forwarded from VFIO side v.s. via userspace ioctl.
>
> Shammer had two patches before and Jason partially reviewed. I
> took those for a side project but haven't sent anywhere. Would
> you please check if they for you?
>
> https://github.com/nicolinc/iommufd/commits/wip/viommu_kvm
That looks pretty reasonable
Raises the point we should not allow mixing kvm pointers, so no matter
what the vfio, idev, viommu all need to agree, and the code should
check that too, eg when associating an idev with a viommu
Jason
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU
2026-03-13 6:15 ` Nicolin Chen
2026-03-13 18:34 ` Jason Gunthorpe
@ 2026-03-16 5:49 ` Aneesh Kumar K.V
1 sibling, 0 replies; 23+ messages in thread
From: Aneesh Kumar K.V @ 2026-03-16 5:49 UTC (permalink / raw)
To: Nicolin Chen
Cc: iommu, linux-kernel, kvm, 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
Nicolin Chen <nicolinc@nvidia.com> writes:
> On Mon, Mar 09, 2026 at 04:47:02PM +0530, Aneesh Kumar K.V (Arm) wrote:
>> 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.
>
> struct vfio_device has the kvm pointer already. So, I think it
> could be forwarded from VFIO side v.s. via userspace ioctl.
>
> Shammer had two patches before and Jason partially reviewed. I
> took those for a side project but haven't sent anywhere. Would
> you please check if they for you?
>
> https://github.com/nicolinc/iommufd/commits/wip/viommu_kvm
>
I will use these patches and add additional patches on top of it.
-aneesh
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU
2026-03-09 11:17 ` [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU Aneesh Kumar K.V (Arm)
2026-03-11 21:18 ` Jonathan Cameron
2026-03-13 6:15 ` Nicolin Chen
@ 2026-03-13 18:31 ` Jason Gunthorpe
2 siblings, 0 replies; 23+ messages in thread
From: Jason Gunthorpe @ 2026-03-13 18:31 UTC (permalink / raw)
To: Aneesh Kumar K.V (Arm)
Cc: iommu, linux-kernel, kvm, Kevin Tian, Joerg Roedel, Will Deacon,
Bjorn Helgaas, Jonathan Cameron, Dan Williams,
Alexey Kardashevskiy, Samuel Ortiz, Xu Yilun, Suzuki K Poulose,
Steven Price
On Mon, Mar 09, 2026 at 04:47:02PM +0530, Aneesh Kumar K.V (Arm) wrote:
> 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.
I'd want Sean to approve this..
But given we once discussed it is better to hold on to the file * than
the kvm as it leaks less kvm stuff I think this is the right approach.
> #include <linux/types.h>
> #include <linux/xarray.h>
> +#include <linux/file.h>
> #include <uapi/linux/iommufd.h>
>
> struct device;
> @@ -58,6 +59,7 @@ struct iommufd_object {
> unsigned int id;
> };
>
> +struct kvm;
That is a weird place to put the forward declaration? How about at the
top of the file with the others?
> +/**
> + * define IOMMU_VIOMMU_KVM_FD - Flag indicating a valid KVM VM file descriptor
> + *
> + * Set this flag when allocating a viommu instance that should be associated
> + * 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)
BIT isn't used in this uapi header, lets not start.
Other cases are using an enum to group the flags
> /**
> * 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)
So you can say 'see enum xyz' here
> @@ -1105,6 +1115,7 @@ struct iommu_viommu_alloc {
> __u32 data_len;
> __u32 __reserved;
> __aligned_u64 data_uptr;
> + __s32 kvm_vm_fd;
Add padding to keep to 8 byte alignment
> @@ -5481,7 +5481,7 @@ bool file_is_kvm(struct file *file)
> {
> return file && file->f_op == &kvm_vm_fops;
> }
> -EXPORT_SYMBOL_FOR_KVM_INTERNAL(file_is_kvm);
> +EXPORT_SYMBOL_GPL(file_is_kvm);
Probably put this in its own patch
Jason
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2 2/3] iommufd/tsm: add vdevice TSM bind/unbind ioctl
2026-03-09 11:17 [PATCH v2 0/3] Add iommufd ioctls to support TSM operations Aneesh Kumar K.V (Arm)
2026-03-09 11:17 ` [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU Aneesh Kumar K.V (Arm)
@ 2026-03-09 11:17 ` Aneesh Kumar K.V (Arm)
2026-03-11 21:35 ` Jonathan Cameron
` (2 more replies)
2026-03-09 11:17 ` [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl Aneesh Kumar K.V (Arm)
2 siblings, 3 replies; 23+ messages in thread
From: Aneesh Kumar K.V (Arm) @ 2026-03-09 11:17 UTC (permalink / raw)
To: iommu, linux-kernel, kvm
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
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 <kevin.tian@intel.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will@kernel.org>
Cc: Bjorn Helgaas <helgaas@kernel.org>
Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Alexey Kardashevskiy <aik@amd.com>
Cc: Samuel Ortiz <sameo@rivosinc.com>
Cc: Xu Yilun <yilun.xu@linux.intel.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Suzuki K Poulose <Suzuki.Poulose@arm.com>
Cc: Steven Price <steven.price@arm.com>
Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
---
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 := \
vfio_compat.o \
viommu.o
+iommufd-$(CONFIG_TSM) += tsm.o
+
iommufd-$(CONFIG_IOMMUFD_TEST) += selftest.o
obj-$(CONFIG_IOMMUFD) += iommufd.o
diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/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 *obj);
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
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[] = {
__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 <linux/tsm.h>
+
+/**
+ * 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 = ucmd->cmd;
+
+ if (cmd->flags)
+ return -EOPNOTSUPP;
+
+ vdev = 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 = -ENODEV;
+ goto out_put_vdev;
+ }
+
+ kvm = vdev->viommu->kvm_filp->private_data;
+ if (!kvm) {
+ rc = -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 = tsm_bind(vdev->idev->dev, kvm, vdev->virt_id);
+ break;
+ case IOMMU_VDEVICE_TSM_UNBIND:
+ rc = tsm_unbind(vdev->idev->dev);
+ break;
+ default:
+ rc = -EINVAL;
+ goto out_put_vdev;
+ }
+
+ if (rc)
+ goto out_put_vdev;
+
+ rc = 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 <linux/cleanup.h>
+#include <linux/tsm.h>
#if IS_ENABLED(CONFIG_KVM)
#include <linux/kvm_host.h>
@@ -171,6 +172,8 @@ void iommufd_vdevice_abort(struct iommufd_object *obj)
lockdep_assert_held(&idev->igroup->lock);
+ 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);
+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 = 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, struct 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 = 0x92,
IOMMUFD_CMD_VEVENTQ_ALLOC = 0x93,
IOMMUFD_CMD_HW_QUEUE_ALLOC = 0x94,
+ IOMMUFD_CMD_VDEVICE_TSM_OP = 0x95,
};
/**
@@ -1174,6 +1175,23 @@ enum iommu_veventq_flag {
IOMMU_VEVENTQ_FLAG_LOST_EVENTS = (1U << 0),
};
+/**
+ * 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
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH v2 2/3] iommufd/tsm: add vdevice TSM bind/unbind ioctl
2026-03-09 11:17 ` [PATCH v2 2/3] iommufd/tsm: add vdevice TSM bind/unbind ioctl Aneesh Kumar K.V (Arm)
@ 2026-03-11 21:35 ` Jonathan Cameron
2026-03-13 18:42 ` Jason Gunthorpe
2026-03-13 18:48 ` Jason Gunthorpe
2026-03-16 7:12 ` Tian, Kevin
2 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2026-03-11 21:35 UTC (permalink / raw)
To: Aneesh Kumar K.V (Arm)
Cc: iommu, linux-kernel, kvm, Kevin Tian, Joerg Roedel, Will Deacon,
Bjorn Helgaas, Dan Williams, Alexey Kardashevskiy, Samuel Ortiz,
Xu Yilun, Jason Gunthorpe, Suzuki K Poulose, Steven Price
On Mon, 9 Mar 2026 16:47:03 +0530
"Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org> wrote:
> 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.
> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
Hi Aneesh,
Some superficial code flow suggestions. I've not gotten
my head around the broader picture yet, so may well come back with
more comments later.
Thanks,
Jonathan
> ---
> 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 := \
> vfio_compat.o \
> viommu.o
>
> +iommufd-$(CONFIG_TSM) += tsm.o
> +
Probably no blank line here. Style choices in these are a bit random
though so this is kind of a taste thing.
> iommufd-$(CONFIG_IOMMUFD_TEST) += selftest.o
>
> obj-$(CONFIG_IOMMUFD) += iommufd.o
> 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 <linux/tsm.h>
> +
> +/**
> + * 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 = ucmd->cmd;
> +
> + if (cmd->flags)
> + return -EOPNOTSUPP;
> +
> + vdev = container_of(iommufd_get_object(ucmd->ictx, cmd->vdevice_id,
> + IOMMUFD_OBJ_VDEVICE),
> + struct iommufd_vdevice, obj);
I'd be tempted to do something with a helper function to simplify flow.
obj = iommufd_get_object();...
if (IS_ERR(obj) //I think it can be?
return PTR_ERR(obj);
rc = iommufd_vdevice_do_tsm_op_ioctl(obj, ...) //name could be improved
iommufd_put_object(ucmd->ictx, &vdev->obj);
return rc;
Then the helper function can do direct returns on errors given the
iommfd_object is managed in outer function.
> + if (IS_ERR(vdev))
> + return PTR_ERR(vdev);
> +
> + if (!vdev->viommu->kvm_filp) {
> + rc = -ENODEV;
> + goto out_put_vdev;
> + }
> +
> + kvm = vdev->viommu->kvm_filp->private_data;
> + if (!kvm) {
> + rc = -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 = tsm_bind(vdev->idev->dev, kvm, vdev->virt_id);
> + break;
> + case IOMMU_VDEVICE_TSM_UNBIND:
> + rc = tsm_unbind(vdev->idev->dev);
> + break;
> + default:
> + rc = -EINVAL;
> + goto out_put_vdev;
> + }
> +
> + if (rc)
> + goto out_put_vdev;
> +
> + rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
> +
> +out_put_vdev:
> + iommufd_put_object(ucmd->ictx, &vdev->obj);
> + return rc;
> +}
> 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, struct 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;
Why up here? struct pci_ide is here for the next two calls, so no need
to group with that.
> int tsm_ide_stream_register(struct pci_ide *ide);
> void tsm_ide_stream_unregister(struct pci_ide *ide);
Feels like the forwards def belongs here.
> +#ifdef CONFIG_TSM
> +int tsm_bind(struct device *dev, struct kvm *kvm, u64 tdi_id);
> +int tsm_unbind(struct device *dev);
> +
White space is a bit inconsistent. I don't mind seeing some
here, but if so, add some around the ifdef above.
> +#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 */
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [PATCH v2 2/3] iommufd/tsm: add vdevice TSM bind/unbind ioctl
2026-03-11 21:35 ` Jonathan Cameron
@ 2026-03-13 18:42 ` Jason Gunthorpe
0 siblings, 0 replies; 23+ messages in thread
From: Jason Gunthorpe @ 2026-03-13 18:42 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Aneesh Kumar K.V (Arm), iommu, linux-kernel, kvm, Kevin Tian,
Joerg Roedel, Will Deacon, Bjorn Helgaas, Dan Williams,
Alexey Kardashevskiy, Samuel Ortiz, Xu Yilun, Suzuki K Poulose,
Steven Price
On Wed, Mar 11, 2026 at 09:35:55PM +0000, Jonathan Cameron wrote:
> > +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 = ucmd->cmd;
> > +
> > + if (cmd->flags)
> > + return -EOPNOTSUPP;
> > +
> > + vdev = container_of(iommufd_get_object(ucmd->ictx, cmd->vdevice_id,
> > + IOMMUFD_OBJ_VDEVICE),
> > + struct iommufd_vdevice, obj);
>
> I'd be tempted to do something with a helper function to simplify flow.
It is already
static inline struct iommufd_vdevice *
iommufd_get_vdevice(struct iommufd_ctx *ictx, u32 id)
{
return container_of(iommufd_get_object(ictx, id,
IOMMUFD_OBJ_VDEVICE),
struct iommufd_vdevice, obj);
}
> Then the helper function can do direct returns on errors given the
> iommfd_object is managed in outer function.
Use cleanup.h ? It is not the iommufd style the break things up into
little functions for error unwind reasons
> > + if (!vdev->viommu->kvm_filp) {
> > + rc = -ENODEV;
> > + goto out_put_vdev;
> > + }
> > +
> > + kvm = vdev->viommu->kvm_filp->private_data;
> > + if (!kvm) {
Ah this I don't think you should be doing. That needs a helper from
kvm
Jason
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 2/3] iommufd/tsm: add vdevice TSM bind/unbind ioctl
2026-03-09 11:17 ` [PATCH v2 2/3] iommufd/tsm: add vdevice TSM bind/unbind ioctl Aneesh Kumar K.V (Arm)
2026-03-11 21:35 ` Jonathan Cameron
@ 2026-03-13 18:48 ` Jason Gunthorpe
2026-03-16 7:12 ` Tian, Kevin
2 siblings, 0 replies; 23+ messages in thread
From: Jason Gunthorpe @ 2026-03-13 18:48 UTC (permalink / raw)
To: Aneesh Kumar K.V (Arm)
Cc: iommu, linux-kernel, kvm, Kevin Tian, Joerg Roedel, Will Deacon,
Bjorn Helgaas, Jonathan Cameron, Dan Williams,
Alexey Kardashevskiy, Samuel Ortiz, Xu Yilun, Suzuki K Poulose,
Steven Price
On Mon, Mar 09, 2026 at 04:47:03PM +0530, Aneesh Kumar K.V (Arm) wrote:
> @@ -1174,6 +1175,23 @@ enum iommu_veventq_flag {
> IOMMU_VEVENTQ_FLAG_LOST_EVENTS = (1U << 0),
> };
>
> +/**
> + * 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
use enum for an op, put it before the struct, add kdocs for the enum
members.
Jason
^ permalink raw reply [flat|nested] 23+ messages in thread* RE: [PATCH v2 2/3] iommufd/tsm: add vdevice TSM bind/unbind ioctl
2026-03-09 11:17 ` [PATCH v2 2/3] iommufd/tsm: add vdevice TSM bind/unbind ioctl Aneesh Kumar K.V (Arm)
2026-03-11 21:35 ` Jonathan Cameron
2026-03-13 18:48 ` Jason Gunthorpe
@ 2026-03-16 7:12 ` Tian, Kevin
2026-03-16 8:45 ` Aneesh Kumar K.V
2 siblings, 1 reply; 23+ messages in thread
From: Tian, Kevin @ 2026-03-16 7:12 UTC (permalink / raw)
To: Aneesh Kumar K.V (Arm), iommu@lists.linux.dev,
linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Cc: Joerg Roedel, Will Deacon, Bjorn Helgaas, Jonathan Cameron,
Williams, Dan J, Alexey Kardashevskiy, Samuel Ortiz, Xu Yilun,
Jason Gunthorpe, Suzuki K Poulose, Steven Price
> From: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
> Sent: Monday, March 9, 2026 7:17 PM
>
> Introduce IOMMU_VDEVICE_TSM_OP to allow userspace to issue TSM
> bind/unbind
> operations for an iommufd vdevice.
How many ops are planned? If just a few I'd prefer to openly defining
it:
IOMMU_VDEVICE_ALLOC,
IOMMU_VDEVICE_TSM_BIND,
IOMMU_VDEVICE_TSM_UNBIND,
just like how we did for IOAS.
> @@ -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;
please follow the alphabetical order
> @@ -493,6 +494,8 @@ static const struct iommufd_ioctl_op
> iommufd_ioctl_ops[] = {
> __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),
ditto
> +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 = ucmd->cmd;
> +
> + if (cmd->flags)
> + return -EOPNOTSUPP;
> +
> + vdev = 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 = -ENODEV;
> + goto out_put_vdev;
> + }
> +
> + kvm = vdev->viommu->kvm_filp->private_data;
> + if (!kvm) {
> + rc = -ENODEV;
> + goto out_put_vdev;
> + }
if (!vdev->viommu->kvm_filp ||
!vdev->viommu->kvm_filp->private_data) {
rc = -ENODEV;
goto out_put_vdev;
}
kvm = vdev->viommu->kvm_filp->private_data;
^ permalink raw reply [flat|nested] 23+ messages in thread* RE: [PATCH v2 2/3] iommufd/tsm: add vdevice TSM bind/unbind ioctl
2026-03-16 7:12 ` Tian, Kevin
@ 2026-03-16 8:45 ` Aneesh Kumar K.V
0 siblings, 0 replies; 23+ messages in thread
From: Aneesh Kumar K.V @ 2026-03-16 8:45 UTC (permalink / raw)
To: Tian, Kevin, iommu@lists.linux.dev, linux-kernel@vger.kernel.org,
kvm@vger.kernel.org
Cc: Joerg Roedel, Will Deacon, Bjorn Helgaas, Jonathan Cameron,
Williams, Dan J, Alexey Kardashevskiy, Samuel Ortiz, Xu Yilun,
Jason Gunthorpe, Suzuki K Poulose, Steven Price
"Tian, Kevin" <kevin.tian@intel.com> writes:
>> From: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
>> Sent: Monday, March 9, 2026 7:17 PM
>>
>> Introduce IOMMU_VDEVICE_TSM_OP to allow userspace to issue TSM
>> bind/unbind
>> operations for an iommufd vdevice.
>
> How many ops are planned? If just a few I'd prefer to openly defining
> it:
>
> IOMMU_VDEVICE_ALLOC,
> IOMMU_VDEVICE_TSM_BIND,
> IOMMU_VDEVICE_TSM_UNBIND,
>
> just like how we did for IOAS.
>
Right now only TSM_BIND and TSM_UNBIND. This was done based on earlier
review feedback.
https://lore.kernel.org/all/20250530181842.GU233377@nvidia.com/
>
>> @@ -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;
>
> please follow the alphabetical order
>
>> @@ -493,6 +494,8 @@ static const struct iommufd_ioctl_op
>> iommufd_ioctl_ops[] = {
>> __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),
>
> ditto
>
>> +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 = ucmd->cmd;
>> +
>> + if (cmd->flags)
>> + return -EOPNOTSUPP;
>> +
>> + vdev = 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 = -ENODEV;
>> + goto out_put_vdev;
>> + }
>> +
>> + kvm = vdev->viommu->kvm_filp->private_data;
>> + if (!kvm) {
>> + rc = -ENODEV;
>> + goto out_put_vdev;
>> + }
>
> if (!vdev->viommu->kvm_filp ||
> !vdev->viommu->kvm_filp->private_data) {
> rc = -ENODEV;
> goto out_put_vdev;
> }
>
> kvm = vdev->viommu->kvm_filp->private_data;
-aneesh
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
2026-03-09 11:17 [PATCH v2 0/3] Add iommufd ioctls to support TSM operations Aneesh Kumar K.V (Arm)
2026-03-09 11:17 ` [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU Aneesh Kumar K.V (Arm)
2026-03-09 11:17 ` [PATCH v2 2/3] iommufd/tsm: add vdevice TSM bind/unbind ioctl Aneesh Kumar K.V (Arm)
@ 2026-03-09 11:17 ` Aneesh Kumar K.V (Arm)
2026-03-11 21:43 ` Jonathan Cameron
` (2 more replies)
2 siblings, 3 replies; 23+ messages in thread
From: Aneesh Kumar K.V (Arm) @ 2026-03-09 11:17 UTC (permalink / raw)
To: iommu, linux-kernel, kvm
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
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 <aik@amd.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will@kernel.org>
Cc: Bjorn Helgaas <helgaas@kernel.org>
Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Alexey Kardashevskiy <aik@amd.com>
Cc: Samuel Ortiz <sameo@rivosinc.com>
Cc: Xu Yilun <yilun.xu@linux.intel.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Suzuki K Poulose <Suzuki.Poulose@arm.com>
Cc: Steven Price <steven.price@arm.com>
Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
---
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/iommufd/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
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[] = {
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_request_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 *ucmd)
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 pass
+ * 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 = ucmd->cmd;
+ struct tsm_guest_req_info info = {
+ .scope = cmd->scope,
+ .req = {
+ .user = u64_to_user_ptr(cmd->req_uptr),
+ .is_kernel = false,
+ },
+ .req_len = cmd->req_len,
+ .resp = {
+ .user = u64_to_user_ptr(cmd->resp_uptr),
+ .is_kernel = false,
+ },
+ .resp_len = cmd->resp_len,
+ };
+
+ vdev = 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 = 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);
+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 = 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 = 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 <linux/types.h>
#include <linux/uuid.h>
#include <linux/device.h>
+#include <linux/sockptr.h>
#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);
+/**
+ * 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
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
#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 = 0x93,
IOMMUFD_CMD_HW_QUEUE_ALLOC = 0x94,
IOMMUFD_CMD_VDEVICE_TSM_OP = 0x95,
+ IOMMUFD_CMD_VDEVICE_TSM_GUEST_REQUEST = 0x96,
};
/**
@@ -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_VDEVICE_TSM_GUEST_REQUEST)
+
#endif
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
2026-03-09 11:17 ` [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl Aneesh Kumar K.V (Arm)
@ 2026-03-11 21:43 ` Jonathan Cameron
2026-03-13 18:46 ` Jason Gunthorpe
2026-03-13 18:49 ` Jason Gunthorpe
2026-03-16 7:31 ` Tian, Kevin
2 siblings, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2026-03-11 21:43 UTC (permalink / raw)
To: Aneesh Kumar K.V (Arm)
Cc: iommu, linux-kernel, kvm, Kevin Tian, Joerg Roedel, Will Deacon,
Bjorn Helgaas, Dan Williams, Alexey Kardashevskiy, Samuel Ortiz,
Xu Yilun, Jason Gunthorpe, Suzuki K Poulose, Steven Price
On Mon, 9 Mar 2026 16:47:04 +0530
"Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org> wrote:
> 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 <aik@amd.com>
> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
Minor stuff inline.
thanks,
Jonathan
> 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 *ucmd)
> 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 pass
> + * 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 = ucmd->cmd;
> + struct tsm_guest_req_info info = {
> + .scope = cmd->scope,
> + .req = {
> + .user = u64_to_user_ptr(cmd->req_uptr),
> + .is_kernel = false,
> + },
> + .req_len = cmd->req_len,
> + .resp = {
> + .user = u64_to_user_ptr(cmd->resp_uptr),
> + .is_kernel = false,
> + },
> + .resp_len = cmd->resp_len,
> + };
> +
> + vdev = container_of(iommufd_get_object(ucmd->ictx, cmd->vdevice_id,
> + IOMMUFD_OBJ_VDEVICE),
As in previous, can the object be PTR_ERR()? Maybe not, but I'd
be surprised if the static analysis tools are convinced.
This might work for now if obj is first element but that's not
elegant or matainable.
> + struct iommufd_vdevice, obj);
> + if (IS_ERR(vdev))
> + return PTR_ERR(vdev);
> +
> + rc = tsm_guest_req(vdev->idev->dev, &info);
This is otherwise effectively the pattern I'm suggesting for previous patch.
> +
> + /* 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);
>
> +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 = pci_tsm_guest_req(to_pci_dev(dev), info->scope,
> + info->req, info->req_len,
> + info->resp, info->resp_len, NULL);
> + return ret;
return pci_tsm....
Given there are no more patches in this series that much change that.
> +}
> +EXPORT_SYMBOL_GPL(tsm_guest_req);
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
2026-03-11 21:43 ` Jonathan Cameron
@ 2026-03-13 18:46 ` Jason Gunthorpe
0 siblings, 0 replies; 23+ messages in thread
From: Jason Gunthorpe @ 2026-03-13 18:46 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Aneesh Kumar K.V (Arm), iommu, linux-kernel, kvm, Kevin Tian,
Joerg Roedel, Will Deacon, Bjorn Helgaas, Dan Williams,
Alexey Kardashevskiy, Samuel Ortiz, Xu Yilun, Suzuki K Poulose,
Steven Price
On Wed, Mar 11, 2026 at 09:43:43PM +0000, Jonathan Cameron wrote:
> > + vdev = container_of(iommufd_get_object(ucmd->ictx, cmd->vdevice_id,
> > + IOMMUFD_OBJ_VDEVICE),
>
> As in previous, can the object be PTR_ERR()? Maybe not, but I'd
> be surprised if the static analysis tools are convinced.
> This might work for now if obj is first element but that's not
> elegant or matainable.
The compiler enforces first element:
#define __iommufd_object_alloc(ictx, ptr, type, obj) \
container_of(_iommufd_object_alloc( \
ictx, \
sizeof(*(ptr)) + BUILD_BUG_ON_ZERO( \
offsetof(typeof(*(ptr)), \
obj) != 0), \
type), \
typeof(*(ptr)), obj)
I have a lovely little series
https://github.com/jgunthorpe/linux/commits/container_of/
For this that I keep meaning to send but then never do
Jason
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
2026-03-09 11:17 ` [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl Aneesh Kumar K.V (Arm)
2026-03-11 21:43 ` Jonathan Cameron
@ 2026-03-13 18:49 ` Jason Gunthorpe
2026-03-13 22:17 ` Dan Williams
2026-03-16 5:47 ` Aneesh Kumar K.V
2026-03-16 7:31 ` Tian, Kevin
2 siblings, 2 replies; 23+ messages in thread
From: Jason Gunthorpe @ 2026-03-13 18:49 UTC (permalink / raw)
To: Aneesh Kumar K.V (Arm)
Cc: iommu, linux-kernel, kvm, Kevin Tian, Joerg Roedel, Will Deacon,
Bjorn Helgaas, Jonathan Cameron, Dan Williams,
Alexey Kardashevskiy, Samuel Ortiz, Xu Yilun, Suzuki K Poulose,
Steven Price
On Mon, Mar 09, 2026 at 04:47:04PM +0530, Aneesh Kumar K.V (Arm) wrote:
> +/**
> + * 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
> + */
This needs a much better kdoc.
Refer to specs that define this.
Explain WTF scope is
> +struct iommu_vdevice_tsm_guest_request {
> + __u32 size;
> + __u32 vdevice_id;
> + __u32 scope;
> + __u32 req_len;
> + __u32 resp_len;
do not leave implicit padding, add a reserved, and check it is 0
Jason
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
2026-03-13 18:49 ` Jason Gunthorpe
@ 2026-03-13 22:17 ` Dan Williams
2026-03-16 7:25 ` Tian, Kevin
2026-03-16 5:47 ` Aneesh Kumar K.V
1 sibling, 1 reply; 23+ messages in thread
From: Dan Williams @ 2026-03-13 22:17 UTC (permalink / raw)
To: Jason Gunthorpe, Aneesh Kumar K.V (Arm)
Cc: iommu, linux-kernel, kvm, Kevin Tian, Joerg Roedel, Will Deacon,
Bjorn Helgaas, Jonathan Cameron, Dan Williams,
Alexey Kardashevskiy, Samuel Ortiz, Xu Yilun, Suzuki K Poulose,
Steven Price
Jason Gunthorpe wrote:
> On Mon, Mar 09, 2026 at 04:47:04PM +0530, Aneesh Kumar K.V (Arm) wrote:
> > +/**
> > + * 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
> > + */
>
> This needs a much better kdoc.
>
> Refer to specs that define this.
>
> Explain WTF scope is
I proposed @scope, yes this needs more documentation, but really it
needs more discussion first. It was inspired by 'enum fwctl_rpc_scope'
Guests that are moving the device through the TDISP setup state machine
need to ask for host services because only the host passes messages over
SPDM in all of these architectures. That is, one SPDM session per
physical device, not per assigned virtual function. In the AMD case
there is less guest direct access to the TSM so it needs to pass
additional messages that the CPU mode based TSMs do not.
Those requests are varying degrees of: host kernel cares, host kernel
does not care but can see the contents of the message, and host kernel
does not care and can not see the contents of the message beyond
envelope.
As far as the host kernel security model is concerned this becomes a
opaque implementation specific passthrough. So the role of @scope is to
have the TSM drivers declare the security model for various messages.
Put the explicit onus on the implmentations to declare that the
guest_request operation being executed in response to a KVM exit is
contained within a given security scope. See 'enum pci_tsm_req_scope'.
^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
2026-03-13 22:17 ` Dan Williams
@ 2026-03-16 7:25 ` Tian, Kevin
0 siblings, 0 replies; 23+ messages in thread
From: Tian, Kevin @ 2026-03-16 7:25 UTC (permalink / raw)
To: Williams, Dan J, Jason Gunthorpe, Aneesh Kumar K.V (Arm)
Cc: iommu@lists.linux.dev, linux-kernel@vger.kernel.org,
kvm@vger.kernel.org, Joerg Roedel, Will Deacon, Bjorn Helgaas,
Jonathan Cameron, Alexey Kardashevskiy, Samuel Ortiz, Xu Yilun,
Suzuki K Poulose, Steven Price
> From: Williams, Dan J <dan.j.williams@intel.com>
> Sent: Saturday, March 14, 2026 6:18 AM
>
> Jason Gunthorpe wrote:
> > On Mon, Mar 09, 2026 at 04:47:04PM +0530, Aneesh Kumar K.V (Arm)
> wrote:
> > > +/**
> > > + * 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
> > > + */
> >
> > This needs a much better kdoc.
> >
> > Refer to specs that define this.
> >
> > Explain WTF scope is
>
> I proposed @scope, yes this needs more documentation, but really it
> needs more discussion first. It was inspired by 'enum fwctl_rpc_scope'
>
> Guests that are moving the device through the TDISP setup state machine
> need to ask for host services because only the host passes messages over
> SPDM in all of these architectures. That is, one SPDM session per
> physical device, not per assigned virtual function. In the AMD case
> there is less guest direct access to the TSM so it needs to pass
> additional messages that the CPU mode based TSMs do not.
>
> Those requests are varying degrees of: host kernel cares, host kernel
> does not care but can see the contents of the message, and host kernel
> does not care and can not see the contents of the message beyond
> envelope.
"host kernel cares" means that the host kernel may check CAP_SYS_RAW_IO
or taint itself to limit commands according to the description of
enum pci_tsm_req_scope?
interestingly commit c316c75d57fb ("PCI/TSM: Add pci_tsm_guest_req()
for managing TDIs ") has the following description:
"
This path is purely a transport for messages from TVM to platform TSM. By
design the host kernel does not and must not care about the content of
these messages. I.e. the host kernel is not in the TCB of the TVM.
"
how to associate "must not care" with above "host kernel cares"?
>
> As far as the host kernel security model is concerned this becomes a
> opaque implementation specific passthrough. So the role of @scope is to
> have the TSM drivers declare the security model for various messages.
> Put the explicit onus on the implmentations to declare that the
> guest_request operation being executed in response to a KVM exit is
> contained within a given security scope. See 'enum pci_tsm_req_scope'.
dumb question - what about a malicious userspace specifies a scope
with a smaller value than what's defined for a request? Would (could) the
tsm driver verify that it’s a wrong value (but if it can then why we need
this field at all)?
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
2026-03-13 18:49 ` Jason Gunthorpe
2026-03-13 22:17 ` Dan Williams
@ 2026-03-16 5:47 ` Aneesh Kumar K.V
2026-03-16 7:28 ` Tian, Kevin
1 sibling, 1 reply; 23+ messages in thread
From: Aneesh Kumar K.V @ 2026-03-16 5:47 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: iommu, linux-kernel, kvm, Kevin Tian, Joerg Roedel, Will Deacon,
Bjorn Helgaas, Jonathan Cameron, Dan Williams,
Alexey Kardashevskiy, Samuel Ortiz, Xu Yilun, Suzuki K Poulose,
Steven Price
Jason Gunthorpe <jgg@ziepe.ca> writes:
> On Mon, Mar 09, 2026 at 04:47:04PM +0530, Aneesh Kumar K.V (Arm) wrote:
>> +/**
>> + * 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
>> + */
>
> This needs a much better kdoc.
>
> Refer to specs that define this.
>
> Explain WTF scope is
>
>> +struct iommu_vdevice_tsm_guest_request {
>> + __u32 size;
>> + __u32 vdevice_id;
>> + __u32 scope;
>> + __u32 req_len;
>> + __u32 resp_len;
>
> do not leave implicit padding, add a reserved, and check it is 0
>
> Jason
How about this change?
modified drivers/iommu/iommufd/tsm.c
@@ -94,6 +94,9 @@ int iommufd_vdevice_tsm_guest_request_ioctl(struct iommufd_ucmd *ucmd)
.resp_len = cmd->resp_len,
};
+ if (cmd->__reserved)
+ return -EOPNOTSUPP;
+
vdev = iommufd_get_vdevice(ucmd->ictx, cmd->vdevice_id);
if (IS_ERR(vdev))
return PTR_ERR(vdev);
modified include/uapi/linux/iommufd.h
@@ -1370,11 +1370,27 @@ struct iommu_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
+ * @scope: Scope classification of the guest request, one of enum
+ * pci_tsm_req_scope values accepted by pci_tsm_guest_req()
+ * @req_len: Size in bytes of the input payload at @req_uptr
+ * @resp_len: Size in bytes of the output buffer at @resp_uptr
+ * @__reserved: Must be 0
+ * @req_uptr: Userspace pointer to the guest-provided request payload
+ * @resp_uptr: Userspace pointer to the guest response buffer
+ *
+ * Forward a guest request to the TSM bound vDevice. This is intended for
+ * guest TSM/TDISP message transport where the host kernel only marshals
+ * bytes between userspace and the TSM implementation.
+ *
+ * @scope limits requests to TDISP state management, or limited debug.
+ * Requests outside the allowed scope are rejected.
+ *
+ * The request payload is read from @req_uptr/@req_len. If a response is
+ * expected, userspace provides @resp_uptr/@resp_len as writable storage for
+ * response bytes returned by the TSM path.
+ *
+ * The ioctl is only suitable for commands and results that the host kernel
+ * has no use, the host is only facilitating guest to TSM communication.
*/
struct iommu_vdevice_tsm_guest_request {
__u32 size;
@@ -1382,6 +1398,7 @@ struct iommu_vdevice_tsm_guest_request {
__u32 scope;
__u32 req_len;
__u32 resp_len;
+ __u32 __reserved;
__aligned_u64 req_uptr;
__aligned_u64 resp_uptr;
};
^ permalink raw reply [flat|nested] 23+ messages in thread* RE: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
2026-03-16 5:47 ` Aneesh Kumar K.V
@ 2026-03-16 7:28 ` Tian, Kevin
0 siblings, 0 replies; 23+ messages in thread
From: Tian, Kevin @ 2026-03-16 7:28 UTC (permalink / raw)
To: Aneesh Kumar K.V, Jason Gunthorpe
Cc: iommu@lists.linux.dev, linux-kernel@vger.kernel.org,
kvm@vger.kernel.org, Joerg Roedel, Will Deacon, Bjorn Helgaas,
Jonathan Cameron, Williams, Dan J, Alexey Kardashevskiy,
Samuel Ortiz, Xu Yilun, Suzuki K Poulose, Steven Price
> From: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
> Sent: Monday, March 16, 2026 1:48 PM
> + * @scope: Scope classification of the guest request, one of enum
> + * pci_tsm_req_scope values accepted by pci_tsm_guest_req()
from what this patch does the tsm core supports device types other
than PCI (though currently only PCI is supported).
suppose there may be other bus-specific scope values accepted?
if yes here better say that for the meaning of scope values please
refer to bus specific tsm definitions. Then in the following detailed
description take PCI as an example referring to pci_tsm_req_scope.
^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl
2026-03-09 11:17 ` [PATCH v2 3/3] iommufd/vdevice: add TSM guest request ioctl Aneesh Kumar K.V (Arm)
2026-03-11 21:43 ` Jonathan Cameron
2026-03-13 18:49 ` Jason Gunthorpe
@ 2026-03-16 7:31 ` Tian, Kevin
2 siblings, 0 replies; 23+ messages in thread
From: Tian, Kevin @ 2026-03-16 7:31 UTC (permalink / raw)
To: Aneesh Kumar K.V (Arm), iommu@lists.linux.dev,
linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Cc: Joerg Roedel, Will Deacon, Bjorn Helgaas, Jonathan Cameron,
Williams, Dan J, Alexey Kardashevskiy, Samuel Ortiz, Xu Yilun,
Jason Gunthorpe, Suzuki K Poulose, Steven Price
> From: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
> Sent: Monday, March 9, 2026 7:17 PM
>
> Add IOMMU_VDEVICE_TSM_GUEST_REQUEST for issuing TSM guest
> request/response
> transactions against an iommufd vdevice.
Does adding '_GUEST_' in the name give any meaningful context?
It's a transparent interface connecting to tsm. why do we care
whether this request actually comes from guest or from the VMM
itself? will there be a TSM_HOST_REQUEST in the future?
I know this has been made this way in many places in this path.
but from uapi p.o.v. let's stick to the minimal required naming.
>
> 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.
tsm cores use "TVM". let's be consistent here (regarding to 'CoCo guests')
^ permalink raw reply [flat|nested] 23+ messages in thread