[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] More time fixes. Now time is set properly in domU's, and



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 10b395bc465ea7ac73302d4987b05f40ee023b22
# Parent  0761551e993a57b81f71f0c2d306f28cba5319d5
More time fixes. Now time is set properly in domU's, and
settimeofday() is simplified and fixed.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 0761551e993a -r 10b395bc465e 
linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c  Thu Aug 11 12:06:32 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c  Thu Aug 11 13:07:08 2005
@@ -227,12 +227,38 @@
        return scale_delta(delta, shadow->tsc_to_usec_mul, shadow->tsc_shift);
 }
 
-static void update_wallclock(void)
-{
-       shared_info_t *s = HYPERVISOR_shared_info;
+static void __update_wallclock(time_t sec, long nsec)
+{
        long wtm_nsec, xtime_nsec;
        time_t wtm_sec, xtime_sec;
-       u64 tmp, nsec;
+       u64 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 -= (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;
+
+       wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - xtime_sec);
+       wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - xtime_nsec);
+
+       set_normalized_timespec(&xtime, xtime_sec, xtime_nsec);
+       set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
+       time_adjust = 0;                /* stop active adjtime() */
+       time_status |= STA_UNSYNC;
+       time_maxerror = NTP_PHASE_LIMIT;
+       time_esterror = NTP_PHASE_LIMIT;
+}
+
+static void update_wallclock(void)
+{
+       shared_info_t *s = HYPERVISOR_shared_info;
 
        do {
                shadow_tv_version = s->wc_version;
@@ -243,25 +269,8 @@
        }
        while ((s->wc_version & 1) | (shadow_tv_version ^ s->wc_version));
 
-       if (independent_wallclock)
-               return;
-
-       /* Adjust wall-clock time base based on wall_jiffies ticks. */
-       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 = nsec;
-       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);
-
-       set_normalized_timespec(&xtime, xtime_sec, xtime_nsec);
-       set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+       if (!independent_wallclock)
+               __update_wallclock(shadow_tv.tv_sec, shadow_tv.tv_nsec);
 }
 
 /*
@@ -408,18 +417,14 @@
 
 int do_settimeofday(struct timespec *tv)
 {
-       time_t wtm_sec, sec = tv->tv_sec;
-       long wtm_nsec;
+       time_t sec;
        s64 nsec;
-       struct timespec xentime;
        unsigned int cpu;
        struct shadow_time_info *shadow;
+       dom0_op_t op;
 
        if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
                return -EINVAL;
-
-       if (!independent_wallclock && !(xen_start_info.flags & SIF_INITDOMAIN))
-               return 0; /* Silent failure? */
 
        cpu = get_cpu();
        shadow = &per_cpu(shadow_time, cpu);
@@ -431,51 +436,30 @@
         * overflows. If that were to happen then our shadow time values would
         * be stale, so we can retry with fresh ones.
         */
- again:
-       nsec = (s64)tv->tv_nsec - (s64)get_nsec_offset(shadow);
-       if (unlikely(!time_values_up_to_date(cpu))) {
+       for ( ; ; ) {
+               nsec = (s64)tv->tv_nsec - (s64)get_nsec_offset(shadow);
+               if (time_values_up_to_date(cpu))
+                       break;
                get_time_values_from_xen();
-               goto again;
-       }
-
+       }
+       sec = tv->tv_sec;
        __normalize_time(&sec, &nsec);
-       set_normalized_timespec(&xentime, sec, nsec);
-
-       /*
-        * This is revolting. We need to set "xtime" correctly. However, the
-        * value in this location is the value at the most recent update of
-        * wall time.  Discover what correction gettimeofday() would have
-        * made, and then undo it!
-        */
-       nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
-
-       nsec -= (shadow->system_timestamp - processed_system_time);
-
-       __normalize_time(&sec, &nsec);
-       wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-       wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-       set_normalized_timespec(&xtime, sec, nsec);
-       set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
-
-#ifdef CONFIG_XEN_PRIVILEGED_GUEST
+
        if ((xen_start_info.flags & SIF_INITDOMAIN) &&
            !independent_wallclock) {
-               dom0_op_t op;
                op.cmd = DOM0_SETTIME;
-               op.u.settime.secs        = xentime.tv_sec;
-               op.u.settime.nsecs       = xentime.tv_nsec;
+               op.u.settime.secs        = sec;
+               op.u.settime.nsecs       = nsec;
                op.u.settime.system_time = shadow->system_timestamp;
-               write_sequnlock_irq(&xtime_lock);
                HYPERVISOR_dom0_op(&op);
-       } else
-#endif
-               write_sequnlock_irq(&xtime_lock);
+               update_wallclock();
+       } else if (independent_wallclock) {
+               nsec -= shadow->system_timestamp;
+               __normalize_time(&sec, &nsec);
+               __update_wallclock(sec, nsec);
+       }
+
+       write_sequnlock_irq(&xtime_lock);
 
        put_cpu();
 
@@ -491,6 +475,9 @@
        int retval;
 
        WARN_ON(irqs_disabled());
+
+       if (!(xen_start_info.flags & SIF_INITDOMAIN))
+               return 0;
 
        /* gets recalled with irq locally disabled */
        spin_lock_irq(&rtc_lock);
@@ -603,8 +590,10 @@
                profile_tick(CPU_PROFILING, regs);
        }
 
-       if (unlikely(shadow_tv_version != HYPERVISOR_shared_info->wc_version))
+       if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) {
                update_wallclock();
+               clock_was_set();
+       }
 }
 
 /*
diff -r 0761551e993a -r 10b395bc465e xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Thu Aug 11 12:06:32 2005
+++ b/xen/arch/x86/domain.c     Thu Aug 11 13:07:08 2005
@@ -279,8 +279,6 @@
     
     shadow_lock_init(d);        
     INIT_LIST_HEAD(&d->arch.free_shadow_frames);
-
-    init_domain_time(d);
 }
 
 void arch_do_boot_vcpu(struct vcpu *v)
@@ -481,7 +479,10 @@
     }
 
     update_pagetables(v);
-    
+
+    if ( v->vcpu_id == 0 )
+        init_domain_time(d);
+
     /* Don't redo final setup */
     set_bit(_VCPUF_initialised, &v->vcpu_flags);
 
diff -r 0761551e993a -r 10b395bc465e xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c       Thu Aug 11 12:06:32 2005
+++ b/xen/arch/x86/domain_build.c       Thu Aug 11 13:07:08 2005
@@ -618,6 +618,8 @@
     /* DOM0 gets access to everything. */
     physdev_init_dom0(d);
 
+    init_domain_time(d);
+
     set_bit(_DOMF_constructed, &d->domain_flags);
 
     new_thread(v, dsi.v_kernentry, vstack_end, vstartinfo_start);
diff -r 0761551e993a -r 10b395bc465e xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Thu Aug 11 12:06:32 2005
+++ b/xen/arch/x86/time.c       Thu Aug 11 13:07:08 2005
@@ -44,6 +44,7 @@
 int timer_ack = 0;
 unsigned long volatile jiffies;
 static u32 wc_sec, wc_nsec; /* UTC time at last 'time update'. */
+static spinlock_t wc_lock = SPIN_LOCK_UNLOCKED;
 
 struct time_scale {
     int shift;
@@ -699,13 +700,14 @@
     struct domain *d;
     shared_info_t *s;
 
-    x = (secs * 1000000000ULL) + (u64)nsecs + system_time_base;
+    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);
+    spin_lock(&wc_lock);
 
     for_each_domain ( d )
     {
@@ -716,15 +718,18 @@
         version_update_end(&s->wc_version);
     }
 
+    spin_unlock(&wc_lock);
     read_unlock(&domlist_lock);
 }
 
 void init_domain_time(struct domain *d)
 {
+    spin_lock(&wc_lock);
     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);
+    spin_unlock(&wc_lock);
 }
 
 static void local_time_calibration(void *unused)

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.