我是在处理一个网卡中断分发问题时看的这些内容,因为是外部中断到处理器的分发问题,因此我关注的重点是I/O APIC和外部设备中断,所以下面这部分内容以及接下来的两篇文章都是从手册里挑着看的。
全文来自Intel开发者手册:Intel? 64 and IA-32 Architectures Software Developer’s Manual Volume 3A System Programming Guide.pdf
注意:下文中已经指出手册中的对应页面和章节,请对照手册原文看,任何个人理解错误,请包涵。
一,以下内容来自(P459):CHAPTER 10 ADVANCED PROGRAMMABLE INTERRUPT CONTROLLER (APIC)
local APIC(后续简写为lapic)为处理器主要做两个事情:
1,接收来自内部(具体见后面的中断源介绍)或外部(比如I/O APIC或其它中断控制器)的中断,并把它们发送给cpu核心进行处理。
2,在多处理器系统(multiple processor (MP) systems)上,lapic用于发送和接收处理器间中断(即interprocessor
interrupt (IPI))信息。IPI可用于把中断分发到系统的多个处理器上,或执行一些系统级的功能。
I/O APIC(后续简写为io apic)属于Intel系统芯片组的一部分,它和外部I/O设备相连并把这些设备的I/O请求作为中断信息转达给lapic。在多处理器系统上,io apic可以将外部中断分发到某个或某组选定的处理器的lapic。
本章仅描述lapic的内容,关于io apic,请见参考1。
二,以下内容来自(P459):10.1 LOCAL AND I/O APIC OVERVIEW
每一个lapic都由一系列的APIC寄存器以及相关硬件组成,它们用于控制中断的投递和IPI信息的产生。APIC寄存器可以通过mov指令进行读/写操作。
lapic可接收以下来源的中断:
1,本地连接的I/O设备(Locally connected I/O devices):这些I/O设备要么直接连接到处理器的本地中断引脚(即LINT0和LINT1),要么是和与处理器的某个本地中断引脚相连的8259类型中断控制器相连。
2,外部连接的I/O设备(Externally connected I/O devices):这些I/O设备与io apic相连,因此设备中断通过io apic投递到一个或多个处理器进行处理。
3,IPI中断(Inter-processor interrupts (IPIs)):Intel 64或IA-32架构上的处理器可使用IPI机制通知系统总线上的另外一个或一组处理器,因此IPI可用来实现软件自我中断(software self-interrupts)、中断转发或抢占式调度。
4,APIC定时器产生中断(APIC timer generated interrupts):通过对lapic定时器进行编程,可以实现在指定时间到达时,向其关联的处理器发送一个本地中断。
5,性能监视计数器中断(Performance monitoring counter interrupts):P6、奔四和至强的处理器提供可在性能监视计数器溢出时,向其关联的处理器发送一个中断的能力。
6,热传感器中断(Thermal Sensor interrupts):奔四和至强的处理器提供可在触发热传感器时,向其关联的处理器发送一个中断的能力。
7,APIC内部错误中断(APIC internal error interrupts):可对APIC进行编程,当lapic内发生一个错误(比如尝试访问尚未实现的寄存器)时,向其关联的处理器发送一个中断。
上面所列中的1、4、5、6、7均被称为本地中断源(local interrupt sources)。当从本地中断源接收到一个中断时,lapic按照APIC的LVT(local vector table)寄存器设置的中断投递协议(interrupt delivery protocol)进行投递。LVT为每一个本地中断源都准备了一个单独的LVT条目,因此可以设置各自不同的特定投递协议。举个例子,如果引脚LINT1准备用来作为NMI中断源,那么LVT中对应LINT1的条目需设置中断向量号为2(即NMI中断)。
通过对lapic的ICR(interrupt command register)寄存器进行编程可使对应处理器产生IPI中断。对ICR进行写操作,就会导致产生一个IPI信息并发送到系统总线(system bus,奔四和至强)或APIC总线(APIC bus,奔腾和P6)。IPI可以被发送到系统的其它处理器或发送给自身(即self-interrupts)。
lapic同样接收来自外部连接设备的中断,这些中断通过io apic进行转交,即由io apic接收系统硬件和I/O设备产生的中断,并把它们作为中断信息转发给lapic。
可以对io apic的引脚进行单独编程,以实现当对应引脚被置位时产生某个特定的中断向量。io apic还有一个虚拟线模式(virtual wire mode)允许它与标准的8259A型外部中断控制器进行通信。由于lapic可以被关闭,因此处理器可以直接接收到8259A型中断控制器的中断。
lapic和io apic都是为多处理器系统而设计的,lapic处理来之io apic的中断,或来之其它处理器的IPI中断,或自身产生的中断。虽然中断同样可以通过本地中断引脚(local interrupt pins)投递到单独的处理器,但这种机制在多处理器系统上并不常用。
在多处理器系统上,IPI机制的典型应用是用来发送固定的中断(即特定向量号的中断)和为了特定的目的而中断系统总线上的处理器。举个例子,lapic可以使用IPI来转发某些固定的中断到其它处理器进行服务。特定目的的IPI(例如NMI、INIT、SMI和SIPI)允许系统总线上的一个或多个处理器执行系统级的启动和控制功能。
三,以下内容来自(P463):10.2 SYSTEM BUS VS. APIC BUS
在P6和奔腾处理器上,io apic和lapic通过3线APIC间总线(3-wire inter-APIC bus)进行通信。lapic同样也使用APIC总线进行IPI的发送与接收。APIC总线和APIC总线信息对软件来说是不可视的,并且没有规划架构。(应该是指lapic还只是属于Intel 82489DX外部APIC架构的一部分,而没有独立划分为一个架构)
而在奔四和至强处理器上,io apic和lapic通过系统总线进行通信,统一为xAPIC架构。io apic通过Intel芯片组的网桥硬件产生发往lapic的中断信息向系统上的处理器发送中断请求。lapic之间的IPI信息通过系统总线直接传送。
四,以下内容来自(P463):10.3 THE INTEL? 82489DX EXTERNAL APIC, THE APIC, THE XAPIC, AND THE X2APIC
在P6和早期奔腾处理器上,lapic只是属于Intel 82489DX外部APIC架构的一部分,而在奔四和至强处理器上,APIC架构得到了进一步的扩展而被称为xAPIC。APIC与xAPIC两种架构之间最大的不同在于xAPIC架构里lapic与io apic通过系统总线进行通信,而在APIC架构里,它们通过APIC总线通信。另外,APIC架构里的部分特征在xAPIC里得到了扩展或修改。
xAPIC的基本操作模式为xAPIC模式。xAPIC架构的进一步扩展为x2APIC架构,主要是提升了处理器寻址能力(processor address ability)。x2APIC架构提供向后兼容(即兼容xAPIC)和向前扩展(即未来Intel新平台)的能力。
五,以下内容来自(P470):10.4.6 Local APIC ID
在通电启动后,系统硬件就会为系统总线或APIC总线上的每一个lapic分配一个唯一的APIC ID号,而该APIC ID号是基于系统拓扑结构和SOCKET位置编码以及簇聚特征进行分配的。在多处理器系统上,lapic的ID号也被BIOS和OS用作处理器ID号。某些处理器允许软件修改APIC ID号,但具体怎么修改依赖于具体的处理器型号,正因为如此,OS软件应该避免去修改lapic ID寄存器。
在P6和奔腾处理器上,lapic的ID号只占4bit,可以用0x0-0xe表示APIC总线上的15个不同处理器。在奔四和至强处理器上,xAPIC将ID号扩展到8bit,因此可以表示最多255个不同的处理器。x2APIC将ID号扩展到32bit,其低8bit用于兼容xAPIC的ID号。
六,以下内容来自(P473):10.4.8 Local APIC Version Register
lapic有一个硬连线版本寄存器(hardwired version register),软件可以通过这个寄存器识别APIC版本。另外,这个寄存器还指定了LVT中的具体条目个数。
三个重要字段:
version(8bit):lapic的版本号。0x1x(前面的0x表示是16禁止,而第二个x表示任意数字)为Local APIC,比如奔四和至强处理器,则是0x14;0x0x为82489DX外部APIC。
Max LVT Entry(8bit):具体LVT条目个数减1。奔四和至强处理器,该值为5;P6处理器为4;奔腾处理器为3。
Suppress EOI-broadcasts(1bit):表示是否可通过软件置位伪中断向量寄存器(Spurious Interrupt Vector Register)第12bit的方式阻止EOI消息的广播。
七,以下内容来自(P474):10.5 HANDLING LOCAL INTERRUPTS
这一章主要描述lapic所提供的处理本地中断的能力,因为当前我不关注一块,所以暂且略过。如果是关注LVT时钟寄存器、温度监控寄存器、性能计数寄存器、LINT0寄存器、LINT1寄存器等,可以仔细看这一章内容。
八,以下内容来自(P484):10.6 ISSUING INTERPROCESSOR INTERRUPTS
这一章主要描述lapic所提供的通过软件方式触发IPI中断的能力,主要也就是ICR寄存器(interrupt command register)。
ICR寄存器有如下功能:
1,发送一个中断到另外一个处理器。
2,允许处理器转发一个它已收到但尚未处理的中断到另外一个处理器进行服务。
3,处理器发送一个中断给自己(self interrupt)。
4,传送特定的IPI(比如SIPI,即start-up IPI)到另外的处理器。
通过ICR寄存器产生的中断通过系统总线或APIC总线进行传送。处理器发送最低优先IPI(lowest priority IPI)的能力是与特定型号相关的,因此BIOS和OS软件需避免使用它。
九,以下内容来自(P490):10.6.2 Determining IPI Destination
IPI中断的接收者目标可以是系统总线上一个、一组或全部处理器。IPI的发送者通过如下APIC寄存器和寄存器内字段来指定中断接收者。
1,ICR寄存器:使用如下寄存器字段来指定IPI接收者。
Destination Mode:目标模式:选择目标模式,可以是physical或logical。
Destination Field:目标字段:如果是physical目标模式,那么该字段用于指定目标处理器的APIC ID号。如果是logical目标模式,那么该字段用于指定MDA(message destination address),而MDA被用来指定cluster聚类里的某一个或多个处理器。
Destination Shorthand:目标快速记法:用来指定全部处理器、除自己以外的全部处理器或自己这三种情况之一的简便快速方法。
Delivery mode, Lowest Priority:投递模式,最低优先:一种与具体架构相关的最低优先仲裁机制,用于在指定的一组处理器里选择一个目标处理器。因为这种机制与具体的CPU架构相关,因此应该避免在BIOS和OS里使用它。
2,Local destination register (LDR):配合logical目标模式中的MDA一起使用,用于选择目标处理器。
3,Destination format register (DFR):配合logical目标模式中的MDA一起使用,用于选择目标处理器。
十,以下内容来自(P491):10.6.2.1 Physical Destination Mode
在physical目标模式下,通过指定lapic ID号来选择目标处理器。对于奔四和至强处理器而言,这既可以是单一目标(lapic ID从00H到FEH),也可以是广播到所有APIC(lapic ID为FFH)。
MDA的28-31bit位为1的广播IPI(应该是接着上一句说的,即在奔四和至强处理器上,0FH不是广播地址,所以这里才说不被支持,后面会提到0FH是P6和奔腾处理器上的广播地址)或被初始化为最低优先投递模式的I/O子系统不被physical目标模式支持,所以软件(这个软件应该设置BIOS或OS)不能做这样的配置。对于任何非广播IPI或被初始化为最低优先投递模式的I/O子系统,软件必须保证中断地址里的目标APIC存在并且可以接收中断。
对于P6和奔腾处理器而言,单一目标的lapic ID从0H到0EH,广播到所有APIC为0FH。
注意:系统总线上可寻址的lapic个数可能会受到硬件的限制。
十一,以下内容来自(P491):10.6.2.2 Logical Destination Mode
在logical目标模式下,通过一个存在于ICR寄存器目标字段里的8bit消息目标地址(message destination address,MDA)来指定IPI目标。当接收到一个通过logical目标模式投递的IPI消息时,lapic将拿消息里的MDA与其LDR和DFR寄存器进行比较,以确定是否需要接受并处理这个IPI。不管是logical目标模式,还是配合最低优先投递模式的logical目标模式,软件都必须负责保证所有的lapic都能够被寻址到(例如如果有超过8个CPU,那么软件就不能设置使用平坦模式,因为它最多只能寻找8个CPU)。
寄存器Logical Destination Register (LDR):
地址:0FEE0 00D0H
重置后值:0000 0000H
字段:
24:31:Logical APIC ID,逻辑APIC ID。这个逻辑ID(logical APIC ID)不要和本地ID(local APIC ID)搞混。
0:23:Reserved,保留。
寄存器destination format register (DFR):
地址:0FEE0 00E0H
重置后值:FFFF FFFFH
字段:
28:31:model,选择flat(1111B)或cluster(0000B)之一。
0:27:保留,全1。
MDA地址可以按两种模式进行解释:
Flat Model:平坦模式。
DFR寄存器的28-31bit为全1。在这种模式下,通过设置每一个lapic的LDR寄存器的逻辑APIC ID字段的不同bit位,最多可以给8个(因为逻辑APIC ID字段只有8bit位)不同的lapic建立各自不同的逻辑APIC ID号。这样之后,通过设置MDA中的一个或多个bit位,可选择一个或多个目标lapic。每一个lapic把它的逻辑APIC ID与MDA进行位与操作,如果为真,则表示是目标lapic,因此接受并处理IPI消息。通过设置MDA为全1,即为广播消息到所有lapic。
Cluster Model:聚类模式。
DFR寄存器的28-31bit为全0。这种模式又支持两种基本目标方案:平坦聚类(flat cluster)和分层聚类(hierarchical cluster)
平坦聚类仅被P6和奔腾处理器支持,使用这种模式的话,会假定所有APIC都通过APIC总线相连。MDA的bit60-63包含目标聚类的编码地址,而bit56-59则用于指定目标聚类里的目标lapic(因为只有4bit,所以最多4个lapic)。先比较MDA的bit60-63与LDR的bit28-31,判断当前lapic是否属于目标聚类;然后比较MDA的bit56-59与LDR的bit24-27,判断当前lapic是否属于目标聚类里的目标lapic;总共可以有15个聚类(地址从0到14),并且每个聚类可以有4个lapic。
对于P6和奔腾处理器的lapic而言,由于APIC仲裁ID只支持15个APIC代理(agent),因此在这种模式下,支持的处理器总数也就限制在15以内。通过设置目标bit位为全1即可达到广播到所有lapic的目的,因为它可以保证匹配所有聚类和选中每个聚类里的所有apic。最低优先投递模式下的广播IPI或I/O子系统广播中断不被聚类模式支持,因此软件不要做这样的配置。
分层聚类可以被奔四、至强以及P6和奔腾处理器使用。在这种模式下,通过不相关联的系统总线或APIC总线把各种不同的平坦聚类连接起来形成一个分层网络。这种模式需要每一个聚类都有一个聚类管理器,它负责对系统总线或APIC总线上的消息进行处理。一个聚类可以包含最多4个代理。15个聚类管理器,每一个聚类管理器有4个代理,那么整个分层网络可以最多有60个APIC代理。值得注意的是:分层APIC网络需要一个不属于lapic或io apic单元的特殊的聚类管理器设备(special cluster manager device)。
参考:
1,Intel? 82093AA I/O Advanced Programmable Interrupt Controller (I/O APIC) Datasheet
http://www.intel.com/design/chipsets/datashts/290566.htm
Intel? 82093AA I/O Advanced Programmable Interrupt Controller (I/O APIC) Specification Update
http://www.intel.com/design/chipsets/specupdt/290710.htm
2,MultiProcessor Specification(http://download.intel.com/design/pentium/datashts/24201606.pdf)
Version 1.4
May 1997