| From 76ce7cfe35ef58f34e6ba85327afb5fbf6c3ff9b Mon Sep 17 00:00:00 2001 |
| From: Pavel Tatashin <pasha.tatashin@oracle.com> |
| Date: Fri, 27 Oct 2017 20:11:00 -0400 |
| Subject: x86/smpboot: Make optimization of delay calibration work correctly |
| |
| From: Pavel Tatashin <pasha.tatashin@oracle.com> |
| |
| commit 76ce7cfe35ef58f34e6ba85327afb5fbf6c3ff9b upstream. |
| |
| If the TSC has constant frequency then the delay calibration can be skipped |
| when it has been calibrated for a package already. This is checked in |
| calibrate_delay_is_known(), but that function is buggy in two aspects: |
| |
| It returns 'false' if |
| |
| (!tsc_disabled && !cpu_has(&cpu_data(cpu), X86_FEATURE_CONSTANT_TSC) |
| |
| which is obviously the reverse of the intended check and the check for the |
| sibling mask cannot work either because the topology links have not been |
| set up yet. |
| |
| Correct the condition and move the call to set_cpu_sibling_map() before |
| invoking calibrate_delay() so the sibling check works correctly. |
| |
| [ tglx: Rewrote changelong ] |
| |
| Fixes: c25323c07345 ("x86/tsc: Use topology functions") |
| Signed-off-by: Pavel Tatashin <pasha.tatashin@oracle.com> |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Cc: peterz@infradead.org |
| Cc: bob.picco@oracle.com |
| Cc: steven.sistare@oracle.com |
| Cc: daniel.m.jordan@oracle.com |
| Link: https://lkml.kernel.org/r/20171028001100.26603-1-pasha.tatashin@oracle.com |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/x86/kernel/smpboot.c | 11 ++++++----- |
| arch/x86/kernel/tsc.c | 8 +++----- |
| 2 files changed, 9 insertions(+), 10 deletions(-) |
| |
| --- a/arch/x86/kernel/smpboot.c |
| +++ b/arch/x86/kernel/smpboot.c |
| @@ -181,6 +181,12 @@ static void smp_callin(void) |
| smp_store_cpu_info(cpuid); |
| |
| /* |
| + * The topology information must be up to date before |
| + * calibrate_delay() and notify_cpu_starting(). |
| + */ |
| + set_cpu_sibling_map(raw_smp_processor_id()); |
| + |
| + /* |
| * Get our bogomips. |
| * Update loops_per_jiffy in cpu_data. Previous call to |
| * smp_store_cpu_info() stored a value that is close but not as |
| @@ -190,11 +196,6 @@ static void smp_callin(void) |
| cpu_data(cpuid).loops_per_jiffy = loops_per_jiffy; |
| pr_debug("Stack at about %p\n", &cpuid); |
| |
| - /* |
| - * This must be done before setting cpu_online_mask |
| - * or calling notify_cpu_starting. |
| - */ |
| - set_cpu_sibling_map(raw_smp_processor_id()); |
| wmb(); |
| |
| notify_cpu_starting(cpuid); |
| --- a/arch/x86/kernel/tsc.c |
| +++ b/arch/x86/kernel/tsc.c |
| @@ -1382,12 +1382,10 @@ void __init tsc_init(void) |
| unsigned long calibrate_delay_is_known(void) |
| { |
| int sibling, cpu = smp_processor_id(); |
| - struct cpumask *mask = topology_core_cpumask(cpu); |
| + int constant_tsc = cpu_has(&cpu_data(cpu), X86_FEATURE_CONSTANT_TSC); |
| + const struct cpumask *mask = topology_core_cpumask(cpu); |
| |
| - if (!tsc_disabled && !cpu_has(&cpu_data(cpu), X86_FEATURE_CONSTANT_TSC)) |
| - return 0; |
| - |
| - if (!mask) |
| + if (tsc_disabled || !constant_tsc || !mask) |
| return 0; |
| |
| sibling = cpumask_any_but(mask, cpu); |