ia64/xen-unstable

changeset 6135:f6d6d17eaeb5

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@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Aug 12 13:06:23 2005 +0000 (2005-08-12)
parents 37ee6b4b409e
children 38bee85ddeb8
files linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c xen/arch/ia64/xentime.c xen/arch/x86/time.c xen/include/public/dom0_ops.h xen/include/public/xen.h xen/include/xen/time.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c	Fri Aug 12 09:14:02 2005 +0000
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c	Fri Aug 12 13:06:23 2005 +0000
     1.3 @@ -231,18 +231,32 @@ static void __update_wallclock(time_t se
     1.4  {
     1.5  	long wtm_nsec, xtime_nsec;
     1.6  	time_t wtm_sec, xtime_sec;
     1.7 -	u64 tmp, wc_nsec;
     1.8 +	s64 tmp, wc_nsec;
     1.9  
    1.10  	/* Adjust wall-clock time base based on wall_jiffies ticks. */
    1.11  	wc_nsec = processed_system_time;
    1.12 -	wc_nsec += (u64)sec * 1000000000ULL;
    1.13 -	wc_nsec += (u64)nsec;
    1.14 +	wc_nsec += (sec * 1000000000LL) + nsec;
    1.15  	wc_nsec -= (jiffies - wall_jiffies) * (u64)(NSEC_PER_SEC / HZ);
    1.16  
    1.17  	/* Split wallclock base into seconds and nanoseconds. */
    1.18 -	tmp = wc_nsec;
    1.19 -	xtime_nsec = do_div(tmp, 1000000000);
    1.20 -	xtime_sec  = (time_t)tmp;
    1.21 +	if ( (tmp = wc_nsec) < 0 )
    1.22 +	{
    1.23 +		/* -ve UTC offset => -ve seconds, +ve nanoseconds. */
    1.24 +		tmp = -tmp;
    1.25 +		xtime_nsec = do_div(tmp, 1000000000);
    1.26 +		tmp = -tmp;
    1.27 +		if ( xtime_nsec != 0 )
    1.28 +		{
    1.29 +			xtime_nsec = 1000000000 - xtime_nsec;
    1.30 +			tmp--;
    1.31 +		}
    1.32 +	}
    1.33 +	else
    1.34 +	{
    1.35 +		/* +ve UTC offset => +ve seconds, +ve nanoseconds. */
    1.36 +		xtime_nsec = do_div(tmp, 1000000000);
    1.37 +	}
    1.38 +	xtime_sec = (time_t)tmp;
    1.39  
    1.40  	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - xtime_sec);
    1.41  	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - xtime_nsec);
     2.1 --- a/xen/arch/ia64/xentime.c	Fri Aug 12 09:14:02 2005 +0000
     2.2 +++ b/xen/arch/ia64/xentime.c	Fri Aug 12 13:06:23 2005 +0000
     2.3 @@ -103,7 +103,7 @@ void update_dom_time(struct vcpu *v)
     2.4  }
     2.5  
     2.6  /* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
     2.7 -void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
     2.8 +void do_settime(s64 secs, u32 nsecs, u64 system_time_base)
     2.9  {
    2.10  #ifdef  CONFIG_VTI
    2.11      u64 _nsecs;
     3.1 --- a/xen/arch/x86/time.c	Fri Aug 12 09:14:02 2005 +0000
     3.2 +++ b/xen/arch/x86/time.c	Fri Aug 12 13:06:23 2005 +0000
     3.3 @@ -43,7 +43,10 @@ unsigned long hpet_address;
     3.4  spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
     3.5  int timer_ack = 0;
     3.6  unsigned long volatile jiffies;
     3.7 -static u32 wc_sec, wc_nsec; /* UTC time at last 'time update'. */
     3.8 +
     3.9 +/* UTC time at system boot. */
    3.10 +static s64 wc_sec;
    3.11 +static u32 wc_nsec;
    3.12  static spinlock_t wc_lock = SPIN_LOCK_UNLOCKED;
    3.13  
    3.14  struct time_scale {
    3.15 @@ -693,18 +696,33 @@ void update_dom_time(struct vcpu *v)
    3.16  }
    3.17  
    3.18  /* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
    3.19 -void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
    3.20 +void do_settime(s64 secs, u32 nsecs, u64 system_time_base)
    3.21  {
    3.22 -    u64 x;
    3.23 -    u32 y, _wc_sec, _wc_nsec;
    3.24 +    s64 x;
    3.25 +    u32 y;
    3.26      struct domain *d;
    3.27      shared_info_t *s;
    3.28  
    3.29 -    x = (secs * 1000000000ULL) + (u64)nsecs - system_time_base;
    3.30 -    y = do_div(x, 1000000000);
    3.31 +    x = (secs * 1000000000LL) + (u64)nsecs - system_time_base;
    3.32 +    if ( x < 0 )
    3.33 +    {
    3.34 +        /* -ve UTC offset => -ve seconds, +ve nanoseconds. */
    3.35 +        x = -x;
    3.36 +        y = do_div(x, 1000000000);
    3.37 +        x = -x;
    3.38 +        if ( y != 0 )
    3.39 +        {
    3.40 +            y = 1000000000 - y;
    3.41 +            x--;
    3.42 +        }
    3.43 +    }
    3.44 +    else
    3.45 +    {
    3.46 +        y = do_div(x, 1000000000);
    3.47 +    }
    3.48  
    3.49 -    wc_sec  = _wc_sec  = (u32)x;
    3.50 -    wc_nsec = _wc_nsec = (u32)y;
    3.51 +    wc_sec  = x;
    3.52 +    wc_nsec = y;
    3.53  
    3.54      read_lock(&domlist_lock);
    3.55      spin_lock(&wc_lock);
    3.56 @@ -713,8 +731,8 @@ void do_settime(unsigned long secs, unsi
    3.57      {
    3.58          s = d->shared_info;
    3.59          version_update_begin(&s->wc_version);
    3.60 -        s->wc_sec  = _wc_sec;
    3.61 -        s->wc_nsec = _wc_nsec;
    3.62 +        s->wc_sec  = x;
    3.63 +        s->wc_nsec = y;
    3.64          version_update_end(&s->wc_version);
    3.65      }
    3.66  
     4.1 --- a/xen/include/public/dom0_ops.h	Fri Aug 12 09:14:02 2005 +0000
     4.2 +++ b/xen/include/public/dom0_ops.h	Fri Aug 12 13:06:23 2005 +0000
     4.3 @@ -133,11 +133,12 @@ typedef struct {
     4.4  /*
     4.5   * Set clock such that it would read <secs,nsecs> after 00:00:00 UTC,
     4.6   * 1 January, 1970 if the current system time was <system_time>.
     4.7 + * NB. <secs> can be negative, but <nsecs> must always be non-negative.
     4.8   */
     4.9  #define DOM0_SETTIME          17
    4.10  typedef struct {
    4.11      /* IN variables. */
    4.12 -    u32 secs;
    4.13 +    s64 secs;
    4.14      u32 nsecs;
    4.15      u64 system_time;
    4.16  } dom0_settime_t;
     5.1 --- a/xen/include/public/xen.h	Fri Aug 12 09:14:02 2005 +0000
     5.2 +++ b/xen/include/public/xen.h	Fri Aug 12 13:06:23 2005 +0000
     5.3 @@ -399,11 +399,12 @@ typedef struct shared_info {
     5.4  
     5.5      /*
     5.6       * Wallclock time: updated only by control software. Guests should base
     5.7 -     * their gettimeofday() syscall on this wallclock-base value.
     5.8 +     * their gettimeofday() syscall on this wallclock-base value, which
     5.9 +     * indicates UTC when system_time == 0 (i.e., at boot).
    5.10       */
    5.11      u32 wc_version;      /* Version counter: see vcpu_time_info_t. */
    5.12 -    u32 wc_sec;          /* Secs  00:00:00 UTC, Jan 1, 1970.  */
    5.13 -    u32 wc_nsec;         /* Nsecs 00:00:00 UTC, Jan 1, 1970.  */
    5.14 +    u32 wc_nsec;         /* Nsecs since 00:00:00 UTC, Jan 1, 1970.  */
    5.15 +    s64 wc_sec;          /* Secs  since 00:00:00 UTC, Jan 1, 1970.  */
    5.16  
    5.17      arch_shared_info_t arch;
    5.18  
     6.1 --- a/xen/include/xen/time.h	Fri Aug 12 09:14:02 2005 +0000
     6.2 +++ b/xen/include/xen/time.h	Fri Aug 12 13:06:23 2005 +0000
     6.3 @@ -56,8 +56,7 @@ s_time_t get_s_time(void);
     6.4  #define MICROSECS(_us)  ((s_time_t)((_us) * 1000ULL))
     6.5  
     6.6  extern void update_dom_time(struct vcpu *v);
     6.7 -extern void do_settime(
     6.8 -    unsigned long secs, unsigned long nsecs, u64 system_time_base);
     6.9 +extern void do_settime(s64 secs, u32 nsecs, u64 system_time_base);
    6.10  
    6.11  #endif /* __XEN_TIME_H__ */
    6.12