From 341102c3ef29c33611586072363cf9982a8bdb77 Mon Sep 17 00:00:00 2001 From: "mike.travis@hpe.com" Date: Thu, 12 Oct 2017 11:32:02 -0500 Subject: x86/tsc: Add option that TSC on Socket 0 being non-zero is valid Add a flag to indicate and process that TSC counters are on chassis that reset at different times during system startup. Therefore which TSC ADJUST values should be zero is not predictable. Signed-off-by: Mike Travis Signed-off-by: Thomas Gleixner Reviewed-by: Dimitri Sivanich Reviewed-by: Russ Anderson Reviewed-by: Andrew Banman Reviewed-by: Peter Zijlstra Cc: Prarit Bhargava Cc: Andrew Banman Cc: Bin Gao Link: https://lkml.kernel.org/r/20171012163201.944370012@stormcage.americas.sgi.com --- arch/x86/kernel/tsc_sync.c | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) (limited to 'arch/x86/kernel/tsc_sync.c') diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c index 7842371bc9e4..3873dcdc7d7b 100644 --- a/arch/x86/kernel/tsc_sync.c +++ b/arch/x86/kernel/tsc_sync.c @@ -30,6 +30,20 @@ struct tsc_adjust { static DEFINE_PER_CPU(struct tsc_adjust, tsc_adjust); +/* + * TSC's on different sockets may be reset asynchronously. + * This may cause the TSC ADJUST value on socket 0 to be NOT 0. + */ +bool __read_mostly tsc_async_resets; + +void mark_tsc_async_resets(char *reason) +{ + if (tsc_async_resets) + return; + tsc_async_resets = true; + pr_info("tsc: Marking TSC async resets true due to %s\n", reason); +} + void tsc_verify_tsc_adjust(bool resume) { struct tsc_adjust *adj = this_cpu_ptr(&tsc_adjust); @@ -71,12 +85,22 @@ static void tsc_sanitize_first_cpu(struct tsc_adjust *cur, s64 bootval, * non zero. We don't do that on non boot cpus because physical * hotplug should have set the ADJUST register to a value > 0 so * the TSC is in sync with the already running cpus. + * + * Also don't force the ADJUST value to zero if that is a valid value + * for socket 0 as determined by the system arch. This is required + * when multiple sockets are reset asynchronously with each other + * and socket 0 may not have an TSC ADJUST value of 0. */ if (bootcpu && bootval != 0) { - pr_warn(FW_BUG "TSC ADJUST: CPU%u: %lld force to 0\n", cpu, - bootval); - wrmsrl(MSR_IA32_TSC_ADJUST, 0); - bootval = 0; + if (likely(!tsc_async_resets)) { + pr_warn(FW_BUG "TSC ADJUST: CPU%u: %lld force to 0\n", + cpu, bootval); + wrmsrl(MSR_IA32_TSC_ADJUST, 0); + bootval = 0; + } else { + pr_info("TSC ADJUST: CPU%u: %lld NOT forced to 0\n", + cpu, bootval); + } } cur->adjusted = bootval; } @@ -117,6 +141,13 @@ bool tsc_store_and_check_tsc_adjust(bool bootcpu) cur->nextcheck = jiffies + HZ; cur->warned = false; + /* + * If a non-zero TSC value for socket 0 may be valid then the default + * adjusted value cannot assumed to be zero either. + */ + if (tsc_async_resets) + cur->adjusted = bootval; + /* * Check whether this CPU is the first in a package to come up. In * this case do not check the boot value against another package -- cgit v1.2.3 From 9514ececa52e9f1436e7682e98c852d1338b699f Mon Sep 17 00:00:00 2001 From: "mike.travis@hpe.com" Date: Thu, 12 Oct 2017 11:32:03 -0500 Subject: x86/tsc: Skip TSC test and error messages if already unstable If the TSC has already been determined to be unstable, then checking TSC ADJUST values is a waste of time and generates unnecessary error messages. Signed-off-by: Mike Travis Signed-off-by: Thomas Gleixner Reviewed-by: Dimitri Sivanich Reviewed-by: Russ Anderson Reviewed-by: Peter Zijlstra Cc: Prarit Bhargava Cc: Andrew Banman Cc: Bin Gao Link: https://lkml.kernel.org/r/20171012163202.060777495@stormcage.americas.sgi.com --- arch/x86/kernel/tsc_sync.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch/x86/kernel/tsc_sync.c') diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c index 3873dcdc7d7b..3bdb983fd11b 100644 --- a/arch/x86/kernel/tsc_sync.c +++ b/arch/x86/kernel/tsc_sync.c @@ -52,6 +52,10 @@ void tsc_verify_tsc_adjust(bool resume) if (!boot_cpu_has(X86_FEATURE_TSC_ADJUST)) return; + /* Skip unnecessary error messages if TSC already unstable */ + if (check_tsc_unstable()) + return; + /* Rate limit the MSR check */ if (!resume && time_before(jiffies, adj->nextcheck)) return; @@ -114,6 +118,10 @@ bool __init tsc_store_and_check_tsc_adjust(bool bootcpu) if (!boot_cpu_has(X86_FEATURE_TSC_ADJUST)) return false; + /* Skip unnecessary error messages if TSC already unstable */ + if (check_tsc_unstable()) + return false; + rdmsrl(MSR_IA32_TSC_ADJUST, bootval); cur->bootval = bootval; cur->nextcheck = jiffies + HZ; -- cgit v1.2.3 From 41e7864ab5ce4ec36e89a9f55d8d9dfe19b0392c Mon Sep 17 00:00:00 2001 From: "mike.travis@hpe.com" Date: Thu, 12 Oct 2017 11:32:04 -0500 Subject: x86/tsc: Drastically reduce the number of firmware bug warnings Prior to the TSC ADJUST MSR being available, the method to set TSC's in sync with each other naturally caused a small skew between cpu threads. This was NOT a firmware bug at the time so introducing a whole avalanche of alarming warning messages might cause unnecessary concern and customer complaints. (Example: >3000 msgs in a 32 socket Skylake system.) Simply report the warning condition, if possible do the necessary fixes, and move on. Signed-off-by: Mike Travis Signed-off-by: Thomas Gleixner Reviewed-by: Dimitri Sivanich Reviewed-by: Russ Anderson Reviewed-by: Peter Zijlstra Cc: Prarit Bhargava Cc: Andrew Banman Cc: Bin Gao Link: https://lkml.kernel.org/r/20171012163202.175062400@stormcage.americas.sgi.com --- arch/x86/kernel/tsc_sync.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'arch/x86/kernel/tsc_sync.c') diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c index 3bdb983fd11b..26ba0530a8a7 100644 --- a/arch/x86/kernel/tsc_sync.c +++ b/arch/x86/kernel/tsc_sync.c @@ -177,10 +177,9 @@ bool tsc_store_and_check_tsc_adjust(bool bootcpu) * Compare the boot value and complain if it differs in the * package. */ - if (bootval != ref->bootval) { - pr_warn(FW_BUG "TSC ADJUST differs: Reference CPU%u: %lld CPU%u: %lld\n", - refcpu, ref->bootval, cpu, bootval); - } + if (bootval != ref->bootval) + printk_once(FW_BUG "TSC ADJUST differs within socket(s), fixing all errors\n"); + /* * The TSC_ADJUST values in a package must be the same. If the boot * value on this newly upcoming CPU differs from the adjustment @@ -188,8 +187,6 @@ bool tsc_store_and_check_tsc_adjust(bool bootcpu) * adjusted value. */ if (bootval != ref->adjusted) { - pr_warn("TSC ADJUST synchronize: Reference CPU%u: %lld CPU%u: %lld\n", - refcpu, ref->adjusted, cpu, bootval); cur->adjusted = ref->adjusted; wrmsrl(MSR_IA32_TSC_ADJUST, ref->adjusted); } -- cgit v1.2.3