linux学习中
分类: LINUX
2014-04-08 10:53:05
6.3 x86处理器如何处理MSI-X中断请求
PCIe设备发出MSI-X中断请求的方法与发出MSI中断请求的方法类似,都是向Message Address所在的地址写Message Data字段包含的数据。只是MSI-X中断机制为了支持更多的中断请求,在MSI-X Capablity结构中存放了一个指向一组Message Address和 Message Data字段的指针,从而一个PCIe设备可以支持的MSI-X中断请求数目大于32个,而且并不要求中断向量号连续。MSI-X机制使用的这组Message Address和 Message Data字段存放在PCIe设备的BAR空间中,而不是在PCIe设备的配置空间中,从而可以由用户决定使用MSI-X中断请求的数目。
当系统软件初始化PCIe设备时,如果该PCIe设备使用MSI-X机制传递中断请求,需要对MSI-X Capability结构指向的Message Address和Message Data字段进行设置,并使能MSI-X Enable位。x86处理器在此处的实现与PowerPC处理器有较大的不同。
在x86处理器系统中,PCIe设备也是通过向Message Address写入Message Data指定的数值实现MSI/MSI-X机制。在x86处理器系统中,PCIe设备使用的Message Adress字段和Message Data字段与PowerPC处理器不同。
在x86处理器系统中,PCIe设备使用的Message Address字段仍然保存PCI总线域的地址,其格式如图6?7所示。
其中第31~20位,存放FSB Interrupts存储器空间的基地址,其值为0xFEE。当PCIe设备对0xFEEX-XXXX这段“PCI总线域”的地址空间进行写操作时,MCH/ICH将会首先进行“PCI总线域”到“存储器域”的地址转换,之后将这个写操作翻译为FSB总线的Interrupt Message总线事务,从而向CPU内核提交中断请求。
x86处理器使用FSB Interrupt Message总线事务转发MSI/MSI-X中断请求。使用这种方法的优点是向CPU内核提交中断请求的同时,提交PCIe设备使用的中断向量,从而CPU不需要使用中断响应周期从寄存器中获得中断向量。FSB Interrupt Message总线事务的详细说明见下文。
Message Address字段其他位的含义如下所示。
以上这些字段的描述与x86处理器使用的APIC中断控制器相关。对APIC的详细说明超出了本书的范围,对此部分感兴趣的读者请参阅Intel 64 and IA-32 Architectures Software Developer’s Manual Volume 3A: System Programming Guide, Part 1。
Message Data字段的格式如图6?8所示。
Trigger Mode字段为0b0x时,PCIe设备使用边沿触发方式申请中断;为0b10时使用低电平触发方式;为0b11时使用高电平触发方式。MSI/MSI-X中断请求使用边沿触发方式,但是FSB Interrupt Message总线事务还支持Legacy INTx中断请求方式,因此在Message Data字段中仍然支持电平触发方式。但是对于PCIe设备而言,该字段为0b0x。
Vector字段表示这个中断请求使用的中断向量。FSB Interrupt Message总线事务在提交中断请求的同时,将中断向量也通知给处理器。因此使用FSB Interrupt Message总线事务时,处理器不需要使用中断响应周期通过读取中断控制器获得中断向量号。与PowerPC的传统方式相比,x86处理器的这种中断请求的效率较高[①]。
值得注意的是,在x86处理器中,MSI机制使用的Message Data字段与MSI-X机制相同。但是当一个PCIe设备支持多个MSI中断请求时,其Message Data字段必须是连续的,因而其使用的Vector字段也必须是连续的,这也是在x86处理器系统中,PCIe设备支持多个MSI中断请求的问题所在,而使用MSI-X机制有效避免了该问题。
Delivery Mode字段表示如何处理来自PCIe设备的中断请求。
边沿触发和电平触发是中断请求常用的两种方式。其中电平触发指外部设备使用逻辑电平1(高电平触发)或者0(低电平触发),提交中断请求。使用电平或者边沿方式提交中断请求时,外部设备一般通过中断线(IRQ_PIN#)与中断控制器相连,其中多个外部设备可能通过相同的中断线与中断控制器相连(线与或者与门)。
外部设备在使用低电平触发,提交中断请求的过程中,首先需要将IRQ_PIN#信号驱动为低。当中断控制器将该中断请求提交给处理器,而且处理器将这个中断请求处理完毕后,处理器将通过写外部设备的某个寄存器来清除此中断源,此时外部设备将不再驱动IRQ_PIN#信号线,从而结束整个中断请求。
IRQ_PIN#信号线可以被多个外部设备共享,在这种情况之下,只有所有外部设备都不驱动IRQ_PIN#信号线时,IRQ_PIN#信号才为高电平。采用电平触发方式进行中断请求的优点是不会丢失中断请求,而缺点是一个优先权较高的中断请求有可能会长期占用中断资源,从而使其他优先权较低的中断不能被及时提交。因为优先级别较高的中断源有可能会持续不断地驱动IRQ_PIN#信号。
而边沿触发使用上升沿(0到1)或者下降沿(1到0)作为触发条件,但是中断控制器并不是使用这个“边沿”作为触发条件。中断控制器使用内部时钟对IRQ_PIN#信号进行采样,如果在前一个时钟周期,IRQ_PIN#信号为0,而后一个时钟周期,IRQ_PIN#信号为1,中断控制器认为外部设备提交了一个有效“上升沿”,中断控制器会锁定这个“上升沿”并向处理器发出中断请求。这也是外部设备至少需要将IRQ_PIN#信号保持一个时钟采样周期的原因,否则中断控制器可能无法识别本次边沿触发的中断请求,从而产生Spurious中断请求。
外部设备使用“上升沿”进行中断申请时,不需要持续地将IRQ_PIN#信号驱动为1,而只需要保证中断控制器可以进行正确采样这些中断信号即可。在处理边沿触发中断请求时,处理器不需要清除中断源。
使用边沿触发可以有效避免“优先级别”较高的中断源长期占用IRQ_PIN#信号的情况,使用“下降沿”触发进行中断请求与“上升沿”触发类似。
但是外部设备使用边沿触发方式时,有可能会丢失一些中断请求。例如在一个处理器系统中,存在一个定时器,这个定时器使用上升沿触发方式向中断控制器定时提交中断。如果当处理器正在处理这个定时器的上一个中断请求时,将不会处理这个定时器发出的其他“边沿”中断请求,从而导致中断丢失。而使用电平触发方式不会出现这类问题,因为电平触发方式是一个“持续”过程,处理器只有处理完毕当前中断,并清除相应中断源之后,才会处理下一个中断源。
MSI中断请求实际上和边沿触发方式非常类似,MSI中断请求通过存储器写TLP实现,这个写动作是一个瞬间的动作,并不是一个持续请求,因此在x86处理器中MSI中断请求使用边沿触发进行中断请求。
还有一些外部设备可以通过I/O APIC进行中断请求[②],这些I/O APIC接收的外部中断需要标明是使用边沿或者电平触发,I/O APIC使用FSB Interrupt Message总线事务将中断请求发向Local APIC,并由Local APIC向处理器提交中断请求。
与MPC8572处理器处理MSI中断请求不同,x86处理器使用FSB的Interrupt Message总线事务,处理PCIe设备的MSI/MSI-X中断请求。由上文所示,MPC8572处理器处理MSI中断请求时,首先由MPIC中断控制器截获这个MSI中断请求,之后由MPIC中断控制器向CPU提交中断请求,而CPU通过中断响应周期从MPIC中断控制器的ACK寄存器中获得中断向量。
采用这种方式的主要问题是,当一个处理器中存在多个CPU时,这些CPU都需要通过中断响应周期从MPIC中断控制器的ACK寄存器中获得中断向量。在一个中断较为密集的应用中,ACK寄存器很可能会成为系统瓶颈。而采用Interrupt Message总线事务可以有效地避免这种系统瓶颈,因为使用这种方式中断信息和中断向量将同时到达指定的CPU,而不需要使用中断响应周期获得中断向量。
x86处理器也具有通过中断控制器提交MSI/MSI-X中断请求的方法,在I/O APIC具有一个 “The IRQ Pin Assertion Register”寄存器,该寄存器地址为0xFEC00020[③],其第4~0位存放IRQ Number。系统软件可以将PCIe设备的Message Address寄存器设置为0xFEC00020,将Meaasge Data寄存器设置为相应的IRQ Number。
当PCIe设备需要提交MSI中断请求时,将向PCI总线域的0xFEC00020地址写入Message Data寄存器中的数据。此时这个存储器写请求将数据写入I/O APIC的The IRQ Pin Assertion Register中,并由I/O APIC将这个MSI中断请求最终发向Local APIC,之后再由Local APIC通过INTR#信号向CPU提交中断请求。
上述步骤与MPC8572处理器传递MSI中断的方法类似。在x86处理器中,这种方式基本上已被弃用。下文以图6?9为例,说明x86处理器如何使用FSB总线的Interrupt Message总线事务,向CPU提交MSI/MSI-X中断请求。
PCIe设备在发送MSI/MSI-X中断请求之前,系统软件需要合理设置PCIe设备MSI/MSI-X Capability寄存器,使Message Address寄存器的值为0xFEExx00y[④],同时合理地设置Message Data寄存器Vector字段。
PCIe设备提交MSI/MSI-X中断请求时,需要向0xFEExx00y地址写Message Data寄存器中包含的数据,并以存储器写TLP的形式发送到RC。如果ICH收到这个存储器写TLP时,将通过DMI接口将这个TLP提交到MCH。MCH收到这个TLP后,发现这个TLP的目的地址在FSB Interrupts存储器空间中,则将PCIe总线的存储器写请求转换为Interrupt Message总线事务,并在FSB总线上广播。
FSB总线上的CPU,根据APIC ID信息,选择是否接收这个Interrupt Message总线事务,并进入中断状态,之后该CPU将直接从这个总线事务中获得中断向量号,执行相应的中断服务例程,而不需要从APIC中断控制器获得中断向量。与PowerPC处理器的MPIC中断控制器相比,这种方法更具优势。
本章详细描述了MSI/MSI-X中断机制的原理,并以PowerPC和x86两个处理器系统为例说明这两种中断机制实现机制。本章因为篇幅有限,并没有详细讲述这两个处理器使用的中断控制器。而理解这些中断控制器的实现机制是进一步理解MSI/MSI-X中断机制的要点。对此部分有兴趣的读者可以继续阅读MPIC中断控制器和APIC中断控制器的实现机制,以加深对MSI/MSI-X中断机制的理解。
设备的中断处理是局部总线的设计难点和重要组成部分,而中断处理的效率直接决定了局部总线的数据传送效率。在一个处理器系统的设计与实现中,中断处理的优化贯彻始终。