硬件总线基础07:PCIe总线基础-事务层(1)

说在开头:关于我的世界(4)

几年前追过一个综艺:《导演请指教》。不仅仅是因为节目中那一部部小电影的诱惑力,更让人上头的是各方的点评:制片人,学院派,影评人,发行人、大众等等,每个人对电影的理解和解读有所不同,甚至完全相反;这个综艺淋漓尽致地表现了每个人眼中的那只“鸡”是什么(人生经历不同而导致“我的世界”的差异),以及他的“屁股”是如何决定他“脑袋”的。我们将自己代入进去,在他们的一波波争论中去寻求自己“世界”的同道者,暗骂“我”所认为的胡说八道者,这是件让人上瘾的事。不过说到底任何人的理解都不过是“个人世界”的投影,我们看的不是电影本身,而是我们自己的心(我们看待任何事情的态度和想法,都只是自己内心世界的反应,它反应的不是这个事件的本身,而是你自己)。

在纵观该综艺所有的解读人中,让人印象最深刻的是陈铭。我发现他的言论抓住了大多数人共情点(共通点),也获得了最多的认同。每个人生活在“自我世界”中,我理所应当的道理,在别人眼里是歪理邪说,对世界不同的理解、不同角度、所处不同位置甚至不同心情都会有不同的观点。但同时我们生长在时下的世界,说着同样的语言,有着基本相同的伦理道德观念,总有一些为我们大多数人认同的、不可抗拒的底线、准则,这是我们共通的:架立在每个“自我世界”之间的桥梁。陈铭如罗翔一样能抓住了大部分普通人“自我世界”中的共通点,并有逻辑的表述出来,这是一种强大的力量。

正如那句话所说:“一千个人的心中有一千个哈姆雷特”;那么任何一本书,一部电影,一张画,甚至一段文字,每个人的感受都是不一样的,这个感受来自于你的道德衡量、认知、人生阅历、文化背景等等(你的世界);我们在故事中感受到的是自我世界,至于作者想表达什么已经不重要,一旦呈现在公共面前,作者本身的理解也只是对故事的其中一个解读。我写的所有这些狗屁倒灶的东西,大家都跟我有一样的理解?我的理解一定是“对”的么?甚至我的表述已经准确地表达了我所想的么?我想这些统统都不重要,而重要的是你内心的真实感受。

​好,那么我们最后还有一个问题:既然我们都生活在“自己”的世界中,我们如何能认识到自我以及这个世界本质的真理呢?如此我们能够消除心中所有的疑惑,最终达到与天地同在。后续“说在开头”的内容,我们就要来看一看这个问题。

李敖大师说,不要跟人谈理想和哲学。这两者是纯主观的东西,每个人都会有自己所不同的哲学和理想,我的想法对大家来说很可能是狗屁不通的,所以每个人只能跟自己谈,这的确让我非常惶恐。

最后分享一个佛陀的故事,乔达摩.悉达多受到一群小朋友的供养,在菩提树下最终悟道成为佛陀,第二天佛陀面对这群小朋友开展了他悟道之后的第一次布道(关于怎样吃橘子):我们平时吃橘子,可以吃的很专注或不专注,那怎样才算是专注呢?当你吃橘子时,很清楚地知道自己在吃橘子并感受到它的香甜:你剥橘子皮时,你知道自己在剥它;当你将一瓣橘子剥下来放到口中时,你知道自己把一瓣橘子剥下来放到口中;当你在品尝橘子的美味时,你察觉着你在经验着那橘子的芳香美味。当我每吃一瓣,都察觉着它是如何难得和美好,而且当我吃橘子的时候,一直没有忘记它;所以对于我来说,橘子是非常真实的,如果橘子是真实的,那么吃它的人也便是真实的了。这就是怎样专注地吃橘子。

那怎样又是不专注的吃橘子呢?当你吃橘子时,你并不知道自己在吃橘子,你并没有经验着橘子的香甜:你剥橘子的皮时,你并不知道你是在剥它的皮;你把一瓣橘子撕下来放入口中,但你却不知道自己正在把一瓣橘子放入口中;当你嗅到橘子的芳香和尝到橘子的美味,你也不知道你嗅着它的香味和品尝着它的味道。这样吃橘子,你是不会欣赏到它可贵和美好的性质的。当你没有察觉到自己在吃橘子,那橘子便不是真的了;而如果橘子不是真的,那吃橘子的人就不是真实的了。这便是不专注的吃橘子。

佛陀告诉我:小朋友,你想认识这个真实世界,修行的途径是:要时刻经验着真实的世界,而不是活在自己头脑的虚幻(想象)中。

一,TLP包概述

事务层是PCIe总线层次结构的最高层(核心层并不归PCIe总线协议管),它接收PCIe设备核心层的数据请求,并将其转换为PCIe总线事务(这些PCIe总线事务在TLP包中定义)。PCIe总线集成了PCI/PCI-X总线的大多数总线事务:存储器(Memory)读写、I/O读写、配置(Configure)读写总线事务和新增的Message总线事务(如下图所示),并增加了原子操作总线事务

——总线事务:源设备发送一个请求包到目标设备,目标设备作为响应请求而返回一个或多个完成包,这二者组合起来就是一个事务;即,一个事务由一个请求包以及所有返回的完成包共同组成

——古希腊哲学家德谟克利特认为:“原子”是组成世界的最小单元,是不可分割的;所以关于原子操作的定义:表示该事务是独立又不可分割的操作,不会被其它线程所中断

这些总线事务可以分为两类: Non‐Posted 和 Posted;

1. 对于Non-Posted总线事务分为两部分进行(Split):1,源设备先向目标设备提交总线读写请求;2,目标设备后向源设备发送完成(Completion)报文(Cpl或CplD)。存储器读、I/O读写和配置读写都是Non-Posted总线事务,PCIe总线使用Split传输方式处理所有的Non-Posted总线事务。

——PCIe继承了PCI-X的Split传输方式,正如我们在《PCI总线基础》中所说,Split传输方式是目标设备收到Non-Posted请求后,主动的将数据发送给给源设备,从而减少了PCI总线不必要的等待时间,提升了PCI总线传输效率。

——I/O 写和配置写请求,尽管它们在发送给目标设备的命令中就已经包含了要写入目标设备的数据,但是这两种总线事务依然需要目标设备在写入完成后返回完成包(Cpl或CplD),以此来让源设备确认数据被正确无误的写入到了目标设备中。

2. 对于Posted总线事务:包括了内存(Memory)写和消息(Message)请求;这意味着目标设备在完成这些总线事务后不需要向源设备返回完成包 TLP。

——Posted总线事务对整体性能提升是有好处的,因为源设备不需要等待响应,也不需要承担对完成包进行处理的额外开销;这里做出的取舍是:源设备无法得到写请求是否被正确无误的完成的反馈信息。

——Posted总线事务是一种不错的操作方法,虽然无法得到反馈信息,但是发生错误的可能性比较小,同时得到了比较明显的性能提升;但是尽管它们不要求返回完成包,Posted写操作仍然要参与数据链路层的 Ack/Nak 协议,以此来保证较为可靠的数据包传输。

在PCIe总线中,不同总线事务采用的路由方式不同,PCIe总线继承了PCI总线的地址路由和ID路由两种方式,并增加了“隐式路由”的方式;如下图所示,TLP包起始于源设备的事务层,终止于目标设备的事务层;当 TLP 途经源设备的数据链路层以及物理层时,这两层分别会向数据包中添加一些信息(头和CRC等),目标设备的数据链路层和物理层会分别根据源设备对应层所添加的信息来进行校验,以此确认数据包是否在链路的传输过程中发生了错误。

1,TLP包传输过程

当处理器访问PCIe设备时,所发送的数据会先经过PCIe事务层封装成一个或多个TLP包,而后通过数据链路层和物理层发出去,其格式如下所示。我们可以从中发现这个TLP包中的不同部分是分别由不同的层来添加的:红色代表事务层,蓝色代表数据链路层,绿色代表物理层(各位胖友看下,这操作和格式像不像以太网报文?)。

1. 设备核心层负责将组成 TLP 的核心部分的信息发送给事务层,即上图中红色的Header和Data。每个 TLP 都会有一个首部,但有些 TLP 会没有数据部分(举个栗子:读请求)。事务层可选择添加 ECRC(End-to-End CRC, 端到端 CRC)字段,ECRC 由事务层进行计算并附加在数据包的后面;

——CRC 是循环冗余校验码,被几乎所有的串行传输架构所使用,因为其实现简单且提供很强的错误检测功能

——CRC可以检测“突发错误”:一串重复的错误比特;这一串比特的长度取决于 CRC 的长度(对于 PCIe 来说是 32比特),这种类型的错误在发送一长串比特时会遇到,因此 CRC 的这种特性非常适合于串行传输。

——ECRC 字段区域在通过源设备和目标设备之间的任何服务点(service point,即PCIe Switch或RC端口)时都不改变,这使得目的端可以用它来验证在整个传输过程中(举个栗子:经过Switch内部转发时)都没有发生错误。

2. TLP 的核心部分由事务层转发至数据链路层,数据链路层负责在 TLP 中添加一个序列号(Sequence)和链路层校验LCRCLink CRC, 链路CRC;LCRC 被接收端用来进行错误检查,并将链路上传输的每个数据包的检查结果都汇报给发送端。

——LCRC只负责PCIe物理链路两端的传输是否正确:当数据包到达PCIe Switch的一个端口,并进行错误检查(LCRC)和路由检查,然后当它被从另一个端口发出时,设备会计算出一个新的 LCRC 值并添加在数据包中,新的LCRC 会取代老的 LCRC

——如果 LCRC 已经证明了链路传输的正确,那么 ECRC 还有什么作用呢?因为LCRC有以个地方的传输错误没有被检查,那就是负责路由数据包的设备内部;因为数据在PCIe Switch的转发过程中(Switch内部交换过程)并不会对LCRC进行校验,此时如果转发过程中出现了错误,那么就需要更内层封装的ECRC来进行校验了;接收端对LCRC的检测只能说明对接的PCIe物理链路传输没有问题,而不能保证TLP数据包本身是否正确。

3. 数据链路层封装好的数据包被转发给物理层,物理层将其他一些字符添加到数据包中,这些字符可以让目标设备知道接下来将会接收什么(标识一个数据包的Start或Stop)。

——对于前两代的 PCIe,物理层将在数据包的头和尾添加控制字符,在PCIe 3.0 中不再使用控制字符,而是在数据包中添加一些额外的比特来提供关于数据包的信息;经过这些处理后,数据包被编码,然后在链路上所有可用通道中以差分形式传输。

当目标设备接收到了输入的比特流时,它需要对源设备组包时添加的部分进行识别和剥除,这样就能恢复出源设备的设备核心层的原始请求信息。如下图所示。

1. 物理层将会确认当前比特流中是否存在正确的“起始”、“结束”或者其他字符,并将它们剥除,然后将剥除了这些字符后的 TLP 转发给数据链路层;

2. 数据链路层进行 LCRC 以及序列号的错误校验:

1,如果是目标设备,并且检测未发现错误:数据链路层会把 LCRC 和序列号从 TLP 剥除,并转发给事务层;

2,如果是一个Switch,那么将在事务层对这个数据包进行解析评估,从它的数据包头中找到路由信息来确定这个数据包要被转发到哪一个端口。

——即使该PCIe Switch并不是 TLP 最终的目的地,它也可以对这个 TLP 进行 ECRC 校验以及在发现错误时进行 ECRC 错误汇报;但Switch不能更改这个 TLP 中的 ECRC,并希望目标设备自身可以检测到这个 ECRC 错误。

3. 如果目标设备有能力并且启用了 ECRC 校验的功能,那么将对 ECRC 进行错误校验,若校验无错误,则在事务层中将把这个 ECRC 字段剥除,使整个数据包只剩下首部和数据部分,并将这些剩余部分转发给核心层。

2,TLP包格式

如下图所示,一个完整TLP由1个或多个TLP Prefix、TLP Head(头)、Data Payload(数据有效负载)和TLP Digest组成。

1. TLP 头是TLP最重要的标志,不同TLP 头的定义不同:包含了当前TLP的总线事务类型、路由信息等;

2. Data Payload(负载):可选项,由业务类型决定;最小为0,最大为1024DW(1 DW = 16 Bit);

——举个栗子:存储器读请求、配置和I/O写完成的TLP并不需要Data Payload。

3. TLP Digest:可选项,存放ECRC校验消息,是否需要由TLP头决定;

4. TLP Prefix:可选项,主要为了扩展TLP头,支持Local TLP Prefix和EP-EP TLP Prefix两类。

1,Local TLP Prefix:主要作用是在PCIe链路的两端传递消息;

2,EP-EP TLP Prefix:主要作用是在发送设备和接收设备之间传递消息。

2.1 TLP Heard

TLP Head由3个或4个 DW组成,其中第一个DW中保存通用的TLP头,其它字段与通用TLP头的Type字段相关;如下所示,通用TLP头由Fmt、Type、TC、Length等字段组成。

——需要说明的是:如果TLP支持64位地址模式时,TLP Head的长度为4DW,否则为3DW完成报文(CplCplD)的TLP头不含有地址信息,所以其TLP头长度为3DW

接下来我们来详细讲解TLP头中的相关定义:

1. Fmt和Type字段确认当前TLP使用的总线事务:

       1,Fmt:标识TLP头的大小是3DW还是4DW,TLP包是否含有有效负载;具体含义,如下图所示;

——所有读请求TLP都不带数据,而写请求TLP带数据;而完成报文可能带或不带数据

2,Type:存放TLP的类型,即PCIe总线支持的总线事务;该字段由5bit组成,其含义如下表格所示;

——存储器读和写请求,I/O读和写请求以及配置读和写请求的Type字段相同,此时依靠Fmt字段进行区分读和写请求:Fmt字段是“带数据”(With Data)的报文表示“写”请求,而Fmt字段是“不带数据”(No Data)的报文则表示“读”报文

——PCIe总线数据报文传输方式与PCI总线相同,如上节所说:存储器写和Message 使用Posted方式,而其它请求采用Non-Posted

3,当进行存储器读、I/O读写或配置读写请求时,首先想目标设备发送数据读写请求TLP,而当目标设备接收到这些读写请求TLP后,将数据和完成信息通过完成报文(Cpl或CplD)发送给源设备;

(1)存储器读、I/O读和配置读的完成报文需要使用CplD报文,因为目标设备需要将数据传输给源设备

(2)I/O写和配置写则使用Cpl报文,因为目标设备不需要将任何数据传输给源设备,但需要通知源设备“写”操作已经完成

4,MRdLk报文:主要作用是与PCI总线的锁操作相兼容,但这会极大影响PCIe总线数据传输效率;

5,Msg(Message)报文:消息报文分别为Msg和MsgD;区别在于:MsgD传递数据而Msg不能传递数据。

2. TC字段:表示当前TLP的传输类型,PCIe定义了8种传输类型:TC0~TC7;与PCIe的QoS相关:PCIe设备使用不同的TC区分不同类型的数据传输,结合VC通道传输优先级设置;

——TC正常默认值为TC0;举个栗子:TC0传输一般数据,而TC7传输实时性要求较强的控制信息,不同TC可以使用PCIe链路中的不同VC,而不同VC的仲裁级别是不一样的

3. Atrr字段:由3Bit组成;1,Bit2表示TLP是否支持PCIe总线的ID-based Ordering;2,Bit1表示TLP是否支持Relaxed Ordering;3,Bit0表示该TLP在经过RC到达存储器时,是否要进行Cache共享一致性处理;

——ID-based Ordering和Relaxed Ordering是两种位序,一个TLP可以同时支持两种位序。

1,标准的强序模型:在数据传输路径中,PCIe设备在处理同类型的TLP时,必须等待前一个TLP包处理完成后才能被处理

2,Relaxed Ordering模型:后一个TLP包可以穿越前一个TLP包提前执行,从而提高了PCIe总线的利用率

3,ID-Base Ordering(IDO)模型:IDO模型与数据传输的“数据流”相关;PCIe链路可以根据“数据流”对TLP进行区分,IDO模型允许分数不同“数据流”的TLP之间没有序的要求,即可以“自由乱序”。

——相同数据源发出的TLP属于相同的“数据流”,而不同源数据发出的TLP属于不同的“数据流”。

——使用IDO模型,有利于Switch对发向不同Egress端口的报文进行优化处理,不需要等待之前的报文被发送出去之后才能发送之后的报文。如下图所示。

4. TH字段:表示当前TLP中含有TPH(TLP Processing Hint)信息;TLP源设备可以使用TPH信息通知目标设备即将访问数据的特性,以便目标设备合理地预读和管理数据;

——可以使目标设备根据源设备对数据的使用情况,合理地安排数据缓冲,从而降低PCIe设备的访问延时,并最大化地利用PCIe设备中的数据缓冲;主要应用于智能设备与处理器之间的数据交换。

5. TD字段:表示是否存在 ECRC(End-to-End CRC);如果当前支持这个可选的特性,并且软件也启用了它,那么设备将会给自己产生的所有 TLP 都计算并且添加上一个 ECRC。

——使用 ECRC 要求设备含有可选的 Advanced Error Reporting 寄存器,这是因为它的能力(Capability)和控制寄存器就位于 Advanced Error Reporting 寄存器中。

6. AT字段:与PCIe总线的地址转换相关,在一些PCIe设备中设置了ATC(Address Translation Cache)部件,该部件的主要功能是进行存储器域和PCI域地址转换,但主要目的是方便多个虚拟主机共享同一个PCIe设备;

1,AT字段为0xb00:TLP的Address字段没有通过ATC进行转换,存放的PCI总线域物理地址;如果PCIe设备进行DMA操作,那么该地址将被RC转化为存储器域物理地址,然后对存储器域进行读写操作;

2,AT字段为0xb01:表示当前TLP报文为“Translation Request”报文,该报文由PCIe设备通过存储器读写请求TLP发出,其目的地为TA;而当TA收到该报文后将根据I/O页表的设置,将合适的地址转换关系,通过存储器读完成TLP,发送给PCIe设备;

3,AT字段为0xb10:表示当前的TLP的Address字段已经通过ATC进行地址转换,当PCIe设备进行DMA操作时,RC不需要进行地址转换,而直接将数据发送给存储器。

7. Length字段:用来描述TLP的有效负载(Data Payload)大小;PCIe总线设置该字段的目的是提高总线的传输效率,因为目标设备可以通过Length字段提前获知源设备发送或请求的数据长度,从而合理的管理缓冲。

——PCIe总线规范规定一个TLP的Data Payload的大小为0~4096B之间。

3,TLP路由

TLP的路由是指TLP通过SwitchPCIe桥时采用哪条路径,并最终到达了EPRC的方法;之前也介绍过了,PCIe总线一共定义了三种路由方法:

1. 基于基地址(Address)的路由:存储器和I/O的读写请求TLP使用基地址路由,该方式使用TLPAddress字段进行路由选择,最终到达目的地

2. 基于ID的路由:配置读写报文、“Vendor_Defined Message”报文、CplCplD报文使用基于ID的路由,该方式使用PCI总线(Bus Number)进行路由选择

3. 隐式路由(Implicit):主要用于Message报文的传输,包括“INTx Interrupt Signaling”,“Power Management Message”和“Error Signal Mesages”等报文

——该路由方式是从下游端口到上游端口进行数据传输的路由方式,或用于RC向EP发出广播报文。

3.1 基于地址的路由

PCIe地址路由与PCI设备的地址路由方式类似,只是PCIe设备TLP进行数据传输而PCI设备使用总线周期进行数据传输;当TLP进行数据传输时,会经过多级Switch后最终到达目的地,而Switch将根据存储器读写、I/O读写请求TLP的目的地址将报文传输到合适Egress端口上。如《PCIe总线基础》中相关章节所述,PCIe Switch内包含了多个虚拟PCI-to-PCI桥,数量与Switch的端口数相同,在虚拟PCI-to-PCI桥的配置寄存器中,包含了PCI桥片能够接收的物理地址范围,而PCIe总线通过这个物理地址范围实现基于地址的路由。如下图所示,当系统软件初始化PCI总线时,将设置这些寄存器,之后当TLP通过这些Switch时根据这些寄存器值来选择合适的路径。

上图所示配置寄存器描述了虚拟PCI-to-PCI桥下游PCI子树使用的三组空间范围:I/O、存储器和可预取的存储器空间;并分别用BaseLimit两个寄存器描述。TLP使用基于地址路由时,要通过查询这两组寄存器值之后再决定传输路径。

——其中Base寄存器:表示可访问空间的基地址;Limit寄存器:表示可访问空间的大小

3.2基于ID的路由

基于ID的路由方式主要用于配置读写请求TLP、Cpl和CplD报文,另外还包括了Vendor_Defined消息报文,而PCI总线只有配置读写请求TLP采用了ID路由方式。如下图所示为基于ID路由的TLP头格式,其与基于地址路由方式的头格式不同。

基于ID路由方式的TLP使用:Bus Number、Device Number和Function Number进行路由寻址;由于PCIe总线规定,在一个PCI总线域空间中:1,最多只能由256PCI总线,因此在一个TLPBus Number8位组成;2,每条总线最多包含32个设备,因此TLP中的Device Number5位组成;3,一个设备中最多包含8个功能,因此TLPFunction Number3位组成

处理器系统在上电之后要进行PCI总线的枚举,此操作为PCI总线分配了总线号(Bus Number),并设置Switch、PCIe桥片或则EP的配置寄存器(Bus Number相关)。如下图所示PCIe Switch和桥片的Bus Number参数的设置同PCI总线中类似。(具体请参考《PCI总线基础》相关章节)

3.3隐式路由

PCIe总线中,有许多消息(Message)是直接发向RC或来自RC的报文,这些报文不使用地址或ID进行路由,而使用Msg和MsgD报文的Route字段进行路由,这种路由方式称为隐式路由。

PCIe总线定义了一些用于:中断请求、错误状态处理、锁定总线事务、热插拔信号处理和“Vendor_Defined Message”消息报文;隐式路由TLP格式如下图所示。

其消息报文的Type中的Route字段含义如下所示。

1. 当报文使用隐式路由向EP发送时,EP将对Route字段进行检查:如果这个报文来自“RC的广播报文:011b”或则“本地报文:110b”,EP将接收此报文;

2. 如果Switch收到一条隐式路由的TLP时,将根据报文的Route字段的不同而分别处理:

1,Switch的上游端口接收到来自“RC的广播报文”:将该报文发向所有的下游端口;

2,Switch接收了一条来自下游端口的“路由到RC”报文:Switch将此报文直接转发到上游端口,直至RC;

3,Switch接收了一条 “本地消息”报文:Switch接收并终结此报文,不再上传或下推。

3. 如果RC收到一个使用隐式路由的TLP时,将根据报文的Route字段而分别处理:

  1. Route字段为000b和101b:RC将接收该TLP,并作响应处理;

2,Route字段为100b:RC将接收该TLP,并结束该TLP报文的传输。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值