PCI总线使用INTA#、INTB#、INTC#和INTD#信号向处理器发出中断请求。这些中断请求信号为低电平有效,并与处理器的中断控制器连接。在PCI体系结构中,这些中断信号属于边带信号(Sideband Signals),PCI总线规范并没有明确规定在一个处理器系统中如何使用这些信号,因为这些信号对于PCI总线是可选信号。所谓边带信号是指这些信号在PCI总线中是可选信号,而且只能在一个处理器系统的内部使用,并不能离开这个处理器环境。
注:PCI Spec对边带信号的定义如下:
Any signal not part of the PCI specification that connects two or more PCI-compliant agents and has meaning only to those agents.
中断信号与中断控制器的连接关系
PCI总线规范没有规定PCI设备的INTx信号如何与中断控制器的IRQ_PINx#信号相连,这为系统软件的设计带来了一定的困难,为此系统软件使用中断路由表存放PCI设备的INTx信号与中断控制器的连接关系。在x86处理器系统中,BIOS可以提供这个中断路由表,而在PowerPC处理器中Firmware也可以提供这个中断路由表。
在一些简单的嵌入式处理器系统中,Firmware并没有提供中断路由表,此时系统软件开发者需要事先了解PCI设备的INTx信号与中断控制器的连接关系。此时外部设备与中断控制器的连接关系由硬件设计人员指定。
我们假设在一个处理器系统中,共有3个PCI插槽(分别为PCI插槽A、B和C),这些PCI插槽与中断控制器的IRQ_PINx引脚(分别为IRQW#、IRQX#、IRQY#和IRQZ#)可以按照下图所示的拓扑结构进行连接。
此时,PCI插槽A、B、C的INTA#、INTB#和INTC#信号将分散连接到中断控制器的IRQW#、IRQX#和IRQY#信号,而所有INTD#信号将共享一个IRQZ#信号。采用这种连接方式时,整个处理器系统使用的中断请求信号,其负载较为均衡。而且这种连接方式保证了每一个插槽的INTA#信号都与一根独立的IRQx#信号对应,从而提高了PCI插槽中断请求的效率。
在一个处理器系统中,多数PCI设备仅使用INTA#信号,很少使用INTB#和INTC#信号,而INTD#信号更是极少使用。在PCI总线中,PCI设备配置空间的Interrupt Pin寄存器记录该设备究竟使用哪个INTx信号。
中断信号与PCI总线的连接关系
在PCI总线中,INTx信号属于边带信号。PCI桥也不会处理这些边带信号。这给PCI设备将中断请求发向处理器带来了一些困难,特别是给挂接在PCI桥之下的PCI设备进行中断请求带来了一些麻烦。
在一些嵌入式处理器系统中,这个问题较易解决。因为嵌入式处理器系统很清楚在当前系统中存在多少个PCI设备,这些PCI设备使用了哪些中断资源。在多数嵌入式处理器系统中,PCI设备的数量小于中断控制器提供的外部中断请求引脚数,而且在嵌入式系统中,多数PCI设备仅使用INTA#信号提交中断请求。
在这类处理器系统中,可能并不含有PCI桥,因而PCI设备的中断请求信号与中断控制器的连接关系较易确定。而在这类处理器系统中,即便存在PCI桥,来自PCI桥之下的PCI设备的中断请求也较易处理。
在多数情况下,嵌入式处理器系统使用的PCI设备仅使用INTA#信号进行中断请求,所以只要将这些INTA#信号挂接到中断控制器的独立IRQ_PIN#引脚上即可。这样每一个PCI设备都可以独占一个单独的中断引脚。
而在x86处理器系统中,这个问题需要BIOS参与来解决。在x86处理器系统中,有许多PCI插槽,处理器系统并不知道在这些插槽上将要挂接哪些PCI设备,而且也并不知道这些PCI设备到底需不需要使用所有的INTx#信号线。因此x86处理器系统必须要对各种情况进行处理。
x86处理器系统还经常使用PCI桥进行PCI总线扩展,扩展出来的PCI总线还可能挂接一些PCI插槽,这些插槽上INTx#信号仍然需要处理。PCI桥规范并没有要求桥片传递其下PCI设备的中断请求。事实上多数PCI桥也没有为下游PCI总线提供中断引脚INTx#,管理其下游总线的PCI设备。但是PCI桥规范推荐使用下面的表建立下游PCI设备的INTx信号与上游PCI总线INTx信号之间的映射关系。
我们举例说明该表的含义。在PCI桥下游总线上的PCI设备,如果其设备号为0,那么这个设备的INTA#引脚将和PCI总线的INTA#引脚相连;如果其设备号为1,其INTA#引脚将和PCI总线的INTB#引脚相连;如果其设备号为2,其INTA#引脚将和PCI总线的INTC#引脚相连;如果其设备号为3,其INTA#引脚将和PCI总线的INTD#引脚相连。
在x86处理器系统中,由BIOS或者APCI表记录PCI总线的INTA~D#信号与中断控制器之间的映射关系,保存这个映射关系的数据结构也被称为中断路由表。大多数BIOS使用表中的映射关系,这也是绝大多数BIOS支持的方式。如果在一个x86处理器系统中,PCI桥下游总线的PCI设备使用的中断映射关系与此不同,那么系统软件程序员需要改动BIOS中的中断路由表。
BIOS初始化代码根据中断路由表中的信息,可以将PCI设备使用的中断向量号写入到该PCI设备配置空间的Interrupt Line register寄存器中。
PCI设备可以通过奇偶校检来检测到来自AD上的地址或者数据的错误,并通过PERR#或者SERR#报告错误。但是需要注意的是,PCI Spec并未规定任何硬件层面上的错误处理或者恢复机制,因此,这些错误都只能通过软件进行处理。
一个简单的PCI总线INTx中断实现流程,如下图所示。
上面的例子主要是基于早期的单核CPU设计的,并没有考虑到目前多核CPU的情况。因此,在后续的PCI Spec中,将PIC替换为IO APIC(Advanced Programmed Interrupt Controller)。如下图所示:
实际上,在PCIe总线中,传统的中断机制(INTx)已经很少被使用,很多应用甚至直接将该功能禁止了。无论是在PCI总线(V2.3及以后的版本),还是PCIe总线中,都可以通过配置空间中的配置命令寄存器(Configuration Command Register来禁止INTx中断机制),如下图所示。不过,需要特别注意的是,虽然该bit的名称为中断禁止(Interrupt Disable),但是其只会影响INTx,对MSI/MSI-X不会造成影响。因为MSI/MSI-X的使能(或禁止)是通过配置空间中的MSI/MSI-X Capability Command Register来实现的,并且一旦使能了MSI/MSI-X,PCI总线/PCIe总线便会自动地禁止INTx。
并且可以通过配置状态寄存器的中断状态(Interrupt Status)bit来确定当前的中断状态,如下图所示:
INTx相关的寄存器在配置空间的位置如下图所示,Interrupt Pin和Interrupt Line分别定义了中断边带信号引脚号(INTA#INTD#)和中断向量号(IRQ0IRQ255)。
然而,PCIe总线继承了PCI总线的INTx中断机制,但是在实际的PCIe设备之间的中断信息传输中使用的并非边带信号INTx,而是基于消息(Message)的。其中Assert_INTx消息表示INTx信号的下降沿。Dessert_INTx消息表示INTx信号的上升沿。当发送这两种消息时,PCIe设备还会将配置空间的相关中断状态bit的值更新。对于PCIe-PCI(X)桥设备来说,会将接收到的来自PCI/PCI-X总线的INTx信号转换为消息,在往上级发送。一个简单的例子如下图所示:
INTx消息的格式为:
桥设备中的INTx消息的类型与设备号的映射关系如下图所示:
对应的,一个简单的例子如下:
当多个设备使用同一个中断信号线时,只有先置位的设备会被中断控制器响应。但是该中断信号线,并不会因为其中一个设备的中断请求得到响应便被清除,而是会等到所有的发送请求的设备的中断请求都得到了响应之后。如下图所示:
The rules associated with the delivery of INTx messages have some unique
characteristics:
• Assert_INTx and Deassert_INTx are only issued in the upstream direction.
• Switches that are collapsing interrupts will only issue INTx messages
upstream when there is a change of the interrupt status.
• Devices on either side of a link must track the current state of INTA‐INTD
assertion.
• A Switch tracks the state of the four virtual wires for each of its downstream
ports, and may present a collapsed set of virtual wires on its upstream port.
• The Root Complex must track the state of the four virtual wires (A‐D) for
each downstream port.
• INTx signaling may be disabled with the Interrupt Disable bit in the Command
Register.
• If any INTx virtual wires are active and device interrupts are then disabled,
a corresponding Deassert_INTx message must be sent.
• If a downstream Switch Port goes to DL_Down status, any active INTx virtual
wires must be deasserted, and the upstream port updated accordingly
(Deassert_INTx message required if that INTx was in active state).