Skip to content

Commit

Permalink
x86/smp: Provide topology_is_primary_thread()
Browse files Browse the repository at this point in the history
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 <tglx@linutronix.de>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Acked-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Thomas Gleixner committed Jun 21, 2018
1 parent ba2591a commit 6a4d265
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 1 deletion.
6 changes: 6 additions & 0 deletions arch/x86/include/asm/apic.h
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,12 @@ extern int default_check_phys_apicid_present(int phys_apicid);

#endif /* CONFIG_X86_LOCAL_APIC */

#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

extern void irq_enter(void);
extern void irq_exit(void);

Expand Down
4 changes: 3 additions & 1 deletion arch/x86/include/asm/topology.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,15 @@ static inline int topology_max_smt_threads(void)
}

int topology_update_package_map(unsigned int apicid, unsigned int cpu);
extern int topology_phys_to_logical_pkg(unsigned int pkg);
int topology_phys_to_logical_pkg(unsigned int pkg);
bool topology_is_primary_thread(unsigned int cpu);
#else
#define topology_max_packages() (1)
static inline int
topology_update_package_map(unsigned int apicid, unsigned int cpu) { return 0; }
static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return 0; }
static inline int topology_max_smt_threads(void) { return 1; }
static inline bool topology_is_primary_thread(unsigned int cpu) { return true; }
#endif

static inline void arch_fix_phys_package_id(int num, u32 slot)
Expand Down
15 changes: 15 additions & 0 deletions arch/x86/kernel/apic/apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -2189,6 +2189,21 @@ static int cpuid_to_apicid[] = {
[0 ... NR_CPUS - 1] = -1,
};

/**
* 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);
}

/*
* Should use this API to allocate logical CPU IDs to keep nr_logical_cpuids
* and cpuid_to_apicid[] synchronized.
Expand Down
9 changes: 9 additions & 0 deletions arch/x86/kernel/smpboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,15 @@ static void notrace start_secondary(void *unused)
cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
}

/**
* 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));
}

/**
* topology_phys_to_logical_pkg - Map a physical package id to a logical
*
Expand Down

0 comments on commit 6a4d265

Please sign in to comment.