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);
}
wait_for_master_cpu(cpu);
+ /* XXX: Make sure siblings don't call this at the same time */
ucode_cpu_init(cpu);
#ifdef CONFIG_NUMA
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;
/*
* 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;
}
/*
ret = do_cpu_up(cpu, tidle);
if (ret)
return ret;
- }
- ret = do_wait_cpu_initialized(cpu);
- if (ret)
- return ret;
+ ret = do_wait_cpu_initialized(cpu);
+ if (ret)
+ return ret;
+ }
ret = do_wait_cpu_callin(cpu);
if (ret)
cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT))
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);
+ }
snp_set_wakeup_secondary_cpu();
}
/* 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);