All of lore.kernel.org
 help / color / mirror / Atom feed
From: Samiullah Khawaja <skhawaja@google.com>
To: Baolu Lu <baolu.lu@linux.intel.com>
Cc: Joerg Roedel <joro@8bytes.org>, Will Deacon <will@kernel.org>,
	 Jason Gunthorpe <jgg@ziepe.ca>,
	David Woodhouse <dwmw2@infradead.org>,
	 Pranjal Shrivastava <praan@google.com>,
	Robin Murphy <robin.murphy@arm.com>,
	 Kevin Tian <kevin.tian@intel.com>,
	Alex Williamson <alex@shazbot.org>,
	 Shuah Khan <shuah@kernel.org>,
	iommu@lists.linux.dev, linux-kernel@vger.kernel.org,
	 kvm@vger.kernel.org, Pratyush Yadav <pratyush@kernel.org>,
	 Pasha Tatashin <pasha.tatashin@soleen.com>,
	David Matlack <dmatlack@google.com>,
	 Andrew Morton <akpm@linux-foundation.org>,
	Vipin Sharma <vipinsh@google.com>,
	 Ankit Soni <Ankit.Soni@amd.com>,
	Nicolin Chen <nicolinc@nvidia.com>,
	 John Starks <dev@jstarks.net>
Subject: Re: [PATCH v6 16/18] iommufd: Add APIs to preserve/unpreserve a vfio cdev
Date: Sat, 31 Oct 2026 03:57:31 +0000	[thread overview]
Message-ID: <auVj8rCNJ8O5fwi1@google.com> (raw)
In-Reply-To: <07a7f12c-3cd8-4c03-9304-af89c32e0b46@linux.intel.com>

On Sat, Oct 31, 2026 at 11:31:47AM +0800, Baolu Lu wrote:
>On 10/25/2026 10:19 AM, Samiullah Khawaja wrote:
>>Add APIs that can be used to preserve and unpreserve a vfio cdev. Use
>>the APIs exported by the IOMMU core to preserve/unpreserve device.
>>
>>The LUO token of the preserved iommufd is fetched and returned back to
>>the caller as that can be used during restore to get the restored
>>iommufd.
>>
>>Reviewed-by: Pranjal Shrivastava <praan@google.com>
>>Signed-off-by: Samiullah Khawaja <skhawaja@google.com>
>>---
>>  drivers/iommu/iommufd/device.c          | 156 ++++++++++++++++++++++++
>>  drivers/iommu/iommufd/iommufd_private.h |   6 +
>>  include/linux/iommufd.h                 |  29 +++++
>>  3 files changed, 191 insertions(+)
>>
>>diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
>>index a664c70a6fe7..c8ea2e288240 100644
>>--- a/drivers/iommu/iommufd/device.c
>>+++ b/drivers/iommu/iommufd/device.c
>>@@ -2,6 +2,7 @@
>>  /* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES
>>   */
>>  #include <linux/iommu.h>
>>+#include <linux/iommu-liveupdate.h>
>>  #include <linux/iommufd.h>
>>  #include <linux/pci-ats.h>
>>  #include <linux/slab.h>
>>@@ -686,6 +687,10 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
>>  	int rc;
>>  	mutex_lock(&igroup->lock);
>>+	if (iommufd_device_is_preserved(idev)) {
>>+		rc = -EBUSY;
>>+		goto err_unlock;
>>+	}
>>  	attach = xa_cmpxchg(&igroup->pasid_attach, pasid, NULL,
>>  			    XA_ZERO_ENTRY, GFP_KERNEL);
>>@@ -868,6 +873,10 @@ iommufd_device_do_replace(struct iommufd_device *idev, ioasid_t pasid,
>>  	int rc;
>>  	mutex_lock(&igroup->lock);
>>+	if (iommufd_device_is_preserved(idev)) {
>>+		rc = -EBUSY;
>>+		goto err_unlock;
>>+	}
>>  	attach = xa_load(&igroup->pasid_attach, pasid);
>>  	if (!attach) {
>>@@ -1747,3 +1756,150 @@ int iommufd_get_hw_info(struct iommufd_ucmd *ucmd)
>>  	iommufd_put_object(ucmd->ictx, &idev->obj);
>>  	return rc;
>>  }
>
>Why is there no such check in iommufd_hw_pagetable_detach()?

Detach can't fail, so it is blocked in the caller,
vfio_df_ioctl_detach_pt() returns -EBUSY for a preserved device. The
other detach path is unbind on close of the device file, which can't
happen while LUO holds a reference to it.

>
>>+
>>+#ifdef CONFIG_IOMMU_LIVEUPDATE
>>+static bool _iommufd_device_has_pasid_attachments(struct iommufd_device *idev)
>>+{
>>+	struct iommufd_group *igroup = idev->igroup;
>>+	unsigned long start = IOMMU_NO_PASID;
>>+
>>+	if (xa_find_after(&igroup->pasid_attach, &start, UINT_MAX, XA_PRESENT))
>>+		return true;
>>+
>>+	return false;
>>+}
>>+
>>+/**
>>+ * iommufd_device_preserve() - Preserve an iommufd device across live update
>>+ * @s: Live update session
>>+ * @idev: Target iommufd device
>>+ * @iommufd_tokenp: Pointer to store outgoing iommufd token
>>+ *
>>+ * Return: 0 on success, or negative error code.
>>+ */
>>+int iommufd_device_preserve(struct liveupdate_session *s,
>>+			    struct iommufd_device *idev,
>>+			    u64 *iommufd_tokenp)
>>+{
>>+	struct iommufd_hwpt_paging *hwpt_paging;
>>+	struct iommufd_hw_pagetable *hwpt;
>>+	struct iommufd_attach *attach;
>>+	struct iommufd_group *igroup;
>>+	int ret;
>>+
>>+	if (!idev)
>>+		return -EINVAL;
>>+
>>+	if (iommufd_device_is_noiommu(idev))
>>+		return -EOPNOTSUPP;
>>+
>>+	igroup = idev->igroup;
>>+	mutex_lock(&igroup->lock);
>>+	if (idev->liveupdate_preserved) {
>>+		ret = -EBUSY;
>>+		goto out;
>>+	}
>>+
>>+	if (_iommufd_device_has_pasid_attachments(idev)) {
>>+		ret = -EOPNOTSUPP;
>>+		goto out;
>>+	}
>>+
>>+	attach = xa_load(&igroup->pasid_attach, IOMMU_NO_PASID);
>>+	if (!attach) {
>>+		ret = -ENOENT;
>>+		goto out;
>>+	}
>>+
>>+	if (!xa_load(&attach->device_array, idev->obj.id)) {
>>+		ret = -ENOENT;
>>+		goto out;
>>+	}
>>+
>>+	hwpt = attach->hwpt;
>>+	if (!hwpt_is_paging(hwpt)) {
>>+		ret = -EOPNOTSUPP;
>>+		goto out;
>>+	}
>>+
>>+	hwpt_paging = to_hwpt_paging(hwpt);
>>+	ret = liveupdate_get_token_outgoing(s, idev->ictx->file, iommufd_tokenp);
>>+	if (ret)
>>+		goto out;
>>+
>>+	if (!hwpt_paging->liveupdate_preserved) {
>>+		ret = -EINVAL;
>>+		goto out;
>>+	}
>>+
>>+	ret = iommu_preserve_device(hwpt_paging->common.domain,
>>+				    idev->dev,
>>+				    *iommufd_tokenp);
>>+
>>+	if (!ret) {
>>+		igroup->num_liveupdate_preserved++;
>>+		idev->liveupdate_preserved = true;
>>+	}
>>+out:
>>+	mutex_unlock(&igroup->lock);
>>+	return ret;
>>+}
>>+EXPORT_SYMBOL_NS_GPL(iommufd_device_preserve, "IOMMUFD");
>>+
>>+/**
>>+ * iommufd_device_unpreserve() - Unpreserve an iommufd device
>>+ * @s: Live update session
>>+ * @idev: Target iommufd device
>>+ */
>>+void iommufd_device_unpreserve(struct liveupdate_session *s,
>>+			       struct iommufd_device *idev)
>>+{
>>+	struct iommufd_hwpt_paging *hwpt_paging;
>>+	struct iommufd_hw_pagetable *hwpt;
>>+	struct iommufd_attach *attach;
>>+	struct iommufd_group *igroup;
>>+
>>+	if (!idev)
>>+		return;
>>+
>>+	igroup = idev->igroup;
>>+	mutex_lock(&igroup->lock);
>>+	if (!idev->liveupdate_preserved)
>>+		goto out;
>>+
>>+	attach = xa_load(&igroup->pasid_attach, IOMMU_NO_PASID);
>>+	if (!attach) {
>>+		WARN(1, "IOMMU_NO_PASID attachment not found");
>>+		goto out;
>>+	}
>>+
>>+	hwpt = attach->hwpt;
>>+	if (WARN(!hwpt_is_paging(hwpt), "Attached HWPT is not a paging HWPT"))
>>+		goto out;
>>+
>>+	hwpt_paging = to_hwpt_paging(hwpt);
>>+	if (!hwpt_paging->liveupdate_preserved) {
>>+		WARN(1, "Attached domain is not preserved");
>>+		goto out;
>>+	}
>>+
>>+	iommu_unpreserve_device(hwpt_paging->common.domain, idev->dev);
>>+	igroup->num_liveupdate_preserved--;
>>+	idev->liveupdate_preserved = false;
>>+out:
>>+	mutex_unlock(&igroup->lock);
>>+}
>>+EXPORT_SYMBOL_NS_GPL(iommufd_device_unpreserve, "IOMMUFD");
>>+
>>+/**
>>+ * iommufd_device_is_preserved() - Check if an iommufd device is preserved
>>+ * @idev: Target iommufd device
>>+ *
>>+ * Return: true if preserved, false otherwise.
>>+ */
>>+bool iommufd_device_is_preserved(struct iommufd_device *idev)
>>+{
>>+	return idev && idev->igroup && idev->igroup->num_liveupdate_preserved;
>>+}
>
>How is it different from
>
>	return idev && idev->liveupdate_preserved;
>
>?
>
>Device preservation requires a singleton group, so these two are
>effectively the same. However, the latter seems more straightforward
>given the function's name. Or anything I overlooked?

Agreed. I kept the group counter for supporting non-singleton groups
later down the road, but for now they are the same. I will use
idev->liveupdate_preserved and drop num_liveupdate_preserved.

>
>>+EXPORT_SYMBOL_NS_GPL(iommufd_device_is_preserved, "IOMMUFD");
>>+#endif
>>diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h
>>index 69d902b69b82..4760fffd2512 100644
>>--- a/drivers/iommu/iommufd/iommufd_private.h
>>+++ b/drivers/iommu/iommufd/iommufd_private.h
>>@@ -507,6 +507,9 @@ struct iommufd_group {
>>  	struct xarray pasid_attach;
>>  	struct iommufd_sw_msi_maps required_sw_msi;
>>  	phys_addr_t sw_msi_start;
>>+#ifdef CONFIG_IOMMU_LIVEUPDATE
>>+	int num_liveupdate_preserved;
>>+#endif
>>  };
>>  /*
>>@@ -524,6 +527,9 @@ struct iommufd_device {
>>  	bool enforce_cache_coherency;
>>  	struct iommufd_vdevice *vdev;
>>  	bool destroying;
>>+#ifdef CONFIG_IOMMU_LIVEUPDATE
>>+	bool liveupdate_preserved;
>>+#endif
>>  };
>>  static inline struct iommufd_device *
>>diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h
>>index 6e7efe83bc5d..80382aceca18 100644
>>--- a/include/linux/iommufd.h
>>+++ b/include/linux/iommufd.h
>>@@ -9,6 +9,7 @@
>>  #include <linux/err.h>
>>  #include <linux/errno.h>
>>  #include <linux/iommu.h>
>>+#include <linux/liveupdate.h>
>>  #include <linux/refcount.h>
>>  #include <linux/types.h>
>>  #include <linux/xarray.h>
>>@@ -213,6 +214,15 @@ int iommufd_access_rw(struct iommufd_access *access, unsigned long iova,
>>  int iommufd_vfio_compat_ioas_get_id(struct iommufd_ctx *ictx, u32 *out_ioas_id);
>>  int iommufd_vfio_compat_ioas_create(struct iommufd_ctx *ictx);
>>  int iommufd_vfio_compat_set_no_iommu(struct iommufd_ctx *ictx);
>>+
>>+#ifdef CONFIG_IOMMU_LIVEUPDATE
>>+int iommufd_device_preserve(struct liveupdate_session *s,
>>+			    struct iommufd_device *idev,
>>+			    u64 *iommufd_tokenp);
>>+void iommufd_device_unpreserve(struct liveupdate_session *s,
>>+			       struct iommufd_device *idev);
>>+bool iommufd_device_is_preserved(struct iommufd_device *idev);
>>+#endif
>>  #else /* !CONFIG_IOMMUFD */
>>  static inline struct iommufd_ctx *iommufd_ctx_from_file(struct file *file)
>>  {
>>@@ -397,4 +407,23 @@ static inline void iommufd_viommu_destroy_mmap(struct iommufd_viommu *viommu,
>>  {
>>  	_iommufd_destroy_mmap(viommu->ictx, &viommu->obj, offset);
>>  }
>>+
>>+#if !IS_ENABLED(CONFIG_IOMMU_LIVEUPDATE) || !IS_ENABLED(CONFIG_IOMMUFD)
>>+static inline int iommufd_device_preserve(struct liveupdate_session *s,
>>+					  struct iommufd_device *idev,
>>+					  u64 *iommufd_tokenp)
>>+{
>>+	return 0;
>
>Why does it return success when IOMMU_LIVEUPDATE is disabled?

This is intentional. vfio-pci live update works without IOMMU state
preservation, so with IOMMU_LIVEUPDATE disabled the device is still
preserved without its IOMMU state. Returning an error here would break
that. I will add a comment explaining this.

>
>>+}
>>+
>>+static inline void iommufd_device_unpreserve(struct liveupdate_session *s,
>>+					     struct iommufd_device *idev)
>>+{
>>+}
>>+
>>+static inline bool iommufd_device_is_preserved(struct iommufd_device *idev)
>>+{
>>+	return false;
>>+}
>>+#endif
>>  #endif
>
>Thanks,
>baolu

Thanks,
Sami

  reply	other threads:[~2026-10-31  3:57 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-25  2:19 [PATCH v6 00/18] iommu: Add live update state preservation Samiullah Khawaja
2026-10-25  2:19 ` [PATCH v6 01/18] iommu: Implement IOMMU Live update FLB callbacks Samiullah Khawaja
2026-10-25  2:19 ` [PATCH v6 02/18] iommu/pages: Add APIs to preserve/unpreserve/restore iommu pages Samiullah Khawaja
2026-10-30  1:26   ` Baolu Lu
2026-10-30 19:41     ` Samiullah Khawaja
2026-10-25  2:19 ` [PATCH v6 03/18] iommupt: Implement preserve/unpreserve/restore callbacks Samiullah Khawaja
2026-10-30  3:07   ` Baolu Lu
2026-10-30 19:42     ` Samiullah Khawaja
2026-10-25  2:19 ` [PATCH v6 04/18] iommu: Implement IOMMU domain preservation Samiullah Khawaja
2026-10-30  4:24   ` Baolu Lu
2026-10-25  2:19 ` [PATCH v6 05/18] iommu: Implement device and IOMMU HW preservation Samiullah Khawaja
2026-10-30  5:12   ` Baolu Lu
2026-10-31  1:45     ` Samiullah Khawaja
2026-10-31  3:04       ` Baolu Lu
2026-10-31  3:39         ` Samiullah Khawaja
2026-10-31  5:27           ` Baolu Lu
2026-10-31  5:34       ` Baolu Lu
2026-10-25  2:19 ` [PATCH v6 06/18] iommu/vt-d: Implement device and iommu preserve/unpreserve ops Samiullah Khawaja
2026-10-28  1:51   ` Baolu Lu
2026-10-28  3:10     ` Samiullah Khawaja
2026-10-25  2:19 ` [PATCH v6 07/18] iommu/vt-d: Clear unpreserved context entries during shutdown Samiullah Khawaja
2026-10-28  3:18   ` Baolu Lu
2026-10-29  0:34     ` Samiullah Khawaja
2026-10-29  3:18   ` Baolu Lu
2026-10-29 22:00     ` Samiullah Khawaja
2026-10-25  2:19 ` [PATCH v6 08/18] iommu: Add APIs to get iommu and device preserved state Samiullah Khawaja
2026-10-30  6:03   ` Baolu Lu
2026-10-31  1:55     ` Samiullah Khawaja
2026-10-25  2:19 ` [PATCH v6 09/18] iommu/vt-d: Combine disable_dmar_iommu() and free_dmar_iommu() Samiullah Khawaja
2026-10-28  6:01   ` Baolu Lu
2026-10-29  0:33     ` Samiullah Khawaja
2026-10-25  2:19 ` [PATCH v6 10/18] iommu/vt-d: Restore IOMMU state and reclaimed domain ids Samiullah Khawaja
2026-10-28  7:14   ` Baolu Lu
2026-10-29  0:32     ` Samiullah Khawaja
2026-10-25  2:19 ` [PATCH v6 11/18] iommu/vt-d: Preserve PASID table of preserved device Samiullah Khawaja
2026-10-29  7:42   ` Baolu Lu
2026-10-25  2:19 ` [PATCH v6 12/18] iommu: Restore and reattach preserved domains to devices Samiullah Khawaja
2026-10-25  2:19 ` [PATCH v6 13/18] iommu/vt-d: Handle reattach of the restored domain Samiullah Khawaja
2026-10-29  8:28   ` Baolu Lu
2026-10-29 22:34     ` Samiullah Khawaja
2026-10-29 23:38       ` Baolu Lu
2026-10-30 19:39         ` Samiullah Khawaja
2026-10-25  2:19 ` [PATCH v6 14/18] iommufd: Implement ioctl to mark HWPT for preservation Samiullah Khawaja
2026-10-30  7:20   ` Baolu Lu
2026-10-31  1:48     ` Samiullah Khawaja
2026-10-25  2:19 ` [PATCH v6 15/18] iommufd: Persist iommu hardware pagetables for live update Samiullah Khawaja
2026-10-31  2:46   ` Baolu Lu
2026-10-31  3:24     ` Samiullah Khawaja
2026-10-25  2:19 ` [PATCH v6 16/18] iommufd: Add APIs to preserve/unpreserve a vfio cdev Samiullah Khawaja
2026-10-31  3:31   ` Baolu Lu
2026-10-31  3:57     ` Samiullah Khawaja [this message]
2026-10-25  2:19 ` [PATCH v6 17/18] vfio/pci: Preserve the iommufd state of the " Samiullah Khawaja
2026-10-31  5:56   ` Baolu Lu
2026-10-25  2:19 ` [PATCH v6 18/18] iommufd/selftest: Add test to verify iommufd preservation Samiullah Khawaja

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=auVj8rCNJ8O5fwi1@google.com \
    --to=skhawaja@google.com \
    --cc=Ankit.Soni@amd.com \
    --cc=akpm@linux-foundation.org \
    --cc=alex@shazbot.org \
    --cc=baolu.lu@linux.intel.com \
    --cc=dev@jstarks.net \
    --cc=dmatlack@google.com \
    --cc=dwmw2@infradead.org \
    --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-kernel@vger.kernel.org \
    --cc=nicolinc@nvidia.com \
    --cc=pasha.tatashin@soleen.com \
    --cc=praan@google.com \
    --cc=pratyush@kernel.org \
    --cc=robin.murphy@arm.com \
    --cc=shuah@kernel.org \
    --cc=vipinsh@google.com \
    --cc=will@kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.