[PATCH v6 12/13] xen/arm: Suspend/resume IOMMU on Xen suspend/resume

Mykola Kvach posted 13 patches 1 month, 4 weeks ago
[PATCH v6 12/13] xen/arm: Suspend/resume IOMMU on Xen suspend/resume
Posted by Mykola Kvach 1 month, 4 weeks ago
From: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>

This is done using generic iommu_suspend/resume functions that cause
IOMMU driver specific suspend/resume handlers to be called for enabled
IOMMU (if one has suspend/resume driver handlers implemented).

Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
---
Changes in V6:
- Drop iommu_enabled check from host system suspend.
---
 xen/arch/arm/suspend.c                | 11 +++++++++++
 xen/drivers/passthrough/arm/smmu-v3.c | 10 ++++++++++
 xen/drivers/passthrough/arm/smmu.c    | 10 ++++++++++
 3 files changed, 31 insertions(+)

diff --git a/xen/arch/arm/suspend.c b/xen/arch/arm/suspend.c
index 35b20581f1..f3a3b831c5 100644
--- a/xen/arch/arm/suspend.c
+++ b/xen/arch/arm/suspend.c
@@ -5,6 +5,7 @@
 
 #include <xen/console.h>
 #include <xen/cpu.h>
+#include <xen/iommu.h>
 #include <xen/llc-coloring.h>
 #include <xen/sched.h>
 #include <xen/tasklet.h>
@@ -62,6 +63,13 @@ static void cf_check system_suspend(void *data)
 
     time_suspend();
 
+    status = iommu_suspend();
+    if ( status )
+    {
+        system_state = SYS_STATE_resume;
+        goto resume_time;
+    }
+
     console_start_sync();
     status = console_suspend();
     if ( status )
@@ -118,6 +126,9 @@ static void cf_check system_suspend(void *data)
     console_resume();
     console_end_sync();
 
+    iommu_resume();
+
+ resume_time:
     time_resume();
 
  resume_nonboot_cpus:
diff --git a/xen/drivers/passthrough/arm/smmu-v3.c b/xen/drivers/passthrough/arm/smmu-v3.c
index 81071f4018..f887faf7dc 100644
--- a/xen/drivers/passthrough/arm/smmu-v3.c
+++ b/xen/drivers/passthrough/arm/smmu-v3.c
@@ -2854,6 +2854,13 @@ static void arm_smmu_iommu_xen_domain_teardown(struct domain *d)
 	xfree(xen_domain);
 }
 
+#ifdef CONFIG_SYSTEM_SUSPEND
+static int arm_smmu_suspend(void)
+{
+	return -ENOSYS;
+}
+#endif
+
 static const struct iommu_ops arm_smmu_iommu_ops = {
 	.page_sizes		= PAGE_SIZE_4K,
 	.init			= arm_smmu_iommu_xen_domain_init,
@@ -2866,6 +2873,9 @@ static const struct iommu_ops arm_smmu_iommu_ops = {
 	.unmap_page		= arm_iommu_unmap_page,
 	.dt_xlate		= arm_smmu_dt_xlate,
 	.add_device		= arm_smmu_add_device,
+#ifdef CONFIG_SYSTEM_SUSPEND
+	.suspend		= arm_smmu_suspend,
+#endif
 };
 
 static __init int arm_smmu_dt_init(struct dt_device_node *dev,
diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c
index 22d306d0cb..45f29ef8ec 100644
--- a/xen/drivers/passthrough/arm/smmu.c
+++ b/xen/drivers/passthrough/arm/smmu.c
@@ -2947,6 +2947,13 @@ static void arm_smmu_iommu_domain_teardown(struct domain *d)
 	xfree(xen_domain);
 }
 
+#ifdef CONFIG_SYSTEM_SUSPEND
+static int arm_smmu_suspend(void)
+{
+	return -ENOSYS;
+}
+#endif
+
 static const struct iommu_ops arm_smmu_iommu_ops = {
     .page_sizes = PAGE_SIZE_4K,
     .init = arm_smmu_iommu_domain_init,
@@ -2960,6 +2967,9 @@ static const struct iommu_ops arm_smmu_iommu_ops = {
     .map_page = arm_iommu_map_page,
     .unmap_page = arm_iommu_unmap_page,
     .dt_xlate = arm_smmu_dt_xlate_generic,
+#ifdef CONFIG_SYSTEM_SUSPEND
+    .suspend = arm_smmu_suspend,
+#endif
 };
 
 static struct arm_smmu_device *find_smmu(const struct device *dev)
-- 
2.48.1
Re: [PATCH v6 12/13] xen/arm: Suspend/resume IOMMU on Xen suspend/resume
Posted by Volodymyr Babchuk 1 month, 4 weeks ago
Hi,

Mykola Kvach <xakep.amatop@gmail.com> writes:

> From: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
>
> This is done using generic iommu_suspend/resume functions that cause
> IOMMU driver specific suspend/resume handlers to be called for enabled
> IOMMU (if one has suspend/resume driver handlers implemented).
>
> Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
> Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>

Reviewed-by: Volodymyr Babchuk <volodymyr_babchuk@epam.com>

> ---
> Changes in V6:
> - Drop iommu_enabled check from host system suspend.
> ---
>  xen/arch/arm/suspend.c                | 11 +++++++++++
>  xen/drivers/passthrough/arm/smmu-v3.c | 10 ++++++++++
>  xen/drivers/passthrough/arm/smmu.c    | 10 ++++++++++
>  3 files changed, 31 insertions(+)
>
> diff --git a/xen/arch/arm/suspend.c b/xen/arch/arm/suspend.c
> index 35b20581f1..f3a3b831c5 100644
> --- a/xen/arch/arm/suspend.c
> +++ b/xen/arch/arm/suspend.c
> @@ -5,6 +5,7 @@
>  
>  #include <xen/console.h>
>  #include <xen/cpu.h>
> +#include <xen/iommu.h>
>  #include <xen/llc-coloring.h>
>  #include <xen/sched.h>
>  #include <xen/tasklet.h>
> @@ -62,6 +63,13 @@ static void cf_check system_suspend(void *data)
>  
>      time_suspend();
>  
> +    status = iommu_suspend();
> +    if ( status )
> +    {
> +        system_state = SYS_STATE_resume;
> +        goto resume_time;
> +    }
> +
>      console_start_sync();
>      status = console_suspend();
>      if ( status )
> @@ -118,6 +126,9 @@ static void cf_check system_suspend(void *data)
>      console_resume();
>      console_end_sync();
>  
> +    iommu_resume();
> +
> + resume_time:
>      time_resume();
>  
>   resume_nonboot_cpus:
> diff --git a/xen/drivers/passthrough/arm/smmu-v3.c b/xen/drivers/passthrough/arm/smmu-v3.c
> index 81071f4018..f887faf7dc 100644
> --- a/xen/drivers/passthrough/arm/smmu-v3.c
> +++ b/xen/drivers/passthrough/arm/smmu-v3.c
> @@ -2854,6 +2854,13 @@ static void arm_smmu_iommu_xen_domain_teardown(struct domain *d)
>  	xfree(xen_domain);
>  }
>  
> +#ifdef CONFIG_SYSTEM_SUSPEND
> +static int arm_smmu_suspend(void)
> +{
> +	return -ENOSYS;
> +}
> +#endif
> +
>  static const struct iommu_ops arm_smmu_iommu_ops = {
>  	.page_sizes		= PAGE_SIZE_4K,
>  	.init			= arm_smmu_iommu_xen_domain_init,
> @@ -2866,6 +2873,9 @@ static const struct iommu_ops arm_smmu_iommu_ops = {
>  	.unmap_page		= arm_iommu_unmap_page,
>  	.dt_xlate		= arm_smmu_dt_xlate,
>  	.add_device		= arm_smmu_add_device,
> +#ifdef CONFIG_SYSTEM_SUSPEND
> +	.suspend		= arm_smmu_suspend,
> +#endif
>  };
>  
>  static __init int arm_smmu_dt_init(struct dt_device_node *dev,
> diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c
> index 22d306d0cb..45f29ef8ec 100644
> --- a/xen/drivers/passthrough/arm/smmu.c
> +++ b/xen/drivers/passthrough/arm/smmu.c
> @@ -2947,6 +2947,13 @@ static void arm_smmu_iommu_domain_teardown(struct domain *d)
>  	xfree(xen_domain);
>  }
>  
> +#ifdef CONFIG_SYSTEM_SUSPEND
> +static int arm_smmu_suspend(void)
> +{
> +	return -ENOSYS;
> +}
> +#endif
> +
>  static const struct iommu_ops arm_smmu_iommu_ops = {
>      .page_sizes = PAGE_SIZE_4K,
>      .init = arm_smmu_iommu_domain_init,
> @@ -2960,6 +2967,9 @@ static const struct iommu_ops arm_smmu_iommu_ops = {
>      .map_page = arm_iommu_map_page,
>      .unmap_page = arm_iommu_unmap_page,
>      .dt_xlate = arm_smmu_dt_xlate_generic,
> +#ifdef CONFIG_SYSTEM_SUSPEND
> +    .suspend = arm_smmu_suspend,
> +#endif
>  };
>  
>  static struct arm_smmu_device *find_smmu(const struct device *dev)

-- 
WBR, Volodymyr
Re: [PATCH v6 12/13] xen/arm: Suspend/resume IOMMU on Xen suspend/resume
Posted by Oleksandr Tyshchenko 1 month, 4 weeks ago

On 02.09.25 01:10, Mykola Kvach wrote:

Hello Mykola

> From: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
> 
> This is done using generic iommu_suspend/resume functions that cause
> IOMMU driver specific suspend/resume handlers to be called for enabled
> IOMMU (if one has suspend/resume driver handlers implemented).
> 
> Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
> Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
> ---
> Changes in V6:
> - Drop iommu_enabled check from host system suspend.

I do not have any comments for the updated version, thanks.


> ---
>   xen/arch/arm/suspend.c                | 11 +++++++++++
>   xen/drivers/passthrough/arm/smmu-v3.c | 10 ++++++++++
>   xen/drivers/passthrough/arm/smmu.c    | 10 ++++++++++
>   3 files changed, 31 insertions(+)
> 
> diff --git a/xen/arch/arm/suspend.c b/xen/arch/arm/suspend.c
> index 35b20581f1..f3a3b831c5 100644
> --- a/xen/arch/arm/suspend.c
> +++ b/xen/arch/arm/suspend.c
> @@ -5,6 +5,7 @@
>   
>   #include <xen/console.h>
>   #include <xen/cpu.h>
> +#include <xen/iommu.h>
>   #include <xen/llc-coloring.h>
>   #include <xen/sched.h>
>   #include <xen/tasklet.h>
> @@ -62,6 +63,13 @@ static void cf_check system_suspend(void *data)
>   
>       time_suspend();
>   
> +    status = iommu_suspend();
> +    if ( status )
> +    {
> +        system_state = SYS_STATE_resume;
> +        goto resume_time;
> +    }
> +
>       console_start_sync();
>       status = console_suspend();
>       if ( status )
> @@ -118,6 +126,9 @@ static void cf_check system_suspend(void *data)
>       console_resume();
>       console_end_sync();
>   
> +    iommu_resume();
> +
> + resume_time:
>       time_resume();
>   
>    resume_nonboot_cpus:
> diff --git a/xen/drivers/passthrough/arm/smmu-v3.c b/xen/drivers/passthrough/arm/smmu-v3.c
> index 81071f4018..f887faf7dc 100644
> --- a/xen/drivers/passthrough/arm/smmu-v3.c
> +++ b/xen/drivers/passthrough/arm/smmu-v3.c
> @@ -2854,6 +2854,13 @@ static void arm_smmu_iommu_xen_domain_teardown(struct domain *d)
>   	xfree(xen_domain);
>   }
>   
> +#ifdef CONFIG_SYSTEM_SUSPEND
> +static int arm_smmu_suspend(void)
> +{
> +	return -ENOSYS;
> +}
> +#endif
> +
>   static const struct iommu_ops arm_smmu_iommu_ops = {
>   	.page_sizes		= PAGE_SIZE_4K,
>   	.init			= arm_smmu_iommu_xen_domain_init,
> @@ -2866,6 +2873,9 @@ static const struct iommu_ops arm_smmu_iommu_ops = {
>   	.unmap_page		= arm_iommu_unmap_page,
>   	.dt_xlate		= arm_smmu_dt_xlate,
>   	.add_device		= arm_smmu_add_device,
> +#ifdef CONFIG_SYSTEM_SUSPEND
> +	.suspend		= arm_smmu_suspend,
> +#endif
>   };
>   
>   static __init int arm_smmu_dt_init(struct dt_device_node *dev,
> diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c
> index 22d306d0cb..45f29ef8ec 100644
> --- a/xen/drivers/passthrough/arm/smmu.c
> +++ b/xen/drivers/passthrough/arm/smmu.c
> @@ -2947,6 +2947,13 @@ static void arm_smmu_iommu_domain_teardown(struct domain *d)
>   	xfree(xen_domain);
>   }
>   
> +#ifdef CONFIG_SYSTEM_SUSPEND
> +static int arm_smmu_suspend(void)
> +{
> +	return -ENOSYS;
> +}
> +#endif
> +
>   static const struct iommu_ops arm_smmu_iommu_ops = {
>       .page_sizes = PAGE_SIZE_4K,
>       .init = arm_smmu_iommu_domain_init,
> @@ -2960,6 +2967,9 @@ static const struct iommu_ops arm_smmu_iommu_ops = {
>       .map_page = arm_iommu_map_page,
>       .unmap_page = arm_iommu_unmap_page,
>       .dt_xlate = arm_smmu_dt_xlate_generic,
> +#ifdef CONFIG_SYSTEM_SUSPEND
> +    .suspend = arm_smmu_suspend,
> +#endif
>   };
>   
>   static struct arm_smmu_device *find_smmu(const struct device *dev)
Re: [PATCH v6 12/13] xen/arm: Suspend/resume IOMMU on Xen suspend/resume
Posted by Mykola Kvach 1 month, 4 weeks ago
Hi Oleksandr,

On Tue, Sep 2, 2025 at 8:25 PM Oleksandr Tyshchenko <olekstysh@gmail.com> wrote:
>
>
>
> On 02.09.25 01:10, Mykola Kvach wrote:
>
> Hello Mykola
>
> > From: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
> >
> > This is done using generic iommu_suspend/resume functions that cause
> > IOMMU driver specific suspend/resume handlers to be called for enabled
> > IOMMU (if one has suspend/resume driver handlers implemented).
> >
> > Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
> > Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
> > ---
> > Changes in V6:
> > - Drop iommu_enabled check from host system suspend.
>
> I do not have any comments for the updated version, thanks.

Thank you for your time and the review!

>
>
> > ---
> >   xen/arch/arm/suspend.c                | 11 +++++++++++
> >   xen/drivers/passthrough/arm/smmu-v3.c | 10 ++++++++++
> >   xen/drivers/passthrough/arm/smmu.c    | 10 ++++++++++
> >   3 files changed, 31 insertions(+)
> >
> > diff --git a/xen/arch/arm/suspend.c b/xen/arch/arm/suspend.c
> > index 35b20581f1..f3a3b831c5 100644
> > --- a/xen/arch/arm/suspend.c
> > +++ b/xen/arch/arm/suspend.c
> > @@ -5,6 +5,7 @@
> >
> >   #include <xen/console.h>
> >   #include <xen/cpu.h>
> > +#include <xen/iommu.h>
> >   #include <xen/llc-coloring.h>
> >   #include <xen/sched.h>
> >   #include <xen/tasklet.h>
> > @@ -62,6 +63,13 @@ static void cf_check system_suspend(void *data)
> >
> >       time_suspend();
> >
> > +    status = iommu_suspend();
> > +    if ( status )
> > +    {
> > +        system_state = SYS_STATE_resume;
> > +        goto resume_time;
> > +    }
> > +
> >       console_start_sync();
> >       status = console_suspend();
> >       if ( status )
> > @@ -118,6 +126,9 @@ static void cf_check system_suspend(void *data)
> >       console_resume();
> >       console_end_sync();
> >
> > +    iommu_resume();
> > +
> > + resume_time:
> >       time_resume();
> >
> >    resume_nonboot_cpus:
> > diff --git a/xen/drivers/passthrough/arm/smmu-v3.c b/xen/drivers/passthrough/arm/smmu-v3.c
> > index 81071f4018..f887faf7dc 100644
> > --- a/xen/drivers/passthrough/arm/smmu-v3.c
> > +++ b/xen/drivers/passthrough/arm/smmu-v3.c
> > @@ -2854,6 +2854,13 @@ static void arm_smmu_iommu_xen_domain_teardown(struct domain *d)
> >       xfree(xen_domain);
> >   }
> >
> > +#ifdef CONFIG_SYSTEM_SUSPEND
> > +static int arm_smmu_suspend(void)
> > +{
> > +     return -ENOSYS;
> > +}
> > +#endif
> > +
> >   static const struct iommu_ops arm_smmu_iommu_ops = {
> >       .page_sizes             = PAGE_SIZE_4K,
> >       .init                   = arm_smmu_iommu_xen_domain_init,
> > @@ -2866,6 +2873,9 @@ static const struct iommu_ops arm_smmu_iommu_ops = {
> >       .unmap_page             = arm_iommu_unmap_page,
> >       .dt_xlate               = arm_smmu_dt_xlate,
> >       .add_device             = arm_smmu_add_device,
> > +#ifdef CONFIG_SYSTEM_SUSPEND
> > +     .suspend                = arm_smmu_suspend,
> > +#endif
> >   };
> >
> >   static __init int arm_smmu_dt_init(struct dt_device_node *dev,
> > diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c
> > index 22d306d0cb..45f29ef8ec 100644
> > --- a/xen/drivers/passthrough/arm/smmu.c
> > +++ b/xen/drivers/passthrough/arm/smmu.c
> > @@ -2947,6 +2947,13 @@ static void arm_smmu_iommu_domain_teardown(struct domain *d)
> >       xfree(xen_domain);
> >   }
> >
> > +#ifdef CONFIG_SYSTEM_SUSPEND
> > +static int arm_smmu_suspend(void)
> > +{
> > +     return -ENOSYS;
> > +}
> > +#endif
> > +
> >   static const struct iommu_ops arm_smmu_iommu_ops = {
> >       .page_sizes = PAGE_SIZE_4K,
> >       .init = arm_smmu_iommu_domain_init,
> > @@ -2960,6 +2967,9 @@ static const struct iommu_ops arm_smmu_iommu_ops = {
> >       .map_page = arm_iommu_map_page,
> >       .unmap_page = arm_iommu_unmap_page,
> >       .dt_xlate = arm_smmu_dt_xlate_generic,
> > +#ifdef CONFIG_SYSTEM_SUSPEND
> > +    .suspend = arm_smmu_suspend,
> > +#endif
> >   };
> >
> >   static struct arm_smmu_device *find_smmu(const struct device *dev)
>

Best regards,
Mykola