IA-32架构(开始于P6家族处理器)定义了一个多处理器(MP)初始化协议,称为多处理器规范版本1.4。该规范定义了IA-32处理器在多处理器系统中所使用的引导协议。(这里,多处理器被定义为两个或更多的处理器)。MP初始化协议具有以下重要特征:
1、它支持受控的多处理器的引导而不需要专用的系统硬件。
2、它允许硬件初始化一个系统的引导而不需要一个专用的信号或一个预定义的引导处理器。
3、它允许所有IA-32处理器以相同的方式被引导,包括那些支持Intel超线程技术的处理器。
4、MP初始化协议也应用于使用Intel 64处理器的MP系统。
执行MP初始化协议的机制依赖于IA-32处理器家族而有所不同:
1、对于P6家族处理器——BSP和AP(见8.4.1小节)的选择通过APIC总线上的总裁,使用BIPI和FIPI消息被处理。见附录C“为P6家族处理器的MP初始化”。
2、家族、模型和步进ID达到F09H的Intel至强处理器——BSP和AP(见8.4.1小节)的选择通过系统总线上的总裁,使用BIPI和FIPI消息被处理。(见8.4.3小节)
3、家族、模型和步进ID为F0AH及以上,6E0H及以上,6F0H及以上的Intel至强处理器——BSP和AP(见8.4.1小节)的选择通过一个特殊的系统总线周期,而不需要BIPI和FIPI消息总裁而被处理。(见8.4.3小节)
8.4.1 BSP和AP处理器
MP初始化协议定义了两类处理器:引导序列处理器(Bootstrap Processor——BSP)以及应用处理器(Application Processor——AP)。在一个MP系统的一次上电或RESET之后,系统硬件动态地选择系统总线上的其中一个处理器作为BSP。剩下的处理器被指派为AP。
作为BSP选择机制的一部分,BSP标志在BSP的IA32_APIC_BASE MSR中被置1(见图10-5),指示它是BSP。该标志为所有其它处理器清0。
BSP运行BIOS的引导序列(boot-strap)代码来配置APIC环境,设置系统宽度的数据结构,并启动和初始化AP(译者注:复数)。当BSP和AP被初始化时,BSP然后开始执行操作系统初始化代码。
在一次上电或复位之后,AP完成一次最小的自我配置,然后等待一个来自BSP处理器的启动信号(一条SIPI消息)。当接收到一条SIPI消息之后,一个AP执行BIOS配置代码,而这以AP被设置在中止(halt)状态而结束。
对于支持Intel超线程技术的Intel 64和IA-32处理器,MP初始化协议将系统总线或相干的连接域上的每个逻辑处理器对待为一个独立的处理器(带有一个独立的APIC ID)。在启动期间,一个逻辑处理器被选择为BSP,而剩下的逻辑处理器被指派为AP。
8.4.2 MP初始化协议要求和限制
MP初始化协议采用以下对系统的要求和限制:
1、MP协议仅在一次上电或复位之后被执行。如果MP协议已被完成,并且一个BSP被选,那么后面的INIT(译者注:复数)(要么对一个特定的处理器宽度,要么是系统宽度)并不致使MP被重复执行。而是,每个逻辑处理器检查自己的BSP标志,以确定它是否应该执行BIOS引导序列代码(如果它是BSP)还是进入一个等待SIPI状态(如果它是一个AP)。
2、能够把中断传递给处理器的系统中的所有设备必须在MP协议执行期间被禁止这么做。在中断必须被禁止的时间周期包括,在BSP发布一条INIT-SIPI-SIPI序列给一个AP时,和AP响应序列中最后一条SIPI时两者之间。
8.4.3 为Intel至强处理器的MP初始化协议算法
在一个MP系统的上电或复位后,系统中的处理器(译者注:复数)执行MP初始化协议算法,来初始化系统总线上或相干连接域上的每个逻辑处理器。在执行此算法的过程中,下列引导和初始化操作被执行。
1、每个逻辑处理器被分派一个唯一的APIC ID,基于系统拓扑。此唯一的ID是一个32位值,如果处理器支持CPUID分枝0BH;否则的话,为一个8位的值。(见8.4.5小节)此ID被写入到每个处理器的本地APIC ID寄存器中。
2、每个逻辑处理器基于其APIC ID被分派一个唯一的仲裁优先级。
3、每个逻辑处理器与总线上的其它逻辑处理器同时执行其内部的BIST。
4、基于BIST的完成,逻辑处理器(译者注:复数)使用一个硬件定义的选择机制来从系统总线上可用的逻辑处理器选择BSP和AP。BSP选择机制依赖于处理器的家族、模型、以及步进ID会有所不同,这些不同点如下:
——F0AH或以上的家族、模型和步进ID:
(1)逻辑处理器开始监视BNR#信号,该信号在不停地切换(译者注:由1到0;0到1)。当BNR#引脚停止切换,每个处理器试图在总线上发布一个NOP特殊周期。
(2)带有最高仲裁优先级的逻辑处理器成功发布一个NOP特殊周期,并且被提名为BSP。该处理器在其IA32_APIC_BASE MSR中置1BSP标志。然后取并开始执行BIOS引导序列代码,此代码起始于复位向量(物理地址为FFFF_FFF0H)
(3)剩余的逻辑处理器(发布一个NOP特殊周期失败的那些)被指派为AP。它们保留自己的BSP标志为清0状态,并进入一个“等待一个SIPI状态”。
——达到F09H的家族、模型和步进ID:
(1)每个处理器对自己以及所有其它处理器广播一条BIPI。广播一条BIPI(并从而接受到自己的BIPI向量)的第一个处理器,将自己选择作为BSP,并在其IA32_APIC_BASE MSR中置1BSP标志(见附录C.1)
(2)剩余的处理器(没有被选作为BSP的那些)被指派为AP。它们保留自己的BSP标志为清0状态,并进入一个“等待一个SIPI状态”。
(3)新建立的BSP对自己以及所有其它处理器广播一条FIPI消息,BSP和AP将此消息对待为MP初始化信号的一个结束。只有BSP标志置1的处理器响应FIPI消息,它通过取并执行BIOS引导序列代码,起始于复位向量(物理地址FFFF FFF0H),进行响应。
5、作为引导序列代码的一部分,BSP创建一个ACPI表和一个MP表,并将其初始的APIC ID适当地添加到这些表中。
6、在引导序列过程结束时,BSP将一个处理器计数器设置为1,然后对系统中的所有AP广播一条SIPI消息。这里,此SIPI消息含有一个对BIOS AP初始化代码的向量(在000VV000H上,VV是在SIPI中所包含的向量)。
7、AP初始化代码的第一个动作是对一个BIOS初始化信号量建立一个竞争(在AP之间)。第一个得到信号量的AP开始执行初始化代码(见8.4.4小节。)作为AP初始化过程的一部分,AP将其APIC ID号适当地添加到ACPI以及MP表并将处理器计数器加1。在初始化过程完成时,AP执行一条CLI指令,并将自己中止。
8、当每个AP获得了对信号量的访问,并执行初始化代码时,BSP为连接到系统总线上的处理器的个数建立一个计数器,完成执行BIOS引导序列代码,并然后开始执行操作系统引导序列代码和启动代码。
9、当BSP正在执行操作系统引导序列代码和启动代码时,AP仍然处于中止状态。在这种状态下,它们仅响应于INITS、NMI、以及SMI。它们也将响应于窥探(snoops)和STPCLK#引脚的断言。
8.4.4 MP初始化例子
以下例子阐明了用于在BSP和AP已被建立之后,在一个MP系统中初始化处理器的MP初始化协议的使用。这些代码运行在使用一个协议的Intel 64和IA-32处理器上。这包括了P6家族处理器、奔腾4处理器、Intel酷睿Duo、Intel酷睿2Duo以及Intel至强处理器。
下列常量和数据定义伴随着代码例子所使用。它们基于表10-1中所定义的APIC寄存器的地址。
ICR_LOW EQU 0FEE00300H
SVR EQU 0FEE000F0H
APIC_ID EQU 0FEE00020H
LVT3 EQU 0FEE00370H
APIC_ENABLED EQU 0100H
BOOT_ID DD?
COUNT EQU 00H
VACANT EQU 00H
8.4.4.1 典型的BSP初始化序列
当BSP和AP已被选择(通过一个硬件协议,见8.4.3小节)之后,BSP在正常的IA-32架构的起始地址(FFFF_FFF0H)开始执行引导序列代码(POST)。引导序列代码典型地执行下列操作:
1、初始化存储器
2、将微代码更新加载到处理器中
3、初始化MTRR(译者注:复数)
4、允许Cache
5、用寄存器EAX中的0H值执行CPUID指令,然后读EBX、ECX、和EDX寄存器以确定BSP是否为“GenuineIntel”。
6、用EAX中的1H值执行CPUID指令,然后将EAX、ECX、和EDX寄存器的值保存在RAM中的一个系统配置空间中稍候使用。
7、为AP加载启动代码到更小的1MB存储器中的一个4KB页中执行。
8、切换到保护模式,并确保APIC地址空间被映射到强非可被Cache的(UC)存储器类型。
9、确定来自本地APIC寄存器(默认为0)的BSP的APIC ID,下面的代码片断是一个例子,应用于一个系统中的逻辑处理器,其本地APIC单元操作在xAPIC模式下,在此模式下,APIC寄存器使用存储器映射接口被访问:
MOV ESI, APIC_ID; 本地APIC ID寄存器的地址
MOV EAX, [ESI];
AND EAX, 0FF000000H; 除了APIC ID,其它位全清0
MOV BOOT_ID, EAX; 保存在存储器中
将APIC ID保存在ACPI和MP表中,以及可选地保存在RAM中的系统配置空间中。
10、将为AP引导代码的4KB页的基地址转为8位向量。此8位向量 定义了实地址模式地址空间(1MB空间)中的一个4KB页的地址。例如,一个0BDH向量指定了一个000BD000H启动存储器地址。
11、通过置1APIC伪向量寄存器(SVR)的比特8来允许本地APIC。
MOV ESI, SVR; SVR的地址
MOV EAX, [ESI];
OR EAX, APIC_ENABLED; 置1比特8来允许(复位后为0)
MOV [ESI], EAX;
12、通过为APIC错误处理建立一个8位向量来设置LVT错误处理入口。
MOV ESI, LVT3;
MOV EAX, [ESI];
AND EAX, FFFFFF00H; 清除先前的向量
OR EAX, 000000xxH; xx是APIC错误处理的8位向量
MOV [ESI], EAX;
13、将锁信号量变量VACANT初始化为00H。AP(译者注:复数)使用此信号量来判定它们执行BIOS AP初始化代码的次序。
14、执行下列操作来设置BSP来探测系统中存在的AP以及处理器的个数:
——设置COUNT变量的置为1
——启动一个定时器(设置一个合适的100毫秒的间隔)。在AP BIOS初始化代码中,AP将递增COUNT变量以指示其存在。当定时器到期时,BSP检查COIUNT变量的值。如果定时器到期,并且COUNT变量没有被递增,那么没有AP存在或有错误发生。
15、对AP广播一条 INIT-SIPI-SIPI IPI序列,以唤醒它们,并对它们初始化:
MOV ESI, ICR_LOW; 加载ICR低双字的地址到ESI
MOV EAX, 000C4500H; 加载为广播INIT IPI的ICR编码到所有AP的EAX中
MOV [ESI], EAX; 对所有的AP广播INIT IPI
; 10毫秒延迟循环
MOV EAX, 000C46XXH; 加载为广播SIPI IP的IC编码到所有AP的EAX中,这里xx是在步骤10中计算出的向量
MOV [ESI], EAX; 对所有的AP广播SIPI IPI
; 200毫秒延迟循环
MOV [ESI], EAX; 对所有AP广播第二条SIPI IPI
; 200毫秒延迟循环
步骤 15:
MOV EAX, 000C46XXH; 从广播SIPI IP加载ICR编码到所有AP的EAX中,这里xx是在步骤8中计算得到的向量
16、等待定时器中断
17、读并计算COUNT变量的值,并建立一个处理器计数器
18、如果有必要的话,重新配置APIC并以剩余的系统诊断适当地继续进行
8.4.4.2 典型的AP初始化序列
当一个AP接收到一条SIPI时,它开始执行在SIPI中被编码的向量处的BIOS AP初始化代码。AP初始化代码一般执行下列操作:
1、等待BIOS初始化锁信号量。当信号量的控制被获得时,初始化继续。
2、将微代码更新加载到处理器中。
3、初始化MTRR(使用用于BSP的相同映射)
4、允许Cache
5、用EAX寄存器中的一个0H值执行CPUID指令,然后读EBX、ECX和EDX寄存器来判定AP是否为“GenuineIntel”。
6、用EAX寄存器中的一个1H值执行CPUID指令,然后将EAX、ECX和EDX中的值保存在RAM中的一个系统配置空间中稍后使用。
7、切换到保护模式并确保APIC地址空间被映射到强不可cache的(UC)存储器类型。
8、从本地APIC ID寄存器确定AP的APIC ID,并将它添加到MP和ACPI表以及可选地,添加到RAM中的系统配置空间。
9、通过设置SVR寄存器中的比特8初始化并配置本地APIC,并为错误处理设置LVT3(错误LVT)(正如在8.4.4.1小节中步骤9和10所描述的)。
10、配置AP(译者注:复数)SMI执行环境。(每个AP以及前面所选出的BSP必须要有不同的SMBASE地址)
11、将COUNT变量递增1
12、释放信号量
13、执行CLI和HLT指令
14、等待一个INIT IPI。