[PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU

Aneesh Kumar K.V (Arm) posted 3 patches 1 month ago
[PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU
Posted by Aneesh Kumar K.V (Arm) 1 month ago
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
Re: [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU
Posted by Jason Gunthorpe 3 weeks, 5 days ago
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
Re: [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU
Posted by Nicolin Chen 3 weeks, 6 days ago
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
Re: [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU
Posted by Aneesh Kumar K.V 3 weeks, 3 days ago
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
Re: [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU
Posted by Jason Gunthorpe 3 weeks, 5 days ago
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
Re: [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU
Posted by Jonathan Cameron 4 weeks ago
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>
>
Re: [PATCH v2 1/3] iommufd/viommu: Allow associating a KVM VM fd with a vIOMMU
Posted by Jason Gunthorpe 3 weeks, 5 days ago
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