You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#0do_boot_cpu (apicid=apicid@entry=1, cpu=cpu@entry=1, idle=idle@entry=0xff1100000570a040,
cpu0_nmi_registered=cpu0_nmi_registered@entry=0xffa0000000013d34) at linux/arch/x86/kernel/smpboot.c:1076
#10xffffffff81119bc0 in native_cpu_up (cpu=1, tidle=0xff1100000570a040) at linux/arch/x86/kernel/smpboot.c:1230
#20xffffffff811b1a18 in __cpu_up (tidle=0xff1100000570a040, cpu=1) at linux/arch/x86/include/asm/smp.h:83
#3bringup_cpu (cpu=1) at linux/kernel/cpu.c:608
#40xffffffff811b1ea1 in cpuhp_invoke_callback (cpu=cpu@entry=1, state=CPUHP_BRINGUP_CPU, bringup=bringup@entry=true,
node=node@entry=0x0 <fixed_percpu_data>, lastp=lastp@entry=0x0 <fixed_percpu_data>) at linux/kernel/cpu.c:192
#50xffffffff811b20c6 in __cpuhp_invoke_callback_range (bringup=bringup@entry=true, cpu=cpu@entry=1, st=st@entry=0xff1100007fb1b6e0,
target=target@entry=CPUHP_BRINGUP_CPU, nofail=nofail@entry=false) at linux/kernel/cpu.c:678
#60xffffffff811b2edf in cpuhp_invoke_callback_range (target=CPUHP_BRINGUP_CPU, st=0xff1100007fb1b6e0, cpu=1, bringup=true)
at linux/kernel/cpu.c:702
#7cpuhp_up_callbacks (target=CPUHP_BRINGUP_CPU, st=0xff1100007fb1b6e0, cpu=1) at linux/kernel/cpu.c:733
#8_cpu_up (cpu=cpu@entry=1, tasks_frozen=tasks_frozen@entry=0, target=CPUHP_BRINGUP_CPU, target@entry=CPUHP_ONLINE)
at linux/kernel/cpu.c:1411
#90xffffffff811b30e2 in cpu_up (target=CPUHP_ONLINE, cpu=1) at linux/kernel/cpu.c:1447
#10cpu_up (cpu=<optimized out>, target=CPUHP_ONLINE) at linux/kernel/cpu.c:1419
#110xffffffff811b36ff in bringup_nonboot_cpus (setup_max_cpus=8192) at linux/kernel/cpu.c:1513
#120xffffffff83eb2c16 in smp_init () at linux/kernel/smp.c:1112
#130xffffffff83e78bd2 in kernel_init_freeable () at linux/init/main.c:1629
#140xffffffff8209c2d6 in kernel_init (unused=<optimized out>) at linux/init/main.c:1526
#150xffffffff81002129 in ret_from_fork () at linux/arch/x86/entry/entry_64.S:308
#160x0000000000000000 in ?? ()
arch/x86/kernel/smpboot.c
/* * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad * (ie clustered apic addressing mode), this is a LOGICAL apic ID. * Returns zero if CPU booted OK, else error code from * ->wakeup_secondary_cpu.*/staticintdo_boot_cpu(int apicid, int cpu, structtask_struct *idle,
int *cpu0_nmi_registered)
{
/* start_ip had better be page-aligned! */unsignedlong start_ip = real_mode_header->trampoline_start;
unsignedlong boot_error = 0;
unsignedlong timeout;
#ifdef CONFIG_X86_64
/* If 64-bit wakeup method exists, use the 64-bit mode trampoline IP */if (apic->wakeup_secondary_cpu_64)
start_ip = real_mode_header->trampoline_start64;
#endif
idle->thread.sp = (unsignedlong)task_pt_regs(idle);
early_gdt_descr.address = (unsignedlong)get_cpu_gdt_rw(cpu);
initial_code = (unsignedlong)start_secondary;
initial_stack = idle->thread.sp;
...
/* * Wake up a CPU in difference cases: * - Use a method from the APIC driver if one defined, with wakeup * straight to 64-bit mode preferred over wakeup to RM. * Otherwise, * - Use an INIT boot APIC message for APs or NMI for BSP.*/if (apic->wakeup_secondary_cpu_64)
boot_error = apic->wakeup_secondary_cpu_64(apicid, start_ip);
elseif (apic->wakeup_secondary_cpu)
boot_error = apic->wakeup_secondary_cpu(apicid, start_ip);
else
boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid,
cpu0_nmi_registered);
...
return boot_error;
}
INIT-SIPI-SIPI 序列
staticintwakeup_secondary_cpu_via_init(int phys_apicid, unsignedlong start_eip)
{
unsignedlong send_status = 0, accept_status = 0;
int maxlvt, num_starts, j;
maxlvt = lapic_get_maxlvt();
/* * Be paranoid about clearing APIC errors.*/if (APIC_INTEGRATED(boot_cpu_apic_version)) {
if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */apic_write(APIC_ESR, 0);
apic_read(APIC_ESR);
}
pr_debug("Asserting INIT\n");
/* * Turn INIT on target chip*//* * Send IPI*/apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT,
phys_apicid);
pr_debug("Waiting for send to finish...\n");
send_status = safe_apic_wait_icr_idle();
udelay(init_udelay);
pr_debug("Deasserting INIT\n");
/* Target chip *//* Send IPI */apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid);
pr_debug("Waiting for send to finish...\n");
send_status = safe_apic_wait_icr_idle();
mb();
/* * Should we send STARTUP IPIs ? * * Determine this based on the APIC version. * If we don't have an integrated APIC, don't send the STARTUP IPIs.*/if (APIC_INTEGRATED(boot_cpu_apic_version))
num_starts = 2;
else
num_starts = 0;
/* * Run STARTUP IPI loop.*/pr_debug("#startup loops: %d\n", num_starts);
for (j = 1; j <= num_starts; j++) {
pr_debug("Sending STARTUP #%d\n", j);
if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */apic_write(APIC_ESR, 0);
apic_read(APIC_ESR);
pr_debug("After apic_write\n");
/* * STARTUP IPI*//* Target chip *//* Boot on the stack *//* Kick the second */apic_icr_write(APIC_DM_STARTUP | (start_eip >> 12),
phys_apicid);
/* * Give the other CPU some time to accept the IPI.*/if (init_udelay == 0)
udelay(10);
elseudelay(300);
pr_debug("Startup point 1\n");
pr_debug("Waiting for send to finish...\n");
send_status = safe_apic_wait_icr_idle();
/* * Give the other CPU some time to accept the IPI.*/if (init_udelay == 0)
udelay(10);
elseudelay(200);
if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */apic_write(APIC_ESR, 0);
accept_status = (apic_read(APIC_ESR) & 0xEF);
if (send_status || accept_status)
break;
}
pr_debug("After Startup\n");
if (send_status)
pr_err("APIC never delivered???\n");
if (accept_status)
pr_err("APIC delivery error (%lx)\n", accept_status);
return (send_status | accept_status);
}
...
/* * Wake up AP by INIT, INIT, STARTUP sequence. * * Instead of waiting for STARTUP after INITs, BSP will execute the BIOS * boot-strap code which is not a desired behavior for waking up BSP. To * void the boot-strap code, wake up CPU0 by NMI instead. * * This works to wake up soft offlined CPU0 only. If CPU0 is hard offlined * (i.e. physically hot removed and then hot added), NMI won't wake it up. * We'll change this code in the future to wake up hard offlined CPU0 if * real platform and request are available.*/staticintwakeup_cpu_via_init_nmi(int cpu, unsignedlong start_ip, int apicid,
int *cpu0_nmi_registered)
{
int id;
int boot_error;
preempt_disable();
/* * Wake up AP by INIT, INIT, STARTUP sequence.*/if (cpu) {
boot_error = wakeup_secondary_cpu_via_init(apicid, start_ip);
goto out;
}
/* * Wake up BSP by nmi. * * Register a NMI handler to help wake up CPU0.*/
boot_error = register_nmi_handler(NMI_LOCAL,
wakeup_cpu0_nmi, 0, "wake_cpu0");
if (!boot_error) {
enable_start_cpu0 = 1;
*cpu0_nmi_registered = 1;
id = apic->dest_mode_logical ? cpu0_logical_apicid : apicid;
boot_error = wakeup_secondary_cpu_via_nmi(id, start_ip);
}
out:
preempt_enable();
return boot_error;
}