PCIe架构概述(四)

非报告事务

普通读:图2-18显示了一个从端点发送到系统内存的内存读取请求的示例。有关TLP内容的详细讨论,请参阅第5章,标题为“TLP Element”,但是任何存储器读取请求的重要部分都是目标地址。内存请求的地址可以是32位或64位,这也确定了数据包的路由。在此示例中,请求通过两个交换机进行路由,这两个交换机将其转发到目标,在本例中目标为根(Root)。当根(Root)对请求进行解码并识别出数据包中的地址以系统内存为目标时(地址指向系统内存),它将取出请求的数据。为了将该数据返回给请求者,根端口的事务层创建所需的完成次数,以将所有请求的数据传递给请求者。PCIe的最大有效数据载荷是每个数据包4KB,但是设备通常被设计为更小的有效载荷(低于4KB),因此可能需要更多“完成”次数才能返回大量数据。


图2-18 非报告的读取示例

这些完成数据包还包含将其引导回请求者的路由信息,因为,请求者在原始请求中包括其返回地址。此“返回地址”为PCI定义的请求者的设备ID,它是三个编号的组合:系统中的PCI总线编号,请求者在该PCI总线上的设备编号以及该设备中的功能编号。此总线编号,设备编号和功能编号组合的信息(Bus,Device,Function有时缩写为BDF)是用于返回原始请求者的路由信息。就像PCI-X一样,请求者可以同时进行多个拆分事务(split transaction),并且必须能够将传入的“完成包”与正确的请求相关联。为方便起见,在原始请求中添加了另一个值:Tag,每个请求有唯一的Tag。完成者复制此事务标记Tag并在“完成包”中使用它,以便请求者可以快速识别正在为哪个请求提供服务。


最后,完成者还可以通过在完成状态字段中设置位来指示错误情况。这样至少可以使请求者对可能出现的问题有一个宽泛的了解。请求者如何处理大多数,这些错误将由软件决定,并且超出PCIe规范的范围。


锁定读取:锁定内存读取旨在支持所谓的“原子读取-修改-写入”操作,这是处理器用于测试和设置信号量等任务的一种不间断事务。在进行测试和设置时,无法访问信号量,否则可能会产生竞争状况。为避免竞争这种情况,处理器使用了一个锁定指示器(lock indicator,或叫锁定指示符)(例如,并行前端总线上的一个单独的引脚),可以阻止总线上的其他事务,直到锁定的指示器完成(即被锁定的事务完成)。接下来的内容只是对该主题的简要介绍。


回顾一下历史,早期的PCI,规范作者就预见了PCI会真正取代处理器总线的情况。因此,PCI规范中包括对处理器在总线上需要执行的操作的支持,例如锁定的事务。但是,PCI很少以这种方式使用,最后,许多处理器总线支持的东西被放弃了。但是,仍然保留锁定周期来支持一些特殊情况,PCIe将此机制向前推进以支持旧式设备。也许是为了加快迁移的速度,禁止新的PCIe设备接受锁定的请求。仅对那些自我标识为旧版设备的用户开放这种功能。在图2-19中所示的示例中,请求者通过发送锁定的请求(MRdLk)开始该过程。根据定义,此类请求仅允许来自CPU,因此在PCIe中,只有根端口RC才能发起这种事务。   


锁定的请求使用目标内存地址通过拓扑路由,并最终到达旧式端点(Legacy Endpoint)。当数据包沿途经过每个路由设备(称为服务点)时,该数据包的出口端口将被锁定,这意味着在未解锁路径之前,不允许该方向路径的其他数据包通过。

    

图2-19:非报告的锁定读取事务协议

当完成器接收到数据包并对其内容进行解码时,它会收集请求所需的数据并使用数据创建一个或多个“锁定完成”。这些完成包使用请求者ID并被“路由”回请求者,然后它们通过的每个出口也被锁定。


 如果“完成程序”遇到问题,它将返回一个没有数据的锁定完成数据包(原始读取应当产生数据,因此,如果我们没有发现任何包含的数据,则该状态出现错误),并且状态字段将指示有关该错误的信息。请求者将理解为该锁定未成功,因此该事务将被取消,并且软件需要决定下一步要做什么。


IO和配置写入(IO and Configuration Writes):图2-20说明了未发布的IO(Non-Posted IO)写事务。像锁定的请求一样,IO周期也只能针对旧式端点EP。该请求将根据IO地址通过交换机进行路由,直到到达目标端点。当计算机接收到请求时,它将接受数据并返回一个没有数据的完整数据包,该数据包用来确认接收者接收到发送的数据包。完成包中的状态字段将报告是否发生了错误,如果发生了错误,则请求者的软件将进行相应的处理。


如果完成包没有报告错误,则请求者知道写数据已成功传递,并且现在允许执行该完成指令序列中的下一步操作。这很好的总结了非发布式写入的动机:与内存写入不同(MWr 是 Posted 的),仅知道数据将在将来的某个时间到达目的地是不够的。取而代之的是,在我们知道到数据达目的之前,下一步的操作就不会在逻辑上进行(数据被送出而且知道数据被送达才会进行下一步的操作)。与锁定操作一样,未发布(Non-Posted)的写入只能来自处理器。


图2-20:非报告的写事务协议

报告写入

内存写入:内存写入始终是发布类型(Posted),并且不需要返回“完成包”。发送请求后,请求者在继续下一个请求之前不会等待任何反馈,也不会花费时间或带宽来返回“完成请求”。因此,已发布(Posted)的写入比未发布(Non-Posted)的请求更快,更高效,并提高了系统性能。如图2-21所示,数据包使用其目标内存地址通过系统路由到目标地点/目标程序。


链路成功发送请求后,该事务将在该链路上就完成连,并且可用于其他数据包的传输。最终,完成者(目的地)接受数据,并真正完成了该事务。当然,这种方法的一个权衡是,由于没有发送“完成数据包”,因此也没有办法将错误报告给请求者。如果“完成程序”遇到错误,则可以将其记录下来并将消息(Message)发送到Root,以将错误告知系统软件,但请求者将无法得知该错误。


图2-21 报告的内存写事务协议


信息写(Message Writes):有趣的是,与目前为止我们看到的其他请求不同,消息有几种可能的路由方法,并且消息中的字段指示要使用的类型。例如,一些消息以针对特定完成者的发布型写请求(Posted),一些消息从根(RC)向所有端点(EP)广播,一些消息从端点(EP)发送则自动路由到根(RC)。要了解有关不同类型路由的更多信息,请参考第4章,标题为”地址空间和事务路由”(“Address Space & Transaction Routing”)。


消息(Message)在PCIe中很有用,有助于实现减少引脚数的设计目标。它们消除了PCI用于报告中断,电源管理事件和错误之类的边带信号(side-band signals)的需要,因为它们可以在正常数据路径上打包相关信息进行报告。

服务质量(QoS/(Quality of Service))

PCIe从一开始就被设计为能够支持对时间敏感的事务,例如,诸如音频或视频流之类的应用程序,在这些应用程序中必须及时传送数据才能有用。这被称为提供服务质量(Quality of Service),它通过添加一些内容来实现。首先,软件会通过在每个数据包中设置一个3位字段(称为流量类别TC/Traffic Class)为它分配优先级。一般而言,为数据包分配编号更高的TC有望使其在系统中具有更高的优先级。其次,在每个端口的硬件中内置了多个称为虚拟通道(VC)的缓冲区,并且根据其TC将数据包放入适当的缓冲区中。第三,由于端口现在具有多个缓冲区,并且在给定时间可以传输数据包,因此需要仲裁逻辑在VC之间进行选择。最后,交换机必须在竞争的输入端口之间进行选择,才能访问给定输出端口的VC,这称为端口仲裁,可以是硬件分配的,也可以是软件编程配置。所有这些硬件都必须在适当的位置,以使系统能够对数据包进行优先级排序。如果正确地编程和设置,这样的系统可以为给定路径提供有保证的服务。


为了说明这一概念,请参看图2-22,其中视频摄像机和SCSI设备都需要向系统DRAM发送数据。区别在于摄像机数据是时间关键的,如果到目标设备的传输路径无法匹配其带宽,帧将丢失。系统必须能够满足让摄像机捕获的视频看起来连贯的最小带宽。同时,需要准确无误地传递SCSI数据,但是花费多长时间并不重要。那么,当同时需要发送视频数据包和SCSI包时,视频流量应具有更高的优先级。QoS是指系统有能力为数据包分配不同的优先级,并以确定的延迟和带宽通过拓扑路由它们。


图2-22 QoS示例

事务序(Transaction Ordering)

在VC中,通常所有数据包都以到达时的相同顺序流过,但该一般规则也有例外,PCI Express协议继承了PCI事务排序模型,包括对随PCI-X体系结构添加的宽松排序(relaxed-ordering)情况的支持。这些排序规则确保使用相同流量类的数据包将以正确的顺序路由通过拓扑,从而避免了潜在的死锁或活锁情况。值得注意的一点是,由于排序规则仅适用于VC,并且使用不同TC的数据包可能不会映射到同一VC,因此软件将不同TC的数据包理解为没有排序关系。此顺序在事务层内的VC中维护。

流量控制(Flow Control)

串行传输使用的典型协议是要求发送器仅在对方有足够的缓冲区空间可以接收时才将数据包发送。这样可以减少总线上浪费性能的事件,例如PCI允许的断开连接和重试,从而消除了传输中的此类问题。折衷方案是,接收器必须经常报告其缓冲区空间,以避免不必要的停顿,这样报告会占用自己的一点带宽。在PCIe中,此报告是使用DLLP(数据链路层数据包Data Link Layer Packet)完成的,我们将在下一部分中看到。原因是要避免使用TLP时可能发生的死锁情况,在这种情况下,发送器由于其自身的接收缓冲区已满而无法获得接收端缓冲区大小更新。DLLP始终可以发送和接收而与缓冲区情况无关,因此可以避免此问题。该流控制协议在硬件级别自动进行管理,并且对软件透明。


图2-23:流控制基础


如图2-23所示,接收器包含保存已接收TLP的VC缓冲区。接收器使用流控制DLLP将这些缓冲区的大小通告给发送器。发送器跟踪接收器VC缓冲区中的可用空间,并且不允许发送超出接收器可容纳的数据包。当接收器处理TLP并将其从缓冲区中删除时,它会定期发送流控制更新DLLP,以使发送器获得有关可用空间的最新信息。要了解有关此内容的更多信息,请参阅第6章,标题为“流控制”/“Flow Control”。

数据链路层(Data Link Layer)

    该逻辑负责链路管理,并执行三个主要功能:TLP纠错,流量控制和某些链路功率管理。它通过生成DLLP(Data Link Layer Packet)来实现这些目的,如图2-24所示。


DLLPs(数据链路层数据包):DLLP在链路上两个相邻设备的数据链路层之间传输。事务层甚至不知道这些数据包,这些数据包仅在相邻设备之间传播,并且没有路由到其他任何地方。与TLP相比,它们很小(总是只有8个字节),这是一件好事,因为它们代表了维护链路(Link)协议的开销。

图2-24 DLLP原始和目标

DLLP组包(DLLP Assembly):如图2-24所示,DLLP起源于发送器的数据链路层,并由接收器的数据链路层使用。DLLP内核中添加了一个16位CRC,以检查接收器处的错误。DLLP内容被转发到物理层,该物理层在数据包后附加一个开始和结束字符(对于前两代PCIe),然后使用所有可用通道在链路上进行编码和差分传输。


DLLP拆包(DLLP Disassembly):当物理层接收到DLLP时,将对比特流进行解码,并删除开始和结束帧字符。其余的数据包转发到数据链路层,后者检查CRC错误,然后根据数据包采取适当的措施。数据链接层是DLLP的目标,因此它不会转发到事务层。

Ack/Nak协议(Ack/Nak Protocol)

    通过基于硬件的自动重试机制(hardware-based automatic retry mechanism)可提供图2-25中所示的纠错功能。如图2-26所示,将LCRC和序列号(Sequence Number)添加到每个传出的TLP,并在接收器处进行检查。发射器的重传缓冲区r(replay buffer)保留已发送的每个TLP的副本,直到确认在相邻设备上已收到为止。该确认采用接收方发送的Ack DLLP(正向确认positive acknowledgement)的形式,其中包含接收方成功接收的上一个TLP的序列号。当发送器看到Ack时,它会将具有该序列号的TLP以及所有在已确认的TLP之前发送的所有TLP都从重传缓冲区中清除。

    如果接收方检测到TLP错误,它将丢弃TLP并将Nak返回给发送方,然后发送方重传所有未确认的TLP,以期在下一次获得更好的结果。由于检测到的错误几乎总是瞬态事件,因此重传通常会在短时间内纠正问题。此过程通常称为Ack/Nak协议(Acknowledge/NotAcknowledge)。

图2-25 数据链路层重播机制

图2-26 数据链路层的TLP和DLLP结构

    图2‐26也显示了DLLP的基本形式,它由一个4字节的DLLP类型字段(可能包含一些其他信息)和一个2字节的CRC组成。图2‐27显示了跨交换机读取内存(memory read TLP)的示例。通常,针对这种情况的步骤如下:

1.步骤1a:请求者发送内存读取请求,并将副本保存在其重传缓冲区(replay buffer)中。交换机收到MRd TLP,并检查LCRC和序列号。

   步骤1b:未发现错误,因此交换机将Ack DLLP返回给请求者。作为响应,请求者从重传缓冲区中删除其TLP副本。

2.步骤2a:交换机使用内存地址将MRd TLP转发到正确的出口端口以进行路由,并将副本保存在出口端口的重传缓冲区中。完成器(Completer)收到MRd TLP并检查错误。

   步骤2b:未发现错误,因此完成器(Completer)将Ack DLLP返回到交换机。交换机端口从其重放缓冲区删除其MRd TLP副本。

3.步骤3a:作为请求的最终目的地,完成者检查MRdTLP中的可选ECRC字段。如没有发现错误,因此请求被传递到核心逻辑。根据该命令,设备将获取所请求的数据并返回带有数据TLP的完成内容(CplD),同时将副本保存在其重传缓冲区中。交换机收到CplD TLP并检查错误。

    步骤3b:未发现错误,因此交换机将Ack DLLP返回给计算机。Completer从其重传缓冲区中删除其CplD TLP的副本。

4.步骤4a:交换机对CplD TLP中的“请求者ID”字段进行解码,并将数据包路由到正确的出口端口,将副本保存在出口端口的重传缓冲区中。请求者收到CplD TLP并检查错误。

   步骤4b:未发现错误,因此请求者将Ack DLLP返回给Switch。Switch从其重传缓冲区中删除其CplD TLP的副本。请求者检查可选的ECRC字段,未发现错误,因此数据被传递到核心逻辑。

图2‐27 使用Ack/Nak协议的未过帐交易

流量控制

数据链路层第二个主要的功能是流控制。上电或复位后,该机制由数据链路层自动在硬件中初始化,然后在运行时更新。关于TLP的部分已经对此进行了概述,因此在此不再赘述。要了解有关此主题的更多信息,请参阅第6章,标题为“流控制”。

电源管理

最后,数据链路层也参与电源管理,因为链路与系统电源状态相关的请求和握手也可以通过 DLLP 来进行。有关此主题的详细讨论,请参阅第16章,标题为“电源管理”。

作者:极客石头

在搞事情的路上越走越远。

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注