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-changelog

[Xen-changelog] More time-interface fixes.

# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 217fb2d1f364176571396fb7b4bf89222927631e
# Parent  7931f14bd447465bfdf2a458f70ccac55edcad03
More time-interface fixes.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 7931f14bd447 -r 217fb2d1f364 
linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c  Sat Aug  6 09:54:57 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c  Sat Aug  6 15:24:22 2005
@@ -115,7 +115,8 @@
        u32 version;
 };
 static DEFINE_PER_CPU(struct shadow_time_info, shadow_time);
-static struct timeval shadow_tv;
+static struct timespec shadow_tv;
+static u32 shadow_tv_version;
 
 /* Keep track of last time we did processing/updating of jiffies and xtime. */
 static u64 processed_system_time;   /* System time (ns) at last processing. */
@@ -123,18 +124,6 @@
 
 #define NS_PER_TICK (1000000000ULL/HZ)
 
-#define HANDLE_USEC_UNDERFLOW(_tv) do {                \
-       while ((_tv).tv_usec < 0) {             \
-               (_tv).tv_usec += USEC_PER_SEC;  \
-               (_tv).tv_sec--;                 \
-       }                                       \
-} while (0)
-#define HANDLE_USEC_OVERFLOW(_tv) do {         \
-       while ((_tv).tv_usec >= USEC_PER_SEC) { \
-               (_tv).tv_usec -= USEC_PER_SEC;  \
-               (_tv).tv_sec++;                 \
-       }                                       \
-} while (0)
 static inline void __normalize_time(time_t *sec, s64 *nsec)
 {
        while (*nsec >= NSEC_PER_SEC) {
@@ -231,14 +220,16 @@
        shared_info_t *s = HYPERVISOR_shared_info;
        long wtm_nsec, xtime_nsec;
        time_t wtm_sec, xtime_sec;
-       u64 tmp, usec;
-
-       if ((shadow_tv.tv_sec == s->wc_sec) &&
-           (shadow_tv.tv_usec == s->wc_usec))
-               return;
-
-       shadow_tv.tv_sec  = s->wc_sec;
-       shadow_tv.tv_usec = s->wc_usec;
+       u64 tmp, nsec;
+
+       do {
+               shadow_tv_version = s->wc_version;
+               rmb();
+               shadow_tv.tv_sec  = s->wc_sec;
+               shadow_tv.tv_nsec = s->wc_nsec;
+               rmb();
+       }
+       while ((s->wc_version & 1) | (shadow_tv_version ^ s->wc_version));
 
        if (INDEPENDENT_WALLCLOCK())
                return;
@@ -247,15 +238,14 @@
                return;
 
        /* Adjust wall-clock time base based on wall_jiffies ticks. */
-       usec = processed_system_time;
-       do_div(usec, 1000);
-       usec += (u64)shadow_tv.tv_sec * 1000000ULL;
-       usec += (u64)shadow_tv.tv_usec;
-       usec -= (jiffies - wall_jiffies) * (USEC_PER_SEC / HZ);
+       nsec = processed_system_time;
+       nsec += (u64)shadow_tv.tv_sec * 1000000000ULL;
+       nsec += (u64)shadow_tv.tv_nsec;
+       nsec -= (jiffies - wall_jiffies) * (u64)(NSEC_PER_SEC / HZ);
 
        /* Split wallclock base into seconds and nanoseconds. */
-       tmp = usec;
-       xtime_nsec = do_div(tmp, 1000000) * 1000ULL;
+       tmp = nsec;
+       xtime_nsec = do_div(tmp, 1000000000);
        xtime_sec  = (time_t)tmp;
 
        wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - xtime_sec);
@@ -279,7 +269,7 @@
        dst = &per_cpu(shadow_time, smp_processor_id());
 
        do {
-               dst->version = src->time_version2;
+               dst->version = src->version;
                rmb();
                dst->tsc_timestamp     = src->tsc_timestamp;
                dst->system_timestamp  = src->system_time;
@@ -287,7 +277,7 @@
                dst->tsc_shift         = src->tsc_shift;
                rmb();
        }
-       while (dst->version != src->time_version1);
+       while ((src->version & 1) | (dst->version ^ src->version));
 
        dst->tsc_to_usec_mul = dst->tsc_to_nsec_mul / 1000;
 }
@@ -300,7 +290,7 @@
        src = &HYPERVISOR_shared_info->vcpu_time[cpu]; 
        dst = &per_cpu(shadow_time, cpu); 
 
-       return (dst->version == src->time_version2);
+       return (dst->version == src->version);
 }
 
 /*
@@ -469,7 +459,7 @@
                dom0_op_t op;
                op.cmd = DOM0_SETTIME;
                op.u.settime.secs        = xentime.tv_sec;
-               op.u.settime.usecs       = xentime.tv_nsec / NSEC_PER_USEC;
+               op.u.settime.nsecs       = xentime.tv_nsec;
                op.u.settime.system_time = shadow->system_timestamp;
                write_sequnlock_irq(&xtime_lock);
                HYPERVISOR_dom0_op(&op);
@@ -574,7 +564,7 @@
        }
        while (!time_values_up_to_date(cpu));
 
-       if (unlikely(delta < 0) || unlikely(delta_cpu < 0)) {
+       if (unlikely(delta < (s64)-1000000) || unlikely(delta_cpu < 0)) {
                printk("Timer ISR/%d: Time went backwards: "
                       "delta=%lld cpu_delta=%lld shadow=%lld "
                       "off=%lld processed=%lld cpu_processed=%lld\n",
@@ -603,7 +593,8 @@
                profile_tick(CPU_PROFILING, regs);
        }
 
-       update_wallclock();
+       if (unlikely(shadow_tv_version != HYPERVISOR_shared_info->wc_version))
+               update_wallclock();
 }
 
 /*
@@ -792,8 +783,6 @@
 #endif
        get_time_values_from_xen();
        update_wallclock();
-       xtime.tv_sec = shadow_tv.tv_sec;
-       xtime.tv_nsec = shadow_tv.tv_usec * NSEC_PER_USEC;
        set_normalized_timespec(&wall_to_monotonic,
                -xtime.tv_sec, -xtime.tv_nsec);
        processed_system_time = per_cpu(shadow_time, 0).system_timestamp;
diff -r 7931f14bd447 -r 217fb2d1f364 xen/arch/ia64/xentime.c
--- a/xen/arch/ia64/xentime.c   Sat Aug  6 09:54:57 2005
+++ b/xen/arch/ia64/xentime.c   Sat Aug  6 15:24:22 2005
@@ -48,7 +48,7 @@
 static s_time_t        stime_irq = 0x0;       /* System time at last 'time 
update' */
 unsigned long itc_scale;
 unsigned long itc_at_irq;
-static unsigned long   wc_sec, wc_usec; /* UTC time at last 'time update'.   */
+static unsigned long   wc_sec, wc_nsec; /* UTC time at last 'time update'.   */
 //static rwlock_t        time_lock = RW_LOCK_UNLOCKED;
 static irqreturn_t vmx_timer_interrupt (int irq, void *dev_id, struct pt_regs 
*regs);
 
@@ -103,25 +103,22 @@
 }
 
 /* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
-void do_settime(unsigned long secs, unsigned long usecs, u64 system_time_base)
+void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
 {
 #ifdef  CONFIG_VTI
-    s64 delta;
-    long _usecs = (long)usecs;
+    u64 _nsecs;
 
     write_lock_irq(&xtime_lock);
 
-    delta = (s64)(stime_irq - system_time_base);
-
-    _usecs += (long)(delta/1000);
-    while ( _usecs >= 1000000 ) 
+    _nsecs = (u64)nsecs + (s64)(stime_irq - system_time_base);
+    while ( _nsecs >= 1000000000 ) 
     {
-        _usecs -= 1000000;
+        _nsecs -= 1000000000;
         secs++;
     }
 
     wc_sec  = secs;
-    wc_usec = _usecs;
+    wc_nsec = (unsigned long)_nsecs;
 
     write_unlock_irq(&xtime_lock);
 
@@ -290,13 +287,13 @@
     /* Wallclock time starts as the initial RTC time. */
     efi_gettimeofday(&tm);
     wc_sec  = tm.tv_sec;
-    wc_usec = tm.tv_nsec/1000;
+    wc_nsec = tm.tv_nsec;
 
 
     printk("Time init:\n");
     printk(".... System Time: %ldns\n", NOW());
     printk(".... scale:       %16lX\n", itc_scale);
-    printk(".... Wall Clock:  %lds %ldus\n", wc_sec, wc_usec);
+    printk(".... Wall Clock:  %lds %ldus\n", wc_sec, wc_nsec/1000);
 
     return 0;
 }
@@ -338,10 +335,10 @@
             (*(unsigned long *)&jiffies_64)++;
 
             /* Update wall time. */
-            wc_usec += 1000000/HZ;
-            if ( wc_usec >= 1000000 )
+            wc_nsec += 1000000000/HZ;
+            if ( wc_nsec >= 1000000000 )
             {
-                wc_usec -= 1000000;
+                wc_nsec -= 1000000000;
                 wc_sec++;
             }
 
diff -r 7931f14bd447 -r 217fb2d1f364 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Sat Aug  6 09:54:57 2005
+++ b/xen/arch/x86/domain.c     Sat Aug  6 15:24:22 2005
@@ -279,6 +279,8 @@
     
     shadow_lock_init(d);        
     INIT_LIST_HEAD(&d->arch.free_shadow_frames);
+
+    init_domain_time(d);
 }
 
 void arch_do_boot_vcpu(struct vcpu *v)
diff -r 7931f14bd447 -r 217fb2d1f364 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Sat Aug  6 09:54:57 2005
+++ b/xen/arch/x86/time.c       Sat Aug  6 15:24:22 2005
@@ -43,7 +43,7 @@
 spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
 int timer_ack = 0;
 unsigned long volatile jiffies;
-static unsigned long wc_sec, wc_usec; /* UTC time at last 'time update'. */
+static u32 wc_sec, wc_nsec; /* UTC time at last 'time update'. */
 
 struct time_scale {
     int shift;
@@ -630,25 +630,32 @@
     return now;
 }
 
+static inline void version_update_begin(u32 *version)
+{
+    /* Explicitly OR with 1 just in case version number gets out of sync. */
+    *version = (*version + 1) | 1;
+    wmb();
+}
+
+static inline void version_update_end(u32 *version)
+{
+    wmb();
+    (*version)++;
+}
+
 static inline void __update_dom_time(struct vcpu *v)
 {
     struct cpu_time       *t = &cpu_time[smp_processor_id()];
     struct vcpu_time_info *u = &v->domain->shared_info->vcpu_time[v->vcpu_id];
 
-    u->time_version1++;
-    wmb();
+    version_update_begin(&u->version);
 
     u->tsc_timestamp     = t->local_tsc_stamp;
     u->system_time       = t->stime_local_stamp;
     u->tsc_to_system_mul = t->tsc_scale.mul_frac;
     u->tsc_shift         = (s8)t->tsc_scale.shift;
 
-    wmb();
-    u->time_version2++;
-
-    /* Should only do this during do_settime(). */
-    v->domain->shared_info->wc_sec  = wc_sec;
-    v->domain->shared_info->wc_usec = wc_usec;
+    version_update_end(&u->version);
 }
 
 void update_dom_time(struct vcpu *v)
@@ -659,21 +666,39 @@
 }
 
 /* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
-void do_settime(unsigned long secs, unsigned long usecs, u64 system_time_base)
-{
-    u64 x, base_usecs;
-    u32 y;
-
-    base_usecs = system_time_base;
-    do_div(base_usecs, 1000);
-
-    x = (secs * 1000000ULL) + (u64)usecs + base_usecs;
-    y = do_div(x, 1000000);
-
-    wc_sec  = (unsigned long)x;
-    wc_usec = (unsigned long)y;
-
-    __update_dom_time(current);
+void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
+{
+    u64 x;
+    u32 y, _wc_sec, _wc_nsec;
+    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;
+
+    read_lock(&domlist_lock);
+
+    for_each_domain ( d )
+    {
+        s = d->shared_info;
+        version_update_begin(&s->wc_version);
+        s->wc_sec  = _wc_sec;
+        s->wc_nsec = _wc_nsec;
+        version_update_end(&s->wc_version);
+    }
+
+    read_unlock(&domlist_lock);
+}
+
+void init_domain_time(struct domain *d)
+{
+    version_update_begin(&d->shared_info->wc_version);
+    d->shared_info->wc_sec  = wc_sec;
+    d->shared_info->wc_nsec = wc_nsec;
+    version_update_end(&d->shared_info->wc_version);
 }
 
 static void local_time_calibration(void *unused)
diff -r 7931f14bd447 -r 217fb2d1f364 xen/common/dom0_ops.c
--- a/xen/common/dom0_ops.c     Sat Aug  6 09:54:57 2005
+++ b/xen/common/dom0_ops.c     Sat Aug  6 15:24:22 2005
@@ -475,7 +475,7 @@
     case DOM0_SETTIME:
     {
         do_settime(op->u.settime.secs, 
-                   op->u.settime.usecs, 
+                   op->u.settime.nsecs, 
                    op->u.settime.system_time);
         ret = 0;
     }
diff -r 7931f14bd447 -r 217fb2d1f364 xen/include/asm-x86/time.h
--- a/xen/include/asm-x86/time.h        Sat Aug  6 09:54:57 2005
+++ b/xen/include/asm-x86/time.h        Sat Aug  6 15:24:22 2005
@@ -7,4 +7,7 @@
 extern void calibrate_tsc_bp(void);
 extern void calibrate_tsc_ap(void);
 
+struct domain;
+extern void init_domain_time(struct domain *d);
+
 #endif /* __X86_TIME_H__ */
diff -r 7931f14bd447 -r 217fb2d1f364 xen/include/public/dom0_ops.h
--- a/xen/include/public/dom0_ops.h     Sat Aug  6 09:54:57 2005
+++ b/xen/include/public/dom0_ops.h     Sat Aug  6 15:24:22 2005
@@ -131,14 +131,14 @@
 } dom0_debug_t;
 
 /*
- * Set clock such that it would read <secs,usecs> after 00:00:00 UTC,
+ * 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>.
  */
 #define DOM0_SETTIME          17
 typedef struct {
     /* IN variables. */
     u32 secs;
-    u32 usecs;
+    u32 nsecs;
     u64 system_time;
 } dom0_settime_t;
 
diff -r 7931f14bd447 -r 217fb2d1f364 xen/include/public/xen.h
--- a/xen/include/public/xen.h  Sat Aug  6 09:54:57 2005
+++ b/xen/include/public/xen.h  Sat Aug  6 15:24:22 2005
@@ -331,14 +331,15 @@
 
 typedef struct vcpu_time_info {
     /*
-     * The following values are updated periodically (and not necessarily
-     * atomically!). The guest OS detects this because 'time_version1' is
-     * incremented just before updating these values, and 'time_version2' is
-     * incremented immediately after. See the Xen-specific Linux code for an
-     * example of how to read these values safely (arch/xen/kernel/time.c).
+     * Updates to the following values are preceded and followed by an
+     * increment of 'version'. The guest can therefore detect updates by
+     * looking for changes to 'version'. If the least-significant bit of
+     * the version number is set then an update is in progress and the guest
+     * must wait to read a consistent set of values.
+     * The correct way to interact with the version number is similar to
+     * Linux's seqlock: see the implementations of read_seqbegin/read_seqretry.
      */
-    u32 time_version1;
-    u32 time_version2;
+    u32 version;
     u64 tsc_timestamp;   /* TSC at last update of time vals.  */
     u64 system_time;     /* Time, in nanosecs, since boot.    */
     /*
@@ -400,8 +401,9 @@
      * Wallclock time: updated only by control software. Guests should base
      * their gettimeofday() syscall on this wallclock-base value.
      */
-    u32                wc_sec;          /* Secs  00:00:00 UTC, Jan 1, 1970.  */
-    u32                wc_usec;         /* Usecs 00:00:00 UTC, Jan 1, 1970.  */
+    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.  */
 
     arch_shared_info_t arch;
 
diff -r 7931f14bd447 -r 217fb2d1f364 xen/include/xen/time.h
--- a/xen/include/xen/time.h    Sat Aug  6 09:54:57 2005
+++ b/xen/include/xen/time.h    Sat Aug  6 15:24:22 2005
@@ -57,7 +57,7 @@
 
 extern void update_dom_time(struct vcpu *v);
 extern void do_settime(
-    unsigned long secs, unsigned long usecs, u64 system_time_base);
+    unsigned long secs, unsigned long nsecs, u64 system_time_base);
 
 #endif /* __XEN_TIME_H__ */
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] More time-interface fixes., Xen patchbot -unstable <=