aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/smpboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/smpboot.c')
-rw-r--r--arch/x86/kernel/smpboot.c99
1 files changed, 68 insertions, 31 deletions
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index bc52fac39dd3..ae2fd975b782 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -111,6 +111,7 @@ atomic_t init_deasserted;
111static void smp_callin(void) 111static void smp_callin(void)
112{ 112{
113 int cpuid, phys_id; 113 int cpuid, phys_id;
114 unsigned long timeout;
114 115
115 /* 116 /*
116 * If waken up by an INIT in an 82489DX configuration 117 * If waken up by an INIT in an 82489DX configuration
@@ -129,6 +130,37 @@ static void smp_callin(void)
129 * (This works even if the APIC is not enabled.) 130 * (This works even if the APIC is not enabled.)
130 */ 131 */
131 phys_id = read_apic_id(); 132 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 }
132 164
133 /* 165 /*
134 * the boot CPU has finished the init stage and is spinning 166 * the boot CPU has finished the init stage and is spinning
@@ -718,8 +750,8 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
718 unsigned long start_ip = real_mode_header->trampoline_start; 750 unsigned long start_ip = real_mode_header->trampoline_start;
719 751
720 unsigned long boot_error = 0; 752 unsigned long boot_error = 0;
753 int timeout;
721 int cpu0_nmi_registered = 0; 754 int cpu0_nmi_registered = 0;
722 unsigned long timeout;
723 755
724 /* Just in case we booted with a single CPU. */ 756 /* Just in case we booted with a single CPU. */
725 alternatives_enable_smp(); 757 alternatives_enable_smp();
@@ -767,15 +799,6 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
767 } 799 }
768 800
769 /* 801 /*
770 * AP might wait on cpu_callout_mask in cpu_init() with
771 * cpu_initialized_mask set if previous attempt to online
772 * it timed-out. Clear cpu_initialized_mask so that after
773 * INIT/SIPI it could start with a clean state.
774 */
775 cpumask_clear_cpu(cpu, cpu_initialized_mask);
776 smp_mb();
777
778 /*
779 * Wake up a CPU in difference cases: 802 * Wake up a CPU in difference cases:
780 * - Use the method in the APIC driver if it's defined 803 * - Use the method in the APIC driver if it's defined
781 * Otherwise, 804 * Otherwise,
@@ -787,41 +810,55 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
787 boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid, 810 boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid,
788 &cpu0_nmi_registered); 811 &cpu0_nmi_registered);
789 812
790
791 if (!boot_error) { 813 if (!boot_error) {
792 /* 814 /*
793 * Wait 10s total for a response from AP 815 * allow APs to start initializing.
794 */ 816 */
795 boot_error = -1; 817 pr_debug("Before Callout %d\n", cpu);
796 timeout = jiffies + 10*HZ; 818 cpumask_set_cpu(cpu, cpu_callout_mask);
797 while (time_before(jiffies, timeout)) { 819 pr_debug("After Callout %d\n", cpu);
798 if (cpumask_test_cpu(cpu, cpu_initialized_mask)) {
799 /*
800 * Tell AP to proceed with initialization
801 */
802 cpumask_set_cpu(cpu, cpu_callout_mask);
803 boot_error = 0;
804 break;
805 }
806 udelay(100);
807 schedule();
808 }
809 }
810 820
811 if (!boot_error) {
812 /* 821 /*
813 * Wait till AP completes initial initialization 822 * Wait 5s total for a response
814 */ 823 */
815 while (!cpumask_test_cpu(cpu, cpu_callin_mask)) { 824 for (timeout = 0; timeout < 50000; timeout++) {
825 if (cpumask_test_cpu(cpu, cpu_callin_mask))
826 break; /* It has booted */
827 udelay(100);
816 /* 828 /*
817 * Allow other tasks to run while we wait for the 829 * Allow other tasks to run while we wait for the
818 * AP to come online. This also gives a chance 830 * AP to come online. This also gives a chance
819 * for the MTRR work(triggered by the AP coming online) 831 * for the MTRR work(triggered by the AP coming online)
820 * to be completed in the stop machine context. 832 * to be completed in the stop machine context.
821 */ 833 */
822 udelay(100);
823 schedule(); 834 schedule();
824 } 835 }
836
837 if (cpumask_test_cpu(cpu, cpu_callin_mask)) {
838 print_cpu_msr(&cpu_data(cpu));
839 pr_debug("CPU%d: has booted.\n", cpu);
840 } else {
841 boot_error = 1;
842 if (*trampoline_status == 0xA5A5A5A5)
843 /* trampoline started but...? */
844 pr_err("CPU%d: Stuck ??\n", cpu);
845 else
846 /* trampoline code not run */
847 pr_err("CPU%d: Not responding\n", cpu);
848 if (apic->inquire_remote_apic)
849 apic->inquire_remote_apic(apicid);
850 }
851 }
852
853 if (boot_error) {
854 /* Try to put things back the way they were before ... */
855 numa_remove_cpu(cpu); /* was set by numa_add_cpu */
856
857 /* was set by do_boot_cpu() */
858 cpumask_clear_cpu(cpu, cpu_callout_mask);
859
860 /* was set by cpu_init() */
861 cpumask_clear_cpu(cpu, cpu_initialized_mask);
825 } 862 }
826 863
827 /* mark "stuck" area as not stuck */ 864 /* mark "stuck" area as not stuck */