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
This commit is contained in:
@@ -111,7 +111,6 @@ atomic_t init_deasserted;
|
||||
static void smp_callin(void)
|
||||
{
|
||||
int cpuid, phys_id;
|
||||
unsigned long timeout;
|
||||
|
||||
/*
|
||||
* If waken up by an INIT in an 82489DX configuration
|
||||
@@ -130,37 +129,6 @@ static void smp_callin(void)
|
||||
* (This works even if the APIC is not enabled.)
|
||||
*/
|
||||
phys_id = read_apic_id();
|
||||
if (cpumask_test_cpu(cpuid, cpu_callin_mask)) {
|
||||
panic("%s: phys CPU#%d, CPU#%d already present??\n", __func__,
|
||||
phys_id, cpuid);
|
||||
}
|
||||
pr_debug("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
|
||||
|
||||
/*
|
||||
* STARTUP IPIs are fragile beasts as they might sometimes
|
||||
* trigger some glue motherboard logic. Complete APIC bus
|
||||
* silence for 1 second, this overestimates the time the
|
||||
* boot CPU is spending to send the up to 2 STARTUP IPIs
|
||||
* by a factor of two. This should be enough.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Waiting 2s total for startup (udelay is not yet working)
|
||||
*/
|
||||
timeout = jiffies + 2*HZ;
|
||||
while (time_before(jiffies, timeout)) {
|
||||
/*
|
||||
* Has the boot CPU finished it's STARTUP sequence?
|
||||
*/
|
||||
if (cpumask_test_cpu(cpuid, cpu_callout_mask))
|
||||
break;
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
if (!time_before(jiffies, timeout)) {
|
||||
panic("%s: CPU%d started up but did not get a callout!\n",
|
||||
__func__, cpuid);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
unsigned long start_ip = real_mode_header->trampoline_start;
|
||||
|
||||
unsigned long boot_error = 0;
|
||||
int timeout;
|
||||
int cpu0_nmi_registered = 0;
|
||||
unsigned long timeout;
|
||||
|
||||
/* Just in case we booted with a single CPU. */
|
||||
alternatives_enable_smp();
|
||||
@@ -838,6 +806,15 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* AP might wait on cpu_callout_mask in cpu_init() with
|
||||
* cpu_initialized_mask set if previous attempt to online
|
||||
* it timed-out. Clear cpu_initialized_mask so that after
|
||||
* INIT/SIPI it could start with a clean state.
|
||||
*/
|
||||
cpumask_clear_cpu(cpu, cpu_initialized_mask);
|
||||
smp_mb();
|
||||
|
||||
/*
|
||||
* Wake up a CPU in difference cases:
|
||||
* - Use the method in the APIC driver if it's defined
|
||||
@@ -852,53 +829,38 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
|
||||
|
||||
if (!boot_error) {
|
||||
/*
|
||||
* allow APs to start initializing.
|
||||
* Wait 10s total for a response from AP
|
||||
*/
|
||||
pr_debug("Before Callout %d\n", cpu);
|
||||
cpumask_set_cpu(cpu, cpu_callout_mask);
|
||||
pr_debug("After Callout %d\n", cpu);
|
||||
|
||||
/*
|
||||
* Wait 5s total for a response
|
||||
*/
|
||||
for (timeout = 0; timeout < 50000; timeout++) {
|
||||
if (cpumask_test_cpu(cpu, cpu_callin_mask))
|
||||
break; /* It has booted */
|
||||
boot_error = -1;
|
||||
timeout = jiffies + 10*HZ;
|
||||
while (time_before(jiffies, timeout)) {
|
||||
if (cpumask_test_cpu(cpu, cpu_initialized_mask)) {
|
||||
/*
|
||||
* Tell AP to proceed with initialization
|
||||
*/
|
||||
cpumask_set_cpu(cpu, cpu_callout_mask);
|
||||
boot_error = 0;
|
||||
break;
|
||||
}
|
||||
udelay(100);
|
||||
schedule();
|
||||
}
|
||||
}
|
||||
|
||||
if (!boot_error) {
|
||||
/*
|
||||
* Wait till AP completes initial initialization
|
||||
*/
|
||||
while (!cpumask_test_cpu(cpu, cpu_callin_mask)) {
|
||||
/*
|
||||
* Allow other tasks to run while we wait for the
|
||||
* AP to come online. This also gives a chance
|
||||
* for the MTRR work(triggered by the AP coming online)
|
||||
* to be completed in the stop machine context.
|
||||
*/
|
||||
udelay(100);
|
||||
schedule();
|
||||
}
|
||||
|
||||
if (cpumask_test_cpu(cpu, cpu_callin_mask)) {
|
||||
print_cpu_msr(&cpu_data(cpu));
|
||||
pr_debug("CPU%d: has booted.\n", cpu);
|
||||
} else {
|
||||
boot_error = 1;
|
||||
if (*trampoline_status == 0xA5A5A5A5)
|
||||
/* trampoline started but...? */
|
||||
pr_err("CPU%d: Stuck ??\n", cpu);
|
||||
else
|
||||
/* trampoline code not run */
|
||||
pr_err("CPU%d: Not responding\n", cpu);
|
||||
if (apic->inquire_remote_apic)
|
||||
apic->inquire_remote_apic(apicid);
|
||||
}
|
||||
}
|
||||
|
||||
if (boot_error) {
|
||||
/* Try to put things back the way they were before ... */
|
||||
numa_remove_cpu(cpu); /* was set by numa_add_cpu */
|
||||
|
||||
/* was set by do_boot_cpu() */
|
||||
cpumask_clear_cpu(cpu, cpu_callout_mask);
|
||||
|
||||
/* was set by cpu_init() */
|
||||
cpumask_clear_cpu(cpu, cpu_initialized_mask);
|
||||
}
|
||||
|
||||
/* mark "stuck" area as not stuck */
|
||||
|
Reference in New Issue
Block a user