WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] Have xen dom0 still handle time of 1970

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] Have xen dom0 still handle time of 1970
From: Steven Rostedt <srostedt@xxxxxxxxxx>
Date: Wed, 17 Jan 2007 10:50:15 -0500
Delivery-date: Wed, 17 Jan 2007 07:50:21 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Thunderbird 1.5.0.4 (X11/20060614)
It's come to our attention, that the time gets screwed up when set between EPOCH and EPOCH + uptime. This may not seem important (because we don't live in the 70s anymore) but it makes LTP fail. LTP has a date test that checks what happens when set to EPOCH + 100 secs + 100 nsecs, and makes sure that it gets a proper result.

The following patches helps xen handle the case where time is set back to Jan 1st 1970 (or anytime from EPOCH to EPOCH + uptime).

Here's what you get without the patch:

# date -u 010100011970
Thu Jan  1 00:01:00 UTC 1970
# date
Mon Feb 22 16:42:30 EST 2010

Here's what you get with the patch:

# date -u 010100011970
Thu Jan  1 00:01:00 UTC 1970
# date
Wed Dec 31 19:01:01 EST 1969

-- Steve

Signed-off-by: Steven Rostedt <srostedt@xxxxxxxxxx>
diff -r fd2667419c53 linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c  Tue Jan 16 14:04:12 
2007 -0500
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c  Wed Jan 17 10:34:06 
2007 -0500
@@ -260,7 +260,8 @@ static void __update_wallclock(time_t se
 {
        long wtm_nsec, xtime_nsec;
        time_t wtm_sec, xtime_sec;
-       u64 tmp, wc_nsec;
+       s64 tmp, wc_nsec;
+       int s;
 
        /* Adjust wall-clock time base based on wall_jiffies ticks. */
        wc_nsec = processed_system_time;
@@ -270,8 +271,17 @@ static void __update_wallclock(time_t se
 
        /* Split wallclock base into seconds and nanoseconds. */
        tmp = wc_nsec;
+       /*
+        * do_div does not like s64, and treats them as u64
+        * and we will not get the expected result.
+        * So for those with time machines, let 1970 work
+        * again!
+        */
+       s = tmp < 0 ? -1 : 1;
+       tmp *= s;
        xtime_nsec = do_div(tmp, 1000000000);
        xtime_sec  = (time_t)tmp;
+       xtime_sec *= s;
 
        wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - xtime_sec);
        wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - xtime_nsec);
@@ -289,7 +299,12 @@ static void update_wallclock(void)
        do {
                shadow_tv_version = s->wc_version;
                rmb();
-               shadow_tv.tv_sec  = s->wc_sec;
+               /*
+                * If someone decides to set the time to something
+                * before EPOCH + uptime, we can get a negative
+                * number here.
+                */
+               shadow_tv.tv_sec  = (s32)s->wc_sec;
                shadow_tv.tv_nsec = s->wc_nsec;
                rmb();
        } while ((s->wc_version & 1) | (shadow_tv_version ^ s->wc_version));
diff -r fd2667419c53 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Tue Jan 16 14:04:12 2007 -0500
+++ b/xen/arch/x86/time.c       Wed Jan 17 10:34:06 2007 -0500
@@ -708,12 +708,23 @@ void update_domain_wallclock_time(struct
 /* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
 void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
 {
-    u64 x;
+    s64 x;
     u32 y, _wc_sec, _wc_nsec;
     struct domain *d;
+    int s;
 
     x = (secs * 1000000000ULL) + (u64)nsecs - system_time_base;
+    s = x < 0 ? -1 : 1;
+    /*
+     * do_div does not like negative s64 numbers and treats them
+     * as u64, thus the result is unexpected if the s64 is
+     * negative. For those that still live in the 70s, and
+     * want their Xen boxes to do the same, we must handle the
+     * negative case.
+     */
+    x *= s;
     y = do_div(x, 1000000000);
+    x *= s;
 
     spin_lock(&wc_lock);
     wc_sec  = _wc_sec  = (u32)x;
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel