Kernel KVM virtualization development
 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>,
	 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>,
	Pranjal Shrivastava <praan@google.com>,
	 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 05/18] iommu: Implement device and IOMMU HW preservation
Date: Sat, 31 Oct 2026 01:45:36 +0000	[thread overview]
Message-ID: <auTzN4NWuKsBvIZU@google.com> (raw)
In-Reply-To: <df75f891-05a0-4d47-8705-d6a00c81ff97@linux.intel.com>

On Fri, Oct 30, 2026 at 01:12:31PM +0800, Baolu Lu wrote:
>On 10/25/2026 10:19 AM, Samiullah Khawaja wrote:
>>Add IOMMU ops to preserve/unpreserve the device state handled by the
>>IOMMU driver. This is IOMMU specific state of the device that needs to
>>be preserved for liveupdate. These ops can be implemented by the IOMMU
>>drivers that support preservation of devices that have their IOMMU
>>domains preserved. During device preservation the state of the
>>associated IOMMU is also preserved as dependency.
>>
>>Signed-off-by: Samiullah Khawaja <skhawaja@google.com>
>>---
>>  drivers/iommu/iommu-priv.h       |   2 +
>>  drivers/iommu/iommu.c            |  72 +++++++++++-
>>  drivers/iommu/liveupdate.c       | 189 +++++++++++++++++++++++++++++++
>>  include/linux/iommu-liveupdate.h |  76 +++++++++++++
>>  include/linux/iommu.h            |  33 ++++++
>>  5 files changed, 371 insertions(+), 1 deletion(-)
>>
>>diff --git a/drivers/iommu/iommu-priv.h b/drivers/iommu/iommu-priv.h
>>index 1f9f886b2c10..6b0ef210b32f 100644
>>--- a/drivers/iommu/iommu-priv.h
>>+++ b/drivers/iommu/iommu-priv.h
>>@@ -21,6 +21,8 @@ static inline const struct iommu_ops *dev_iommu_ops(struct device *dev)
>>  void dev_iommu_free(struct device *dev);
>>+bool iommu_group_is_singleton(struct iommu_group *group);
>>+
>>  const struct iommu_ops *iommu_ops_from_fwnode(const struct fwnode_handle *fwnode);
>>  static inline const struct iommu_ops *iommu_fwspec_ops(struct iommu_fwspec *fwspec)
>>diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
>>index b486b8bbd1fc..a66363789ca9 100644
>>--- a/drivers/iommu/iommu.c
>>+++ b/drivers/iommu/iommu.c
>>@@ -18,6 +18,7 @@
>>  #include <linux/errno.h>
>>  #include <linux/host1x_context_bus.h>
>>  #include <linux/iommu.h>
>>+#include <linux/iommu-liveupdate.h>
>>  #include <linux/iommufd.h>
>>  #include <linux/idr.h>
>>  #include <linux/err.h>
>>@@ -328,6 +329,47 @@ void iommu_device_unregister(struct iommu_device *iommu)
>>  }
>>  EXPORT_SYMBOL_GPL(iommu_device_unregister);
>>+struct iommu_dev_iter {
>>+	struct iommu_device *iommu;
>>+	iommu_dev_iter_fn fn;
>>+};
>>+
>>+static int _iommu_for_each_dev_cb(struct device *dev, void *data)
>>+{
>>+	struct iommu_dev_iter *iter = data;
>>+
>>+	if (dev->iommu && dev->iommu->iommu_dev == iter->iommu)
>>+		return iter->fn(dev, iter->iommu);
>>+
>>+	return 0;
>>+}
>>+
>>+/**
>>+ * iommu_for_each_dev() - Iterate over all devices attached to an IOMMU
>>+ * @iommu: IOMMU instance
>>+ * @fn: Callback to call for each device attached to @iommu
>>+ *
>>+ * Return: 0 on success, or negative error code.
>>+ */
>>+int iommu_for_each_dev(struct iommu_device *iommu, iommu_dev_iter_fn fn)
>>+{
>>+	struct iommu_dev_iter iter = {
>>+		.iommu = iommu,
>>+		.fn = fn,
>>+	};
>>+	int ret;
>>+
>>+	for (int i = 0; i < ARRAY_SIZE(iommu_buses); i++) {
>>+		ret = bus_for_each_dev(iommu_buses[i], NULL, &iter,
>>+				       _iommu_for_each_dev_cb);
>>+		if (ret)
>>+			return ret;
>>+	}
>>+
>>+	return 0;
>>+}
>>+EXPORT_SYMBOL_GPL(iommu_for_each_dev);
>
>The function has no locking against iommu probe or release, so the
>callback can read dev->iommu while it is being freed or before it is
>fully set up.

It is only called from intel_iommu_shutdown(), which runs after the
other CPUs are stopped and interrupts are disabled, so probe and release
can't run. I will rename it to iommu_for_each_dev_unsafe(), document
that it must only be called at shutdown and drop the export, since the
only user is built in.

>
>>+
>>  #if IS_ENABLED(CONFIG_IOMMUFD_TEST)
>>  void iommu_device_unregister_bus(struct iommu_device *iommu,
>>  				 const struct bus_type *bus,
>>@@ -626,8 +668,8 @@ DEFINE_MUTEX(iommu_probe_device_lock);
>>  static int __iommu_probe_device(struct device *dev, struct list_head *group_list)
>>  {
>>+	struct group_device *gdev, *gdev2;
>>  	struct iommu_group *group;
>>-	struct group_device *gdev;
>>  	int ret;
>>  	/*
>>@@ -661,6 +703,13 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
>>  		goto err_put_group;
>>  	}
>>+	for_each_group_device(group, gdev2) {
>>+		if (dev_iommu_has_preserved_state(gdev2->dev)) {
>>+			ret = -EBUSY;
>>+			goto err_free_gdev;
>>+		}
>>+	}
>>+
>>  	/*
>>  	 * The gdev must be in the list before calling
>>  	 * iommu_setup_default_domain()
>>@@ -697,6 +746,7 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
>>  err_remove_gdev:
>>  	list_del(&gdev->list);
>>+err_free_gdev:
>>  	__iommu_group_free_device(group, gdev);
>>  err_put_group:
>>  	iommu_deinit_device(dev);
>>@@ -3543,6 +3593,26 @@ bool iommu_group_dma_owner_claimed(struct iommu_group *group)
>>  }
>>  EXPORT_SYMBOL_GPL(iommu_group_dma_owner_claimed);
>>+/**
>>+ * iommu_group_is_singleton() - Query if group contains exactly one device
>>+ * @group: The group.
>>+ *
>>+ * Return: true if group contains exactly 1 device, false otherwise.
>>+ */
>
>We discussed this interface before, and the consensus was that such an
>interface is not feasible, because the membership of an iommu_group is
>not fixed, given the hot-plug support of buses like PCI.
>
>I am fine with the usage model of ensuring the iommu group of a
>preserved device to be a singleton, but I don't think we even need such
>a kAPI. It should be handled case by case.

The iommu_group membership can change, this is why we check it in two
places, both under group->mutex:

- During preservation we check that the group is a singleton, and check
   again after setting device_ser.
- During probe we refuse to add a device to a group that has a preserved
   device.

So if a device is added to the group while we are preserving, either the
probe fails because the group already has a preserved device, or the
preservation fails because the group is no longer a singleton. Could you
please elaborate what you mean by handling it case by case?

>>+bool iommu_group_is_singleton(struct iommu_group *group)
>>+{
>>+	bool ret;
>>+
>>+	if (!group)
>>+		return false;
>>+
>>+	mutex_lock(&group->mutex);
>>+	ret = (list_count_nodes(&group->devices) == 1);
>>+	mutex_unlock(&group->mutex);
>>+
>>+	return ret;
>>+}
>>+
>>  static void iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid,
>>  				   struct iommu_domain *domain)
>>  {
>>diff --git a/drivers/iommu/liveupdate.c b/drivers/iommu/liveupdate.c
>>index b7eda5615189..d1d11b28ae79 100644
>>--- a/drivers/iommu/liveupdate.c
>>+++ b/drivers/iommu/liveupdate.c
>>@@ -43,6 +43,9 @@
>>  #include <linux/kexec_handover.h>
>>  #include <linux/kho_block.h>
>>  #include <linux/liveupdate.h>
>>+#include <linux/pci.h>
>>+
>>+#include "iommu-priv.h"
>>  /**
>>   * struct iommu_ser_set - Set of serialized objects of one type
>>@@ -358,3 +361,189 @@ void iommu_unpreserve_domain(struct iommu_domain *domain)
>>  	liveupdate_flb_put_outgoing(&iommu_flb);
>>  }
>>  EXPORT_SYMBOL_GPL(iommu_unpreserve_domain);
>>+
>>+static int iommu_preserve_locked(struct iommu_device *iommu,
>>+				 struct iommu_flb_obj *flb_obj)
>>+{
>>+	struct iommu_hw_ser *iommu_hw_ser;
>>+	int ret;
>>+
>>+	if (!iommu->ops->preserve || !iommu->ops->unpreserve)
>>+		return -EOPNOTSUPP;
>>+
>>+	lockdep_assert_held(&flb_obj->lock);
>>+	if (iommu->iommu_ser) {
>>+		iommu->iommu_ser->hdr.ref_count++;
>>+		return 0;
>>+	}
>>+
>>+	iommu_hw_ser = iommu_ser_set_alloc(&flb_obj->iommu_set);
>>+	if (IS_ERR(iommu_hw_ser))
>>+		return PTR_ERR(iommu_hw_ser);
>>+
>>+	ret = iommu->ops->preserve(iommu, iommu_hw_ser);
>>+	if (ret) {
>>+		iommu_hw_ser->hdr.flags |= IOMMU_SER_FLAG_DELETED;
>>+		return ret;
>>+	}
>>+
>>+	iommu->iommu_ser = iommu_hw_ser;
>>+	return ret;
>>+}
>>+
>>+static void iommu_unpreserve_locked(struct iommu_device *iommu,
>>+				    struct iommu_flb_obj *flb_obj)
>>+{
>>+	struct iommu_hw_ser *iommu_hw_ser = iommu->iommu_ser;
>>+
>>+	lockdep_assert_held(&flb_obj->lock);
>>+	if (WARN_ON(!iommu_hw_ser))
>>+		return;
>>+
>>+	if (WARN_ON_ONCE(!iommu->ops->preserve ||
>>+			 !iommu->ops->unpreserve))
>>+		return;
>>+
>>+	iommu_hw_ser->hdr.ref_count--;
>>+	if (iommu_hw_ser->hdr.ref_count)
>>+		return;
>>+
>>+	iommu->iommu_ser = NULL;
>>+	iommu->ops->unpreserve(iommu, iommu_hw_ser);
>>+	iommu_hw_ser->hdr.flags |= IOMMU_SER_FLAG_DELETED;
>>+}
>>+
>>+/**
>>+ * iommu_preserve_device() - Preserve device state across live update
>>+ * @domain: Associated IOMMU domain
>>+ * @dev: Device to preserve
>>+ * @dma_owner_token: Token to identify DMA owner of this device
>>+ *
>>+ * Return: 0 on success, or negative error code.
>>+ */
>>+int iommu_preserve_device(struct iommu_domain *domain,
>>+			  struct device *dev, u64 dma_owner_token)
>>+{
>>+	struct iommu_device_ser *device_ser;
>>+	struct iommu_flb_obj *flb_obj;
>>+	struct dev_iommu *iommu;
>>+	struct pci_dev *pdev;
>>+	int ret;
>>+
>>+	if (!dev_is_pci(dev))
>>+		return -EOPNOTSUPP;
>>+
>>+	if (!iommu_group_dma_owner_claimed(dev->iommu_group))
>>+		return -EINVAL;
>>+
>>+	if (!iommu_group_is_singleton(dev->iommu_group))
>>+		return -EOPNOTSUPP;
>>+
>>+	pdev = to_pci_dev(dev);
>>+	iommu = dev->iommu;
>>+	if (!iommu->iommu_dev->ops->preserve_device ||
>>+	    !iommu->iommu_dev->ops->unpreserve_device ||
>>+	    !iommu->iommu_dev->ops->preserve ||
>>+	    !iommu->iommu_dev->ops->unpreserve)
>>+		return -EOPNOTSUPP;
>>+
>>+	ret = liveupdate_flb_get_outgoing(&iommu_flb, (void **)&flb_obj);
>>+	if (ret)
>>+		return ret;
>>+
>>+	mutex_lock(&flb_obj->lock);
>>+	if (!domain->domain_ser) {
>>+		ret = -EINVAL;
>>+		goto out_unlock;
>>+	}
>
>Should we check that @domain is actually attached to the device? The
>iommu core tracks the device's domain attachment, so what happens if
>the caller's @domain doesn't match what the iommu core has recorded?

The caller of this API does that check before calling
iommu_preserve_device. But I agree and I will add a check here.
>
>>+
>>+	if (dev_iommu_preserved_state(dev)) {
>>+		ret = -EBUSY;
>>+		goto out_unlock;
>>+	}
>>+
>>+	device_ser = iommu_ser_set_alloc(&flb_obj->device_set);
>>+	if (IS_ERR(device_ser)) {
>>+		ret = PTR_ERR(device_ser);
>>+		goto out_unlock;
>>+	}
>>+
>>+	ret = iommu_preserve_locked(iommu->iommu_dev, flb_obj);
>>+	if (ret) {
>>+		device_ser->hdr.flags |= IOMMU_SER_FLAG_DELETED;
>>+		goto out_unlock;
>>+	}
>>+
>>+	device_ser->attachment.domain_phys = virt_to_phys(domain->domain_ser);
>>+	device_ser->iommu_phys = virt_to_phys(iommu->iommu_dev->iommu_ser);
>>+	device_ser->devid = pci_dev_id(pdev);
>>+	device_ser->pci_domain_nr = pci_domain_nr(pdev->bus);
>>+	device_ser->dma_owner_token = dma_owner_token;
>>+
>>+	ret = iommu->iommu_dev->ops->preserve_device(dev, device_ser);
>>+	if (!ret) {
>>+		WRITE_ONCE(dev->iommu->device_ser, device_ser);
>>+
>>+		/* Validate that no sibling device was added concurrently */
>>+		if (!iommu_group_is_singleton(dev->iommu_group)) {
>>+			iommu->iommu_dev->ops->unpreserve_device(dev, device_ser);
>>+			WRITE_ONCE(dev->iommu->device_ser, NULL);
>>+			ret = -EOPNOTSUPP;
>>+		}
>>+	}
>>+
>>+	if (ret) {
>>+		device_ser->hdr.flags |= IOMMU_SER_FLAG_DELETED;
>>+		iommu_unpreserve_locked(iommu->iommu_dev, flb_obj);
>>+		goto out_unlock;
>>+	}
>>+
>>+out_unlock:
>>+	mutex_unlock(&flb_obj->lock);
>>+	liveupdate_flb_put_outgoing(&iommu_flb);
>>+	return ret;
>>+}
>>+EXPORT_SYMBOL_GPL(iommu_preserve_device);
>>+
>>+/**
>>+ * iommu_unpreserve_device() - Unpreserve device state
>>+ * @domain: Associated IOMMU domain
>
>@domain is not used anywhere in this function. Why is it needed?

Agreed. I will remove this.
>
>>+ * @dev: Device to unpreserve
>>+ */
>>+void iommu_unpreserve_device(struct iommu_domain *domain, struct device *dev)
>>+{
>>+	struct iommu_device_ser *iommu_device_ser;
>>+	struct iommu_flb_obj *flb_obj;
>>+	struct dev_iommu *iommu;
>>+	int ret;
>>+
>>+	if (!dev_is_pci(dev))
>>+		return;
>>+
>>+	if (!iommu_group_dma_owner_claimed(dev->iommu_group))
>>+		return;
>>+
>>+	iommu = dev->iommu;
>>+	if (WARN_ON(!iommu->iommu_dev->ops->unpreserve_device ||
>>+		    !iommu->iommu_dev->ops->unpreserve))
>>+		return;
>>+
>>+	ret = liveupdate_flb_get_outgoing(&iommu_flb, (void **)&flb_obj);
>>+	if (WARN_ON(ret))
>>+		return;
>>+
>>+	mutex_lock(&flb_obj->lock);
>>+	iommu_device_ser = dev_iommu_preserved_state(dev);
>>+	if (WARN_ON(!iommu_device_ser))
>>+		goto out_unlock;
>>+
>>+	iommu_device_ser->hdr.flags |= IOMMU_SER_FLAG_DELETED;
>>+	iommu->iommu_dev->ops->unpreserve_device(dev, iommu_device_ser);
>>+	WRITE_ONCE(dev->iommu->device_ser, NULL);
>>+
>>+	iommu_unpreserve_locked(iommu->iommu_dev, flb_obj);
>>+out_unlock:
>>+	mutex_unlock(&flb_obj->lock);
>>+	liveupdate_flb_put_outgoing(&iommu_flb);
>>+}
>>+EXPORT_SYMBOL_GPL(iommu_unpreserve_device);
>>diff --git a/include/linux/iommu-liveupdate.h b/include/linux/iommu-liveupdate.h
>>index caa9778eee2d..cdf8a82b7f1d 100644
>>--- a/include/linux/iommu-liveupdate.h
>>+++ b/include/linux/iommu-liveupdate.h
>>@@ -8,6 +8,7 @@
>>  #ifndef _LINUX_IOMMU_LIVEUPDATE_H
>>  #define _LINUX_IOMMU_LIVEUPDATE_H
>>+#include <linux/device.h>
>>  #include <linux/iommu.h>
>>  #include <linux/liveupdate.h>
>>  #include <linux/kho/abi/iommu.h>
>>@@ -15,8 +16,58 @@
>>  #ifdef CONFIG_IOMMU_LIVEUPDATE
>>  int iommu_liveupdate_register_flb(struct liveupdate_file_handler *handler);
>>  void iommu_liveupdate_unregister_flb(struct liveupdate_file_handler *handler);
>>+
>>+/**
>>+ * dev_iommu_has_preserved_state() - Check if a device has live update state
>>+ * @dev: Target device
>>+ *
>>+ * Unlike dev_iommu_preserved_state() and dev_iommu_restored_state(), this does
>>+ * not dereference the serialized state, so it is safe to call without holding
>>+ * a reference on the live update FLB.
>>+ *
>>+ * Return: true if @dev has preserved (outgoing) or restored (incoming) state.
>>+ */
>>+static inline bool dev_iommu_has_preserved_state(struct device *dev)
>>+{
>>+	return dev->iommu && READ_ONCE(dev->iommu->device_ser);
>>+}
>>+
>>+/**
>>+ * dev_iommu_preserved_state() - Get preserved state of a device
>>+ * @dev: Target device
>>+ *
>>+ * Return: Pointer to preserved device state, or NULL if not preserved.
>>+ */
>>+static inline void *dev_iommu_preserved_state(struct device *dev)
>>+{
>>+	struct iommu_device_ser *ser;
>>+
>>+	if (!dev->iommu)
>>+		return NULL;
>>+
>>+	ser = READ_ONCE(dev->iommu->device_ser);
>>+	if (ser && !(ser->hdr.flags & IOMMU_SER_FLAG_INCOMING))
>>+		return ser;
>>+
>>+	return NULL;
>>+}
>>+
>>  int iommu_preserve_domain(struct iommu_domain *domain, struct iommu_domain_ser **ser);
>>  void iommu_unpreserve_domain(struct iommu_domain *domain);
>>+int iommu_preserve_device(struct iommu_domain *domain,
>>+			  struct device *dev, u64 dma_owner_token);
>>+void iommu_unpreserve_device(struct iommu_domain *domain, struct device *dev);
>>+
>>+/**
>>+ * iommu_preserved_state() - Get preserved state of an IOMMU instance
>>+ * @iommu: IOMMU hardware instance
>>+ *
>>+ * Return: Pointer to preserved state, or NULL if not preserved.
>>+ */
>>+static inline void *iommu_preserved_state(struct iommu_device *iommu)
>>+{
>>+	return iommu->iommu_ser;
>>+}
>>  #else
>>  static inline int iommu_liveupdate_register_flb(struct liveupdate_file_handler *handler)
>>  {
>>@@ -27,6 +78,16 @@ static inline void iommu_liveupdate_unregister_flb(struct liveupdate_file_handle
>>  {
>>  }
>>+static inline bool dev_iommu_has_preserved_state(struct device *dev)
>>+{
>>+	return false;
>>+}
>>+
>>+static inline void *dev_iommu_preserved_state(struct device *dev)
>>+{
>>+	return NULL;
>>+}
>>+
>>  static inline int iommu_preserve_domain(struct iommu_domain *domain, struct iommu_domain_ser **ser)
>>  {
>>  	return -EOPNOTSUPP;
>>@@ -35,5 +96,20 @@ static inline int iommu_preserve_domain(struct iommu_domain *domain, struct iomm
>>  static inline void iommu_unpreserve_domain(struct iommu_domain *domain)
>>  {
>>  }
>>+
>>+static inline int iommu_preserve_device(struct iommu_domain *domain,
>>+					struct device *dev, u64 dma_owner_token)
>>+{
>>+	return -EOPNOTSUPP;
>>+}
>>+
>>+static inline void iommu_unpreserve_device(struct iommu_domain *domain, struct device *dev)
>>+{
>>+}
>>+
>>+static inline void *iommu_preserved_state(struct iommu_device *iommu)
>>+{
>>+	return NULL;
>>+}
>>  #endif
>>  #endif /* _LINUX_IOMMU_LIVEUPDATE_H */
>>diff --git a/include/linux/iommu.h b/include/linux/iommu.h
>>index 71e73c5181b5..35d028fe7126 100644
>>--- a/include/linux/iommu.h
>>+++ b/include/linux/iommu.h
>>@@ -684,6 +684,10 @@ __iommu_copy_struct_to_user(const struct iommu_user_data *dst_data,
>>   *               resources shared/passed to user space IOMMU instance. Associate
>>   *               it with a nesting @parent_domain. It is required for driver to
>>   *               set @viommu->ops pointing to its own viommu_ops
>>+ * @preserve_device: Preserve state of a device for liveupdate.
>>+ * @unpreserve_device: Unpreserve state that was preserved earlier.
>>+ * @preserve: Preserve state of iommu translation hardware for liveupdate.
>>+ * @unpreserve: Unpreserve state of iommu that was preserved earlier.
>>   * @owner: Driver module providing these ops
>>   * @identity_domain: An always available, always attachable identity
>>   *                   translation.
>>@@ -740,6 +744,13 @@ struct iommu_ops {
>>  			   struct iommu_domain *parent_domain,
>>  			   const struct iommu_user_data *user_data);
>>+#ifdef CONFIG_IOMMU_LIVEUPDATE
>>+	int (*preserve_device)(struct device *dev, struct iommu_device_ser *device_ser);
>>+	void (*unpreserve_device)(struct device *dev, struct iommu_device_ser *device_ser);
>>+	int (*preserve)(struct iommu_device *iommu, struct iommu_hw_ser *iommu_ser);
>>+	void (*unpreserve)(struct iommu_device *iommu, struct iommu_hw_ser *iommu_ser);
>>+#endif
>>+
>>  	const struct iommu_domain_ops *default_domain_ops;
>>  	struct module *owner;
>>  	struct iommu_domain *identity_domain;
>>@@ -827,6 +838,7 @@ struct iommu_domain_ops {
>>   * @singleton_group: Used internally for drivers that have only one group
>>   * @max_pasids: number of supported PASIDs
>>   * @ready: set once iommu_device_register() has completed successfully
>>+ * @iommu_ser: preserved iommu state of outgoing kernel for liveupdate.
>>   */
>>  struct iommu_device {
>>  	struct list_head list;
>>@@ -836,6 +848,10 @@ struct iommu_device {
>>  	struct iommu_group *singleton_group;
>>  	u32 max_pasids;
>>  	bool ready;
>>+
>>+#ifdef CONFIG_IOMMU_LIVEUPDATE
>>+	struct iommu_hw_ser *iommu_ser;
>>+#endif
>>  };
>>  /**
>>@@ -875,6 +891,8 @@ struct iommu_fault_param {
>>   * @pci_32bit_workaround: Limit DMA allocations to 32-bit IOVAs
>>   * @require_direct: device requires IOMMU_RESV_DIRECT regions
>>   * @shadow_on_flush: IOTLB flushes are used to sync shadow tables
>>+ * @device_ser: preserved (outgoing) or restored (incoming) liveupdate state
>>+ *		of this device
>>   *
>>   * TODO: migrate other per device data pointers under iommu_dev_data, e.g.
>>   *	struct iommu_group	*iommu_group;
>>@@ -890,6 +908,9 @@ struct dev_iommu {
>>  	u32				pci_32bit_workaround:1;
>>  	u32				require_direct:1;
>>  	u32				shadow_on_flush:1;
>>+#ifdef CONFIG_IOMMU_LIVEUPDATE
>>+	struct iommu_device_ser		*device_ser;
>>+#endif
>>  };
>>  int iommu_device_register(struct iommu_device *iommu,
>>@@ -1204,6 +1225,18 @@ static inline void *dev_iommu_priv_get(struct device *dev)
>>  void dev_iommu_priv_set(struct device *dev, void *priv);
>>+/**
>>+ * typedef iommu_dev_iter_fn - Callback for iterating IOMMU attached devices
>>+ * @dev: Attached device
>>+ * @iommu: IOMMU instance
>>+ *
>>+ * Return: 0 on success, or negative error code.
>>+ */
>>+typedef int (*iommu_dev_iter_fn)(struct device *dev,
>>+				 struct iommu_device *iommu);
>>+
>>+int iommu_for_each_dev(struct iommu_device *iommu, iommu_dev_iter_fn fn);
>>+
>>  extern struct mutex iommu_probe_device_lock;
>>  int iommu_probe_device(struct device *dev);
>
>Thanks,
>baolu

Thanks,
Sami

  reply	other threads:[~2026-10-31  1:45 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 [this message]
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
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=auTzN4NWuKsBvIZU@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox