Skip to content

Commit 090610b

Browse files
committed
x86/cpu/topology: Use topology bitmaps for sizing
Now that all possible APIC IDs are tracked in the topology bitmaps, its trivial to retrieve the real information from there. This gets rid of the guesstimates for the maximal packages and dies per package as the actual numbers can be determined before a single AP has been brought up. The number of SMT threads can now be determined correctly from the bitmaps in all situations. Up to now a system which has SMT disabled in the BIOS will still claim that it is SMT capable, because the lowest APIC ID bit is reserved for that and CPUID leaf 0xb/0x1f still enumerates the SMT domain accordingly. By calculating the bitmap weights of the SMT and the CORE domain and setting them into relation the SMT disabled in BIOS situation reports correctly that the system is not SMT capable. It also handles the situation correctly when a hybrid systems boot CPU does not have SMT as it takes the SMT capability of the APs fully into account. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Michael Kelley <mhklinux@outlook.com> Tested-by: Sohil Mehta <sohil.mehta@intel.com> Link: https://lore.kernel.org/r/20240213210252.681709880@linutronix.de
1 parent 354da4c commit 090610b

8 files changed

Lines changed: 39 additions & 60 deletions

File tree

arch/x86/include/asm/smp.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include <asm/current.h>
99
#include <asm/thread_info.h>
1010

11-
extern int smp_num_siblings;
11+
extern unsigned int smp_num_siblings;
1212

1313
DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map);
1414
DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_map);
@@ -109,7 +109,6 @@ void cpu_disable_common(void);
109109
void native_smp_prepare_boot_cpu(void);
110110
void smp_prepare_cpus_common(void);
111111
void native_smp_prepare_cpus(unsigned int max_cpus);
112-
void calculate_max_logical_packages(void);
113112
void native_smp_cpus_done(unsigned int max_cpus);
114113
int common_cpu_up(unsigned int cpunum, struct task_struct *tidle);
115114
int native_kick_ap(unsigned int cpu, struct task_struct *tidle);

arch/x86/include/asm/topology.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,18 @@ extern const struct cpumask *cpu_clustergroup_mask(int cpu);
143143

144144
#define topology_amd_node_id(cpu) (cpu_data(cpu).topo.amd_node_id)
145145

146-
extern unsigned int __max_die_per_package;
146+
extern unsigned int __max_dies_per_package;
147+
extern unsigned int __max_logical_packages;
148+
149+
static inline unsigned int topology_max_packages(void)
150+
{
151+
return __max_logical_packages;
152+
}
153+
154+
static inline unsigned int topology_max_die_per_package(void)
155+
{
156+
return __max_dies_per_package;
157+
}
147158

148159
#ifdef CONFIG_SMP
149160
#define topology_cluster_id(cpu) (cpu_data(cpu).topo.l2c_id)
@@ -152,14 +163,6 @@ extern unsigned int __max_die_per_package;
152163
#define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu))
153164
#define topology_sibling_cpumask(cpu) (per_cpu(cpu_sibling_map, cpu))
154165

155-
extern unsigned int __max_logical_packages;
156-
#define topology_max_packages() (__max_logical_packages)
157-
158-
static inline int topology_max_die_per_package(void)
159-
{
160-
return __max_die_per_package;
161-
}
162-
163166
extern int __max_smt_threads;
164167

165168
static inline int topology_max_smt_threads(void)
@@ -193,13 +196,11 @@ static inline bool topology_is_primary_thread(unsigned int cpu)
193196
}
194197

195198
#else /* CONFIG_SMP */
196-
#define topology_max_packages() (1)
197199
static inline int
198200
topology_update_package_map(unsigned int apicid, unsigned int cpu) { return 0; }
199201
static inline int
200202
topology_update_die_map(unsigned int dieid, unsigned int cpu) { return 0; }
201203
static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return 0; }
202-
static inline int topology_max_die_per_package(void) { return 1; }
203204
static inline int topology_max_smt_threads(void) { return 1; }
204205
static inline bool topology_is_primary_thread(unsigned int cpu) { return true; }
205206
static inline unsigned int topology_amd_nodes_per_pkg(void) { return 0; };

arch/x86/kernel/cpu/common.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,14 @@
7373
u32 elf_hwcap2 __read_mostly;
7474

7575
/* Number of siblings per CPU package */
76-
int smp_num_siblings = 1;
76+
unsigned int smp_num_siblings __ro_after_init = 1;
7777
EXPORT_SYMBOL(smp_num_siblings);
7878

79-
unsigned int __max_die_per_package __read_mostly = 1;
80-
EXPORT_SYMBOL(__max_die_per_package);
79+
unsigned int __max_dies_per_package __ro_after_init = 1;
80+
EXPORT_SYMBOL(__max_dies_per_package);
81+
82+
unsigned int __max_logical_packages __ro_after_init = 1;
83+
EXPORT_SYMBOL(__max_logical_packages);
8184

8285
static struct ppin_info {
8386
int feature;

arch/x86/kernel/cpu/debugfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ static int cpu_debug_show(struct seq_file *m, void *p)
2929
seq_printf(m, "amd_node_id: %u\n", c->topo.amd_node_id);
3030
seq_printf(m, "amd_nodes_per_pkg: %u\n", topology_amd_nodes_per_pkg());
3131
seq_printf(m, "max_cores: %u\n", c->x86_max_cores);
32-
seq_printf(m, "max_die_per_pkg: %u\n", __max_die_per_package);
32+
seq_printf(m, "max_dies_per_pkg: %u\n", __max_dies_per_package);
3333
seq_printf(m, "smp_num_siblings: %u\n", smp_num_siblings);
3434
return 0;
3535
}

arch/x86/kernel/cpu/topology.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,8 @@ void __init topology_init_possible_cpus(void)
348348
{
349349
unsigned int assigned = topo_info.nr_assigned_cpus;
350350
unsigned int disabled = topo_info.nr_disabled_cpus;
351+
unsigned int cnta, cntb, cpu, allowed = 1;
351352
unsigned int total = assigned + disabled;
352-
unsigned int cpu, allowed = 1;
353353
u32 apicid;
354354

355355
if (!restrict_to_up()) {
@@ -372,6 +372,24 @@ void __init topology_init_possible_cpus(void)
372372
total_cpus = allowed;
373373
set_nr_cpu_ids(allowed);
374374

375+
cnta = domain_weight(TOPO_PKG_DOMAIN);
376+
cntb = domain_weight(TOPO_DIE_DOMAIN);
377+
__max_logical_packages = cnta;
378+
__max_dies_per_package = 1U << (get_count_order(cntb) - get_count_order(cnta));
379+
380+
pr_info("Max. logical packages: %3u\n", cnta);
381+
pr_info("Max. logical dies: %3u\n", cntb);
382+
pr_info("Max. dies per package: %3u\n", __max_dies_per_package);
383+
384+
cnta = domain_weight(TOPO_CORE_DOMAIN);
385+
cntb = domain_weight(TOPO_SMT_DOMAIN);
386+
/*
387+
* Can't use order delta here as order(cnta) can be equal
388+
* order(cntb) even if cnta != cntb.
389+
*/
390+
smp_num_siblings = DIV_ROUND_UP(cntb, cnta);
391+
pr_info("Max. threads per core: %3u\n", smp_num_siblings);
392+
375393
pr_info("Allowing %u present CPUs plus %u hotplug CPUs\n", assigned, disabled);
376394
if (topo_info.nr_rejected_cpus)
377395
pr_info("Rejected CPUs %u\n", topo_info.nr_rejected_cpus);

arch/x86/kernel/cpu/topology_common.c

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -196,16 +196,6 @@ void cpu_parse_topology(struct cpuinfo_x86 *c)
196196
tscan.dom_shifts[dom], x86_topo_system.dom_shifts[dom]);
197197
}
198198

199-
/* Bug compatible with the existing parsers */
200-
if (tscan.dom_ncpus[TOPO_SMT_DOMAIN] > smp_num_siblings) {
201-
if (system_state == SYSTEM_BOOTING) {
202-
pr_warn_once("CPU%d: SMT detected and enabled late\n", cpu);
203-
smp_num_siblings = tscan.dom_ncpus[TOPO_SMT_DOMAIN];
204-
} else {
205-
pr_warn_once("CPU%d: SMT detected after init. Too late!\n", cpu);
206-
}
207-
}
208-
209199
topo_set_ids(&tscan);
210200
topo_set_max_cores(&tscan);
211201
}
@@ -231,20 +221,6 @@ void __init cpu_init_topology(struct cpuinfo_x86 *c)
231221
topo_set_ids(&tscan);
232222
topo_set_max_cores(&tscan);
233223

234-
/*
235-
* Bug compatible with the existing code. If the boot CPU does not
236-
* have SMT this ends up with one sibling. This needs way deeper
237-
* changes further down the road to get it right during early boot.
238-
*/
239-
smp_num_siblings = tscan.dom_ncpus[TOPO_SMT_DOMAIN];
240-
241-
/*
242-
* Neither it's clear whether there are as many dies as the APIC
243-
* space indicating die level is. But assume that the actual number
244-
* of CPUs gives a proper indication for now to stay bug compatible.
245-
*/
246-
__max_die_per_package = tscan.dom_ncpus[TOPO_DIE_DOMAIN] /
247-
tscan.dom_ncpus[TOPO_DIE_DOMAIN - 1];
248224
/*
249225
* AMD systems have Nodes per package which cannot be mapped to
250226
* APIC ID.

arch/x86/kernel/smpboot.c

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,6 @@ static DEFINE_PER_CPU_READ_MOSTLY(struct logical_maps, logical_maps) = {
139139
.phys_die_id = U32_MAX,
140140
};
141141

142-
unsigned int __max_logical_packages __read_mostly;
143-
EXPORT_SYMBOL(__max_logical_packages);
144142
static unsigned int logical_packages __read_mostly;
145143
static unsigned int logical_die __read_mostly;
146144

@@ -1267,24 +1265,10 @@ void __init native_smp_prepare_boot_cpu(void)
12671265
native_pv_lock_init();
12681266
}
12691267

1270-
void __init calculate_max_logical_packages(void)
1271-
{
1272-
int ncpus;
1273-
1274-
/*
1275-
* Today neither Intel nor AMD support heterogeneous systems so
1276-
* extrapolate the boot cpu's data to all packages.
1277-
*/
1278-
ncpus = cpu_data(0).booted_cores * topology_max_smt_threads();
1279-
__max_logical_packages = DIV_ROUND_UP(total_cpus, ncpus);
1280-
pr_info("Max logical packages: %u\n", __max_logical_packages);
1281-
}
1282-
12831268
void __init native_smp_cpus_done(unsigned int max_cpus)
12841269
{
12851270
pr_debug("Boot done\n");
12861271

1287-
calculate_max_logical_packages();
12881272
build_sched_topology();
12891273
nmi_selftest();
12901274
impress_friends();

arch/x86/xen/smp.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,6 @@ void __init xen_smp_cpus_done(unsigned int max_cpus)
123123
{
124124
if (xen_hvm_domain())
125125
native_smp_cpus_done(max_cpus);
126-
else
127-
calculate_max_logical_packages();
128126
}
129127

130128
void xen_smp_send_reschedule(int cpu)

0 commit comments

Comments
 (0)