aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/tsc_sync.c21
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);