diff options
Diffstat (limited to 'arch/x86/kernel/smpboot.c')
| -rw-r--r-- | arch/x86/kernel/smpboot.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 0bd9c9f7861f..50eff9b7fe7f 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -220,6 +220,17 @@ static void ap_calibrate_delay(void) cpu_data(smp_processor_id()).loops_per_jiffy = loops_per_jiffy; } +static void wait_for_master_cpu(int cpu) +{ + /* + * Wait for release by control CPU before continuing with AP + * initialization. + */ + WARN_ON(cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)); + while (!cpumask_test_cpu(cpu, cpu_callout_mask)) + cpu_relax(); +} + /* * Activate a secondary processor. */ @@ -237,13 +248,16 @@ static void notrace start_secondary(void *unused) load_cr3(swapper_pg_dir); __flush_tlb_all(); #endif + cpu_init_exception_handling(); + /* - * Sync point with wait_cpu_initialized(). Before proceeding through - * cpu_init(), the AP will call wait_for_master_cpu() which sets its - * own bit in cpu_initialized_mask and then waits for the BSP to set - * its bit in cpu_callout_mask to release it. + * Sync point with wait_cpu_initialized(). Sets AP in + * cpu_initialized_mask and then waits for the control CPU + * to release it. */ - cpu_init_secondary(); + wait_for_master_cpu(raw_smp_processor_id()); + + cpu_init(); rcu_cpu_starting(raw_smp_processor_id()); x86_cpuinit.early_percpu_clock_init(); |
