diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-13 12:16:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-13 12:16:32 -0400 |
commit | 19e00d593e9a273ecbfbe131676ed11c140670ac (patch) | |
tree | 35198f6fc524976db5465e9bb57cd26c759b67e0 | |
parent | 197fe6b0e6843b6859c6a1436ff19e3c444c0502 (diff) | |
parent | eeeda4cd06e828b331b15741a204ff9f5874d28d (diff) |
Merge branch 'x86-boot-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 bootup updates from Ingo Molnar:
"The changes in this cycle were:
- Fix rare SMP-boot hang (mostly in virtual environments)
- Fix build warning with certain (rare) toolchains"
* 'x86-boot-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/relocs: Make per_cpu_load_addr static
x86/smpboot: Initialize secondary CPU only if master CPU will wait for it
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 29 | ||||
-rw-r--r-- | arch/x86/kernel/smpboot.c | 98 | ||||
-rw-r--r-- | arch/x86/tools/relocs.c | 2 | ||||
-rw-r--r-- | arch/x86/xen/smp.c | 2 |
4 files changed, 51 insertions, 80 deletions
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index c649f236e288..d8b1166c7888 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -1266,6 +1266,19 @@ static void dbg_restore_debug_regs(void) | |||
1266 | #define dbg_restore_debug_regs() | 1266 | #define dbg_restore_debug_regs() |
1267 | #endif /* ! CONFIG_KGDB */ | 1267 | #endif /* ! CONFIG_KGDB */ |
1268 | 1268 | ||
1269 | static void wait_for_master_cpu(int cpu) | ||
1270 | { | ||
1271 | #ifdef CONFIG_SMP | ||
1272 | /* | ||
1273 | * wait for ACK from master CPU before continuing | ||
1274 | * with AP initialization | ||
1275 | */ | ||
1276 | WARN_ON(cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)); | ||
1277 | while (!cpumask_test_cpu(cpu, cpu_callout_mask)) | ||
1278 | cpu_relax(); | ||
1279 | #endif | ||
1280 | } | ||
1281 | |||
1269 | /* | 1282 | /* |
1270 | * cpu_init() initializes state that is per-CPU. Some data is already | 1283 | * cpu_init() initializes state that is per-CPU. Some data is already |
1271 | * initialized (naturally) in the bootstrap process, such as the GDT | 1284 | * initialized (naturally) in the bootstrap process, such as the GDT |
@@ -1281,16 +1294,17 @@ void cpu_init(void) | |||
1281 | struct task_struct *me; | 1294 | struct task_struct *me; |
1282 | struct tss_struct *t; | 1295 | struct tss_struct *t; |
1283 | unsigned long v; | 1296 | unsigned long v; |
1284 | int cpu; | 1297 | int cpu = stack_smp_processor_id(); |
1285 | int i; | 1298 | int i; |
1286 | 1299 | ||
1300 | wait_for_master_cpu(cpu); | ||
1301 | |||
1287 | /* | 1302 | /* |
1288 | * Load microcode on this cpu if a valid microcode is available. | 1303 | * Load microcode on this cpu if a valid microcode is available. |
1289 | * This is early microcode loading procedure. | 1304 | * This is early microcode loading procedure. |
1290 | */ | 1305 | */ |
1291 | load_ucode_ap(); | 1306 | load_ucode_ap(); |
1292 | 1307 | ||
1293 | cpu = stack_smp_processor_id(); | ||
1294 | t = &per_cpu(init_tss, cpu); | 1308 | t = &per_cpu(init_tss, cpu); |
1295 | oist = &per_cpu(orig_ist, cpu); | 1309 | oist = &per_cpu(orig_ist, cpu); |
1296 | 1310 | ||
@@ -1302,9 +1316,6 @@ void cpu_init(void) | |||
1302 | 1316 | ||
1303 | me = current; | 1317 | me = current; |
1304 | 1318 | ||
1305 | if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)) | ||
1306 | panic("CPU#%d already initialized!\n", cpu); | ||
1307 | |||
1308 | pr_debug("Initializing CPU#%d\n", cpu); | 1319 | pr_debug("Initializing CPU#%d\n", cpu); |
1309 | 1320 | ||
1310 | clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); | 1321 | clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); |
@@ -1381,13 +1392,9 @@ void cpu_init(void) | |||
1381 | struct tss_struct *t = &per_cpu(init_tss, cpu); | 1392 | struct tss_struct *t = &per_cpu(init_tss, cpu); |
1382 | struct thread_struct *thread = &curr->thread; | 1393 | struct thread_struct *thread = &curr->thread; |
1383 | 1394 | ||
1384 | show_ucode_info_early(); | 1395 | wait_for_master_cpu(cpu); |
1385 | 1396 | ||
1386 | if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)) { | 1397 | show_ucode_info_early(); |
1387 | printk(KERN_WARNING "CPU#%d already initialized!\n", cpu); | ||
1388 | for (;;) | ||
1389 | local_irq_enable(); | ||
1390 | } | ||
1391 | 1398 | ||
1392 | printk(KERN_INFO "Initializing CPU#%d\n", cpu); | 1399 | printk(KERN_INFO "Initializing CPU#%d\n", cpu); |
1393 | 1400 | ||
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 9b1c0f8f68e6..1c3443d98105 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -111,7 +111,6 @@ atomic_t init_deasserted; | |||
111 | static void smp_callin(void) | 111 | static void smp_callin(void) |
112 | { | 112 | { |
113 | int cpuid, phys_id; | 113 | int cpuid, phys_id; |
114 | unsigned long timeout; | ||
115 | 114 | ||
116 | /* | 115 | /* |
117 | * If waken up by an INIT in an 82489DX configuration | 116 | * If waken up by an INIT in an 82489DX configuration |
@@ -130,37 +129,6 @@ static void smp_callin(void) | |||
130 | * (This works even if the APIC is not enabled.) | 129 | * (This works even if the APIC is not enabled.) |
131 | */ | 130 | */ |
132 | phys_id = read_apic_id(); | 131 | phys_id = read_apic_id(); |
133 | if (cpumask_test_cpu(cpuid, cpu_callin_mask)) { | ||
134 | panic("%s: phys CPU#%d, CPU#%d already present??\n", __func__, | ||
135 | phys_id, cpuid); | ||
136 | } | ||
137 | pr_debug("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id); | ||
138 | |||
139 | /* | ||
140 | * STARTUP IPIs are fragile beasts as they might sometimes | ||
141 | * trigger some glue motherboard logic. Complete APIC bus | ||
142 | * silence for 1 second, this overestimates the time the | ||
143 | * boot CPU is spending to send the up to 2 STARTUP IPIs | ||
144 | * by a factor of two. This should be enough. | ||
145 | */ | ||
146 | |||
147 | /* | ||
148 | * Waiting 2s total for startup (udelay is not yet working) | ||
149 | */ | ||
150 | timeout = jiffies + 2*HZ; | ||
151 | while (time_before(jiffies, timeout)) { | ||
152 | /* | ||
153 | * Has the boot CPU finished it's STARTUP sequence? | ||
154 | */ | ||
155 | if (cpumask_test_cpu(cpuid, cpu_callout_mask)) | ||
156 | break; | ||
157 | cpu_relax(); | ||
158 | } | ||
159 | |||
160 | if (!time_before(jiffies, timeout)) { | ||
161 | panic("%s: CPU%d started up but did not get a callout!\n", | ||
162 | __func__, cpuid); | ||
163 | } | ||
164 | 132 | ||
165 | /* | 133 | /* |
166 | * the boot CPU has finished the init stage and is spinning | 134 | * the boot CPU has finished the init stage and is spinning |
@@ -790,8 +758,8 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle) | |||
790 | unsigned long start_ip = real_mode_header->trampoline_start; | 758 | unsigned long start_ip = real_mode_header->trampoline_start; |
791 | 759 | ||
792 | unsigned long boot_error = 0; | 760 | unsigned long boot_error = 0; |
793 | int timeout; | ||
794 | int cpu0_nmi_registered = 0; | 761 | int cpu0_nmi_registered = 0; |
762 | unsigned long timeout; | ||
795 | 763 | ||
796 | /* Just in case we booted with a single CPU. */ | 764 | /* Just in case we booted with a single CPU. */ |
797 | alternatives_enable_smp(); | 765 | alternatives_enable_smp(); |
@@ -839,6 +807,15 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle) | |||
839 | } | 807 | } |
840 | 808 | ||
841 | /* | 809 | /* |
810 | * AP might wait on cpu_callout_mask in cpu_init() with | ||
811 | * cpu_initialized_mask set if previous attempt to online | ||
812 | * it timed-out. Clear cpu_initialized_mask so that after | ||
813 | * INIT/SIPI it could start with a clean state. | ||
814 | */ | ||
815 | cpumask_clear_cpu(cpu, cpu_initialized_mask); | ||
816 | smp_mb(); | ||
817 | |||
818 | /* | ||
842 | * Wake up a CPU in difference cases: | 819 | * Wake up a CPU in difference cases: |
843 | * - Use the method in the APIC driver if it's defined | 820 | * - Use the method in the APIC driver if it's defined |
844 | * Otherwise, | 821 | * Otherwise, |
@@ -852,53 +829,38 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle) | |||
852 | 829 | ||
853 | if (!boot_error) { | 830 | if (!boot_error) { |
854 | /* | 831 | /* |
855 | * allow APs to start initializing. | 832 | * Wait 10s total for a response from AP |
856 | */ | 833 | */ |
857 | pr_debug("Before Callout %d\n", cpu); | 834 | boot_error = -1; |
858 | cpumask_set_cpu(cpu, cpu_callout_mask); | 835 | timeout = jiffies + 10*HZ; |
859 | pr_debug("After Callout %d\n", cpu); | 836 | while (time_before(jiffies, timeout)) { |
837 | if (cpumask_test_cpu(cpu, cpu_initialized_mask)) { | ||
838 | /* | ||
839 | * Tell AP to proceed with initialization | ||
840 | */ | ||
841 | cpumask_set_cpu(cpu, cpu_callout_mask); | ||
842 | boot_error = 0; | ||
843 | break; | ||
844 | } | ||
845 | udelay(100); | ||
846 | schedule(); | ||
847 | } | ||
848 | } | ||
860 | 849 | ||
850 | if (!boot_error) { | ||
861 | /* | 851 | /* |
862 | * Wait 5s total for a response | 852 | * Wait till AP completes initial initialization |
863 | */ | 853 | */ |
864 | for (timeout = 0; timeout < 50000; timeout++) { | 854 | while (!cpumask_test_cpu(cpu, cpu_callin_mask)) { |
865 | if (cpumask_test_cpu(cpu, cpu_callin_mask)) | ||
866 | break; /* It has booted */ | ||
867 | udelay(100); | ||
868 | /* | 855 | /* |
869 | * Allow other tasks to run while we wait for the | 856 | * Allow other tasks to run while we wait for the |
870 | * AP to come online. This also gives a chance | 857 | * AP to come online. This also gives a chance |
871 | * for the MTRR work(triggered by the AP coming online) | 858 | * for the MTRR work(triggered by the AP coming online) |
872 | * to be completed in the stop machine context. | 859 | * to be completed in the stop machine context. |
873 | */ | 860 | */ |
861 | udelay(100); | ||
874 | schedule(); | 862 | schedule(); |
875 | } | 863 | } |
876 | |||
877 | if (cpumask_test_cpu(cpu, cpu_callin_mask)) { | ||
878 | print_cpu_msr(&cpu_data(cpu)); | ||
879 | pr_debug("CPU%d: has booted.\n", cpu); | ||
880 | } else { | ||
881 | boot_error = 1; | ||
882 | if (*trampoline_status == 0xA5A5A5A5) | ||
883 | /* trampoline started but...? */ | ||
884 | pr_err("CPU%d: Stuck ??\n", cpu); | ||
885 | else | ||
886 | /* trampoline code not run */ | ||
887 | pr_err("CPU%d: Not responding\n", cpu); | ||
888 | if (apic->inquire_remote_apic) | ||
889 | apic->inquire_remote_apic(apicid); | ||
890 | } | ||
891 | } | ||
892 | |||
893 | if (boot_error) { | ||
894 | /* Try to put things back the way they were before ... */ | ||
895 | numa_remove_cpu(cpu); /* was set by numa_add_cpu */ | ||
896 | |||
897 | /* was set by do_boot_cpu() */ | ||
898 | cpumask_clear_cpu(cpu, cpu_callout_mask); | ||
899 | |||
900 | /* was set by cpu_init() */ | ||
901 | cpumask_clear_cpu(cpu, cpu_initialized_mask); | ||
902 | } | 864 | } |
903 | 865 | ||
904 | /* mark "stuck" area as not stuck */ | 866 | /* mark "stuck" area as not stuck */ |
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c index bbb1d2259ecf..a5efb21d5228 100644 --- a/arch/x86/tools/relocs.c +++ b/arch/x86/tools/relocs.c | |||
@@ -695,7 +695,7 @@ static void walk_relocs(int (*process)(struct section *sec, Elf_Rel *rel, | |||
695 | * | 695 | * |
696 | */ | 696 | */ |
697 | static int per_cpu_shndx = -1; | 697 | static int per_cpu_shndx = -1; |
698 | Elf_Addr per_cpu_load_addr; | 698 | static Elf_Addr per_cpu_load_addr; |
699 | 699 | ||
700 | static void percpu_init(void) | 700 | static void percpu_init(void) |
701 | { | 701 | { |
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index c670d7518cf4..8650cdb53209 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c | |||
@@ -365,6 +365,8 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) | |||
365 | struct desc_struct *gdt; | 365 | struct desc_struct *gdt; |
366 | unsigned long gdt_mfn; | 366 | unsigned long gdt_mfn; |
367 | 367 | ||
368 | /* used to tell cpu_init() that it can proceed with initialization */ | ||
369 | cpumask_set_cpu(cpu, cpu_callout_mask); | ||
368 | if (cpumask_test_and_set_cpu(cpu, xen_cpu_initialized_map)) | 370 | if (cpumask_test_and_set_cpu(cpu, xen_cpu_initialized_map)) |
369 | return 0; | 371 | return 0; |
370 | 372 | ||