# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID f6d6d17eaeb5f04efea7f9d8f753a91ffff0479d
# Parent 37ee6b4b409e67001d2c3054e9300bc08bc49fa9
Fix wallclock time when the offset relative to the epoch
(1 Jan 1970 00:00:00) is negative. This happens in some
LTP tests, for example.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
diff -r 37ee6b4b409e -r f6d6d17eaeb5
linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Fri Aug 12 09:14:02 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Fri Aug 12 13:06:23 2005
@@ -231,18 +231,32 @@
{
long wtm_nsec, xtime_nsec;
time_t wtm_sec, xtime_sec;
- u64 tmp, wc_nsec;
+ s64 tmp, wc_nsec;
/* Adjust wall-clock time base based on wall_jiffies ticks. */
wc_nsec = processed_system_time;
- wc_nsec += (u64)sec * 1000000000ULL;
- wc_nsec += (u64)nsec;
+ wc_nsec += (sec * 1000000000LL) + nsec;
wc_nsec -= (jiffies - wall_jiffies) * (u64)(NSEC_PER_SEC / HZ);
/* Split wallclock base into seconds and nanoseconds. */
- tmp = wc_nsec;
- xtime_nsec = do_div(tmp, 1000000000);
- xtime_sec = (time_t)tmp;
+ if ( (tmp = wc_nsec) < 0 )
+ {
+ /* -ve UTC offset => -ve seconds, +ve nanoseconds. */
+ tmp = -tmp;
+ xtime_nsec = do_div(tmp, 1000000000);
+ tmp = -tmp;
+ if ( xtime_nsec != 0 )
+ {
+ xtime_nsec = 1000000000 - xtime_nsec;
+ tmp--;
+ }
+ }
+ else
+ {
+ /* +ve UTC offset => +ve seconds, +ve nanoseconds. */
+ xtime_nsec = do_div(tmp, 1000000000);
+ }
+ xtime_sec = (time_t)tmp;
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - xtime_sec);
wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - xtime_nsec);
diff -r 37ee6b4b409e -r f6d6d17eaeb5 xen/arch/ia64/xentime.c
--- a/xen/arch/ia64/xentime.c Fri Aug 12 09:14:02 2005
+++ b/xen/arch/ia64/xentime.c Fri Aug 12 13:06:23 2005
@@ -103,7 +103,7 @@
}
/* 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)
+void do_settime(s64 secs, u32 nsecs, u64 system_time_base)
{
#ifdef CONFIG_VTI
u64 _nsecs;
diff -r 37ee6b4b409e -r f6d6d17eaeb5 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c Fri Aug 12 09:14:02 2005
+++ b/xen/arch/x86/time.c Fri Aug 12 13:06:23 2005
@@ -43,7 +43,10 @@
spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
int timer_ack = 0;
unsigned long volatile jiffies;
-static u32 wc_sec, wc_nsec; /* UTC time at last 'time update'. */
+
+/* UTC time at system boot. */
+static s64 wc_sec;
+static u32 wc_nsec;
static spinlock_t wc_lock = SPIN_LOCK_UNLOCKED;
struct time_scale {
@@ -693,18 +696,33 @@
}
/* 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;
- u32 y, _wc_sec, _wc_nsec;
+void do_settime(s64 secs, u32 nsecs, u64 system_time_base)
+{
+ s64 x;
+ u32 y;
struct domain *d;
shared_info_t *s;
- x = (secs * 1000000000ULL) + (u64)nsecs - system_time_base;
- y = do_div(x, 1000000000);
-
- wc_sec = _wc_sec = (u32)x;
- wc_nsec = _wc_nsec = (u32)y;
+ x = (secs * 1000000000LL) + (u64)nsecs - system_time_base;
+ if ( x < 0 )
+ {
+ /* -ve UTC offset => -ve seconds, +ve nanoseconds. */
+ x = -x;
+ y = do_div(x, 1000000000);
+ x = -x;
+ if ( y != 0 )
+ {
+ y = 1000000000 - y;
+ x--;
+ }
+ }
+ else
+ {
+ y = do_div(x, 1000000000);
+ }
+
+ wc_sec = x;
+ wc_nsec = y;
read_lock(&domlist_lock);
spin_lock(&wc_lock);
@@ -713,8 +731,8 @@
{
s = d->shared_info;
version_update_begin(&s->wc_version);
- s->wc_sec = _wc_sec;
- s->wc_nsec = _wc_nsec;
+ s->wc_sec = x;
+ s->wc_nsec = y;
version_update_end(&s->wc_version);
}
diff -r 37ee6b4b409e -r f6d6d17eaeb5 xen/include/public/dom0_ops.h
--- a/xen/include/public/dom0_ops.h Fri Aug 12 09:14:02 2005
+++ b/xen/include/public/dom0_ops.h Fri Aug 12 13:06:23 2005
@@ -133,11 +133,12 @@
/*
* Set clock such that it would read <secs,nsecs> after 00:00:00 UTC,
* 1 January, 1970 if the current system time was <system_time>.
+ * NB. <secs> can be negative, but <nsecs> must always be non-negative.
*/
#define DOM0_SETTIME 17
typedef struct {
/* IN variables. */
- u32 secs;
+ s64 secs;
u32 nsecs;
u64 system_time;
} dom0_settime_t;
diff -r 37ee6b4b409e -r f6d6d17eaeb5 xen/include/public/xen.h
--- a/xen/include/public/xen.h Fri Aug 12 09:14:02 2005
+++ b/xen/include/public/xen.h Fri Aug 12 13:06:23 2005
@@ -399,11 +399,12 @@
/*
* Wallclock time: updated only by control software. Guests should base
- * their gettimeofday() syscall on this wallclock-base value.
+ * their gettimeofday() syscall on this wallclock-base value, which
+ * indicates UTC when system_time == 0 (i.e., at boot).
*/
u32 wc_version; /* Version counter: see vcpu_time_info_t. */
- u32 wc_sec; /* Secs 00:00:00 UTC, Jan 1, 1970. */
- u32 wc_nsec; /* Nsecs 00:00:00 UTC, Jan 1, 1970. */
+ u32 wc_nsec; /* Nsecs since 00:00:00 UTC, Jan 1, 1970. */
+ s64 wc_sec; /* Secs since 00:00:00 UTC, Jan 1, 1970. */
arch_shared_info_t arch;
diff -r 37ee6b4b409e -r f6d6d17eaeb5 xen/include/xen/time.h
--- a/xen/include/xen/time.h Fri Aug 12 09:14:02 2005
+++ b/xen/include/xen/time.h Fri Aug 12 13:06:23 2005
@@ -56,8 +56,7 @@
#define MICROSECS(_us) ((s_time_t)((_us) * 1000ULL))
extern void update_dom_time(struct vcpu *v);
-extern void do_settime(
- unsigned long secs, unsigned long nsecs, u64 system_time_base);
+extern void do_settime(s64 secs, u32 nsecs, u64 system_time_base);
#endif /* __XEN_TIME_H__ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|