cpumask_var_t cpu_initialized_mask;
cpumask_var_t cpu_callout_mask;
cpumask_var_t cpu_callin_mask;
+cpumask_var_t cpu_finishup_mask;
/* representing cpus for which sibling maps can be computed */
cpumask_var_t cpu_sibling_setup_mask;
alloc_bootmem_cpumask_var(&cpu_initialized_mask);
alloc_bootmem_cpumask_var(&cpu_callin_mask);
alloc_bootmem_cpumask_var(&cpu_callout_mask);
+ alloc_bootmem_cpumask_var(&cpu_finishup_mask);
alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask);
}
wmb();
/*
- * This runs the AP through all the cpuhp states to its target
- * state (CPUHP_ONLINE in the case of serial bringup).
+ * Allow the master to continue.
*/
- notify_cpu_starting(cpuid);
+ cpumask_set_cpu(cpuid, cpu_callin_mask);
+ while (!cpumask_test_cpu(cpuid, cpu_finishup_mask))
+ cpu_relax();
/*
- * Allow the master to continue.
+ * This runs the AP through all the cpuhp states to its target
+ * state (CPUHP_ONLINE in the case of serial bringup).
*/
- cpumask_set_cpu(cpuid, cpu_callin_mask);
+ static arch_spinlock_t cpuhp_lock = __ARCH_SPIN_LOCK_UNLOCKED;
+ arch_spin_lock(&cpuhp_lock);
+ notify_cpu_starting(cpuid);
+ arch_spin_unlock(&cpuhp_lock);
}
static int cpu0_logical_apicid;
init_espfix_ap(cpu);
/* So we see what's up */
- announce_cpu(cpu, apicid);
+ //announce_cpu(cpu, apicid);
/*
* This grunge runs the startup process for
/*
* Wait till AP completes initial initialization.
*/
- return do_wait_cpu_cpumask(cpu, cpu_callin_mask);
+ if (do_wait_cpu_cpumask(cpu, cpu_callin_mask))
+ return -1;
+
+ cpumask_set_cpu(cpu, cpu_finishup_mask);
+ return 0;
}
/*
{
int ret;
+ t[3] = get_cycles();
/* If parallel AP bringup isn't enabled, perform the first steps now. */
if (!do_parallel_bringup) {
ret = do_cpu_up(cpu, tidle);
if (ret)
return ret;
+
+ ret = do_wait_cpu_initialized(cpu);
+ if (ret)
+ return ret;
}
- t[3] = get_cycles();
- ret = do_wait_cpu_initialized(cpu);
- if (ret)
- return ret;
+
t[4] = get_cycles();
+
ret = do_wait_cpu_callin(cpu);
if (ret)
return ret;
if (IS_ENABLED(CONFIG_X86_32) || boot_cpu_data.cpuid_level < 0x0B)
do_parallel_bringup = false;
- if (do_parallel_bringup)
+ if (do_parallel_bringup) {
cpuhp_setup_state_nocalls(CPUHP_BP_PARALLEL_DYN, "x86/cpu:kick",
native_cpu_kick, NULL);
+ cpuhp_setup_state_nocalls(CPUHP_BP_PARALLEL_DYN, "x86/cpu:wait-init",
+ do_wait_cpu_initialized, NULL);
+ }
}
void arch_thaw_secondary_cpus_begin(void)
switch_to_new_gdt(me);
/* already set me in cpu_online_mask in boot_cpu_init() */
cpumask_set_cpu(me, cpu_callout_mask);
+ cpumask_set_cpu(me, cpu_finishup_mask);
cpu_set_state_online(me);
native_pv_lock_init();
}
{
set_cpu_online(cpu, false);
cpumask_clear_cpu(cpu, cpu_callout_mask);
+ cpumask_clear_cpu(cpu, cpu_finishup_mask);
cpumask_clear_cpu(cpu, cpu_callin_mask);
/* was set by cpu_init() */
cpumask_clear_cpu(cpu, cpu_initialized_mask);