[PATCH v8 07/15] iommufd/viommu: Keep a reference to the KVM file

From: Aneesh Kumar K.V (Arm)

Date: Wed Nov 04 2026 - 11:39:03 EST


From: Nicolin Chen <nicolinc@xxxxxxxxxx>

The TSM vDevice operations need access to the KVM associated with the
device's vIOMMU. Save the device's KVM file in the iommufd_viommu when the
vIOMMU is allocated, and take a file reference so it remains valid for the
lifetime of the vIOMMU.

Release the reference when the vIOMMU is destroyed.

Reject vdevice allocation when the device's KVM association differs from
the vIOMMU's, including when only one has a KVM association. Allow
allocation when both associations are NULL.

Based on an original patch by
Shameer Kolothum <shameerali.kolothum.thodi@xxxxxxxxxx>

[nicolinc: hold kvm's users_count]
Signed-off-by: Nicolin Chen <nicolinc@xxxxxxxxxx>
[aneesh.kumar: Switch to use kvm_file]
Cc: Jason Gunthorpe <jgg@xxxxxxxx>
Cc: Kevin Tian <kevin.tian@xxxxxxxxx>
Cc: Joerg Roedel <joro@xxxxxxxxxx>
Cc: Will Deacon <will@xxxxxxxxxx>
Cc: Robin Murphy <robin.murphy@xxxxxxx>
Reviewed-by: Jason Gunthorpe <jgg@xxxxxxxxxx>
Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@xxxxxxxxxx>
---
drivers/iommu/iommufd/viommu.c | 10 ++++++++++
include/linux/iommufd.h | 1 +
2 files changed, 11 insertions(+)

diff --git a/drivers/iommu/iommufd/viommu.c b/drivers/iommu/iommufd/viommu.c
index f7951057a1e5..0dbd382eeb98 100644
--- a/drivers/iommu/iommufd/viommu.c
+++ b/drivers/iommu/iommufd/viommu.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES
*/
+#include <linux/file.h>
#include "iommufd_private.h"

void iommufd_viommu_destroy(struct iommufd_object *obj)
@@ -11,6 +12,8 @@ void iommufd_viommu_destroy(struct iommufd_object *obj)
if (viommu->ops && viommu->ops->destroy)
viommu->ops->destroy(viommu);
refcount_dec(&viommu->hwpt->common.obj.users);
+ if (viommu->kvm_file)
+ fput(viommu->kvm_file);
xa_destroy(&viommu->vdevs);
}

@@ -82,6 +85,8 @@ int iommufd_viommu_alloc_ioctl(struct iommufd_ucmd *ucmd)
}

xa_init(&viommu->vdevs);
+ if (idev->kvm_file)
+ viommu->kvm_file = get_file(idev->kvm_file);
viommu->type = cmd->type;
viommu->ictx = ucmd->ictx;
viommu->hwpt = hwpt_paging;
@@ -171,6 +176,11 @@ int iommufd_vdevice_alloc_ioctl(struct iommufd_ucmd *ucmd)
goto out_put_viommu;
}

+ if (idev->kvm_file != viommu->kvm_file) {
+ rc = -EINVAL;
+ goto out_put_idev;
+ }
+
iommu_dev = iommufd_device_get_iommu_dev(idev);
if (!iommu_dev || viommu->iommu_dev != iommu_dev) {
rc = -EINVAL;
diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h
index b03ce0187454..c15d80f611b9 100644
--- a/include/linux/iommufd.h
+++ b/include/linux/iommufd.h
@@ -103,6 +103,7 @@ struct iommufd_viommu {
struct iommufd_ctx *ictx;
struct iommu_device *iommu_dev;
struct iommufd_hwpt_paging *hwpt;
+ struct file *kvm_file;

const struct iommufd_viommu_ops *ops;

--
2.43.0