diff mbox series

[11/19] xen/arm: Suspend/resume timer interrupt generation

Message ID 63e5551cc906d8603abfbe9596403fdd8107c849.1665137247.git.mykyta_poturai@epam.com (mailing list archive)
State New, archived
Headers show
Series [01/19] xen/arm: Implement PSCI system suspend | expand

Commit Message

Mykyta Poturai Oct. 7, 2022, 10:32 a.m. UTC
From: Mirela Simonovic <mirela.simonovic@aggios.com>

Timer interrupts have to be disabled while the system is in suspend.
Otherwise, a timer interrupt would fire and wake-up the system.
Suspending the timer interrupts consists of disabling physical EL1
and EL2 timers. The resume consists only of raising timer softirq,
which will trigger the generic timer code to reprogram the EL2 timer
as needed. Enabling of EL1 physical timer will be triggered by an
entity which uses it.

Signed-off-by: Mirela Simonovic <mirela.simonovic@aggios.com>
Signed-off-by: Saeed Nowshadi <saeed.nowshadi@xilinx.com>
---
 xen/arch/arm/suspend.c     |  4 ++++
 xen/arch/arm/time.c        | 22 ++++++++++++++++++++++
 xen/include/asm-arm/time.h |  3 +++
 3 files changed, 29 insertions(+)

Comments

Julien Grall Dec. 6, 2022, 9:29 p.m. UTC | #1
Hi,

On 07/10/2022 11:32, Mykyta Poturai wrote:
> From: Mirela Simonovic <mirela.simonovic@aggios.com>
> 
> Timer interrupts have to be disabled while the system is in suspend.
> Otherwise, a timer interrupt would fire and wake-up the system.
> Suspending the timer interrupts consists of disabling physical EL1
> and EL2 timers. The resume consists only of raising timer softirq,
> which will trigger the generic timer code to reprogram the EL2 timer
> as needed. Enabling of EL1 physical timer will be triggered by an
> entity which uses it.
> 
> Signed-off-by: Mirela Simonovic <mirela.simonovic@aggios.com>
> Signed-off-by: Saeed Nowshadi <saeed.nowshadi@xilinx.com>
> ---
>   xen/arch/arm/suspend.c     |  4 ++++
>   xen/arch/arm/time.c        | 22 ++++++++++++++++++++++
>   xen/include/asm-arm/time.h |  3 +++
>   3 files changed, 29 insertions(+)
> 
> diff --git a/xen/arch/arm/suspend.c b/xen/arch/arm/suspend.c
> index b94a6df86d..05c43ce502 100644
> --- a/xen/arch/arm/suspend.c
> +++ b/xen/arch/arm/suspend.c
> @@ -151,6 +151,8 @@ static long system_suspend(void *data)
>           goto resume_nonboot_cpus;
>       }
>   
> +    time_suspend();
> +
>       local_irq_save(flags);
>       status = gic_suspend();
>       if ( status )
> @@ -166,6 +168,8 @@ static long system_suspend(void *data)
>   resume_irqs:
>       local_irq_restore(flags);
>   
> +    time_resume();
> +
>   resume_nonboot_cpus:
>       rcu_barrier();
>       enable_nonboot_cpus();
> diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c
> index dec53b5f7d..ca54bcfe68 100644
> --- a/xen/arch/arm/time.c
> +++ b/xen/arch/arm/time.c
> @@ -363,6 +363,28 @@ void domain_set_time_offset(struct domain *d, int64_t time_offset_seconds)
>       /* XXX update guest visible wallclock time */
>   }
>   
> +void time_suspend(void)
> +{
> +    /* Disable physical EL1 timer */
> +    WRITE_SYSREG(0, CNTP_CTL_EL0);
> +
> +    /* Disable hypervisor's timer */
> +    WRITE_SYSREG(0, CNTHP_CTL_EL2);
> +    isb();
> +}
> +
> +void time_resume(void)
> +{
> +    /*
> +     * Raising timer softirq will trigger generic timer code to reprogram_timer
> +     * with the correct timeout value (which is not known here). There is no
> +     * need to do anything else in order to recover the time keeping from power
> +     * down, because the system counter is not affected by the power down (it
> +     * resides out of the ARM's cluster in an always-on part of the SoC).
> +     */

Can you point me to the section in the Arm Arm stating the system 
counter is in an always-on part of the SoC?

> +    raise_softirq(TIMER_SOFTIRQ);

My expectation is that the time_resume() would closely match the x86 
version (aside the arch specific part). I can't see the raise_softirq(). 
So why do we need it here?

Also, there is a missing call to do_settime() and update_vcpu_system_time().

> +}
> +
>   static int cpu_time_callback(struct notifier_block *nfb,
>                                unsigned long action,
>                                void *hcpu)
> diff --git a/xen/include/asm-arm/time.h b/xen/include/asm-arm/time.h
> index 4b401c1110..ded93b490a 100644
> --- a/xen/include/asm-arm/time.h
> +++ b/xen/include/asm-arm/time.h
> @@ -107,6 +107,9 @@ void preinit_xen_time(void);
>   
>   void force_update_vcpu_system_time(struct vcpu *v);
>   
> +void time_suspend(void);
> +void time_resume(void);
> +
>   #endif /* __ARM_TIME_H__ */
>   /*
>    * Local variables:

Cheers,
diff mbox series

Patch

diff --git a/xen/arch/arm/suspend.c b/xen/arch/arm/suspend.c
index b94a6df86d..05c43ce502 100644
--- a/xen/arch/arm/suspend.c
+++ b/xen/arch/arm/suspend.c
@@ -151,6 +151,8 @@  static long system_suspend(void *data)
         goto resume_nonboot_cpus;
     }
 
+    time_suspend();
+
     local_irq_save(flags);
     status = gic_suspend();
     if ( status )
@@ -166,6 +168,8 @@  static long system_suspend(void *data)
 resume_irqs:
     local_irq_restore(flags);
 
+    time_resume();
+
 resume_nonboot_cpus:
     rcu_barrier();
     enable_nonboot_cpus();
diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c
index dec53b5f7d..ca54bcfe68 100644
--- a/xen/arch/arm/time.c
+++ b/xen/arch/arm/time.c
@@ -363,6 +363,28 @@  void domain_set_time_offset(struct domain *d, int64_t time_offset_seconds)
     /* XXX update guest visible wallclock time */
 }
 
+void time_suspend(void)
+{
+    /* Disable physical EL1 timer */
+    WRITE_SYSREG(0, CNTP_CTL_EL0);
+
+    /* Disable hypervisor's timer */
+    WRITE_SYSREG(0, CNTHP_CTL_EL2);
+    isb();
+}
+
+void time_resume(void)
+{
+    /*
+     * Raising timer softirq will trigger generic timer code to reprogram_timer
+     * with the correct timeout value (which is not known here). There is no
+     * need to do anything else in order to recover the time keeping from power
+     * down, because the system counter is not affected by the power down (it
+     * resides out of the ARM's cluster in an always-on part of the SoC).
+     */
+    raise_softirq(TIMER_SOFTIRQ);
+}
+
 static int cpu_time_callback(struct notifier_block *nfb,
                              unsigned long action,
                              void *hcpu)
diff --git a/xen/include/asm-arm/time.h b/xen/include/asm-arm/time.h
index 4b401c1110..ded93b490a 100644
--- a/xen/include/asm-arm/time.h
+++ b/xen/include/asm-arm/time.h
@@ -107,6 +107,9 @@  void preinit_xen_time(void);
 
 void force_update_vcpu_system_time(struct vcpu *v);
 
+void time_suspend(void);
+void time_resume(void);
+
 #endif /* __ARM_TIME_H__ */
 /*
  * Local variables: