[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |