1.概述
PCIe总线事务层位于应用层和数据链路层之间。发送时将应用层的数据请求转换成PCIe总线事务,然后发送到数据链路层。接收时,从来自数据链路层报文中提取PCIe总线事务,并将数据提交到应用层。事务层使用TLP表示PCIe总线事务,其由头、数据(若有)和尾(可选)组成。下图展示了TLP的发送过程和接收过程。
PCIe总线事务类型和地址空间对应关系如下表所示:
Address Space | Transaction Types | Basic Usage |
---|---|---|
Memory | Read Request/Completion,Write Request,AtomicOp Request/Completion | Transfer data to/from a memory-mapped location |
I/O | Read Request/Completion,Write Request/Completion | Transfer data to/from an I/O-mapped location |
Configuration | Read Request/Completion,Write Request/Completion | Device Function configuration/setup |
Message | Baseline(including Vendor-Defined) | From event signaling mechanism to general purpose messaging |
2.TLP格式
TLP由前缀(TLP Prefixes,可选)、头(Header)、数据(Data,若有)和尾(TLP Digest,可选)组成,具体如下图所示。TLP前缀由PCIe V2.1总线规范引入,分为Local TLP Prefix和EP-EP TLP Prefix两类。用来实现PASID(Process Address Space ID) 、MR-IOV(Multi Root I/O Virtualization)、Peer-Peer及其他verndor自定义的功能。TLP头定义了事务类型、路由信息、数据长度和完成状态等信息,非常重要。TLP尾是可选的End‐to‐End CRC,用来校验整个TLP报文。
2.通用TLP头格式
TLP头定义了PCIe总线事务类型、路由、数据长度等信息。TLP头由12字节或者16字节组成,通用TLP头格式如下图所示。
下面的表描述了TLP头各个位域的的意义。
位域 | 意义 |
---|---|
FMT | TLP格式,定义TLP头的长度(12字节或者16字节)和是否携带数据 |
Type | TLP类型,和FMT一起定义总线事务类型 |
TC(Traffic Class) | 总共定义了TC0-TC7 8种传输类型,用来控制PCIe总线的QoS。TC0为通用的传输类型(必须支持),不保证实时性和顺序,TC1-TC7根据WRR或优先级区分。TC0和VC0对应,其他TC和VC的映射关系在VC Capability中 |
Attr | Attr分为两个域,分别是Byte1的Attr[2]和Byte2的Attr[1:0]。Attr[2]和Attr[1]用于设置PCIe总线顺序属性,Attr[0]用于设置Cache一致性 |
TH(TLP Processing Hints) | PCIe V2.1引入的一个重要功能,TH为1时表示TLP头部有TPH信息。发送端使用TPH信息通知接收端将要访问数据的类型,以便接收端合理的安排数据缓冲,降低访问延时 |
TD | 表示TLP是否包含TLP Digest,即End‐to‐End CRC |
EP(Error Poisoned) | 表示TLP是否发生错误 |
AT( Address Type) | 对于Memory and Atomic请求,用于支持虚拟化系统地址转换。主要目的是方便多个虚拟机共享同一个PCIe设备。0x0-默认/不转换,0x1-转换请求,0x2-已转化,0x3-保留 |
Length | TLP报文中数据负载长度,单位为DW(4字节),Length=0表示最大1024个DW,即4KB,Length=0x3FF表示1023个DW。若长度不是DW的整数倍,需要借助DW BE字段 |
First DW BE(First DW Byte Enables) | 表示第一个DW的有效字节 |
Last DW BE(Last DW Byte Enables) | 表示最后一个DW的有效字节 |
2.1.FMT和Type
FMT和Type字段共同定义了PCIe总线事务类型,具体见下图。
注:
- Msg和MsgD Type字段的bit[2:0](rrr)表示路由方式,由Byte1中的bit[7]、bit[3]、bit[1]决定。
- Local TLP Prefix的L3-L0由TYPE[3:0]决定。
- End‐to‐End TLP Prefix的E3-E0由TYPE[3:0]决定。
- TLP头为3DW/12字节时,若携带数据或者请求数据,则数据地址为32位。
2.2.Attr
Attr[2]和Attr[1]用于设置PCIe总线顺序属性。具体见下面的图。0x0为默认顺序,即PCI强序模式,后面的报文必须等待前面的报文传输完成。0x1为PCI-X弱序模式,允许总线对报文进行重新排序。0x2为基于ID的顺序模式。0x3为基于ID的弱序模式。
Attr[0]用于设置Cache一致性
2.3.First/Last DW BE
当数据的起始地址和结束地址没有按DW对齐时,需要使用First/Last DW BE字段。First/Last DW BE通常用于Memory、I/O和Configuration请求。First DW BE表示第一个DW的有效字节。Last DW BE表示最后一个DW的有效字节。
- 如果数据长度在1DW之内,则First DW BE对应的位设置为1,Last DW BE全为0。如果数据长度超过1DW,Last DW BE不能全为0。
- 如果数据长度超过1DW,则First DW BE字段至少有一个位设置为1,不能出现First DW BE全为0的情况。
- 如果传送的数据长度大于等于3DW,则First DW BE和Last DW BE字段中不能出现不连续的置1位。
- 如果数据长度在1DW(包括)之内,则First DW BE允许不连续的位置1,此时允许传输1DW的第1、3字节或者第0、2字节。
- 如果数据长度在2DW(包括)之内,则First DW BE和Last DW BE字段中允许出现不连续的置1位。
- 对于Zero-Length读请求,Length=0x1,而First DW BE和Last DW BE字段都为0,即所有字段都不使能,即读完成请求中不包含数据。Zero-Length读请求实现了读刷新,确保使用Posted请求(存储器写)的数据已完全写入目的地。
- 对于Zero-Length写请求,Length=0x1,而First DW BE和Last DW BE字段都为0。Zero-Length写用于某些明确的协议中,如LN协议。
3.事务描述符
如下图所示,事务描述符由三部分组成,分别为TC、Attr和事务ID(Transaction ID)。TC和Attr前面描述过,这里不赘述。事务ID(Transaction ID)由Requester ID和Tag组成。
Requester ID记录了请求报文的来源,当源设备和目标设备需要交互时,则源设备将自己的Requester ID填到请求报文中发送给目标设备,目标设备根据源设备的Requester ID发送响应报文。只有TLP报文使用ID路由时,Requester ID才有真实意义。Requester ID字段描述了源PCIe设备Function的Bus Numner、Device Number和Function Number。对于Non-Posted请求(存储器读、I/O和配置读写请求,请求需要使用完成报文应答),其请求报文必须包含Requester ID,目标设备收到请求报文之后,使用完成报文进行响应,而完成报文中使用源设备的Requester ID。对于Posted请求(存储器写请求),PCIe总线规范没有明确规定是否需要Requester ID,但一般硬件都实现了该功能。与Requester ID类似的是Completer ID,只是Completer ID保存是发送完成报文PCIe设备Function的BDF。
Tag是一个标签,由源设备产生,和Requester ID一起组成Transaction ID。在一段时间内,同一个PCIe设备Function发送的Non-Posted请求,不能出现两个相同的Transaction ID,且在没有获取到完成报文之前,该Transaction ID不能释放。设计Tag字段的目的是应对报文出错或者丢失需要重传的场景。PCIe4.0版本将Tag字段扩展到10位。
参考资料
- PCIEXPRESS体系结构导读
- PCI Express technology 3.0
- PCI Express® Base Specification Revision 5.0 Version 1.0