Giovanni Gherdovich 7e982d
From: "Peter Zijlstra (Intel)" <peterz@infradead.org>
Giovanni Gherdovich 7e982d
Date: Wed, 15 Apr 2020 08:10:47 +0200
Giovanni Gherdovich 7e982d
Subject: x86, sched: Don't enable static key when starting secondary CPUs
Giovanni Gherdovich 286ea1
Patch-mainline: v5.7-rc3
Giovanni Gherdovich 286ea1
Git-commit: b56e7d45e80796ca963ac10902245b244d823caf
Giovanni Gherdovich 7e982d
References: bsc#1169518
Giovanni Gherdovich 7e982d
Giovanni Gherdovich 7e982d
The static key arch_scale_freq_key only needs to be enabled once (at
Giovanni Gherdovich 7e982d
boot). This change fixes a bug by which the key was enabled every time cpu0
Giovanni Gherdovich 7e982d
is started, even as a secondary CPU during cpu hotplug. Secondary CPUs are
Giovanni Gherdovich 7e982d
started from the idle thread: setting a static key from there means
Giovanni Gherdovich 7e982d
acquiring a lock and may result in sleeping in the idle task, causing CPU
Giovanni Gherdovich 7e982d
lockup.
Giovanni Gherdovich 7e982d
Giovanni Gherdovich 7e982d
Another consequence of this change is that init_counter_refs() is now
Giovanni Gherdovich 7e982d
called on each CPU correctly; previously the function on_each_cpu() was
Giovanni Gherdovich 7e982d
used, but it was called at boot when the only online cpu is cpu0.
Giovanni Gherdovich 7e982d
Giovanni Gherdovich 7e982d
[ggherdovich@suse.cz: Tested and wrote changelog]
Giovanni Gherdovich 7e982d
Reported-by: Chris Wilson <chris@chris-wilson.co.uk>
Giovanni Gherdovich 7e982d
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Giovanni Gherdovich 7e982d
Signed-off-by: Giovanni Gherdovich <ggherdovich@suse.cz>
Giovanni Gherdovich 7e982d
Fixes: 1567c3e3467c ("x86, sched: Add support for frequency invariance")
Giovanni Gherdovich 7e982d
---
Giovanni Gherdovich 7e982d
 arch/x86/kernel/smpboot.c |   21 ++++++++++++++-------
Giovanni Gherdovich 7e982d
 1 file changed, 14 insertions(+), 7 deletions(-)
Giovanni Gherdovich 7e982d
Giovanni Gherdovich 7e982d
--- a/arch/x86/kernel/smpboot.c
Giovanni Gherdovich 7e982d
+++ b/arch/x86/kernel/smpboot.c
Giovanni Gherdovich 7e982d
@@ -147,7 +147,7 @@ static inline void smpboot_restore_warm_
Giovanni Gherdovich 7e982d
 	*((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0;
Giovanni Gherdovich 7e982d
 }
Giovanni Gherdovich 7e982d
 
Giovanni Gherdovich 7e982d
-static void init_freq_invariance(void);
Giovanni Gherdovich 7e982d
+static void init_freq_invariance(bool secondary);
Giovanni Gherdovich 7e982d
 
Giovanni Gherdovich 7e982d
 /*
Giovanni Gherdovich 7e982d
  * Report back to the Boot Processor during boot time or to the caller processor
Giovanni Gherdovich 7e982d
@@ -185,7 +185,7 @@ static void smp_callin(void)
Giovanni Gherdovich 7e982d
 	 */
Giovanni Gherdovich 7e982d
 	set_cpu_sibling_map(raw_smp_processor_id());
Giovanni Gherdovich 7e982d
 
Giovanni Gherdovich 7e982d
-	init_freq_invariance();
Giovanni Gherdovich 7e982d
+	init_freq_invariance(true);
Giovanni Gherdovich 7e982d
 
Giovanni Gherdovich 7e982d
 	/*
Giovanni Gherdovich 7e982d
 	 * Get our bogomips.
Giovanni Gherdovich 7e982d
@@ -1346,7 +1346,7 @@ void __init native_smp_prepare_cpus(unsi
Giovanni Gherdovich 7e982d
 	set_sched_topology(x86_topology);
Giovanni Gherdovich 7e982d
 
Giovanni Gherdovich 7e982d
 	set_cpu_sibling_map(0);
Giovanni Gherdovich 7e982d
-	init_freq_invariance();
Giovanni Gherdovich 7e982d
+	init_freq_invariance(false);
Giovanni Gherdovich 7e982d
 	smp_sanity_check();
Giovanni Gherdovich 7e982d
 
Giovanni Gherdovich 7e982d
 	switch (apic_intr_mode) {
Giovanni Gherdovich 7e982d
@@ -2010,7 +2010,7 @@ out:
Giovanni Gherdovich 7e982d
 	return true;
Giovanni Gherdovich 7e982d
 }
Giovanni Gherdovich 7e982d
 
Giovanni Gherdovich 7e982d
-static void init_counter_refs(void *arg)
Giovanni Gherdovich 7e982d
+static void init_counter_refs(void)
Giovanni Gherdovich 7e982d
 {
Giovanni Gherdovich 7e982d
 	u64 aperf, mperf;
Giovanni Gherdovich 7e982d
 
Giovanni Gherdovich 7e982d
@@ -2021,18 +2021,25 @@ static void init_counter_refs(void *arg)
Giovanni Gherdovich 7e982d
 	this_cpu_write(arch_prev_mperf, mperf);
Giovanni Gherdovich 7e982d
 }
Giovanni Gherdovich 7e982d
 
Giovanni Gherdovich 7e982d
-static void init_freq_invariance(void)
Giovanni Gherdovich 7e982d
+static void init_freq_invariance(bool secondary)
Giovanni Gherdovich 7e982d
 {
Giovanni Gherdovich 7e982d
 	bool ret = false;
Giovanni Gherdovich 7e982d
 
Giovanni Gherdovich 7e982d
-	if (smp_processor_id() != 0 || !boot_cpu_has(X86_FEATURE_APERFMPERF))
Giovanni Gherdovich 7e982d
+	if (!boot_cpu_has(X86_FEATURE_APERFMPERF))
Giovanni Gherdovich 7e982d
 		return;
Giovanni Gherdovich 7e982d
 
Giovanni Gherdovich 7e982d
+	if (secondary) {
Giovanni Gherdovich 7e982d
+		if (static_branch_likely(&arch_scale_freq_key)) {
Giovanni Gherdovich 7e982d
+			init_counter_refs();
Giovanni Gherdovich 7e982d
+		}
Giovanni Gherdovich 7e982d
+		return;
Giovanni Gherdovich 7e982d
+	}
Giovanni Gherdovich 7e982d
+
Giovanni Gherdovich 7e982d
 	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
Giovanni Gherdovich 7e982d
 		ret = intel_set_max_freq_ratio();
Giovanni Gherdovich 7e982d
 
Giovanni Gherdovich 7e982d
 	if (ret) {
Giovanni Gherdovich 7e982d
-		on_each_cpu(init_counter_refs, NULL, 1);
Giovanni Gherdovich 7e982d
+		init_counter_refs();
Giovanni Gherdovich 7e982d
 		static_branch_enable(&arch_scale_freq_key);
Giovanni Gherdovich 7e982d
 	} else {
Giovanni Gherdovich 7e982d
 		pr_debug("Couldn't determine max cpu frequency, necessary for scale-invariant accounting.\n");