系列文章目录
PCIe扫盲(一)
PCIe扫盲(二)
PCIe扫盲(三)
PCIe扫盲(四)
PCIe扫盲(五)
PCIe扫盲(六)
PCIe扫盲(七)
PCIe扫盲(八)
PCIe扫盲(九)
PCIe扫盲(10)
PCIe扫盲(11)
文章目录
- 系列文章目录
- 两种中断传递方式
- 中断机制介绍(INTx)
- 中断机制介绍(MSI)
- 中断机制介绍(MSI-X)
- 复位机制介绍(Fundamental & Hot)
- 复位机制介绍(FLR)
- 转载链接
两种中断传递方式
为了能够让一些优先级高的事务得到优先处理,PCI 总线支持外设中断用以提高总线性能。PCIe 总线继承了 PCI 总线的所有中断特性(包括 INTx 和 MSI/MSI-X),以兼容早期的一些 PCI 应用层软件。本次连载的文章只是简单的介绍 PCIe 中断的一些基本概念和特性,如需深入了解 PCI/PCIe 总线的中断内容,请参阅 PCI/PCI-X Spec 或者 Mindshare 的书籍(PCI System Architecture)。
PCI 总线最早采用的中断机制是 INTx ,这是基于边带信号的。后续的 PCI/PCI-X 版本,为了消除边带信号,降低系统的硬件设计复杂度,逐渐采用了 MSI/MSI-X(消息信号中断)的中断机制。
INTx 一般被称为传统的(Legacy)PCI 中断机制,每个 PCI 设备最多支持四个中断信号(边带信号,INTA#、INTB#、INTC# 和 INTD#)。一个简单的例子如下图所示:
也可以参考一下之前的文章(关于 INTx 的):PCI总线的中断和错误处理
MSI/MSI-X 是后续的 PCI/PCI-X 总线改进后的中断机制,其中 MSI-X(MSI-eXtented)是 PCI-X 中提出的升级版本。需要特别注意的是,MSI/MSI-X 与 PCIe 总线中的消息(Message)的概念完全不同!MSI/MSI-X 本质上是一种 Posted Memory Write 。
一个简单的例子如下图所示:
中断机制介绍(INTx)
一个简单的 PCI 总线 INTx 中断实现流程,如下图所示。
-
首先,PCI 设备通过 INTx 边带信号产生中断请求,经过中断控制器(Interrupt Controller,PIC)后,转换为 INTR 信号,并直接发送至 CPU ;
-
CPU 收到 INTR 信号置位后,意识到了中断请求的发生,但是此时并不知道是什么中断请求。于是通过一个特殊的指令来查询中断请求信息,该过程一般被称为中断应答(Interrupt Acknowledge);
-
该特殊指令被发送至 PIC 后,PIC 会返回一个 8bits 的中断向量(Interrupt Vector)值给 CPU 。该中断向量值与其发送的 INTR 请求是对应的;
-
CPU 收到来自 PIC 的中断向量值后,会去其 Memory 中的中断向量表(Interrupt Table)中查找对应的中断服务程序(Interrupt Service Routines,ISR)在 Memory 的位置;
-
然后 CPU 读取 ISR 程序,进而处理该中断。
上面的例子主要是基于早期的单核 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#)和中断向量号(IRQ0 ~ IRQ255)。
然而,PCIe 总线继承了 PCI 总线的 INTx 中断机制,但是在实际的 PCIe 设备之间的中断信息传输中使用的并非边带信号 INTx ,而是基于消息(Message)的。其中 Assert_INTx 消息表示 INTx 信号的下降沿。Dessert_INTx 消息表示 INTx 信号的上升沿。当发送这两种消息时,PCIe 设备还会将配置空间的相关中断状态 bit 的值更新。对于 PCIe-PCI(X) 桥设备来说,会将接收到的来自 PCI/PCI-X 总线的 INTx 信号转换为消息,在往上级发送。一个简单的例子如下图所示:
INTx 消息的格式为:
桥设备中的 INTx 消息的类型与设备号的映射关系如下图所示:
对应的,一个简单的例子如下:
当多个设备使用同一个中断信号线时,只有先置位的设备会被中断控制器响应。但是该中断信号线,并不会因为其中一个设备的中断请求得到响应便被清除,而是会等到所有的发送请求的设备的中断请求都得到了响应之后。如下图所示:
中断机制介绍(MSI)
前面的文章中介绍过,MSI 本质上是一种 Memory Write,和 PCIe 总线中的 Message 概念半毛钱关系都没有。并且,MSI 的 Data Payload 也是固定的,始终为 1DW 。
由于MSI也是从PCI总线继承而来的,因此MSI相关的寄存器也存在于配置空间中的PCI兼容部分(前256个字节)。如下图所示,MSI有四种类型:
其中Capability ID的值是只读的,05h表示支持MSI功能。
Next Capability Pointer也是只读的,其用于查找下一个Capability Structure的位置,其值为00h则表示到达Linked List的最后了。
Message Control Register用于确定MSI的格式与支持的功能等信息,如下图所示:
具体描述如下:
Message Address Register:32-bit最低两位固定为0,使得该地址是DW对齐的。
当Mask Bits将相关的中断向量(Interrupt Vector)屏蔽后,该MSI将不会被发送。软件可以通过这种方式来使能或者禁止某些MSI的发送。如果相关中断向量没有被屏蔽,则如果发生了相关中断请求,这时Pending Bits中的相应bit则会被置位。一旦中断信息被发出,则该bit会立即被清零。
注:可能有的人会有疑惑了(无论是Mindshare的书,还是PCI的Spec都没有明确解释),因为Mask Bits和Pending Bits都只有32位,而8位的中断向量号最多可以表示256个!显然,32位最多只能对应32个中断向量号,无法支持256个的。实际上,一般的系统不会支持256个中断向量号的,32个就已经足够用了,所以并不用担心这个问题。
PCIe设备会根据配置空间中的MSI请求信息,来创建Memory Write TLP,来讲MSI信息发送出去。作为一种特殊的TLP,传递MSI的TLP需要遵循以下规则:
-
No Snoop和Relaxed Ordering bits的值必须为0
-
TLP长度值必须为01h
-
First BE必须为1111b
-
Last BE必须为0000b
-
地址是直接从配置空间中的响应位置复制过来的
如下图所示:
中断机制介绍(MSI-X)
PCI总线自3.0版本开始支持MSI-X机制,对MSI做出了一些升级和改进,以克服MSI机制的三个主要的缺陷:
-
随着系统的发展,对于特定的大型应用,32个中断向量不够用了(参考前一篇文章);
-
只有一个目标地址使得多核CPU情况下的,静态中断分配变得困难。如果能够使每个向量对应不同的唯一的地址,便会灵活很多;
-
某些应用中的中断优先级混乱问题。
有趣的是,MSI只支持32个中断向量,而MSI-X支持多达2048个中断向量,但是MSI-X的相关寄存器在配置空间中占用的空间却更小。这是因为中断向量信息并不直接存储在这里,而是在一款特殊的Memory(MIMO)中。并通过BIR(Base address Indicator Register, or BAR Index Register)来确定其在MIMO中的具体位置。如下图所示:
Message Control寄存器的具体描述如下:
MSI-X查找表的示意图如下:
结构图如下:
类似的,Pending Bits则位于另一个Memory中,其结构图如下:
注:无论是MSI还是MSI-X,其本质上都是基于Memory Write 的,因此也可能会产生错误。比如PCIe中的ECRC错误等。
复位机制介绍(Fundamental & Hot)
PCIe总线中定义了四种复位名称:冷复位(Cold Reset)、暖复位(Warm Reset)、热复位(Hot Reset)和功能层复位(Function-Level Reset,FLR)。其中FLR是PCIe Spec V2.0加入的功能,因此一般把另外三种复位统称为传统的复位方式(Conventional Reset)。其中冷复位和暖复位是基于边带信号PERST#的,又被统称为基本的复位方式(Fundamental Reset)。
基本复位由硬件自动处理,会复位整个PCIe设备,初始化所有与状态机相关的硬件逻辑,端口状态以及配置空间中的配置寄存器等等。但是,也有一个例外,就是前面介绍PCIe错误报告机制的相关文章中提到过Sticky(不受复位影响)的概念。这里指的不受复位影响的前提是,PCIe设备的电源并未被完全切断。Sticky这一功能有助于系统定位错误与分析错误起因。
基本复位中的冷复位(Cold Reset)指的是因为主电源断开后重新连接导致的复位。需要注意的是,即使主电源断开了,如果PCIe设备仍有辅助电源Vaux为其供电,该复位仍不会影响到Sticky的bits。
PCIe Spec允许两种实现基本复位的方式。一是直接通过边带信号PERST#(PCI Express Reset);二是不使用边带信号PERST#,PCIe设备在主电源被切断时,自行产生一个复位信号。一个简单的例子如下图所示:
暖复位(Warm Rest)是可选的,指的是在不关闭主电源的情况下,产生的复位。然而,PCIe Spec并未明确规定暖复位的产生机制,因此,如果产生暖复位完全是由系统设计者决定的。
热复位(Hot Reset)是一种In-band 复位,其并不使用边带信号。PCIe设备通过向其链路(Link)相邻的设备发送数个TS1 Ordered Set(其中第五个字符的bit0为1),如下图所示。这些TS1OS在所有的通道(Lane)上同时发送,并持续2ms左右。
注:关于Ordered Set以及LTSSM等相关内容,请参考前面介绍链路初始化与训练的相关文章。
主要注意的是,如果Switch的Upstream端口收到了热复位,则会将其广播至所有的Downstream端口,并复位其自己。如果PCIe设备的Downstream端口接收到热复位,则只需要复位其自己即可。
当PCIe设备接收到热复位后,LTSSM会进入Recovery and Hot Reset状态,然后返回值Detect状态,并重新开始链路初始化训练。其该PCIe设备的所有状态机,硬件逻辑,端口状态和配置空间中的寄存器(除了Sticky bits)都将被初始化值默认状态。
软件可以通过向桥设备的,特定端口的配置空间中的二级总线复位(Secondary Bus Reset)bit先写0再写1,来产生热复位,如下图所示:
需要注意的是,如果软件设置的是Switch的Upstream端口的二级总线复位bit,则该Switch会往其所有的Downstream端口广播热复位信号。而PCIe-to-PCI桥则会将接收到的热复位信号转换为PRST#置位,发送给PCI设备。
二级总线复位(Secondary Bus Reset)bit在配置空间的位置如下图所示:
PCIe Spec还允许软件禁止某个链路(Link),强制使其进入电气空闲状态(Electrical Idle)。如果将某个链路禁止,则该链路所有的下游PCIe设备都将收到链路禁止信号(通过TS1OS,如下图所示)。
复位机制介绍(FLR)
PCIe总线自V2.0加入了功能层复位(Function Level Reset,FLR)的功能。该功能主要针对的是支持多个功能的PCIe设备(Multi-Fun PCIe Device),可以实现只对特定的Function复位,而其他的Function不受影响。当然,该功能是可选的,并非强制的,软件可以通过查询配置空间中的设备功能寄存器(Device Capability Register)来查询该PCIe设备是否支持FLR。如下图所示:
并可以通过设备控制寄存器(Device Control Register)中的将Initiate Function Level Reset bit置1,来产生FLR。
FLR只复位对应Function的内部状态和寄存器(使其暂时不变化,Making it quiescent),但是并不影响Sticky bits、有硬件初始化的值(Hardware-initialized bits)和链路专用寄存器(比如Captured Power,ASPM Control、Max Payload Size以及VC等寄存器)。如果该设备在FLR前,发出了Assert INTx中断消息,必须在开始FLR之前在发出对应的Deassert INTx消息,除非该INTx已经被与其他Function共享了。当收到FLR后,该Function的所有的其他功能都应被立即停止(Required to cease)。
此外,PCIe Spec还明确给出了FLR的完成时间应在100ms以内。
PCIe Spec还明确规定了,当某个Function处于FLR状态时的一些特性:
-
该Function不能有任何与外界通信的(外部)接口;
-
该Function必须将任何软件可读取的状态(可能包括加密信息等)打乱。换句话说,任何内部存储都必须被清零或者随机化;
-
该Function必须可以被另一个Diver配置为一般模式;
-
该Function必须为其收到的包含有FLR信息的配置写(Configuration Write)返回一个Completion,然后再进行FLR操作。
在进入FLR状态后,还需要:
-
该Function接收到的任何请求都应该被直接丢弃,且不登记(Logging),也不报错误。但是FC Credits必须要被更新,以维持链路的正常操作;
-
该Function接收到的任何Completion都应该被当做Unexpected Completions,然后直接丢弃,且不登记,也不报错。
转载链接
- 两种中断传递方式
- 中断机制介绍(INTx)
- 中断机制介绍(MSI)
- 中断机制介绍(MSI-X)
- 复位机制介绍(Fundamental & Hot)
☆