Home PCIe中断机制
Post
Cancel

PCIe中断机制

为了能够让一些优先级高的事务得到优先处理,PCI总线支持外设中断用以提高总线性能。 PCIe总线继承了PCI总线的所有中断特性(包括INTx和MSI/MSI-X),以兼容早期的一些PCI应用层软件。

PCI总线最早采用的中断机制是INTx,这是基于边带信号的。后续的PCI/PCI-X版本,为了消除边带信号, 降低系统的硬件设计复杂度,逐渐采用了MSI/MSI-X(消息信号中断)的中断机制。

INTx一般被称为传统的(Legacy)PCI中断机制,每个PCI设备最多支持四个中断信号(边带信号,INTA#、INTB#、INTC#和INTD#)。 一个简单的例子如下图所示:

PCI_INTx中断

MSI/MSI-X是后续的PCI/PCI-X总线改进后的中断机制,其中MSI-X(MSI-eXtented)是PCI-X中提出的升级版本。 需要特别注意的是,MSI/MSI-X与PCIe总线中的消息(Message)的概念完全不同!MSI/MSI-X本质上是一种Posted Memory Write

一个简单的例子如下图所示:

PCIe_MSI示例1

PCIE设备必须只能使用MSI/MSI-X 发送中断,传统的INTx中断仅是PCIE为了兼容非常老的PCI设备,使之能够工作。 PCIE到PCIX桥需要支持INTx中断信息。

中断机制介绍(INTx)

一个简单的PCI总线INTx中断实现流程,如下图所示。

  1. 首先,PCI设备通过INTx边带信号产生中断请求,经过中断控制器(Interrupt Controller,PIC)后,转换为INTR信号,并直接发送至CPU;
  2. CPU收到INTR信号置位后,意识到了中断请求的发生,但是此时并不知道是什么中断请求。于是通过一个特殊的指令来查询中断请求信息, 该过程一般被称为中断应答(Interrupt Acknowledge);
  3. 该特殊指令被发送至PIC后,PIC会返回一个8bits的中断向量(Interrupt Vector)值给CPU。该中断向量值与其发送的INTR请求是对应的;
  4. CPU收到来自PIC的中断向量值后,会去其Memory中的中断向量表(Interrupt Table)中查找 对应的中断服务程序(Interrupt Service Routines,ISR)在Memory的位置;
  5. 然后CPU读取ISR程序,进而处理该中断。

PCI_INTx中断介绍1

上面的例子主要是基于早期的单核CPU设计的,并没有考虑到目前多核CPU的情况。 因此,在后续的PCI Spec中,将PIC替换为IO APIC(Advanced Programmed Interrupt Controller)。如下图所示:

PCI_INTx中断介绍2

实际上,在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。

PCI_INTx中断介绍3

并且可以通过配置状态寄存器的中断状态(Interrupt Status)bit来确定当前的中断状态,如下图所示:

PCI_INTx中断介绍4

INTx相关的寄存器在配置空间的位置如下图所示, Interrupt Pin和Interrupt Line分别定义了中断边带信号引脚号(INTA#~INTD#)和中断向量号(IRQ0~IRQ255)

PCI_INTx中断介绍5

然而,PCIe总线继承了PCI总线的INTx中断机制,但是在实际的PCIe设备之间的中断信息传输中使用的并非边带信号INTx,而是基于消息(Message)的。 其中Assert_INTx消息表示INTx信号的下降沿。Dessert_INTx消息表示INTx信号的上升沿。 当发送这两种消息时,PCIe设备还会将配置空间的相关中断状态bit的值更新。 对于PCIe-PCI(X)桥设备来说,会将接收到的来自PCI/PCI-X总线的INTx信号转换为消息,在往上级发送。一个简单的例子如下图所示:

PCI_INTx中断介绍6

INTx消息的格式为:

PCI_INTx中断介绍7

桥设备中的INTx消息的类型与设备号的映射关系如下图所示:

PCI_INTx中断介绍8

对应的,一个简单的例子如下:

PCI_INTx中断介绍9

当多个设备使用同一个中断信号线时,只有先置位的设备会被中断控制器响应。 但是该中断信号线,并不会因为其中一个设备的中断请求得到响应便被清除, 而是会等到所有的发送请求的设备的中断请求都得到了响应之后。如下图所示:

PCI_INTx中断介绍10

中断机制介绍(MSI)

MSI本质上是一种Memory Write,和PCIe总线中的Message概念半毛钱关系都没有。并且,MSI的Data Payload也是固定的,始终为1DW。

由于MSI也是从PCI总线继承而来的,因此MSI相关的寄存器也存在于配置空间中的PCI兼容部分(前256个字节)。如下图所示,MSI有四种类型:

PCIe_MSI介绍1

PCIe_MSI介绍2

  • 其中Capability ID的值是只读的,05h表示支持MSI功能。
  • Next Capability Pointer也是只读的,其用于查找下一个Capability Structure的位置,其值为00h则表示到达Linked List的最后了。
  • Message Address字段。当MSI Enable位有效时,该字段存放MSI存储器写事务的目的地址的低32位。 该字段的31:2字段有效,系统软件可以对该字段进行读写操作;该字段的第1~0位为0。
  • Message Upper Address字段。如果64 bit Address Capable位有效,该字段存放MSI存储器写事务的目的地址的高32位。
  • Message Data字段,该字段可读写。当MSI Enable位有效时,该字段存放MSI报文使用的数据。该字段保存的数值与处理器系统相关, 在PCIe设备进行初始化时,处理器将初始化该字段,而且不同的处理器填写该字段的规则并不相同。 如果Multiple Message Enable字段不为0b000时(即该设备支持多个中断请求时), PCIe设备可以通过改变Message Data字段的低位数据发送不同的中断请求。
  • Mask Bits字段。PCIe总线规定当一个设备使用MSI中断机制时,最多可以使用32个中断向量,从而一个设备最多可以发送32种中断请求。 Mask Bits字段由32位组成,其中每一位对应一种中断请求。当相应位为1时表示对应的中断请求被屏蔽,为0时表示允许该中断请求。 系统软件可读写该字段,系统初始化时该字段为全0,表示允许所有中断请求。 该字段和Pending Bits字段对于MSI中断机制是可选字段,但是PCIe总线规范强烈建议所有PCIe设备支持这两个字段。
  • Pending Bits字段。该字段对于系统软件是只读位,PCIe设备内部逻辑可以改变该字段的值。 该字段由32位组成,并与PCIe设备使用的MSI中断一一对应。该字段需要与Mask Bits字段联合使用。 当Mask Bits字段的相应位为1时,如果PCIe设备需要发送对应的中断请求时,Pending Bits字段的对应位将被PCIe设备的内部逻辑置1, 此时PCIe设备并不会使用MSI报文向中断控制器提交中断请求;当系统软件将Mask Bits字段的相应位从1改写为0时, PCIe设备将发送MSI报文向处理器提交中断请求,同时将Pending Bit字段的对应位清零。 在设备驱动程序的开发中,有时需要联合使用Mask Bits和Pending Bits字段防止处理器丢弃中断请求。

当Mask Bits将相关的中断向量(Interrupt Vector)屏蔽后,该MSI将不会被发送。软件可以通过这种方式来使能或者禁止某些MSI的发送。 如果相关中断向量没有被屏蔽,则如果发生了相关中断请求,这时Pending Bits中的相应bit则会被置位。一旦中断信息被发出,则该bit会立即被清零。

MSI机制提交中断请求的方式类似与边界触发方式,而使用边界触发方式时,处理器可能会丢失某些中断请求, 因此在设备驱动程序的开发过程中,可能需要使用这两个字段

  • Message Control Register用于确定MSI的格式与支持的功能等信息, 如下图所示:

PCIe_MSI介绍3

PCIe_MSI介绍4

中文参考:

PCIe_MSI介绍5

PCIe设备会根据配置空间中的MSI请求信息,来创建Memory Write TLP,来将MSI信息发送出去。 作为一种特殊的TLP,传递MSI的TLP需要遵循以下规则:

  • No Snoop和Relaxed Ordering bits的值必须为0
  • TLP长度值必须为01h
  • First BE必须为1111b
  • Last BE必须为0000b
  • 地址是直接从配置空间中的响应位置复制过来的

如下图所示:

PCIe_MSI介绍6

中断机制介绍(MSI-X)

PCIe设备可以使用MSI或者MSI-X报文向处理器提交中断请求,但是对于某个具体的PCIe设备,可能仅支持一种报文。 在PCIe设备中含有两个Capability结构,一个是MSI Capability结构,另一个是MSI-X Capability结构。 通常情况下一个PCIe设备仅包含一种结构,或者为MSI Capability结构,或者为MSI-X Capability结构。

MSI-X Capability中断机制与MSI Capability的中断机制类似。 PCIe总线引出MSI-X机制的主要目的是为了扩展PCIe设备使用中断向量的个数,同时解决MSI中断机制要求使用中断向量号连续所带来的问题。

MSI中断机制最多只能使用32个中断向量,而MSI-X可以使用更多的中断向量。目前Intel的许多PCIe设备支持MSI-X中断机制。 与MSI中断机制相比,MSI-X机制更为合理。首先MSI-X可以支持更多的中断请求,但是这并不是引入MSI-X中断机制最重要的原因。 因为对于多数PCIe设备,32种中断请求已经足够了。而引入MSI-X中断机制的主要原因是,使用该机制不需要中断控制器分配给该设备的中断向量号连续。

如果一个PCIe设备需要使用8个中断请求时,如果使用MSI机制时,Message Data的[2:0]字段可以为0b000~0b111,因此可以发送8种中断请求, 但是这8种中断请求的Message Data字段必须连续。在许多中断控制器中,Message Data字段连续也意味着中断控制器需要为这个PCIe设备分配8个连续的中断向量号。

有时在一个中断控制器中,虽然具有8个以上的中断向量号,但是很难保证这些中断向量号是连续的。 因此中断控制器将无法为这些PCIe设备分配足够的中断请求,此时该设备的“Multiple Message Enable”字段将小于“Multiple Message Capable”。

而使用MSI-X机制可以合理解决该问题。在MSI-X Capability结构中, 每一个中断请求都使用独立的Message Address字段和Message Data字段,从而中断控制器可以更加合理地为该设备分配中断资源。

与MSI Capability寄存器相比,MSI-X Capability寄存器使用一个数组存放Message Address字段和Message Data字段,而不是将这两个字段放入Capability寄存器中, 本篇将这个数组称为MSI-X Table。从而当PCIe设备使用MSI-X机制时,每一个中断请求可以使用独立的Message Address字段和Message Data字段

除此之外MSI-X中断机制还使用了独立的Pending Table表,该表用来存放与每一个中断向量对应的Pending位。 这个Pending位的定义与MSI Capability寄存器的Pending位类似。MSI-X Table和Pending Table存放在PCIe设备的BAR空间中。 MSI-X机制必须支持这个Pending Table,而MSI机制的Pending Bits字段是可选的。

PCI总线自3.0版本开始支持MSI-X机制,MSI只支持32个中断向量,而MSI-X支持多达2048个中断向量,但是MSI-X的相关寄存器在配置空间中占用的空间却更小。 这是因为中断向量信息并不直接存储在这里,而是在一款特殊的Memory(MIMO)中。并通过 BIR(Base address Indicator Register, or BAR Index Register)来确定其在MIMO中的具体位置。如下图所示:

PCIe_MSIX介绍1

Message Control寄存器的具体描述如下:

PCIe_MSIX介绍2

  • Table BIR(BAR Indicator Register:PCIe总线规范规定MSI-X Table存放在设备的BAR空间中。 该字段表示设备使用BAR0~5寄存器中的哪个空间存放MSI-X table。该字段由三位组成,其中0b000~0b101与BAR0~5空间一一对应。
  • Table Offset字段。该字段存放MSI-X Table在相应BAR空间中的偏移。
  • PBA(Pending Bit Array) BIR字段。该字段存放Pending Table在PCIe设备的哪个BAR空间中。 在通常情况下,Pending Table和MSI-X Table存放在PCIe设备的同一个BAR空间中。
  • PBA Offset字段。该字段存放Pending Table在相应BAR空间中的偏移。

MSI-X查找表的示意图如下:

PCIe_MSIX介绍3

结构图如下:

PCIe_MSIX介绍4

MSI-X Table由多个Entry组成,其中每个Entry与一个中断请求对应。其中每一个Entry中有四个参数,其含义如下所示。

  • Msg Addr。当MSI-X Enable位有效时,该字段存放MSI-X存储器写事务的目的地址的低32位。 该双字的31:2字段有效,系统软件可读写;1:0字段复位时为0,PCIe设备可以根据需要将这个字段设为只读,或者可读写。不同的处理器填入该寄存器的数据并不相同。
  • Msg Upper Addr,该字段可读写,存放MSI-X存储器写事务的目的地址的高32位。
  • Msg Data,该字段可读写,存放MSI-X报文使用的数据。其定义与处理器系统使用的中断控制器和PCIe设备相关。
  • Vector Control,该字段可读写。该字段只有第0位(即Per Vector Mask位)有效,其他位保留。 当该位为1时,PCIe设备不能使用该Entry提交中断请求;为0时可以提交中断请求。该位在复位时为0。Per Vector Mask位的使用方法与MSI机制的Mask位类似。

类似的,Pending Bits则位于另一个Memory中,其结构图如下:

PCIe_MSIX介绍5

如上图所示,在Pending Table中,一个Entry由64位组成,其中每一位与MSI-X Table中的一个Entry对应, 即Pending Table中的每一个Entry与MSI-X Table的64个Entry对应。与MSI机制类似,Pending位需要与Per Vector Mask位配置使用。

当Per Vector Mask位为1时,PCIe设备不能立即发送MSI-X中断请求,而是将对应的Pending位置1; 当系统软件将Per Vector Mask位清零时,PCIe设备需要提交MSI-X中断请求,同时将Pending位清零。

无论是MSI还是MSI-X,其本质上都是基于Memory Write 的,因此也可能会产生错误。比如PCIe中的ECRC错误等。

This post is licensed under CC BY 4.0 by the author.