[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 04/18] xen/arm: While a domain is suspended put its watchdogs on pause



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 equal to the expire
value prior to suspend plus the period of time for which the watchdog
was on pause (the domain was suspended). In order to save the suspend
timestamp and afterwards calculate for how long the domain was suspended,
a 'suspended' variable is added into the generic timer structure.
Programming of the timers is triggered when a VCPU of the suspended
domain is scheduled in on resume.

Signed-off-by: Mirela Simonovic <mirela.simonovic@xxxxxxxxxx>
Signed-off-by: Saeed Nowshadi <saeed.nowshadi@xxxxxxxxxx>

---
Changes in v2:

-Fixed typo in commit message
---
 xen/arch/arm/domain.c   |  1 +
 xen/arch/arm/suspend.c  |  3 +++
 xen/common/schedule.c   | 38 ++++++++++++++++++++++++++++++++++++++
 xen/include/xen/sched.h |  7 +++++++
 xen/include/xen/timer.h |  3 +++
 5 files changed, 52 insertions(+)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index bebe3238e8..68f038458f 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -192,6 +192,7 @@ static void ctxt_switch_to(struct vcpu *n)
     {
         n->domain->is_shut_down = 0;
         n->domain->shutdown_code = SHUTDOWN_CODE_INVALID;
+        watchdog_domain_resume(n->domain);
     }
 
     p2m_restore_state(n);
diff --git a/xen/arch/arm/suspend.c b/xen/arch/arm/suspend.c
index 9eea9214e1..f2338e41db 100644
--- a/xen/arch/arm/suspend.c
+++ b/xen/arch/arm/suspend.c
@@ -146,6 +146,9 @@ int32_t domain_suspend(register_t epoint, register_t cid)
     d->is_shut_down = 1;
     d->shutdown_code = SHUTDOWN_suspend;
 
+    /* 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/schedule.c b/xen/common/schedule.c
index a957c5e57c..9b2882a168 100644
--- a/xen/common/schedule.c
+++ b/xen/common/schedule.c
@@ -1172,6 +1172,44 @@ void watchdog_domain_destroy(struct domain *d)
         kill_timer(&d->watchdog_timer[i]);
 }
 
+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) )
+        {
+            struct timer *timer = &d->watchdog_timer[i];
+            timer->suspended = NOW();
+            stop_timer(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) )
+        {
+            struct timer *timer = &d->watchdog_timer[i];
+            s_time_t sleep_interval = NOW() - timer->suspended;
+            set_timer(timer, timer->expires + sleep_interval);
+        }
+    }
+
+    spin_unlock(&d->watchdog_lock);
+}
+
 int vcpu_pin_override(struct vcpu *v, int cpu)
 {
     spinlock_t *lock;
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 1f4e86524f..366acaf69a 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -862,6 +862,13 @@ 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
  *    (that is, this would not be suitable for a driver domain)
diff --git a/xen/include/xen/timer.h b/xen/include/xen/timer.h
index 4513260b0d..4a88af7de0 100644
--- a/xen/include/xen/timer.h
+++ b/xen/include/xen/timer.h
@@ -18,6 +18,9 @@ struct timer {
     /* System time expiry value (nanoseconds since boot). */
     s_time_t expires;
 
+    /* Suspend timestamp value (nanoseconds since boot). */
+    s_time_t suspended;
+
     /* Position in active-timer data structure. */
     union {
         /* Timer-heap offset (TIMER_STATUS_in_heap). */
-- 
2.13.0


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.