x86/smp: Add a per-cpu view of SMT state
authorBalbir Singh <sblbir@amazon.com>
Fri, 8 Jan 2021 12:10:52 +0000 (23:10 +1100)
committerThomas Gleixner <tglx@linutronix.de>
Wed, 28 Jul 2021 09:42:23 +0000 (11:42 +0200)
A new field smt_active in cpuinfo_x86 identifies if the current core/cpu
is in SMT mode or not.

This is helpful when the system has some of its cores with threads offlined
and can be used for cases where action is taken based on the state of SMT.

The upcoming support for paranoid L1D flush will make use of this information.

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Balbir Singh <sblbir@amazon.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20210108121056.21940-2-sblbir@amazon.com
arch/x86/include/asm/processor.h
arch/x86/kernel/smpboot.c

index f3020c54e2cb3db1347a3e497770be8648f71b8a..1e0d13c9fda6e8d0f2f1214efabcb4f89b5e657e 100644 (file)
@@ -136,6 +136,8 @@ struct cpuinfo_x86 {
        u16                     logical_die_id;
        /* Index into per_cpu list: */
        u16                     cpu_index;
+       /*  Is SMT active on this core? */
+       bool                    smt_active;
        u32                     microcode;
        /* Address space bits used by the cache internally */
        u8                      x86_cache_bits;
index 9320285a5e295e3380ebbf5dff8b8cc2bd8866e8..85f6e242b6b45195f74766c5a81b63a3a7e24f8c 100644 (file)
@@ -610,6 +610,9 @@ void set_cpu_sibling_map(int cpu)
        if (threads > __max_smt_threads)
                __max_smt_threads = threads;
 
+       for_each_cpu(i, topology_sibling_cpumask(cpu))
+               cpu_data(i).smt_active = threads > 1;
+
        /*
         * This needs a separate iteration over the cpus because we rely on all
         * topology_sibling_cpumask links to be set-up.
@@ -1552,8 +1555,13 @@ static void remove_siblinginfo(int cpu)
 
        for_each_cpu(sibling, topology_die_cpumask(cpu))
                cpumask_clear_cpu(cpu, topology_die_cpumask(sibling));
-       for_each_cpu(sibling, topology_sibling_cpumask(cpu))
+
+       for_each_cpu(sibling, topology_sibling_cpumask(cpu)) {
                cpumask_clear_cpu(cpu, topology_sibling_cpumask(sibling));
+               if (cpumask_weight(topology_sibling_cpumask(sibling)) == 1)
+                       cpu_data(sibling).smt_active = false;
+       }
+
        for_each_cpu(sibling, cpu_llc_shared_mask(cpu))
                cpumask_clear_cpu(cpu, cpu_llc_shared_mask(sibling));
        cpumask_clear(cpu_llc_shared_mask(cpu));