debuggers.hg
changeset 20957:f330b15f885d
Some time-handling fixes.
Fixes my domU boot hangs (when using vtsc) due to vtsc_offset less
then local cpu's stime_local_stamp, leading to bogus
vcpu_time_info.tsc_timestamp.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Fixes my domU boot hangs (when using vtsc) due to vtsc_offset less
then local cpu's stime_local_stamp, leading to bogus
vcpu_time_info.tsc_timestamp.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Mon Feb 08 10:14:48 2010 +0000 (2010-02-08) |
parents | 5e49312fcb44 |
children | 391cb20b6ea9 |
files | xen/arch/x86/time.c |
line diff
1.1 --- a/xen/arch/x86/time.c Mon Feb 08 08:50:03 2010 +0000 1.2 +++ b/xen/arch/x86/time.c Mon Feb 08 10:14:48 2010 +0000 1.3 @@ -827,14 +827,14 @@ static void __update_vcpu_system_time(st 1.4 u = &vcpu_info(v, time); 1.5 1.6 if ( d->arch.vtsc ) 1.7 - tsc_stamp = scale_delta(t->stime_local_stamp - d->arch.vtsc_offset, 1.8 - &d->arch.ns_to_vtsc); 1.9 + { 1.10 + u64 delta = max_t(s64, t->stime_local_stamp - d->arch.vtsc_offset, 0); 1.11 + tsc_stamp = scale_delta(delta, &d->arch.ns_to_vtsc); 1.12 + } 1.13 else 1.14 + { 1.15 tsc_stamp = t->local_tsc_stamp; 1.16 - 1.17 - /* Don't bother unless timestamps have changed or we are forced. */ 1.18 - if ( !force && (u->tsc_timestamp == tsc_stamp) ) 1.19 - return; 1.20 + } 1.21 1.22 memset(&_u, 0, sizeof(_u)); 1.23 1.24 @@ -853,6 +853,11 @@ static void __update_vcpu_system_time(st 1.25 _u.tsc_shift = (s8)t->tsc_scale.shift; 1.26 } 1.27 1.28 + /* Don't bother unless timestamp record has changed or we are forced. */ 1.29 + _u.version = u->version; /* make versions match for memcmp test */ 1.30 + if ( !force && !memcmp(u, &_u, sizeof(_u)) ) 1.31 + return; 1.32 + 1.33 /* 1. Update guest kernel version. */ 1.34 _u.version = u->version = version_update_begin(u->version); 1.35 wmb(); 1.36 @@ -1617,6 +1622,7 @@ void pv_soft_rdtsc(struct vcpu *v, struc 1.37 { 1.38 s_time_t now = get_s_time(); 1.39 struct domain *d = v->domain; 1.40 + u64 delta; 1.41 1.42 spin_lock(&d->arch.vtsc_lock); 1.43 1.44 @@ -1632,7 +1638,8 @@ void pv_soft_rdtsc(struct vcpu *v, struc 1.45 1.46 spin_unlock(&d->arch.vtsc_lock); 1.47 1.48 - now = scale_delta(now - d->arch.vtsc_offset, &d->arch.ns_to_vtsc); 1.49 + delta = max_t(s64, now - d->arch.vtsc_offset, 0); 1.50 + now = scale_delta(delta, &d->arch.ns_to_vtsc); 1.51 1.52 regs->eax = (uint32_t)now; 1.53 regs->edx = (uint32_t)(now >> 32); 1.54 @@ -1693,7 +1700,9 @@ void tsc_get_info(struct domain *d, uint 1.55 uint32_t *incarnation) 1.56 { 1.57 *incarnation = d->arch.incarnation; 1.58 - switch ( *tsc_mode = d->arch.tsc_mode ) 1.59 + *tsc_mode = d->arch.tsc_mode; 1.60 + 1.61 + switch ( *tsc_mode ) 1.62 { 1.63 case TSC_MODE_NEVER_EMULATE: 1.64 *elapsed_nsec = *gtsc_khz = 0; 1.65 @@ -1707,7 +1716,9 @@ void tsc_get_info(struct domain *d, uint 1.66 { 1.67 *elapsed_nsec = get_s_time() - d->arch.vtsc_offset; 1.68 *gtsc_khz = d->arch.tsc_khz; 1.69 - } else { 1.70 + } 1.71 + else 1.72 + { 1.73 uint64_t tsc = 0; 1.74 rdtscll(tsc); 1.75 *elapsed_nsec = scale_delta(tsc,&d->arch.vtsc_to_ns); 1.76 @@ -1719,15 +1730,20 @@ void tsc_get_info(struct domain *d, uint 1.77 { 1.78 *elapsed_nsec = get_s_time() - d->arch.vtsc_offset; 1.79 *gtsc_khz = cpu_khz; 1.80 - } else { 1.81 + } 1.82 + else 1.83 + { 1.84 uint64_t tsc = 0; 1.85 rdtscll(tsc); 1.86 - *elapsed_nsec = scale_delta(tsc,&d->arch.vtsc_to_ns) - 1.87 - d->arch.vtsc_offset; 1.88 + *elapsed_nsec = (scale_delta(tsc,&d->arch.vtsc_to_ns) - 1.89 + d->arch.vtsc_offset); 1.90 *gtsc_khz = 0; /* ignored by tsc_set_info */ 1.91 } 1.92 break; 1.93 } 1.94 + 1.95 + if ( (int64_t)*elapsed_nsec < 0 ) 1.96 + *elapsed_nsec = 0; 1.97 } 1.98 1.99 /*