From: David Woodhouse Date: Tue, 14 Dec 2021 19:58:54 +0000 (+0000) Subject: parallel part 2 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=5a3f1ac5adb28c7ff6f2c90c6146adc5dde489bb;p=users%2Fdwmw2%2Flinux.git parallel part 2 --- diff --git a/arch/x86/include/asm/cpumask.h b/arch/x86/include/asm/cpumask.h index c5aed9e9226c6..3156b3d6f9913 100644 --- a/arch/x86/include/asm/cpumask.h +++ b/arch/x86/include/asm/cpumask.h @@ -7,6 +7,7 @@ extern cpumask_var_t cpu_callin_mask; extern cpumask_var_t cpu_callout_mask; extern cpumask_var_t cpu_initialized_mask; +extern cpumask_var_t cpu_finishup_mask; extern cpumask_var_t cpu_sibling_setup_mask; extern void setup_cpu_local_masks(void); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index cf1a4eff7a765..0f120047cfb55 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -71,6 +71,7 @@ u32 elf_hwcap2 __read_mostly; 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; @@ -174,6 +175,7 @@ void __init setup_cpu_local_masks(void) 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); } @@ -2230,6 +2232,7 @@ void cpu_init(void) wait_for_master_cpu(cpu); + /* XXX: Make sure siblings don't call this at the same time */ ucode_cpu_init(cpu); #ifdef CONFIG_NUMA diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index f53a060a899b7..638dc63bc1d11 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -204,15 +204,20 @@ static void smp_callin(void) 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; @@ -1250,7 +1255,11 @@ static int do_wait_cpu_callin(unsigned int cpu) /* * 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; } /* @@ -1353,11 +1362,11 @@ int native_cpu_up(unsigned int cpu, struct task_struct *tidle) 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) @@ -1569,9 +1578,12 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) 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(); } @@ -1599,6 +1611,7 @@ void __init native_smp_prepare_boot_cpu(void) /* 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(); } @@ -1782,6 +1795,7 @@ static void remove_cpu_from_maps(int cpu) { 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); diff --git a/arch/x86/xen/smp_pv.c b/arch/x86/xen/smp_pv.c index 09f94f9406895..c797c0ff4401f 100644 --- a/arch/x86/xen/smp_pv.c +++ b/arch/x86/xen/smp_pv.c @@ -254,6 +254,7 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) /* used to tell cpu_init() that it can proceed with initialization */ cpumask_set_cpu(cpu, cpu_callout_mask); + cpumask_set_cpu(cpu, cpu_finishup_mask); if (cpumask_test_and_set_cpu(cpu, xen_cpu_initialized_map)) return 0;