Skip to content

Commit aff47b6

Browse files
dwmw2sirlucjan
authored andcommitted
x86/smpboot: Serialize topology updates for secondary bringup
The toplogy update is performed by the AP via smp_callin() after the BSP has called do_wait_cpu_initialized(), setting the AP's bit in cpu_callout_mask to allow it to proceed. In preparation to enable further parallelism of AP bringup, add locking to serialize the update even if multiple APs are (in future) permitted to proceed through the next stages of bringup in parallel. Without such ordering (and with that future extra parallelism), confusion ensues: [ 1.360149] x86: Booting SMP configuration: [ 1.360221] .... node #0, CPUs: #1 #2 #3 #4 #5 torvalds#6 torvalds#7 torvalds#8 torvalds#9 torvalds#10 torvalds#11 torvalds#12 torvalds#13 torvalds#14 torvalds#15 torvalds#16 torvalds#17 torvalds#18 torvalds#19 torvalds#20 torvalds#21 torvalds#22 torvalds#23 [ 1.366225] .... node #1, CPUs: torvalds#24 torvalds#25 torvalds#26 torvalds#27 torvalds#28 torvalds#29 torvalds#30 torvalds#31 torvalds#32 torvalds#33 torvalds#34 torvalds#35 torvalds#36 torvalds#37 torvalds#38 torvalds#39 torvalds#40 torvalds#41 torvalds#42 torvalds#43 torvalds#44 torvalds#45 torvalds#46 torvalds#47 [ 1.370219] .... node #0, CPUs: torvalds#48 torvalds#49 torvalds#50 torvalds#51 #52 #53 torvalds#54 torvalds#55 torvalds#56 torvalds#57 #58 torvalds#59 torvalds#60 torvalds#61 torvalds#62 torvalds#63 torvalds#64 torvalds#65 torvalds#66 torvalds#67 torvalds#68 torvalds#69 #70 torvalds#71 [ 1.378226] .... node #1, CPUs: torvalds#72 torvalds#73 torvalds#74 torvalds#75 torvalds#76 torvalds#77 torvalds#78 torvalds#79 torvalds#80 torvalds#81 torvalds#82 torvalds#83 torvalds#84 torvalds#85 torvalds#86 torvalds#87 torvalds#88 torvalds#89 torvalds#90 torvalds#91 torvalds#92 torvalds#93 torvalds#94 torvalds#95 [ 1.382037] Brought 96 CPUs to x86/cpu:kick in 72232606 cycles [ 0.104104] smpboot: CPU 26 Converting physical 0 to logical die 1 [ 0.104104] smpboot: CPU 27 Converting physical 1 to logical package 2 [ 0.104104] smpboot: CPU 24 Converting physical 1 to logical package 3 [ 0.104104] smpboot: CPU 27 Converting physical 0 to logical die 2 [ 0.104104] smpboot: CPU 25 Converting physical 1 to logical package 4 [ 1.385609] Brought 96 CPUs to x86/cpu:wait-init in 9269218 cycles [ 1.395285] Brought CPUs online in 28930764 cycles [ 1.395469] smp: Brought up 2 nodes, 96 CPUs [ 1.395689] smpboot: Max logical packages: 2 [ 1.396222] smpboot: Total of 96 processors activated (576000.00 BogoMIPS) [Usama Arif: fixed rebase conflict] Signed-off-by: David Woodhouse <[email protected]> Signed-off-by: Usama Arif <[email protected]>
1 parent 0663bd0 commit aff47b6

File tree

5 files changed

+48
-41
lines changed

5 files changed

+48
-41
lines changed

arch/x86/include/asm/smp.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ struct smp_ops {
4848
};
4949

5050
/* Globals due to paravirt */
51-
extern void set_cpu_sibling_map(int cpu);
52-
5351
#ifdef CONFIG_SMP
5452
extern struct smp_ops smp_ops;
5553

@@ -137,7 +135,7 @@ void native_send_call_func_single_ipi(int cpu);
137135
void x86_idle_thread_init(unsigned int cpu, struct task_struct *idle);
138136

139137
void smp_store_boot_cpu_info(void);
140-
void smp_store_cpu_info(int id);
138+
void smp_store_cpu_info(int id, bool force_single_core);
141139

142140
asmlinkage __visible void smp_reboot_interrupt(void);
143141
__visible void smp_reschedule_interrupt(struct pt_regs *regs);

arch/x86/include/asm/topology.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,6 @@ static inline int topology_max_smt_threads(void)
136136
return __max_smt_threads;
137137
}
138138

139-
int topology_update_package_map(unsigned int apicid, unsigned int cpu);
140-
int topology_update_die_map(unsigned int dieid, unsigned int cpu);
141139
int topology_phys_to_logical_pkg(unsigned int pkg);
142140
int topology_phys_to_logical_die(unsigned int die, unsigned int cpu);
143141
bool topology_is_primary_thread(unsigned int cpu);

arch/x86/kernel/cpu/common.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1766,7 +1766,7 @@ static void generic_identify(struct cpuinfo_x86 *c)
17661766
* Validate that ACPI/mptables have the same information about the
17671767
* effective APIC id and update the package map.
17681768
*/
1769-
static void validate_apic_and_package_id(struct cpuinfo_x86 *c)
1769+
static void validate_apic_id(struct cpuinfo_x86 *c)
17701770
{
17711771
#ifdef CONFIG_SMP
17721772
unsigned int apicid, cpu = smp_processor_id();
@@ -1777,8 +1777,6 @@ static void validate_apic_and_package_id(struct cpuinfo_x86 *c)
17771777
pr_err(FW_BUG "CPU%u: APIC id mismatch. Firmware: %x APIC: %x\n",
17781778
cpu, apicid, c->initial_apicid);
17791779
}
1780-
BUG_ON(topology_update_package_map(c->phys_proc_id, cpu));
1781-
BUG_ON(topology_update_die_map(c->cpu_die_id, cpu));
17821780
#else
17831781
c->logical_proc_id = 0;
17841782
#endif
@@ -1969,7 +1967,7 @@ void identify_secondary_cpu(struct cpuinfo_x86 *c)
19691967
#ifdef CONFIG_X86_32
19701968
enable_sep_cpu();
19711969
#endif
1972-
validate_apic_and_package_id(c);
1970+
validate_apic_id(c);
19731971
x86_spec_ctrl_setup_ap();
19741972
update_srbds_msr();
19751973

arch/x86/kernel/smpboot.c

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -180,16 +180,12 @@ static void smp_callin(void)
180180
apic_ap_setup();
181181

182182
/*
183-
* Save our processor parameters. Note: this information
184-
* is needed for clock calibration.
185-
*/
186-
smp_store_cpu_info(cpuid);
187-
188-
/*
183+
* Save our processor parameters and update topology.
184+
* Note: this information is needed for clock calibration.
189185
* The topology information must be up to date before
190186
* calibrate_delay() and notify_cpu_starting().
191187
*/
192-
set_cpu_sibling_map(raw_smp_processor_id());
188+
smp_store_cpu_info(cpuid, false);
193189

194190
ap_init_aperfmperf();
195191

@@ -243,6 +239,12 @@ static void notrace start_secondary(void *unused)
243239
* its bit bit in cpu_callout_mask to release it.
244240
*/
245241
cpu_init_secondary();
242+
243+
/*
244+
* Even though notify_cpu_starting() will do this, it does so too late
245+
* as the AP may already have triggered lockdep splats by then. See
246+
* commit 29368e093 ("x86/smpboot: Move rcu_cpu_starting() earlier").
247+
*/
246248
rcu_cpu_starting(raw_smp_processor_id());
247249
x86_cpuinit.early_percpu_clock_init();
248250

@@ -351,7 +353,7 @@ EXPORT_SYMBOL(topology_phys_to_logical_die);
351353
* @pkg: The physical package id as retrieved via CPUID
352354
* @cpu: The cpu for which this is updated
353355
*/
354-
int topology_update_package_map(unsigned int pkg, unsigned int cpu)
356+
static int topology_update_package_map(unsigned int pkg, unsigned int cpu)
355357
{
356358
int new;
357359

@@ -374,7 +376,7 @@ int topology_update_package_map(unsigned int pkg, unsigned int cpu)
374376
* @die: The die id as retrieved via CPUID
375377
* @cpu: The cpu for which this is updated
376378
*/
377-
int topology_update_die_map(unsigned int die, unsigned int cpu)
379+
static int topology_update_die_map(unsigned int die, unsigned int cpu)
378380
{
379381
int new;
380382

@@ -405,25 +407,7 @@ void __init smp_store_boot_cpu_info(void)
405407
c->initialized = true;
406408
}
407409

408-
/*
409-
* The bootstrap kernel entry code has set these up. Save them for
410-
* a given CPU
411-
*/
412-
void smp_store_cpu_info(int id)
413-
{
414-
struct cpuinfo_x86 *c = &cpu_data(id);
415-
416-
/* Copy boot_cpu_data only on the first bringup */
417-
if (!c->initialized)
418-
*c = boot_cpu_data;
419-
c->cpu_index = id;
420-
/*
421-
* During boot time, CPU0 has this setup already. Save the info when
422-
* bringing up AP or offlined CPU0.
423-
*/
424-
identify_secondary_cpu(c);
425-
c->initialized = true;
426-
}
410+
static arch_spinlock_t topology_lock = __ARCH_SPIN_LOCK_UNLOCKED;
427411

428412
static bool
429413
topology_same_node(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
@@ -629,7 +613,7 @@ static struct sched_domain_topology_level x86_topology[] = {
629613
*/
630614
static bool x86_has_numa_in_package;
631615

632-
void set_cpu_sibling_map(int cpu)
616+
static void set_cpu_sibling_map(int cpu)
633617
{
634618
bool has_smt = smp_num_siblings > 1;
635619
bool has_mp = has_smt || boot_cpu_data.x86_max_cores > 1;
@@ -708,6 +692,37 @@ void set_cpu_sibling_map(int cpu)
708692
}
709693
}
710694

695+
/*
696+
* The bootstrap kernel entry code has set these up. Save them for
697+
* a given CPU
698+
*/
699+
void smp_store_cpu_info(int id, bool force_single_core)
700+
{
701+
struct cpuinfo_x86 *c = &cpu_data(id);
702+
703+
/* Copy boot_cpu_data only on the first bringup */
704+
if (!c->initialized)
705+
*c = boot_cpu_data;
706+
c->cpu_index = id;
707+
/*
708+
* During boot time, CPU0 has this setup already. Save the info when
709+
* bringing up AP or offlined CPU0.
710+
*/
711+
identify_secondary_cpu(c);
712+
713+
arch_spin_lock(&topology_lock);
714+
BUG_ON(topology_update_package_map(c->phys_proc_id, id));
715+
BUG_ON(topology_update_die_map(c->cpu_die_id, id));
716+
c->initialized = true;
717+
718+
/* For Xen PV */
719+
if (force_single_core)
720+
c->x86_max_cores = 1;
721+
722+
set_cpu_sibling_map(id);
723+
arch_spin_unlock(&topology_lock);
724+
}
725+
711726
/* maps the cpu to the sched domain representing multi-core */
712727
const struct cpumask *cpu_coregroup_mask(int cpu)
713728
{

arch/x86/xen/smp_pv.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,7 @@ static void cpu_bringup(void)
7171
xen_enable_syscall();
7272
}
7373
cpu = smp_processor_id();
74-
smp_store_cpu_info(cpu);
75-
cpu_data(cpu).x86_max_cores = 1;
76-
set_cpu_sibling_map(cpu);
74+
smp_store_cpu_info(cpu, true);
7775

7876
speculative_store_bypass_ht_init();
7977

0 commit comments

Comments
 (0)