Procházet zdrojové kódy

x86/smpboot: Make optimization of delay calibration work correctly

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
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/20171028001100.26603-1-pasha.tatashin@oracle.com
Pavel Tatashin před 7 roky
rodič
revize
76ce7cfe35
2 změnil soubory, kde provedl 9 přidání a 10 odebrání
  1. 6 5
      arch/x86/kernel/smpboot.c
  2. 3 5
      arch/x86/kernel/tsc.c

+ 6 - 5
arch/x86/kernel/smpboot.c

@@ -193,6 +193,12 @@ static void smp_callin(void)
 	 */
 	 */
 	smp_store_cpu_info(cpuid);
 	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.
 	 * Get our bogomips.
 	 * Update loops_per_jiffy in cpu_data. Previous call to
 	 * Update loops_per_jiffy in cpu_data. Previous call to
@@ -203,11 +209,6 @@ static void smp_callin(void)
 	cpu_data(cpuid).loops_per_jiffy = loops_per_jiffy;
 	cpu_data(cpuid).loops_per_jiffy = loops_per_jiffy;
 	pr_debug("Stack at about %p\n", &cpuid);
 	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();
 	wmb();
 
 
 	notify_cpu_starting(cpuid);
 	notify_cpu_starting(cpuid);

+ 3 - 5
arch/x86/kernel/tsc.c

@@ -1346,12 +1346,10 @@ void __init tsc_init(void)
 unsigned long calibrate_delay_is_known(void)
 unsigned long calibrate_delay_is_known(void)
 {
 {
 	int sibling, cpu = smp_processor_id();
 	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;
 		return 0;
 
 
 	sibling = cpumask_any_but(mask, cpu);
 	sibling = cpumask_any_but(mask, cpu);