Index: sys/arch/xen/xen/clock.c =================================================================== RCS file: /cvsroot/src/sys/arch/xen/xen/clock.c,v retrieving revision 1.64 diff -p -u -r1.64 clock.c --- sys/arch/xen/xen/clock.c 12 Jun 2016 09:08:09 -0000 1.64 +++ sys/arch/xen/xen/clock.c 29 Oct 2017 16:46:07 -0000 @@ -74,6 +74,8 @@ struct shadow { uint32_t freq_mul; int8_t freq_shift; struct timespec ts; + uint64_t last_vcpu_time; + bool last_vcpu_time_set; }; /* Protects volatile variables ci_shadow & xen_clock_bias */ @@ -118,22 +120,36 @@ get_time_values_from_xen(struct cpu_info KASSERT(mutex_owned(&tmutex)); do { - shadow->time_version = t->version; + if (1 & (shadow->time_version = t->version)) { + /* update in progress */ + SPINLOCK_BACKOFF_HOOK; + continue; + } xen_rmb(); shadow->tsc_stamp = t->tsc_timestamp; - shadow->system_time = t->system_time; + { + uint64_t systime = t->system_time; + if (systime < shadow->system_time) { + printf("xen systime ran backwards %"PRId64"ns", + shadow->system_time - systime); + } + shadow->system_time = systime; + } shadow->freq_mul = t->tsc_to_system_mul; shadow->freq_shift = t->tsc_shift; xen_rmb(); - } while ((t->version & 1) || (shadow->time_version != t->version)); + } while (shadow->time_version != t->version); do { - tversion = HYPERVISOR_shared_info->wc_version; + if (1 & (tversion = HYPERVISOR_shared_info->wc_version)) { + /* update in progress */ + SPINLOCK_BACKOFF_HOOK; + continue; + } xen_rmb(); shadow->ts.tv_sec = HYPERVISOR_shared_info->wc_sec; shadow->ts.tv_nsec = HYPERVISOR_shared_info->wc_nsec; xen_rmb(); - } while ((HYPERVISOR_shared_info->wc_version & 1) || - (tversion != HYPERVISOR_shared_info->wc_version)); + } while (tversion != HYPERVISOR_shared_info->wc_version); } /* @@ -192,6 +208,9 @@ get_tsc_offset_ns(struct cpu_info *ci) KASSERT(mutex_owned(&tmutex)); tsc_delta = cpu_counter() - shadow->tsc_stamp; + if ((int64_t)tsc_delta < 0) + printf("cpu counter ran behind tsc stamp: %"PRId64"\n", + (int64_t)tsc_delta); offset = scale_delta(tsc_delta, shadow->freq_mul, shadow->freq_shift); @@ -220,6 +239,14 @@ get_vcpu_time(struct cpu_info *ci) } while (!time_values_up_to_date(ci)); + if (shadow->last_vcpu_time_set) { + if (stime < shadow->last_vcpu_time) + printf("vcpu time ran backwards by %"PRId64"ns\n", + shadow->last_vcpu_time - stime); + } + shadow->last_vcpu_time = stime; + shadow->last_vcpu_time_set = true; + return stime; }