From: "Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>
To: linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org
Cc: "Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>,
Ackerley Tng <ackerleytng@google.com>,
Alex Williamson <alex@shazbot.org>,
David Woodhouse <dwmw2@infradead.org>,
David Hildenbrand <david@kernel.org>,
Jason Gunthorpe <jgg@ziepe.ca>,
"Joerg Roedel (AMD)" <joro@8bytes.org>,
Kevin Tian <kevin.tian@intel.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Robin Murphy <robin.murphy@arm.com>,
Sean Christopherson <seanjc@google.com>,
Will Deacon <will@kernel.org>, Alexey Kardashevskiy <aik@amd.com>,
Xu Yilun <yilun.xu@linux.intel.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Steven Price <steven.price@arm.com>,
Fred Griffoul <griffoul@gmail.com>,
iommu@lists.linux.dev, kvm@vger.kernel.org
Subject: [RFC PATCH v1 3/6] iommufd: Support MMIO provider attachment to vDEVICEs
Date: Sat, 10 Oct 2026 12:55:01 +0530 [thread overview]
Message-ID: <20261010072504.536230-4-aneesh.kumar@kernel.org> (raw)
In-Reply-To: <20261010072504.536230-1-aneesh.kumar@kernel.org>
Allow a device MMIO provider to attach to the existing vDEVICE after the
backend validates its association with the VM. Keep the vDEVICE and
IOMMUFD context alive until the provider detaches.
Add a per-vDEVICE MMIO mutex to serialize provider attachment and
detachment, and allow providers and backends to use the same lock for
memory conversion and device state changes. Provide callbacks to
invalidate MMIO mappings and query whether private ranges remain.
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: "Joerg Roedel (AMD)" <joro@8bytes.org>
Cc: Will Deacon <will@kernel.org>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: iommu@lists.linux.dev
Cc: linux-kernel@vger.kernel.org
Assisted-by: Codex
Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
---
drivers/iommu/iommufd/viommu.c | 90 ++++++++++++++++++++++++++++++++++
include/linux/iommufd.h | 33 +++++++++++++
2 files changed, 123 insertions(+)
diff --git a/drivers/iommu/iommufd/viommu.c b/drivers/iommu/iommufd/viommu.c
index 9155d0dcb4b4..24a817fb2ae8 100644
--- a/drivers/iommu/iommufd/viommu.c
+++ b/drivers/iommu/iommufd/viommu.c
@@ -250,6 +250,7 @@ int iommufd_vdevice_alloc_ioctl(struct iommufd_ucmd *ucmd)
goto out_unlock_igroup;
}
+ mutex_init(&vdev->mmio_lock);
vdev->virt_id = virt_id;
vdev->viommu = viommu;
refcount_inc(&viommu->obj.users);
@@ -487,3 +488,92 @@ int iommufd_hw_queue_alloc_ioctl(struct iommufd_ucmd *ucmd)
iommufd_put_object(ucmd->ictx, &viommu->obj);
return rc;
}
+
+struct iommufd_vdevice *
+iommufd_device_attach_mmio_provider(struct iommufd_device *idev,
+ struct kvm *kvm, void *data,
+ void (*invalidate_mmio)(void *),
+ bool (*has_private_mmio)(void *),
+ unsigned long *owner)
+{
+ struct iommufd_vdevice *vdev;
+ int ret;
+
+ if (!idev)
+ return ERR_PTR(-ENODEV);
+
+ guard(mutex)(&idev->igroup->lock);
+ if (idev->destroying)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ vdev = idev->vdev;
+ if (!vdev)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ if (!vdev->viommu->ops ||
+ !vdev->viommu->ops->vdevice_get_mmio_owner)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ guard(mutex)(&vdev->mmio_lock);
+ if (vdev->mmio_provider_data)
+ return ERR_PTR(-EBUSY);
+
+ ret = vdev->viommu->ops->vdevice_get_mmio_owner(vdev, kvm, owner);
+ if (ret)
+ return ERR_PTR(ret);
+
+ /* IOMMU_DESTROY must wait for the attached gmem provider to detach. */
+ ret = iommufd_try_inc_users(idev->ictx, &vdev->obj);
+ if (ret)
+ return ERR_PTR(ret);
+
+ iommufd_ctx_get(idev->ictx);
+ vdev->mmio_provider_data = data;
+ vdev->invalidate_mmio = invalidate_mmio;
+ vdev->has_private_mmio = has_private_mmio;
+ invalidate_mmio(data);
+ return vdev;
+}
+EXPORT_SYMBOL_NS_GPL(iommufd_device_attach_mmio_provider, "IOMMUFD");
+
+void iommufd_vdevice_detach_mmio_provider(struct iommufd_vdevice *vdev)
+{
+ struct iommufd_ctx *ictx = vdev->viommu->ictx;
+
+ scoped_guard(mutex, &vdev->mmio_lock) {
+ WARN_ON(iommufd_vdevice_has_private_mmio(vdev));
+ vdev->mmio_provider_data = NULL;
+ vdev->invalidate_mmio = NULL;
+ vdev->has_private_mmio = NULL;
+ }
+ refcount_dec(&vdev->obj.users);
+ iommufd_ctx_put(ictx);
+}
+EXPORT_SYMBOL_NS_GPL(iommufd_vdevice_detach_mmio_provider, "IOMMUFD");
+
+void iommufd_vdevice_mmio_lock(struct iommufd_vdevice *vdev)
+{
+ mutex_lock(&vdev->mmio_lock);
+}
+EXPORT_SYMBOL_NS_GPL(iommufd_vdevice_mmio_lock, "IOMMUFD");
+
+void iommufd_vdevice_mmio_unlock(struct iommufd_vdevice *vdev)
+{
+ mutex_unlock(&vdev->mmio_lock);
+}
+EXPORT_SYMBOL_NS_GPL(iommufd_vdevice_mmio_unlock, "IOMMUFD");
+
+/**
+ * iommufd_vdevice_has_private_mmio() - check for private MMIO ranges
+ * @vdev: vDEVICE whose private MMIO state is being checked
+ *
+ * Return: true if the attached provider has committed private ranges.
+ */
+bool iommufd_vdevice_has_private_mmio(struct iommufd_vdevice *vdev)
+{
+ lockdep_assert_held(&vdev->mmio_lock);
+ if (!vdev->has_private_mmio)
+ return false;
+ return vdev->has_private_mmio(vdev->mmio_provider_data);
+}
+EXPORT_SYMBOL_NS_GPL(iommufd_vdevice_has_private_mmio, "IOMMUFD");
diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h
index 2e67846d6f35..3f3b9d1dd22a 100644
--- a/include/linux/iommufd.h
+++ b/include/linux/iommufd.h
@@ -7,10 +7,12 @@
#define __LINUX_IOMMUFD_H
#include <linux/bits.h>
+#include <linux/cleanup.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/iommu.h>
#include <linux/refcount.h>
+#include <linux/mutex.h>
#include <linux/types.h>
#include <linux/xarray.h>
#include <uapi/linux/iommufd.h>
@@ -26,6 +28,7 @@ struct iommufd_device;
struct iommufd_viommu_ops;
struct tsm_dev;
struct page;
+struct kvm;
struct tsm_guest_req_info;
enum iommufd_object_type {
@@ -73,6 +76,20 @@ int iommufd_device_replace(struct iommufd_device *idev, ioasid_t pasid,
u32 *pt_id);
void iommufd_device_detach(struct iommufd_device *idev, ioasid_t pasid);
+/* The returned opaque vDEVICE pins its IOMMUFD context and physical owner. */
+struct iommufd_vdevice *
+iommufd_device_attach_mmio_provider(struct iommufd_device *idev,
+ struct kvm *kvm, void *data,
+ void (*invalidate_mmio)(void *),
+ bool (*has_private_mmio)(void *),
+ unsigned long *owner);
+void iommufd_vdevice_detach_mmio_provider(struct iommufd_vdevice *vdev);
+void iommufd_vdevice_mmio_lock(struct iommufd_vdevice *vdev);
+void iommufd_vdevice_mmio_unlock(struct iommufd_vdevice *vdev);
+DEFINE_GUARD(iommufd_vdevice_mmio, struct iommufd_vdevice *,
+ iommufd_vdevice_mmio_lock(_T), iommufd_vdevice_mmio_unlock(_T))
+bool iommufd_vdevice_has_private_mmio(struct iommufd_vdevice *vdev);
+
struct iommufd_ctx *iommufd_device_to_ictx(struct iommufd_device *idev);
u32 iommufd_device_to_id(struct iommufd_device *idev);
@@ -130,6 +147,18 @@ struct iommufd_vdevice {
*/
u64 virt_id;
+ /* Serializes provider attachment and conversion. */
+ struct mutex mmio_lock;
+ /* Attached provider and callbacks, protected by mmio_lock until detach. */
+ void *mmio_provider_data;
+ /*
+ * Revoke VFIO userspace BAR mappings and shared guest stage-2 mappings
+ * before delegation. Private guest mappings remain intact; guest_memfd
+ * removes them through its architecture unmap operation.
+ */
+ void (*invalidate_mmio)(void *data);
+ bool (*has_private_mmio)(void *data);
+
/* Guest TSM requests accepted by this vdevice; set by vdevice_init(). */
u64 tsm_req_op_mask;
u32 tsm_tvm_arch;
@@ -187,6 +216,7 @@ struct iommufd_hw_queue {
* include/uapi/linux/iommufd.h)
* If driver has a deinit function to revert what vdevice_init op
* does, it should set it to the @vdev->destroy function pointer
+ * @vdevice_get_mmio_owner: Validate the VM and return its MMIO owner.
* @vdevice_tsm_req: Forward a guest TSM request to a driver-owned vDEVICE
* @get_hw_queue_size: Get the size of a driver-defined HW queue structure for a
* given @viommu corresponding to @queue_type. Driver should
@@ -218,6 +248,9 @@ struct iommufd_viommu_ops {
const struct iommu_user_data *user_data);
int (*cache_invalidate)(struct iommufd_viommu *viommu,
struct iommu_user_data_array *array);
+ /* Owner lookup runs with vdevice->mmio_lock held. */
+ int (*vdevice_get_mmio_owner)(struct iommufd_vdevice *vdev,
+ struct kvm *kvm, unsigned long *owner);
const size_t vdevice_size;
int (*vdevice_init)(struct iommufd_vdevice *vdev);
ssize_t (*vdevice_tsm_req)(struct iommufd_vdevice *vdev,
--
2.43.0
next prev parent reply other threads:[~2026-10-10 7:25 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-10 7:24 [RFC PATCH v1 0/6] KVM/VFIO: guest_memfd support for device MMIO resources Aneesh Kumar K.V (Arm)
2026-10-10 7:24 ` [RFC PATCH v1 1/6] KVM: guest_memfd: attach and bind device resources Aneesh Kumar K.V (Arm)
2026-10-10 7:25 ` [RFC PATCH v1 2/6] KVM: guest_memfd: Support private/shared conversion of device memory Aneesh Kumar K.V (Arm)
2026-10-10 7:25 ` Aneesh Kumar K.V (Arm) [this message]
2026-10-10 7:25 ` [RFC PATCH v1 4/6] vfio/pci: Provide guest_memfd backing for PCI BARs Aneesh Kumar K.V (Arm)
2026-10-10 7:25 ` [RFC PATCH v1 5/6] KVM/VFIO: Remove device mappings during guest_memfd teardown Aneesh Kumar K.V (Arm)
2026-10-10 7:25 ` [RFC PATCH v1 6/6] KVM: Invalidate guest_memfd mappings before removing memslot bindings Aneesh Kumar K.V (Arm)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261010072504.536230-4-aneesh.kumar@kernel.org \
--to=aneesh.kumar@kernel.org \
--cc=ackerleytng@google.com \
--cc=aik@amd.com \
--cc=alex@shazbot.org \
--cc=catalin.marinas@arm.com \
--cc=david@kernel.org \
--cc=dwmw2@infradead.org \
--cc=griffoul@gmail.com \
--cc=iommu@lists.linux.dev \
--cc=jgg@ziepe.ca \
--cc=joro@8bytes.org \
--cc=kevin.tian@intel.com \
--cc=kvm@vger.kernel.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=robin.murphy@arm.com \
--cc=seanjc@google.com \
--cc=steven.price@arm.com \
--cc=suzuki.poulose@arm.com \
--cc=will@kernel.org \
--cc=yilun.xu@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®