diff options
| -rw-r--r-- | arch/x86/kernel/tsc_sync.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c index 1d8508fd15f7..d0db011051a5 100644 --- a/arch/x86/kernel/tsc_sync.c +++ b/arch/x86/kernel/tsc_sync.c | |||
| @@ -73,9 +73,11 @@ static void tsc_sanitize_first_cpu(struct tsc_adjust *cur, s64 bootval, | |||
| 73 | * the TSC is in sync with the already running cpus. | 73 | * the TSC is in sync with the already running cpus. |
| 74 | * | 74 | * |
| 75 | * But we always force positive ADJUST values. Otherwise the TSC | 75 | * But we always force positive ADJUST values. Otherwise the TSC |
| 76 | * deadline timer creates an interrupt storm. Sigh! | 76 | * deadline timer creates an interrupt storm. We also have to |
| 77 | * prevent values > 0x7FFFFFFF as those wreckage the timer as well. | ||
| 77 | */ | 78 | */ |
| 78 | if ((bootcpu && bootval != 0) || (!bootcpu && bootval < 0)) { | 79 | if ((bootcpu && bootval != 0) || (!bootcpu && bootval < 0) || |
| 80 | (bootval > 0x7FFFFFFF)) { | ||
| 79 | pr_warn(FW_BUG "TSC ADJUST: CPU%u: %lld force to 0\n", cpu, | 81 | pr_warn(FW_BUG "TSC ADJUST: CPU%u: %lld force to 0\n", cpu, |
| 80 | bootval); | 82 | bootval); |
| 81 | wrmsrl(MSR_IA32_TSC_ADJUST, 0); | 83 | wrmsrl(MSR_IA32_TSC_ADJUST, 0); |
| @@ -448,13 +450,22 @@ retry: | |||
| 448 | * that the warp is not longer detectable when the observed warp | 450 | * that the warp is not longer detectable when the observed warp |
| 449 | * value is used. In the worst case the adjustment needs to go | 451 | * value is used. In the worst case the adjustment needs to go |
| 450 | * through a 3rd run for fine tuning. | 452 | * through a 3rd run for fine tuning. |
| 451 | * | ||
| 452 | * But we must make sure that the value doesn't become negative | ||
| 453 | * otherwise TSC deadline timer will create an interrupt storm. | ||
| 454 | */ | 453 | */ |
| 455 | cur->adjusted += cur_max_warp; | 454 | cur->adjusted += cur_max_warp; |
| 455 | |||
| 456 | /* | ||
| 457 | * TSC deadline timer stops working or creates an interrupt storm | ||
| 458 | * with adjust values < 0 and > x07ffffff. | ||
| 459 | * | ||
| 460 | * To allow adjust values > 0x7FFFFFFF we need to disable the | ||
| 461 | * deadline timer and use the local APIC timer, but that requires | ||
| 462 | * more intrusive changes and we do not have any useful information | ||
| 463 | * from Intel about the underlying HW wreckage yet. | ||
| 464 | */ | ||
| 456 | if (cur->adjusted < 0) | 465 | if (cur->adjusted < 0) |
| 457 | cur->adjusted = 0; | 466 | cur->adjusted = 0; |
| 467 | if (cur->adjusted > 0x7FFFFFFF) | ||
| 468 | cur->adjusted = 0x7FFFFFFF; | ||
| 458 | 469 | ||
| 459 | pr_warn("TSC ADJUST compensate: CPU%u observed %lld warp. Adjust: %lld\n", | 470 | pr_warn("TSC ADJUST compensate: CPU%u observed %lld warp. Adjust: %lld\n", |
| 460 | cpu, cur_max_warp, cur->adjusted); | 471 | cpu, cur_max_warp, cur->adjusted); |
