]> 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>
Thu, 9 Feb 2023 13:01:55 +0000 (13:01 +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 3ec5182d9698951123d154a87817731f654ad850..016d2f23bb7dcfe431586bd98b44d74bc17608d3 100644 (file)
@@ -202,15 +202,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;
@@ -1243,7 +1248,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;
 }
 
 /*
@@ -1346,11 +1355,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)
@@ -1594,6 +1603,8 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
        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();
@@ -1622,6 +1633,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();
 }
@@ -1805,6 +1817,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;