Home PCIe事务层(Transaction Layer)(第三层)
Post
Cancel

PCIe事务层(Transaction Layer)(第三层)

请求类型

在介绍事务层之前,首先简单地了解一下PCIe总线的通信机制。假设某个设备要对另一个设备进行读取数据的操作, 首先这个设备(称之为Requester)需要向另一个设备发送一个Request,然后另一个设备(称之为Completer)通过Completion Packet返回数据或者错误信息。 在PCIe Spec中,规定了四种类型的请求(Request):Memory、IO、Configuration和Messages。 其中,前三种都是从PCI/PCI-X总线中继承过来的,第四种Messages是PCIe新增加的类型。详细的信息如下表所示:

PCIe请求包

只有Memory Write和Message是Posted类型的,其他的都是Non-Posted类型的。

所谓Non-posted,就是Requester发送了一个包含Request的包之后,必须要得到一个包含Completion的包的应答,这次传输才算结束,否则会进行等待。

所谓Posted,就是Requester的请求并不需要Completer通过发送包含Completion的包进行应答,当然也就不需要进行等待了。 很显然,Posted类型的操作对总线的利用率(效率)要远高于Non-Posted型。

那么为什么要分为Non-Posted和Posted两种类型呢?对于Memory Writes来说,对效率要求较高,因此采用了Posted的方式。 但是这并不意味着Posted类型的操作完全不需要Completer进行应答,Completer仍然可采用另一种应答机制——Ack/Nak的机制(在数据链路层实现的)

PCIe的TLP包共有一下几种类型:

PCIeTLP包类型

几种事务传输

Non-Posted Transaction(包括Ordinary Read、Locked Read和IO/Configuration Writes)与Posted Writes(包括Memory Writes和Message Writes)。

Non-Posted Transaction

Ordinary Reads (普通读)

下图显示的是一个Endpoint向System Memory发送读请求(Read Request)的例子。

PCIeOrdinaryReads

在这个例子中,Endpoint的读请求通过了两个Switch,然后到达其目标,即Root。
Root对读请求的包进行解码后,并从中识别出操作的地址,然后锁存数据,并将数据发送至Endpoint,即包含数据的Completion包,ClpD。
需要注意的是,PCIe允许每个包的最大数据量(Max Data Payload)为4KB,但实际上设计者往往会采用较小的Max Payload Size(比如128,256,512,1024和2048)。
因此,常常一个读请求会对应多个ClpD,即将大于Max Payload Size的数据分成多个包发送。如果遇到错误,则Root会通过Completion包告知相应的Endpoint。 (Payload 4KB正好对应linux MMU的页(page)大小,默认也是4KB)
注:Root向发送请求的Endpoint发送Completion包,是通过Request包中的BDF信息(Bus,Device和Function)进行查找对应的Endpoint的。

Locked Reads

Locked请求实际上是PCIe为了兼容早期的PCI总线而设置的一种方式,对于非PCI兼容的设计中,是不允许使用Locked操作的。 并且也只有Root可以发起Locked请求操作,Endpoint是不可以发起Locked请求操作的。下图显示的是一个简单的Locked Read请求操作:

PCIeLockedReads

Locked Read主要用于支持一种叫做Atomic Read-Modify-Write操作,这是一种高优先级且不可被打断的操作。主要用于测试链路状况等任务。
(针对PCI设备,PCIe设备禁止使用Locked操作)
此外,Locked操作采用的是目标存储寻址(Target Memory Address)来寻找Legacy Endpoint(PCI设备),而不是采用前面介绍的BDF

个人补充:这个Locked Read是PCIE用来兼容老的PCI的一种方式,本身PCIE设备是不会使用这种方式的, 只有在PCIE中桥接了老的PCI设备时,访问老的PCI设备时才会用到这种读。为了兼容老的PCI设备专门做的。

IO/Configuration Writes

下图是一个Non-Posted IO写操作的例子。和Locked操作一样,IO操作也是为了兼容早期的PCI设备,在PCIe设备中也是不建议使用。

PCIeIOWrite

Posted Writes

Memory Writes

前面的文章有所提及,PCIe中的Memory写操作都是Posted的,因此Requester并不需要来自Completer的Completion。一个简单的Memory Writes例子如下图所示:

PCIeMemoryWrite

因此没有返回Completion,所以当发生错误时,Requester也不会知道。但是,此时Completer会将错误记录到日志(Log),然后向Root发送包含错误信息的Message。

Message Writes

和其他的几种类型不太一样,Message支持多种Routing方式。比如Requester可以将Message发送至一个指定的Completer, 但是不管指定的Completer是不是Root,Root都会自动的收到来自任何一个Endpoint发送的Message。 此外,当Requester是Root的时候,Requester还可以向所有的Endpoint进行广播发送Message。

不得不说,Message机制的提出帮助PCIe总线省去了很多PCI总线中的边带信号。 PCI中很多用于中断、功耗管理、错误报告的边带信号,在PCIe中都通过了Message来进行实现了。

服务质量(QoS)

PCIE支持QoS,PCI和PCI-X不支持。QoS,包括传输速率,有效带宽,延迟,优先级,误码率等等。 比如,音视频相对于硬盘类存储设备,需要更高的优先级,以及稳定的带宽保证,低延迟保证。

PCIe Spec中为每一个包都分配了一个优先级,通过TLP的Header中的3位(即TC,Traffic Class)。如下图所示:

PCIeTC

TC值越大,表示优先级越高,对应的包也就会得到优先发送。一般来说,支持QoS(Quality of Service)的PCIe总线系统, 对于每一个TC值都会有一个独立Virtual Channel(VC)与之对应。这个Virtual Channel实际上就是一个Buffer,用于缓存数据包。

注:当然也有那些只有一个VC Buffer的,此时不管包的TC值如何,都只能缓存在同一个VC Buffer中,自然也就没有办法保证按优先级传输了。 这样的PCIe设备称之为不支持QoS的PCIe设备

PCIeQoS_example

图中左下角的Endpoint(即Isochronous Traffic)的优先级(假设为7)比右边的Endpoint(即Ordinary Traffic)的优先级(假设为0)要高。 因此,在Switch中,来自左边的Endpoint的包会得到优先传输。而Switch的这种判决操作叫做端口仲裁(Port Arbitration)。 (Switch 将两个数据包分别移动到各自的虚拟信道缓冲区中Virtual Channels,VC0和VC7,VC缓冲区的优先级是可配的, 假设VC7优先级更高,则VC7优先发送,因为公共的出端口就一个。这样就实现了QoS 带宽保证,低延迟保证)

默认情况下,VC Buffer中的数据包是按照包达到的时间顺序,依次放入VC Buffer中的。但是也并不是总是这样, PCIe总线继承了PCI/PCI-X总线关于Transaction-Ordering和Relaxed-Ordering的架构,但也只是针对相同的TC值才有效。 关于Transaction-Ordering和Relaxed-Ordering,可以去参考PCI-X的Spec。

流量类别TC和虚拟信道VC

TC是在数据包内发送的一个TLP头字段,在端到端通过结构时没有改变。本地应用软件和系统软件应根据性能要求确定某个TLP使用什么样的TC标志。 VC是物理缓冲区,它通过使用发送和接收器虚拟信道缓冲区,提供一种在物理链路上支持多个独立逻辑数据流的手段。 不同的TC会被映射到不同的VC,最简单的方式是将TC和VC一一对应。

PCIeTC号与VC缓冲区

端口仲裁和VC仲裁

对于每个出端口,交换器能实现两种类型的仲裁:端口仲裁和VC仲裁。 端口仲裁在抵达不同的入端口、但映射到公共出端口的同一虚拟信道(经过TC-VC映射之后)的两个数据包之间进行仲裁。端口仲裁器能实现循环仲裁、加权循环仲裁或基于时间的可编程循环仲裁方案,可通过配置寄存器来选择。 VC仲裁发生在端口仲裁之后。对于给定的出端口,来自所有VC的数据包竞争同一个出端口发送。VC仲裁解决不同的VC缓冲区中的TLP转发至链路的顺序问题。所支持的VC仲裁策略包括严格的优先级仲裁、循环仲裁和加权循环仲裁方案,可通过配置寄存器选择。 另外,端点设备Endpoint和只有一个端口的Root Complex不支持端口仲裁。它们仅支持处理层VC仲裁。

PCIe端口仲裁和VC仲裁

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

PCIe数据传输

PCIe数据链路层(Data Link Layer)(第二层)