# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1265624088 0
# Node ID f330b15f885ded7ee26594bd8ab27e206e2cb4cc
# Parent 5e49312fcb4465ec6715e204b6a50b0f06abf1c2
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@xxxxxxxxxx>
---
xen/arch/x86/time.c | 40 ++++++++++++++++++++++++++++------------
1 files changed, 28 insertions(+), 12 deletions(-)
diff -r 5e49312fcb44 -r f330b15f885d xen/arch/x86/time.c
--- a/xen/arch/x86/time.c Mon Feb 08 08:50:03 2010 +0000
+++ b/xen/arch/x86/time.c Mon Feb 08 10:14:48 2010 +0000
@@ -827,14 +827,14 @@ static void __update_vcpu_system_time(st
u = &vcpu_info(v, time);
if ( d->arch.vtsc )
- tsc_stamp = scale_delta(t->stime_local_stamp - d->arch.vtsc_offset,
- &d->arch.ns_to_vtsc);
+ {
+ u64 delta = max_t(s64, t->stime_local_stamp - d->arch.vtsc_offset, 0);
+ tsc_stamp = scale_delta(delta, &d->arch.ns_to_vtsc);
+ }
else
+ {
tsc_stamp = t->local_tsc_stamp;
-
- /* Don't bother unless timestamps have changed or we are forced. */
- if ( !force && (u->tsc_timestamp == tsc_stamp) )
- return;
+ }
memset(&_u, 0, sizeof(_u));
@@ -852,6 +852,11 @@ static void __update_vcpu_system_time(st
_u.tsc_to_system_mul = t->tsc_scale.mul_frac;
_u.tsc_shift = (s8)t->tsc_scale.shift;
}
+
+ /* Don't bother unless timestamp record has changed or we are forced. */
+ _u.version = u->version; /* make versions match for memcmp test */
+ if ( !force && !memcmp(u, &_u, sizeof(_u)) )
+ return;
/* 1. Update guest kernel version. */
_u.version = u->version = version_update_begin(u->version);
@@ -1617,6 +1622,7 @@ void pv_soft_rdtsc(struct vcpu *v, struc
{
s_time_t now = get_s_time();
struct domain *d = v->domain;
+ u64 delta;
spin_lock(&d->arch.vtsc_lock);
@@ -1632,7 +1638,8 @@ void pv_soft_rdtsc(struct vcpu *v, struc
spin_unlock(&d->arch.vtsc_lock);
- now = scale_delta(now - d->arch.vtsc_offset, &d->arch.ns_to_vtsc);
+ delta = max_t(s64, now - d->arch.vtsc_offset, 0);
+ now = scale_delta(delta, &d->arch.ns_to_vtsc);
regs->eax = (uint32_t)now;
regs->edx = (uint32_t)(now >> 32);
@@ -1693,7 +1700,9 @@ void tsc_get_info(struct domain *d, uint
uint32_t *incarnation)
{
*incarnation = d->arch.incarnation;
- switch ( *tsc_mode = d->arch.tsc_mode )
+ *tsc_mode = d->arch.tsc_mode;
+
+ switch ( *tsc_mode )
{
case TSC_MODE_NEVER_EMULATE:
*elapsed_nsec = *gtsc_khz = 0;
@@ -1707,7 +1716,9 @@ void tsc_get_info(struct domain *d, uint
{
*elapsed_nsec = get_s_time() - d->arch.vtsc_offset;
*gtsc_khz = d->arch.tsc_khz;
- } else {
+ }
+ else
+ {
uint64_t tsc = 0;
rdtscll(tsc);
*elapsed_nsec = scale_delta(tsc,&d->arch.vtsc_to_ns);
@@ -1719,15 +1730,20 @@ void tsc_get_info(struct domain *d, uint
{
*elapsed_nsec = get_s_time() - d->arch.vtsc_offset;
*gtsc_khz = cpu_khz;
- } else {
+ }
+ else
+ {
uint64_t tsc = 0;
rdtscll(tsc);
- *elapsed_nsec = scale_delta(tsc,&d->arch.vtsc_to_ns) -
- d->arch.vtsc_offset;
+ *elapsed_nsec = (scale_delta(tsc,&d->arch.vtsc_to_ns) -
+ d->arch.vtsc_offset);
*gtsc_khz = 0; /* ignored by tsc_set_info */
}
break;
}
+
+ if ( (int64_t)*elapsed_nsec < 0 )
+ *elapsed_nsec = 0;
}
/*
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|