]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
parallel part 2
authorDavid Woodhouse <dwmw@amazon.co.uk>
Tue, 14 Dec 2021 19:58:54 +0000 (19:58 +0000)
committerDavid Woodhouse <dwmw@amazon.co.uk>
Sat, 4 Feb 2023 15:33:36 +0000 (15:33 +0000)
arch/x86/include/asm/cpumask.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/smpboot.c
arch/x86/xen/smp_pv.c

index c5aed9e9226c669fe03b67431ef01984a4d98002..3156b3d6f991378f310e927c9cc27b7382fe4f33 100644 (file)
@@ -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);
index cf1a4eff7a7658399098e585ca0843a5d3bee678..0f120047cfb5549635ad41ed0ed713e738916e35 100644 (file)
@@ -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
index f53a060a899b7854962b3ff25ff3aaad3b1ed41f..638dc63bc1d115bca6821e613aaa0f9de9a493b0 100644 (file)
@@ -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);
index 09f94f9406895fde453c73b69b8f23299d32ffea..c797c0ff4401f9296a9ef34969382d75a9abfbe0 100644 (file)
@@ -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;