ia64/xen-unstable
changeset 6108:10b395bc465e
More time fixes. Now time is set properly in domU's, and
settimeofday() is simplified and fixed.
Signed-off-by: Keir Fraser <keir@xensource.com>
settimeofday() is simplified and fixed.
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Thu Aug 11 13:07:08 2005 +0000 (2005-08-11) |
parents | 0761551e993a |
children | 37ac3cf33506 |
files | linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c xen/arch/x86/domain.c xen/arch/x86/domain_build.c xen/arch/x86/time.c |
line diff
1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Thu Aug 11 12:06:32 2005 +0000 1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Thu Aug 11 13:07:08 2005 +0000 1.3 @@ -227,12 +227,38 @@ static unsigned long get_usec_offset(str 1.4 return scale_delta(delta, shadow->tsc_to_usec_mul, shadow->tsc_shift); 1.5 } 1.6 1.7 +static void __update_wallclock(time_t sec, long nsec) 1.8 +{ 1.9 + long wtm_nsec, xtime_nsec; 1.10 + time_t wtm_sec, xtime_sec; 1.11 + u64 tmp, wc_nsec; 1.12 + 1.13 + /* Adjust wall-clock time base based on wall_jiffies ticks. */ 1.14 + wc_nsec = processed_system_time; 1.15 + wc_nsec += (u64)sec * 1000000000ULL; 1.16 + wc_nsec += (u64)nsec; 1.17 + wc_nsec -= (jiffies - wall_jiffies) * (u64)(NSEC_PER_SEC / HZ); 1.18 + 1.19 + /* Split wallclock base into seconds and nanoseconds. */ 1.20 + tmp = wc_nsec; 1.21 + xtime_nsec = do_div(tmp, 1000000000); 1.22 + xtime_sec = (time_t)tmp; 1.23 + 1.24 + wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - xtime_sec); 1.25 + wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - xtime_nsec); 1.26 + 1.27 + set_normalized_timespec(&xtime, xtime_sec, xtime_nsec); 1.28 + set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); 1.29 + 1.30 + time_adjust = 0; /* stop active adjtime() */ 1.31 + time_status |= STA_UNSYNC; 1.32 + time_maxerror = NTP_PHASE_LIMIT; 1.33 + time_esterror = NTP_PHASE_LIMIT; 1.34 +} 1.35 + 1.36 static void update_wallclock(void) 1.37 { 1.38 shared_info_t *s = HYPERVISOR_shared_info; 1.39 - long wtm_nsec, xtime_nsec; 1.40 - time_t wtm_sec, xtime_sec; 1.41 - u64 tmp, nsec; 1.42 1.43 do { 1.44 shadow_tv_version = s->wc_version; 1.45 @@ -243,25 +269,8 @@ static void update_wallclock(void) 1.46 } 1.47 while ((s->wc_version & 1) | (shadow_tv_version ^ s->wc_version)); 1.48 1.49 - if (independent_wallclock) 1.50 - return; 1.51 - 1.52 - /* Adjust wall-clock time base based on wall_jiffies ticks. */ 1.53 - nsec = processed_system_time; 1.54 - nsec += (u64)shadow_tv.tv_sec * 1000000000ULL; 1.55 - nsec += (u64)shadow_tv.tv_nsec; 1.56 - nsec -= (jiffies - wall_jiffies) * (u64)(NSEC_PER_SEC / HZ); 1.57 - 1.58 - /* Split wallclock base into seconds and nanoseconds. */ 1.59 - tmp = nsec; 1.60 - xtime_nsec = do_div(tmp, 1000000000); 1.61 - xtime_sec = (time_t)tmp; 1.62 - 1.63 - wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - xtime_sec); 1.64 - wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - xtime_nsec); 1.65 - 1.66 - set_normalized_timespec(&xtime, xtime_sec, xtime_nsec); 1.67 - set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); 1.68 + if (!independent_wallclock) 1.69 + __update_wallclock(shadow_tv.tv_sec, shadow_tv.tv_nsec); 1.70 } 1.71 1.72 /* 1.73 @@ -408,19 +417,15 @@ EXPORT_SYMBOL(do_gettimeofday); 1.74 1.75 int do_settimeofday(struct timespec *tv) 1.76 { 1.77 - time_t wtm_sec, sec = tv->tv_sec; 1.78 - long wtm_nsec; 1.79 + time_t sec; 1.80 s64 nsec; 1.81 - struct timespec xentime; 1.82 unsigned int cpu; 1.83 struct shadow_time_info *shadow; 1.84 + dom0_op_t op; 1.85 1.86 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) 1.87 return -EINVAL; 1.88 1.89 - if (!independent_wallclock && !(xen_start_info.flags & SIF_INITDOMAIN)) 1.90 - return 0; /* Silent failure? */ 1.91 - 1.92 cpu = get_cpu(); 1.93 shadow = &per_cpu(shadow_time, cpu); 1.94 1.95 @@ -431,51 +436,30 @@ int do_settimeofday(struct timespec *tv) 1.96 * overflows. If that were to happen then our shadow time values would 1.97 * be stale, so we can retry with fresh ones. 1.98 */ 1.99 - again: 1.100 - nsec = (s64)tv->tv_nsec - (s64)get_nsec_offset(shadow); 1.101 - if (unlikely(!time_values_up_to_date(cpu))) { 1.102 + for ( ; ; ) { 1.103 + nsec = (s64)tv->tv_nsec - (s64)get_nsec_offset(shadow); 1.104 + if (time_values_up_to_date(cpu)) 1.105 + break; 1.106 get_time_values_from_xen(); 1.107 - goto again; 1.108 + } 1.109 + sec = tv->tv_sec; 1.110 + __normalize_time(&sec, &nsec); 1.111 + 1.112 + if ((xen_start_info.flags & SIF_INITDOMAIN) && 1.113 + !independent_wallclock) { 1.114 + op.cmd = DOM0_SETTIME; 1.115 + op.u.settime.secs = sec; 1.116 + op.u.settime.nsecs = nsec; 1.117 + op.u.settime.system_time = shadow->system_timestamp; 1.118 + HYPERVISOR_dom0_op(&op); 1.119 + update_wallclock(); 1.120 + } else if (independent_wallclock) { 1.121 + nsec -= shadow->system_timestamp; 1.122 + __normalize_time(&sec, &nsec); 1.123 + __update_wallclock(sec, nsec); 1.124 } 1.125 1.126 - __normalize_time(&sec, &nsec); 1.127 - set_normalized_timespec(&xentime, sec, nsec); 1.128 - 1.129 - /* 1.130 - * This is revolting. We need to set "xtime" correctly. However, the 1.131 - * value in this location is the value at the most recent update of 1.132 - * wall time. Discover what correction gettimeofday() would have 1.133 - * made, and then undo it! 1.134 - */ 1.135 - nsec -= (jiffies - wall_jiffies) * TICK_NSEC; 1.136 - 1.137 - nsec -= (shadow->system_timestamp - processed_system_time); 1.138 - 1.139 - __normalize_time(&sec, &nsec); 1.140 - wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); 1.141 - wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); 1.142 - 1.143 - set_normalized_timespec(&xtime, sec, nsec); 1.144 - set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); 1.145 - 1.146 - time_adjust = 0; /* stop active adjtime() */ 1.147 - time_status |= STA_UNSYNC; 1.148 - time_maxerror = NTP_PHASE_LIMIT; 1.149 - time_esterror = NTP_PHASE_LIMIT; 1.150 - 1.151 -#ifdef CONFIG_XEN_PRIVILEGED_GUEST 1.152 - if ((xen_start_info.flags & SIF_INITDOMAIN) && 1.153 - !independent_wallclock) { 1.154 - dom0_op_t op; 1.155 - op.cmd = DOM0_SETTIME; 1.156 - op.u.settime.secs = xentime.tv_sec; 1.157 - op.u.settime.nsecs = xentime.tv_nsec; 1.158 - op.u.settime.system_time = shadow->system_timestamp; 1.159 - write_sequnlock_irq(&xtime_lock); 1.160 - HYPERVISOR_dom0_op(&op); 1.161 - } else 1.162 -#endif 1.163 - write_sequnlock_irq(&xtime_lock); 1.164 + write_sequnlock_irq(&xtime_lock); 1.165 1.166 put_cpu(); 1.167 1.168 @@ -492,6 +476,9 @@ static int set_rtc_mmss(unsigned long no 1.169 1.170 WARN_ON(irqs_disabled()); 1.171 1.172 + if (!(xen_start_info.flags & SIF_INITDOMAIN)) 1.173 + return 0; 1.174 + 1.175 /* gets recalled with irq locally disabled */ 1.176 spin_lock_irq(&rtc_lock); 1.177 if (efi_enabled) 1.178 @@ -603,8 +590,10 @@ static inline void do_timer_interrupt(in 1.179 profile_tick(CPU_PROFILING, regs); 1.180 } 1.181 1.182 - if (unlikely(shadow_tv_version != HYPERVISOR_shared_info->wc_version)) 1.183 + if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) { 1.184 update_wallclock(); 1.185 + clock_was_set(); 1.186 + } 1.187 } 1.188 1.189 /*
2.1 --- a/xen/arch/x86/domain.c Thu Aug 11 12:06:32 2005 +0000 2.2 +++ b/xen/arch/x86/domain.c Thu Aug 11 13:07:08 2005 +0000 2.3 @@ -279,8 +279,6 @@ void arch_do_createdomain(struct vcpu *v 2.4 2.5 shadow_lock_init(d); 2.6 INIT_LIST_HEAD(&d->arch.free_shadow_frames); 2.7 - 2.8 - init_domain_time(d); 2.9 } 2.10 2.11 void arch_do_boot_vcpu(struct vcpu *v) 2.12 @@ -481,7 +479,10 @@ int arch_set_info_guest( 2.13 } 2.14 2.15 update_pagetables(v); 2.16 - 2.17 + 2.18 + if ( v->vcpu_id == 0 ) 2.19 + init_domain_time(d); 2.20 + 2.21 /* Don't redo final setup */ 2.22 set_bit(_VCPUF_initialised, &v->vcpu_flags); 2.23
3.1 --- a/xen/arch/x86/domain_build.c Thu Aug 11 12:06:32 2005 +0000 3.2 +++ b/xen/arch/x86/domain_build.c Thu Aug 11 13:07:08 2005 +0000 3.3 @@ -618,6 +618,8 @@ int construct_dom0(struct domain *d, 3.4 /* DOM0 gets access to everything. */ 3.5 physdev_init_dom0(d); 3.6 3.7 + init_domain_time(d); 3.8 + 3.9 set_bit(_DOMF_constructed, &d->domain_flags); 3.10 3.11 new_thread(v, dsi.v_kernentry, vstack_end, vstartinfo_start);
4.1 --- a/xen/arch/x86/time.c Thu Aug 11 12:06:32 2005 +0000 4.2 +++ b/xen/arch/x86/time.c Thu Aug 11 13:07:08 2005 +0000 4.3 @@ -44,6 +44,7 @@ spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED 4.4 int timer_ack = 0; 4.5 unsigned long volatile jiffies; 4.6 static u32 wc_sec, wc_nsec; /* UTC time at last 'time update'. */ 4.7 +static spinlock_t wc_lock = SPIN_LOCK_UNLOCKED; 4.8 4.9 struct time_scale { 4.10 int shift; 4.11 @@ -699,13 +700,14 @@ void do_settime(unsigned long secs, unsi 4.12 struct domain *d; 4.13 shared_info_t *s; 4.14 4.15 - x = (secs * 1000000000ULL) + (u64)nsecs + system_time_base; 4.16 + x = (secs * 1000000000ULL) + (u64)nsecs - system_time_base; 4.17 y = do_div(x, 1000000000); 4.18 4.19 wc_sec = _wc_sec = (u32)x; 4.20 wc_nsec = _wc_nsec = (u32)y; 4.21 4.22 read_lock(&domlist_lock); 4.23 + spin_lock(&wc_lock); 4.24 4.25 for_each_domain ( d ) 4.26 { 4.27 @@ -716,15 +718,18 @@ void do_settime(unsigned long secs, unsi 4.28 version_update_end(&s->wc_version); 4.29 } 4.30 4.31 + spin_unlock(&wc_lock); 4.32 read_unlock(&domlist_lock); 4.33 } 4.34 4.35 void init_domain_time(struct domain *d) 4.36 { 4.37 + spin_lock(&wc_lock); 4.38 version_update_begin(&d->shared_info->wc_version); 4.39 d->shared_info->wc_sec = wc_sec; 4.40 d->shared_info->wc_nsec = wc_nsec; 4.41 version_update_end(&d->shared_info->wc_version); 4.42 + spin_unlock(&wc_lock); 4.43 } 4.44 4.45 static void local_time_calibration(void *unused)