Skip to content

Commit b284909

Browse files
jpoimboeKAGA-KOKO
authored andcommitted
cpu/hotplug: Fix "SMT disabled by BIOS" detection for KVM
With the following commit: 73d5e2b ("cpu/hotplug: detect SMT disabled by BIOS") ... the hotplug code attempted to detect when SMT was disabled by BIOS, in which case it reported SMT as permanently disabled. However, that code broke a virt hotplug scenario, where the guest is booted with only primary CPU threads, and a sibling is brought online later. The problem is that there doesn't seem to be a way to reliably distinguish between the HW "SMT disabled by BIOS" case and the virt "sibling not yet brought online" case. So the above-mentioned commit was a bit misguided, as it permanently disabled SMT for both cases, preventing future virt sibling hotplugs. Going back and reviewing the original problems which were attempted to be solved by that commit, when SMT was disabled in BIOS: 1) /sys/devices/system/cpu/smt/control showed "on" instead of "notsupported"; and 2) vmx_vm_init() was incorrectly showing the L1TF_MSG_SMT warning. I'd propose that we instead consider #1 above to not actually be a problem. Because, at least in the virt case, it's possible that SMT wasn't disabled by BIOS and a sibling thread could be brought online later. So it makes sense to just always default the smt control to "on" to allow for that possibility (assuming cpuid indicates that the CPU supports SMT). The real problem is #2, which has a simple fix: change vmx_vm_init() to query the actual current SMT state -- i.e., whether any siblings are currently online -- instead of looking at the SMT "control" sysfs value. So fix it by: a) reverting the original "fix" and its followup fix: 73d5e2b ("cpu/hotplug: detect SMT disabled by BIOS") bc2d8d2 ("cpu/hotplug: Fix SMT supported evaluation") and b) changing vmx_vm_init() to query the actual current SMT state -- instead of the sysfs control value -- to determine whether the L1TF warning is needed. This also requires the 'sched_smt_present' variable to exported, instead of 'cpu_smt_control'. Fixes: 73d5e2b ("cpu/hotplug: detect SMT disabled by BIOS") Reported-by: Igor Mammedov <imammedo@redhat.com> Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Joe Mario <jmario@redhat.com> Cc: Jiri Kosina <jikos@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: kvm@vger.kernel.org Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/e3a85d585da28cc333ecbc1e78ee9216e6da9396.1548794349.git.jpoimboe@redhat.com
1 parent 34d66ca commit b284909

File tree

6 files changed

+8
-35
lines changed

6 files changed

+8
-35
lines changed

arch/x86/kernel/cpu/bugs.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ void __init check_bugs(void)
7171
* identify_boot_cpu() initialized SMT support information, let the
7272
* core code know.
7373
*/
74-
cpu_smt_check_topology_early();
74+
cpu_smt_check_topology();
7575

7676
if (!IS_ENABLED(CONFIG_SMP)) {
7777
pr_info("CPU: ");

arch/x86/kvm/vmx/vmx.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <linux/mod_devicetable.h>
2727
#include <linux/mm.h>
2828
#include <linux/sched.h>
29+
#include <linux/sched/smt.h>
2930
#include <linux/slab.h>
3031
#include <linux/tboot.h>
3132
#include <linux/trace_events.h>
@@ -6823,7 +6824,7 @@ static int vmx_vm_init(struct kvm *kvm)
68236824
* Warn upon starting the first VM in a potentially
68246825
* insecure environment.
68256826
*/
6826-
if (cpu_smt_control == CPU_SMT_ENABLED)
6827+
if (sched_smt_active())
68276828
pr_warn_once(L1TF_MSG_SMT);
68286829
if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER)
68296830
pr_warn_once(L1TF_MSG_L1D);

include/linux/cpu.h

-2
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,10 @@ enum cpuhp_smt_control {
180180
#if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT)
181181
extern enum cpuhp_smt_control cpu_smt_control;
182182
extern void cpu_smt_disable(bool force);
183-
extern void cpu_smt_check_topology_early(void);
184183
extern void cpu_smt_check_topology(void);
185184
#else
186185
# define cpu_smt_control (CPU_SMT_ENABLED)
187186
static inline void cpu_smt_disable(bool force) { }
188-
static inline void cpu_smt_check_topology_early(void) { }
189187
static inline void cpu_smt_check_topology(void) { }
190188
#endif
191189

kernel/cpu.c

+4-29
Original file line numberDiff line numberDiff line change
@@ -376,9 +376,6 @@ void __weak arch_smt_update(void) { }
376376

377377
#ifdef CONFIG_HOTPLUG_SMT
378378
enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED;
379-
EXPORT_SYMBOL_GPL(cpu_smt_control);
380-
381-
static bool cpu_smt_available __read_mostly;
382379

383380
void __init cpu_smt_disable(bool force)
384381
{
@@ -397,25 +394,11 @@ void __init cpu_smt_disable(bool force)
397394

398395
/*
399396
* The decision whether SMT is supported can only be done after the full
400-
* CPU identification. Called from architecture code before non boot CPUs
401-
* are brought up.
402-
*/
403-
void __init cpu_smt_check_topology_early(void)
404-
{
405-
if (!topology_smt_supported())
406-
cpu_smt_control = CPU_SMT_NOT_SUPPORTED;
407-
}
408-
409-
/*
410-
* If SMT was disabled by BIOS, detect it here, after the CPUs have been
411-
* brought online. This ensures the smt/l1tf sysfs entries are consistent
412-
* with reality. cpu_smt_available is set to true during the bringup of non
413-
* boot CPUs when a SMT sibling is detected. Note, this may overwrite
414-
* cpu_smt_control's previous setting.
397+
* CPU identification. Called from architecture code.
415398
*/
416399
void __init cpu_smt_check_topology(void)
417400
{
418-
if (!cpu_smt_available)
401+
if (!topology_smt_supported())
419402
cpu_smt_control = CPU_SMT_NOT_SUPPORTED;
420403
}
421404

@@ -428,18 +411,10 @@ early_param("nosmt", smt_cmdline_disable);
428411

429412
static inline bool cpu_smt_allowed(unsigned int cpu)
430413
{
431-
if (topology_is_primary_thread(cpu))
414+
if (cpu_smt_control == CPU_SMT_ENABLED)
432415
return true;
433416

434-
/*
435-
* If the CPU is not a 'primary' thread and the booted_once bit is
436-
* set then the processor has SMT support. Store this information
437-
* for the late check of SMT support in cpu_smt_check_topology().
438-
*/
439-
if (per_cpu(cpuhp_state, cpu).booted_once)
440-
cpu_smt_available = true;
441-
442-
if (cpu_smt_control == CPU_SMT_ENABLED)
417+
if (topology_is_primary_thread(cpu))
443418
return true;
444419

445420
/*

kernel/sched/fair.c

+1
Original file line numberDiff line numberDiff line change
@@ -5980,6 +5980,7 @@ static inline int find_idlest_cpu(struct sched_domain *sd, struct task_struct *p
59805980

59815981
#ifdef CONFIG_SCHED_SMT
59825982
DEFINE_STATIC_KEY_FALSE(sched_smt_present);
5983+
EXPORT_SYMBOL_GPL(sched_smt_present);
59835984

59845985
static inline void set_idle_cores(int cpu, int val)
59855986
{

kernel/smp.c

-2
Original file line numberDiff line numberDiff line change
@@ -584,8 +584,6 @@ void __init smp_init(void)
584584
num_nodes, (num_nodes > 1 ? "s" : ""),
585585
num_cpus, (num_cpus > 1 ? "s" : ""));
586586

587-
/* Final decision about SMT support */
588-
cpu_smt_check_topology();
589587
/* Any cleanup work */
590588
smp_cpus_done(setup_max_cpus);
591589
}

0 commit comments

Comments
 (0)