From: Thomas Gleixner Date: Tue, 29 May 2018 15:50:22 +0000 (+0200) Subject: x86/smp: Provide topology_is_primary_thread() X-Git-Tag: v4.1.12-124.31.3~662 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=02d4a704e8bbba232c890bac6bf7106388e55ac4;p=users%2Fjedix%2Flinux-maple.git x86/smp: Provide topology_is_primary_thread() If the CPU is supporting SMT then the primary thread can be found by checking the lower APIC ID bits for zero. smp_num_siblings is used to build the mask for the APIC ID bits which need to be taken into account. This uses the MPTABLE or ACPI/MADT supplied APIC ID, which can be different than the initial APIC ID in CPUID. But according to AMD the lower bits have to be consistent. Intel gave a tentative confirmation as well. Preparatory patch to support disabling SMT at boot/runtime. Signed-off-by: Thomas Gleixner Reviewed-by: Konrad Rzeszutek Wilk Acked-by: Ingo Molnar Orabug: 28220674 CVE: CVE-2018-3620 (cherry picked from commit 6a4d2657e048f096c7ffcad254010bd94891c8c0) Signed-off-by: Mihai Carabas Reviewed-by: Darren Kenny Reviewed-by: Boris Ostrovsky Conflicts: arch/x86/include/asm/apic.h arch/x86/include/asm/topology.h arch/x86/kernel/apic/apic.c arch/x86/kernel/smpboot.c Contextual --- diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 69078eb679bb..1349b2842a55 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -115,6 +115,12 @@ static inline bool apic_is_x2apic_enabled(void) return msr & X2APIC_ENABLE; } +#ifdef CONFIG_SMP +bool apic_id_is_primary_thread(unsigned int id); +#else +static inline bool apic_id_is_primary_thread(unsigned int id) { return false; } +#endif + #ifdef CONFIG_X86_X2APIC /* * Make previous memory operations globally visible before diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h index 0e8f04f2c26f..bf9b53421a6f 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h @@ -122,6 +122,12 @@ extern const struct cpumask *cpu_coregroup_mask(int cpu); #define topology_physical_package_id(cpu) (cpu_data(cpu).phys_proc_id) #define topology_core_id(cpu) (cpu_data(cpu).cpu_core_id) +#ifdef CONFIG_SMP +bool topology_is_primary_thread(unsigned int cpu); +#else +static inline bool topology_is_primary_thread(unsigned int cpu) { return true; } +#endif + #ifdef ENABLE_TOPO_DEFINES #define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu)) #define topology_thread_cpumask(cpu) (per_cpu(cpu_sibling_map, cpu)) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index b69e79d707e3..e900f44a36f7 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1986,6 +1986,21 @@ void disconnect_bsp_APIC(int virt_wire_setup) apic_write(APIC_LVT1, value); } +/** + * apic_id_is_primary_thread - Check whether APIC ID belongs to a primary thread + * @id: APIC ID to check + */ +bool apic_id_is_primary_thread(unsigned int apicid) +{ + u32 mask; + + if (smp_num_siblings == 1) + return true; + /* Isolate the SMT bit(s) in the APICID and check for 0 */ + mask = (1U << (fls(smp_num_siblings) - 1)) - 1; + return !(apicid & mask); +} + int generic_processor_info(int apicid, int version) { int cpu, max = nr_cpu_ids; diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 05520fb819f6..76c42a0d26c4 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -270,6 +270,15 @@ static void notrace start_secondary(void *unused) cpu_startup_entry(CPUHP_ONLINE); } +/** + * topology_is_primary_thread - Check whether CPU is the primary SMT thread + * @cpu: CPU to check + */ +bool topology_is_primary_thread(unsigned int cpu) +{ + return apic_id_is_primary_thread(per_cpu(x86_cpu_to_apicid, cpu)); +} + void __init smp_store_boot_cpu_info(void) { int id = 0; /* CPU 0 */