diff options
| -rw-r--r-- | arch/x86/kernel/tsc_sync.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c index 78083bf23ed1..40f8edd55151 100644 --- a/arch/x86/kernel/tsc_sync.c +++ b/arch/x86/kernel/tsc_sync.c | |||
| @@ -37,6 +37,7 @@ static arch_spinlock_t sync_lock = __ARCH_SPIN_LOCK_UNLOCKED; | |||
| 37 | static cycles_t last_tsc; | 37 | static cycles_t last_tsc; |
| 38 | static cycles_t max_warp; | 38 | static cycles_t max_warp; |
| 39 | static int nr_warps; | 39 | static int nr_warps; |
| 40 | static int random_warps; | ||
| 40 | 41 | ||
| 41 | /* | 42 | /* |
| 42 | * TSC-warp measurement loop running on both CPUs. This is not called | 43 | * TSC-warp measurement loop running on both CPUs. This is not called |
| @@ -45,7 +46,7 @@ static int nr_warps; | |||
| 45 | static void check_tsc_warp(unsigned int timeout) | 46 | static void check_tsc_warp(unsigned int timeout) |
| 46 | { | 47 | { |
| 47 | cycles_t start, now, prev, end; | 48 | cycles_t start, now, prev, end; |
| 48 | int i; | 49 | int i, cur_warps = 0; |
| 49 | 50 | ||
| 50 | start = rdtsc_ordered(); | 51 | start = rdtsc_ordered(); |
| 51 | /* | 52 | /* |
| @@ -85,7 +86,14 @@ static void check_tsc_warp(unsigned int timeout) | |||
| 85 | if (unlikely(prev > now)) { | 86 | if (unlikely(prev > now)) { |
| 86 | arch_spin_lock(&sync_lock); | 87 | arch_spin_lock(&sync_lock); |
| 87 | max_warp = max(max_warp, prev - now); | 88 | max_warp = max(max_warp, prev - now); |
| 89 | /* | ||
| 90 | * Check whether this bounces back and forth. Only | ||
| 91 | * one CPU should observe time going backwards. | ||
| 92 | */ | ||
| 93 | if (cur_warps != nr_warps) | ||
| 94 | random_warps++; | ||
| 88 | nr_warps++; | 95 | nr_warps++; |
| 96 | cur_warps = nr_warps; | ||
| 89 | arch_spin_unlock(&sync_lock); | 97 | arch_spin_unlock(&sync_lock); |
| 90 | } | 98 | } |
| 91 | } | 99 | } |
| @@ -160,6 +168,8 @@ void check_tsc_sync_source(int cpu) | |||
| 160 | smp_processor_id(), cpu); | 168 | smp_processor_id(), cpu); |
| 161 | pr_warning("Measured %Ld cycles TSC warp between CPUs, " | 169 | pr_warning("Measured %Ld cycles TSC warp between CPUs, " |
| 162 | "turning off TSC clock.\n", max_warp); | 170 | "turning off TSC clock.\n", max_warp); |
| 171 | if (random_warps) | ||
| 172 | pr_warning("TSC warped randomly between CPUs\n"); | ||
| 163 | mark_tsc_unstable("check_tsc_sync_source failed"); | 173 | mark_tsc_unstable("check_tsc_sync_source failed"); |
| 164 | } else { | 174 | } else { |
| 165 | pr_debug("TSC synchronization [CPU#%d -> CPU#%d]: passed\n", | 175 | pr_debug("TSC synchronization [CPU#%d -> CPU#%d]: passed\n", |
| @@ -170,6 +180,7 @@ void check_tsc_sync_source(int cpu) | |||
| 170 | * Reset it - just in case we boot another CPU later: | 180 | * Reset it - just in case we boot another CPU later: |
| 171 | */ | 181 | */ |
| 172 | atomic_set(&start_count, 0); | 182 | atomic_set(&start_count, 0); |
| 183 | random_warps = 0; | ||
| 173 | nr_warps = 0; | 184 | nr_warps = 0; |
| 174 | max_warp = 0; | 185 | max_warp = 0; |
| 175 | last_tsc = 0; | 186 | last_tsc = 0; |
