aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/hvm/rtc.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-06-04 10:05:42 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-06-04 10:05:42 +0100
commit9c667640ec3b50d10af660d7742f4372c70f30e7 (patch)
treee72d8e1f52a52ce61067fb46d0e0d33987c8c9c4 /xen/arch/x86/hvm/rtc.c
parent288f75ff8e23d183fd6ee19e77d8263d1cb93d9d (diff)
downloadxen-9c667640ec3b50d10af660d7742f4372c70f30e7.tar.gz
xen-9c667640ec3b50d10af660d7742f4372c70f30e7.tar.bz2
xen-9c667640ec3b50d10af660d7742f4372c70f30e7.zip
Add a safety valve to the HVM RTC model for big time jumps
If xen's time leaps forward by a large amount, the RTC will try to model a tick for every second that it thinks has passed. This can livelock a CPU with a series of timer requests each of which fires immediately and requests the next one. This patch treats a delay of more than a day between ticks as a special case, abandoning the attempt to catch up. That should be good enough to avoid livelock but doesn't fix the underlying time problem. Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
Diffstat (limited to 'xen/arch/x86/hvm/rtc.c')
-rw-r--r--xen/arch/x86/hvm/rtc.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/xen/arch/x86/hvm/rtc.c b/xen/arch/x86/hvm/rtc.c
index 1eb4854276..256c3c660e 100644
--- a/xen/arch/x86/hvm/rtc.c
+++ b/xen/arch/x86/hvm/rtc.c
@@ -281,9 +281,22 @@ static void rtc_next_second(RTCState *s)
static void rtc_update_second(void *opaque)
{
RTCState *s = opaque;
+ s_time_t now = NOW();
spin_lock(&s->lock);
+ /* If we somehow get way out of sync (say, Xen time leaps forward),
+ * don't livelock the system trying to emulate every second. Time
+ * is already in bad trouble, so just skip forward rather than
+ * trying to sync the RTC registers */
+ if ( unlikely(now - s->next_second_time > SECONDS(86400)) )
+ {
+ dprintk(XENLOG_WARNING, "HVM RTC: dom %u skipping %llu seconds\n",
+ vrtc_domain(s)->domain_id,
+ (now - s->next_second_time) / SYSTEM_TIME_HZ);
+ s->next_second_time = now;
+ }
+
/* if the oscillator is not in normal operation, we do not update */
if ( (s->hw.cmos_data[RTC_REG_A] & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ )
{