系统共设置了3个CPU,对应了一个BSP以及两个AP。系统设置如下图所示。
本章对应的代码是:ap_16.asm,用于对AP进行初始化。
ap_16.asm的代码被放在0x0001B000处,与bp_32.asm中的指令:mov DWORD [0xFEE00300],000C461BH 一致。该指令向所有AP广播Start-up消息,并指明AP的初始化代码从物理地址0x1B000开始。
ap_16.asm与mbr.asm类似,完成AP从实模式到32位保护模式的转变。
初始化AP对应的DS和SS段寄存器。
屏蔽NMI和8259可能产生的中断。特别是8259的中断,我们的外部中断都由IO APIC来产生,因此需要先屏蔽8259。
这里是使用了线程锁。由于下面需要对GDT进行操作,而两个AP几乎同时接收到Start-up消息并执行初始化代码,GDT有很大的几率被两个AP同时修改,造成写入错误。这里使用线程锁保证对GDT段的原子操作。
这里是将在BSP中已经设置好的GDT段再次写入AP的GDT寄存器,复用系统的代码段和数据段。
AP打开A20,设置CR0的PE位,AP进入保护模式。
初始化各段寄存器。栈指针指向0x0000A000页的末尾。
获取CPU的ID号,如果本CPU对应的ID号不为1,则栈指针指向0x00010000页的末尾。
下面要修改AP的GDT段对应的地址(映射到虚拟地址2G以上),设置线程锁。
将GDT的虚拟地址映射到从2G以上。
复用BSP已经设置好的页目录,BSP和两个AP都使用相同的内存映射空间。设置CR0的最高位,启动AP的页管理机制。
堆栈指针映射到虚拟地址的2G以上。
直接跳转到AP的32位保护模式代码的后半部分(0x8001C000)开始执行。
ap_16.asm的源代码地址:https://download.csdn.net/download/hanspruce_bird/87502147