Skip to content

Commit 6a4d265

Browse files
committed
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 <[email protected]> Reviewed-by: Konrad Rzeszutek Wilk <[email protected]> Acked-by: Ingo Molnar <[email protected]>
1 parent ba2591a commit 6a4d265

File tree

4 files changed

+33
-1
lines changed

4 files changed

+33
-1
lines changed

arch/x86/include/asm/apic.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,12 @@ extern int default_check_phys_apicid_present(int phys_apicid);
502502

503503
#endif /* CONFIG_X86_LOCAL_APIC */
504504

505+
#ifdef CONFIG_SMP
506+
bool apic_id_is_primary_thread(unsigned int id);
507+
#else
508+
static inline bool apic_id_is_primary_thread(unsigned int id) { return false; }
509+
#endif
510+
505511
extern void irq_enter(void);
506512
extern void irq_exit(void);
507513

arch/x86/include/asm/topology.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,15 @@ static inline int topology_max_smt_threads(void)
123123
}
124124

125125
int topology_update_package_map(unsigned int apicid, unsigned int cpu);
126-
extern int topology_phys_to_logical_pkg(unsigned int pkg);
126+
int topology_phys_to_logical_pkg(unsigned int pkg);
127+
bool topology_is_primary_thread(unsigned int cpu);
127128
#else
128129
#define topology_max_packages() (1)
129130
static inline int
130131
topology_update_package_map(unsigned int apicid, unsigned int cpu) { return 0; }
131132
static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return 0; }
132133
static inline int topology_max_smt_threads(void) { return 1; }
134+
static inline bool topology_is_primary_thread(unsigned int cpu) { return true; }
133135
#endif
134136

135137
static inline void arch_fix_phys_package_id(int num, u32 slot)

arch/x86/kernel/apic/apic.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,6 +2189,21 @@ static int cpuid_to_apicid[] = {
21892189
[0 ... NR_CPUS - 1] = -1,
21902190
};
21912191

2192+
/**
2193+
* apic_id_is_primary_thread - Check whether APIC ID belongs to a primary thread
2194+
* @id: APIC ID to check
2195+
*/
2196+
bool apic_id_is_primary_thread(unsigned int apicid)
2197+
{
2198+
u32 mask;
2199+
2200+
if (smp_num_siblings == 1)
2201+
return true;
2202+
/* Isolate the SMT bit(s) in the APICID and check for 0 */
2203+
mask = (1U << (fls(smp_num_siblings) - 1)) - 1;
2204+
return !(apicid & mask);
2205+
}
2206+
21922207
/*
21932208
* Should use this API to allocate logical CPU IDs to keep nr_logical_cpuids
21942209
* and cpuid_to_apicid[] synchronized.

arch/x86/kernel/smpboot.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,15 @@ static void notrace start_secondary(void *unused)
265265
cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
266266
}
267267

268+
/**
269+
* topology_is_primary_thread - Check whether CPU is the primary SMT thread
270+
* @cpu: CPU to check
271+
*/
272+
bool topology_is_primary_thread(unsigned int cpu)
273+
{
274+
return apic_id_is_primary_thread(per_cpu(x86_cpu_to_apicid, cpu));
275+
}
276+
268277
/**
269278
* topology_phys_to_logical_pkg - Map a physical package id to a logical
270279
*

0 commit comments

Comments
 (0)