Have xen dom0 still handle time of 1970
PATCH 1/1 Have xen dom0 still handle time of 1970
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
linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c +17 -2
@@ -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));
xen/arch/x86/time.c +12 -1
@@ -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
[email protected]
http://lists.xensource.com/xen-devel
Quoted 7 lines · Steven Rostedt
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
Quoted 6 lines
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
The Xen interface is defined relative to UTC, not local time zone, so negative numbers shuld not be involved if you are setting a time value after the epoch (which you are). Perhaps our assumption that xtime is a UTC variable is broken? If that's the case, is there a way to translate between local time zone and UTC inside the kernel? If not we have a bit of a problem since it really makes sense for Xen to work in UTC and let each guest apply its own time-zone transformation.
-- Keir
Quoted 16 lines · Keir Fraser
Quoted 7 lines · Steven Rostedt
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 2010Quoted 6 lines
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
Quoted 8 lines
The Xen interface is defined relative to UTC, not local time zone, so negative numbers shuld not be involved if you are setting a time value after the epoch (which you are). Perhaps our assumption that xtime is a UTC variable is broken? If that's the case, is there a way to translate between local time zone and UTC inside the kernel? If not we have a bit of a problem since it really makes sense for Xen to work in UTC and let each guest apply its own time-zone transformation.
It doesn't matter about the TZ. If I do this on a machine that has been running xen for more than a day, it will still fail with setting date to
date -u 010123001970
Which is not effected by the TZ (the result is after EPOCH).
The problem is that the calculation uses the uptime and compares that with the given time past EPOCH (using UTC). So if that time is less than uptime, it will fail the time conversion.
Have a box with Xen running more than a day? (I currently don't), and if you do, try the above date command. You'll see what I'm talking about.
The example is bad, but I didn't have a machine to show that has been running a Xen kernel for more than an hour or two.
-- Steve
Quoted 5 lines · Steven Rostedt
Have a box with Xen running more than a day? (I currently don't), and if you do, try the above date command. You'll see what I'm talking about.
The example is bad, but I didn't have a machine to show that has been running a Xen kernel for more than an hour or two.
Oh, I see. But it kind of feels silly to work around a synthetic correctness test. If we make wc_sec implicitly signed (which is pretty gross) then we lose 1 bit of magnitude which also isn't great -- I'd rather be able to represent years 2038 through 2106 than 1902 through 1970.
What we could do, to keep LTP happy, is set the local domain's time as specified but clamp the time sent to Xen at epoch+uptime. This would require dom0 to read wc_time from Xen only once at boot. OTOH perhaps we just do not really care -- after all by default this LTP test will fail on all domU because settimeofday() is a no-op unless /proc/sys/xen/independent_wallclock is asserted. And if you set that flag on dom0, the LTP test will magically start working there too! :-)
Perhaps at least we should fail or clamp the settimeofday() call, rather than doing some mad warp into the future...
-- Keir
Quoted 5 lines · Keir Fraser
Quoted 3 lines · Steven Rostedt
Have a box with Xen running more than a day? (I currently don't), and if you do, try the above date command. You'll see what I'm talking about.
Quoted 7 lines
Quoted 2 lines
The example is bad, but I didn't have a machine to show that has been running a Xen kernel for more than an hour or two.
Oh, I see. But it kind of feels silly to work around a synthetic correctness test. If we make
wc_secimplicitly signed (which is pretty gross) then we lose 1 bit of magnitude which also isn't great -- I'd rather be able to represent years 2038 through 2106 than 1902 through 1970.
Isn't unsigned long 64 bits on 64 bit systems anyway?
That would give us a lot more time...
Signature · 3 lines
Politics is the struggle between those who want to make their country the best in the world, and those who believe it already is. Each group calls the other unpatriotic.
Quoted 8 lines · Rik van Riel
Quoted 4 lines
Oh, I see. But it kind of feels silly to work around a synthetic correctness test. If we make
wc_secimplicitly signed (which is pretty gross) then we lose 1 bit of magnitude which also isn't great -- I'd rather be able to represent years 2038 through 2106 than 1902 through 1970.Isn't unsigned long 64 bits on 64 bit systems anyway?
That would give us a lot more time...
Yeah it is, but wc_sec in shared_info is uint32_t. Perhaps I wasn't optimistic enough about Xen's longevity. :-) With tricks we could be good out to about 2250 without needing to increase wc_sec's size.
-- Keir