@@ -120,12 +120,15 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src)
static atomic64_t last_value = ATOMIC64_INIT(0);
+int pvclock_backwards = 0;
+
cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src)
{
struct pvclock_shadow_time shadow;
unsigned version;
cycle_t ret, offset;
u64 last;
+ bool backwards;
do {
version = pvclock_get_time_values(&shadow, src);
@@ -153,13 +156,26 @@ cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src)
* updating at the same time, and one of them could be slightly behind,
* making the assumption that last_value always go forward fail to hold.
*/
+ backwards = false;
last = atomic64_read(&last_value);
do {
- if (ret < last)
- return last;
+ if (ret < last) {
+ if ( last - ret < 25000000 )
+ return last;
+ else
+ /* The clock will go backwards instead of being stuck at last value for a very long time
+ * The return value of the previous call to pvclock_clocksource_read was most probably
+ * very far into te future because the clock for that CPU hadn't been setup yet
+ */
+ backwards = true;
+ }
last = atomic64_cmpxchg(&last_value, last, ret);
} while (unlikely(last != ret));
+ /* Increment outside of the while loop, because it always loops twice */
+ if (backwards)
+ pvclock_backwards++;
+
return ret;
}
@@ -1,3 +1,5 @@
+#define DEBUG
+
/*
* x86 SMP booting functions
*
@@ -687,6 +687,8 @@ static inline void printk_delay(void)
}
}
+extern int pvclock_backwards;
+
asmlinkage int vprintk(const char *fmt, va_list args)
{
int printed_len = 0;
@@ -778,9 +780,13 @@ asmlinkage int vprintk(const char *fmt, va_list args)
unsigned long long t;
unsigned long nanosec_rem;
+ int pvclock_backwards_prev = pvclock_backwards;
t = cpu_clock(printk_cpu);
nanosec_rem = do_div(t, 1000000000);
- tlen = sprintf(tbuf, "[%5lu.%06lu] ",
+ tlen = sprintf(tbuf, "[%d;%d/%d:%5lu.%06lu] ",
+ printk_cpu,
+ pvclock_backwards_prev,
+ pvclock_backwards,
(unsigned long) t,
nanosec_rem / 1000);