294 /*
295 * If the CPU has support for VME, turn it on.
296 */
297 testl $CPUID_VME, R(cpu_feature)
298 jz 1f
299 movl %cr4, %eax
300 orl $CR4_VME, %eax
301 movl %eax, %cr4
302 1:
如果cpu支持VME,则将cr4寄存器的CR4_VME(0)比特设置为1。
312 movl R(IdlePTD), %eax
313 movl %eax,%cr3 /* load ptd addr into mmu */
将IdlePTD(0x101e000)写入cr3寄存器。
315 movl %cr0,%eax /* get control word */
316 orl $CR0_PE|CR0_PG,%eax /* enable paging */
317 movl %eax,%cr0 /* and let's page NOW! */
318
319 pushl $begin /* jump to high virtualized address */
320 ret
设置cr0寄存器中的CR0_PE(打开保护模式)和CR0_PG(打开调页机制)标志,启动
调页机制。此后程序中使用的就是虚拟地址了。此处通过将begin符号所代表的虚拟
地址压栈再立即返回的形式跳转到虚拟地址begin处(0xc0458a99)。
322 /* now running relocated at KERNBASE where the system is linked to run */
323 begin:
324 /* set up bootstrap stack */
325 movl proc0kstack,%eax /* location of in-kernel stack */
326 /* bootstrap stack end location */
327 leal (KSTACK_PAGES*PAGE_SIZE-PCB_SIZE)(%eax),%esp
328
329 xorl %ebp,%ebp /* mark end of frames */
330
331 #ifdef PAE
332 movl IdlePDPT,%esi
333 #else
334 movl IdlePTD,%esi
335 #endif
336 movl %esi,(KSTACK_PAGES*PAGE_SIZE-PCB_SIZE+PCB_CR3)(%eax)
337
338 pushl physfree /* value of first for init386(first) */
339 call init386 /* wire 386 chip for unix operation */
325行将内核栈起始地址proc0kstack(0xc101f000)写入eax,内核栈共有两个页面,
8192字节,pcb结构体的尺寸是624字节,从这两个页面的顶端去掉624字节之后,
将esp指向向下增长的起始位置(proc0kstack+(8192-624)),即0xc1020d90。
329行将ebp清0。334行将IdlePTD(0x101e000)写入esi。将esi的内容(IdlePTD所表示的
页表目录页面的物理地址)写入内核栈中的pcb结构体中的pcb_cr3字段。
physfree目前指向的是0x01028000,这是之前分配完SMPptpa之后的位置。此处将其压栈,
作为入参first调用init386函数。
