Skip to content

Commit bc2d8d2

Browse files
committed
cpu/hotplug: Fix SMT supported evaluation
Josh reported that the late SMT evaluation in cpu_smt_state_init() sets cpu_smt_control to CPU_SMT_NOT_SUPPORTED in case that 'nosmt' was supplied on the kernel command line as it cannot differentiate between SMT disabled by BIOS and SMT soft disable via 'nosmt'. That wreckages the state and makes the sysfs interface unusable. Rework this so that during bringup of the non boot CPUs the availability of SMT is determined in cpu_smt_allowed(). If a newly booted CPU is not a 'primary' thread then set the local cpu_smt_available marker and evaluate this explicitely right after the initial SMP bringup has finished. SMT evaulation on x86 is a trainwreck as the firmware has all the information _before_ booting the kernel, but there is no interface to query it. Fixes: 73d5e2b ("cpu/hotplug: detect SMT disabled by BIOS") Reported-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
1 parent 5b76a3c commit bc2d8d2

File tree

4 files changed

+33
-14
lines changed

4 files changed

+33
-14
lines changed

arch/x86/kernel/cpu/bugs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ void __init check_bugs(void)
6363
* identify_boot_cpu() initialized SMT support information, let the
6464
* core code know.
6565
*/
66-
cpu_smt_check_topology();
66+
cpu_smt_check_topology_early();
6767

6868
if (!IS_ENABLED(CONFIG_SMP)) {
6969
pr_info("CPU: ");

include/linux/cpu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,12 @@ enum cpuhp_smt_control {
178178
#if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT)
179179
extern enum cpuhp_smt_control cpu_smt_control;
180180
extern void cpu_smt_disable(bool force);
181+
extern void cpu_smt_check_topology_early(void);
181182
extern void cpu_smt_check_topology(void);
182183
#else
183184
# define cpu_smt_control (CPU_SMT_ENABLED)
184185
static inline void cpu_smt_disable(bool force) { }
186+
static inline void cpu_smt_check_topology_early(void) { }
185187
static inline void cpu_smt_check_topology(void) { }
186188
#endif
187189

kernel/cpu.c

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,8 @@ EXPORT_SYMBOL_GPL(cpu_hotplug_enable);
347347
enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED;
348348
EXPORT_SYMBOL_GPL(cpu_smt_control);
349349

350+
static bool cpu_smt_available __read_mostly;
351+
350352
void __init cpu_smt_disable(bool force)
351353
{
352354
if (cpu_smt_control == CPU_SMT_FORCE_DISABLED ||
@@ -363,14 +365,28 @@ void __init cpu_smt_disable(bool force)
363365

364366
/*
365367
* The decision whether SMT is supported can only be done after the full
366-
* CPU identification. Called from architecture code.
368+
* CPU identification. Called from architecture code before non boot CPUs
369+
* are brought up.
367370
*/
368-
void __init cpu_smt_check_topology(void)
371+
void __init cpu_smt_check_topology_early(void)
369372
{
370373
if (!topology_smt_supported())
371374
cpu_smt_control = CPU_SMT_NOT_SUPPORTED;
372375
}
373376

377+
/*
378+
* If SMT was disabled by BIOS, detect it here, after the CPUs have been
379+
* brought online. This ensures the smt/l1tf sysfs entries are consistent
380+
* with reality. cpu_smt_available is set to true during the bringup of non
381+
* boot CPUs when a SMT sibling is detected. Note, this may overwrite
382+
* cpu_smt_control's previous setting.
383+
*/
384+
void __init cpu_smt_check_topology(void)
385+
{
386+
if (!cpu_smt_available)
387+
cpu_smt_control = CPU_SMT_NOT_SUPPORTED;
388+
}
389+
374390
static int __init smt_cmdline_disable(char *str)
375391
{
376392
cpu_smt_disable(str && !strcmp(str, "force"));
@@ -380,10 +396,18 @@ early_param("nosmt", smt_cmdline_disable);
380396

381397
static inline bool cpu_smt_allowed(unsigned int cpu)
382398
{
383-
if (cpu_smt_control == CPU_SMT_ENABLED)
399+
if (topology_is_primary_thread(cpu))
384400
return true;
385401

386-
if (topology_is_primary_thread(cpu))
402+
/*
403+
* If the CPU is not a 'primary' thread and the booted_once bit is
404+
* set then the processor has SMT support. Store this information
405+
* for the late check of SMT support in cpu_smt_check_topology().
406+
*/
407+
if (per_cpu(cpuhp_state, cpu).booted_once)
408+
cpu_smt_available = true;
409+
410+
if (cpu_smt_control == CPU_SMT_ENABLED)
387411
return true;
388412

389413
/*
@@ -2125,15 +2149,6 @@ static const struct attribute_group cpuhp_smt_attr_group = {
21252149

21262150
static int __init cpu_smt_state_init(void)
21272151
{
2128-
/*
2129-
* If SMT was disabled by BIOS, detect it here, after the CPUs have
2130-
* been brought online. This ensures the smt/l1tf sysfs entries are
2131-
* consistent with reality. Note this may overwrite cpu_smt_control's
2132-
* previous setting.
2133-
*/
2134-
if (topology_max_smt_threads() == 1)
2135-
cpu_smt_control = CPU_SMT_NOT_SUPPORTED;
2136-
21372152
return sysfs_create_group(&cpu_subsys.dev_root->kobj,
21382153
&cpuhp_smt_attr_group);
21392154
}

kernel/smp.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,8 @@ 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();
587589
/* Any cleanup work */
588590
smp_cpus_done(setup_max_cpus);
589591
}

0 commit comments

Comments
 (0)