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>
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  /*