Head.s部分代码:
ENTRY(startup_32_smp)
cld
movl $(__BOOT_DS),%eax
movl %eax,%ds
movl %eax,%es
movl %eax,%fs
movl %eax,%gs
xorl %ebx,%ebx
incl %ebx
如果是AP的话,将bx设置为1
movl $swapper_pg_dir-__PAGE_OFFSET,%eax
movl %eax,%cr3 /* set the page table pointer.. */
movl %cr0,%eax
orl $0x80000000,%eax
movl %eax,%cr0 /* ..and set paging (PG) bit */
ljmp $__BOOT_CS,$1f /* Clear prefetch and normalize %eip */
启用分页,
lss stack_start,%esp
使esp执行fork创建的进程内核堆栈部分,以便后续跳转到start_secondary
#ifdef CONFIG_SMP
movb ready, %cl
movb $1, ready
cmpb $0,%cl
je 1f # the first CPU calls start_kernel
# all other CPUs call initialize_secondary
call initialize_secondary
jmp L6
1:
#endif /* CONFIG_SMP */
call start_kernel
如果是AP启动的话,就调用initialize_secondary函数。
void __devinit initialize_secondary(void)
{
/*
* We don't actually need to load the full TSS,
* basically just the stack pointer and the eip.
*/
asm volatile(
"movl %0,%%esp/n/t"
"jmp *%1"
:
:"r" (current->thread.esp),"r" (current->thread.eip));
}
设置堆栈为fork创建时的堆栈,ip为fork时的ip,这样就跳转的了start_secondary。
start_secondary函数中处理如下:
while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
rep_nop();
进行smp_commenced_mask判断,是否启动AP运行。smp_commenced_mask 在smp_init()中设置。
cpu_idle();
如果启动了,调用cpu_idle进行任务调度。