diff mbox series

[03/19] xen/arm: While a domain is suspended put its watchdogs on pause

Message ID fffb1b6e07974cfa81fbcf8793c9d540a7fed00e.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>

While a domain is suspended its watchdogs must be paused. Otherwise,
if the domain stays in the suspend state for a longer period of time
compared to the watchdog period, the domain would be shutdown on resume.
Proper solution to this problem is to stop (suspend) the watchdog timers
after the domain suspends and to restart (resume) the watchdog timers
before the domain resumes. The suspend/resume of watchdog timers is done
in Xen and is invisible to the guests.
Just before the domain starts resuming the watchdog timers are programmed
with a new expire value. The new expire value is set according to the
last offset provided by the last hypercall before suspend was triggered,
effectively restarting the timer.

Signed-off-by: Mirela Simonovic <mirela.simonovic@aggios.com>
Signed-off-by: Saeed Nowshadi <saeed.nowshadi@xilinx.com>
Signed-off-by: Mykyta Poturai <mykyta_poturai@epam.com>
---
 xen/arch/arm/suspend.c  |  4 ++++
 xen/common/sched/core.c | 36 ++++++++++++++++++++++++++++++++++++
 xen/include/xen/sched.h |  7 +++++++
 3 files changed, 47 insertions(+)
diff mbox series

Patch

diff --git a/xen/arch/arm/suspend.c b/xen/arch/arm/suspend.c
index 987ba6ac11..d19545744f 100644
--- a/xen/arch/arm/suspend.c
+++ b/xen/arch/arm/suspend.c
@@ -128,6 +128,7 @@  void vcpu_resume(struct vcpu *v)
 
     /* Initialize VCPU registers */
     arch_set_info_guest(v, &ctxt);
+    watchdog_domain_resume(v->domain);
     clear_bit(_VPF_suspended, &v->pause_flags);
 }
 
@@ -162,6 +163,9 @@  int32_t domain_suspend(register_t epoint, register_t cid)
      */
     vcpu_suspend(epoint, cid);
 
+    /* Disable watchdogs of this domain */
+    watchdog_domain_suspend(d);
+
     /*
      * The calling domain is suspended by blocking its last running VCPU. If an
      * event is pending the domain will resume right away (VCPU will not block,
diff --git a/xen/common/sched/core.c b/xen/common/sched/core.c
index 0ecb41cfe1..ebed0ec49e 100644
--- a/xen/common/sched/core.c
+++ b/xen/common/sched/core.c
@@ -1616,6 +1616,42 @@  void watchdog_domain_destroy(struct domain *d)
         kill_timer(&d->watchdog_timer[i].timer);
 }
 
+void watchdog_domain_suspend(struct domain *d)
+{
+    unsigned int i;
+
+    spin_lock(&d->watchdog_lock);
+
+    for ( i = 0; i < NR_DOMAIN_WATCHDOG_TIMERS; i++ )
+    {
+        if ( test_bit(i, &d->watchdog_inuse_map) )
+        {
+            stop_timer(&d->watchdog_timer[i].timer);
+        }
+    }
+
+    spin_unlock(&d->watchdog_lock);
+}
+
+void watchdog_domain_resume(struct domain *d)
+{
+    unsigned int i;
+
+    spin_lock(&d->watchdog_lock);
+
+    for ( i = 0; i < NR_DOMAIN_WATCHDOG_TIMERS; i++ )
+    {
+        if ( test_bit(i, &d->watchdog_inuse_map) )
+        {
+            set_timer(&d->watchdog_timer[i].timer,
+                      NOW() + SECONDS(d->watchdog_timer[i].timeout));
+        }
+    }
+
+    spin_unlock(&d->watchdog_lock);
+}
+
+
 /*
  * Pin a vcpu temporarily to a specific CPU (or restore old pinning state if
  * cpu is NR_CPUS).
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 7a4aef4c17..00a939aa01 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -1025,6 +1025,13 @@  void scheduler_disable(void);
 void watchdog_domain_init(struct domain *d);
 void watchdog_domain_destroy(struct domain *d);
 
+/*
+ * Suspend/resume watchdogs of domain (while the domain is suspended its
+ * watchdogs should be on pause)
+ */
+void watchdog_domain_suspend(struct domain *d);
+void watchdog_domain_resume(struct domain *d);
+
 /*
  * Use this check when the following are both true:
  *  - Using this feature or interface requires full access to the hardware