[RFC PATCH 05/15] iommu: Introduce API to preserve iommu domain

Samiullah Khawaja posted 15 patches 3 days, 2 hours ago
[RFC PATCH 05/15] iommu: Introduce API to preserve iommu domain
Posted by Samiullah Khawaja 3 days, 2 hours ago
Add an API that can be called by the iommu users to preserve iommu
domain. Currently it only marks the iommu_domain as preserved.

Signed-off-by: Samiullah Khawaja <skhawaja@google.com>
---
 drivers/iommu/iommu.c | 20 ++++++++++++++++++++
 include/linux/iommu.h | 10 ++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index bfa7c8653720..2e6e9c3f26ec 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -2002,6 +2002,10 @@ static void iommu_domain_init(struct iommu_domain *domain, unsigned int type,
 	domain->owner = ops;
 	if (!domain->ops)
 		domain->ops = ops->default_domain_ops;
+
+#ifdef CONFIG_LIVEUPDATE
+	atomic_set(&domain->preserved, 0);
+#endif
 }
 
 static struct iommu_domain *
@@ -2054,6 +2058,22 @@ EXPORT_SYMBOL_GPL(iommu_paging_domain_alloc_flags);
 
 #ifdef CONFIG_LIVEUPDATE
 DECLARE_RWSEM(liveupdate_state_rwsem);
+
+int iommu_domain_preserve(struct iommu_domain *domain)
+{
+	int ret;
+
+	lockdep_assert_held(&liveupdate_state_rwsem);
+	if (!domain->ops->preserve)
+		return -EOPNOTSUPP;
+
+	ret = domain->ops->preserve(domain);
+	if (!ret)
+		atomic_set(&domain->preserved, 1);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(iommu_domain_preserve);
 #endif
 
 void iommu_domain_free(struct iommu_domain *domain)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 40801d8eac61..aafd06134f5c 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -14,6 +14,7 @@
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/iova_bitmap.h>
+#include <linux/atomic.h>
 #include <uapi/linux/iommufd.h>
 
 #define IOMMU_READ	(1 << 0)
@@ -248,6 +249,10 @@ struct iommu_domain {
 			struct list_head next;
 		};
 	};
+
+#ifdef CONFIG_LIVEUPDATE
+	atomic_t preserved;
+#endif
 };
 
 static inline bool iommu_is_dma_domain(struct iommu_domain *domain)
@@ -915,6 +920,11 @@ static inline struct iommu_domain *iommu_paging_domain_alloc(struct device *dev)
 {
 	return iommu_paging_domain_alloc_flags(dev, 0);
 }
+
+#ifdef CONFIG_LIVEUPDATE
+int iommu_domain_preserve(struct iommu_domain *domain);
+#endif
+
 extern void iommu_domain_free(struct iommu_domain *domain);
 extern int iommu_attach_device(struct iommu_domain *domain,
 			       struct device *dev);
-- 
2.51.0.536.g15c5d4f767-goog
Re: [RFC PATCH 05/15] iommu: Introduce API to preserve iommu domain
Posted by Jason Gunthorpe 2 days, 5 hours ago
On Sun, Sep 28, 2025 at 07:06:13PM +0000, Samiullah Khawaja wrote:
> Add an API that can be called by the iommu users to preserve iommu
> domain. Currently it only marks the iommu_domain as preserved.

Merge it with the previous path

> +#ifdef CONFIG_LIVEUPDATE
> +	atomic_set(&domain->preserved, 0);
> +#endif

The memory is kzallocated, I don't think this is needed

> +int iommu_domain_preserve(struct iommu_domain *domain)
> +{

I expect this to accept some kind of luo pointer to signal what stream
the domain is part of.

Domains are linked to iommufd's which are linked to luo sessions. This
all needs to be carefully conveyed down to all the lower levels.

I also expect preserve to return some kind of handle that the caller
can hide away to deserialize.

> +	lockdep_assert_held(&liveupdate_state_rwsem);
> +	if (!domain->ops->preserve)
> +		return -EOPNOTSUPP;
> +
> +	ret = domain->ops->preserve(domain);
> +	if (!ret)
> +		atomic_set(&domain->preserved, 1);

And if we have a caller handle then there is probably no reason to
have this state tracking atomic.

Jason
Re: [RFC PATCH 05/15] iommu: Introduce API to preserve iommu domain
Posted by Samiullah Khawaja 2 days, 3 hours ago
On Mon, Sep 29, 2025 at 8:54 AM Jason Gunthorpe <jgg@ziepe.ca> wrote:
>
> On Sun, Sep 28, 2025 at 07:06:13PM +0000, Samiullah Khawaja wrote:
> > Add an API that can be called by the iommu users to preserve iommu
> > domain. Currently it only marks the iommu_domain as preserved.
>
> Merge it with the previous path
>
> > +#ifdef CONFIG_LIVEUPDATE
> > +     atomic_set(&domain->preserved, 0);
> > +#endif
>
> The memory is kzallocated, I don't think this is needed
>
> > +int iommu_domain_preserve(struct iommu_domain *domain)
> > +{
>
> I expect this to accept some kind of luo pointer to signal what stream
> the domain is part of.
>
> Domains are linked to iommufd's which are linked to luo sessions. This
> all needs to be carefully conveyed down to all the lower levels.
>

Agreed. Currently this is based on LUOv3 and once I rebase on top of
LUOv4 I will rework all this.
> I also expect preserve to return some kind of handle that the caller
> can hide away to deserialize.
>
> > +     lockdep_assert_held(&liveupdate_state_rwsem);
> > +     if (!domain->ops->preserve)
> > +             return -EOPNOTSUPP;
> > +
> > +     ret = domain->ops->preserve(domain);
> > +     if (!ret)
> > +             atomic_set(&domain->preserved, 1);
>
> And if we have a caller handle then there is probably no reason to
> have this state tracking atomic.

Yes, all the domain states can be serialized and backed by the caller
handle. But we will still need to mark the backing iommus for
preservation, because the state of preserved iommus will be needed for
restoration during iommu init during boot. That is why I have a LUO
subsystem registered for IOMMU.
>
> Jason