PCIe split transaction协议

在解释completion timeout机制前,我们首先说一下PCIe split transaction协议是什么,以及为什么PCIe要选择split transaction?
Split transaction协议是从PCI-X总线的引入的一个重要特性,该传输协议替代了PCI总线的delayed 数据传输方式,提高了Non-Posted transaction的传输效率。
Split transaction交互过程,如果上图所示:
-
requester 发起一个read transaction。
-
read请求到达completer,但是completer不能马上返回data(completer需要准备对应的数据)。
-
completer会记住这个transaction(address、transaction type、byte count、requester ID等)。
-
completer 返回split的response(ACK或者NCK),此时对PCI-X总线而言, requester可以结束整个read request的bus cycle,其他的request可以继续占用总线了。
-
completer准备好数据后,重新申请总线,初始化一个split completion bus cycle并使用split completion返回数据。
-
requester收到completion with data,整个read request完成。
相对PCI而言,PCI-X这种completer准备好数据后,主动发起split completion的方式类似write bus cycle。在两个bus transaction(read request和split completion transaction直接)之间,bus可以被其他的transaction利用,这种处理方式有效提高了PCI-X总线的使用效率。PCIe总线继承了PCI-X的这种 splittransaction。
根据PCI Express System Architecture的数据,相对PCI的50%-60%的传输效率,这种split的方式可以把PCI-X传输效率提高到85%。


Completion timeout机制

Split transaction带来效率提升的好处,也带来了风险:requester可能无法接收到期望的completion(可能是completion被错误地路由到别的地方导致requester永远不能收到completion,也可能是completer返回completion比较慢,或者requester和completer之间链路的问题导致超过了requester的等待时间,completion都没有返回到requester)。当这种情况发生时,为了让requester有一个恢复机制,就定义了completion timeout机制。
针对completion timeout机制,协议规定如下:
(1)具备发出需要completion的request(Non-Posted request)能力的PCIe设备,必现要实现completion timeout机制。
由于switch不会主动发出需要completion的请求(即switch不会主动发起non posted请求),因此,completion timeout机制仅仅适用于RC、PCIe-PCI bridge和endpoint。
(2)Configuration software可以disable掉completion timeout机制。Completion timeout的大小可以通过Device ctrl 2 寄存器的completion timeout value字段设置。Completion timeout通过requester来报错,也就说了completion timeout的错误是requester发出的。
(3)对于memory read request,可能需要多个completion,只有当requester收到了所有的completion后才认为request完成了。如果在completion timeout前,requester只收到了部分但不是全部的completion,requester可以保存或者丢弃completiontimeout前接收到的数据。

Completion timeout相关的reg


Device capabilities 2 reg 的bit[3:0] Completion Timeout Ranges Supported,这个字段规定device function支持的completion timeout value。值得注意的是It is strongly recommended that theCompletion Timeout mechanism not expire in less than 10 ms,也就说Range A 50us to 10ms的这个Range是不被推荐的。
Device capabilities 2 reg 的bit[4] Completion Timeout Disable Supported字段显示是否支持disable completion timeou机制。
对于RootPort来说,Completion Timeout Disable Supported是可选的。


Device control 2 reg 的bit[3:0] Completion Timeout Value,这个字段规定device function等待completion的时间。该字段必须是Devicecapabilities 2 reg 的bit[3:0] Completion Timeout Ranges Supported的range。
Software可以在任何时候改变completion timeout value字段。如果在completion timeout字段被修改时,还有pending的request,对于outstanding的request,hardware可以使用新的或者旧的completion timeout value。hardware计算completion超时的起始时间可以从completion timeout value被修改的时间点算,也可以从request发出的时间点算。
值得注意的是Spec再一次强调:It is strongly recommended that the Completion Timeout mechanism not expire inless than 10 ms。
Device control 2 reg 的bit4 Completion Timeout Disable用来disable completion timeout机制(必须要Device capabilities 2 reg 的bit[4] Completion Timeout Disable Supported字段为1b时,才能设置该bit)。
Completion timeout产生的场景

当requester发出Non-Posted request,并且直到requester的completion timeout超时,requester都没有收到对应的completion。那么,允许requester通过发出新的请求来recover这个错误。允许requester尝试恢复0次,1次或者多次,但是次数必须是有限的。如果没有后续的recovery动作,requester必须通过uncorrectable error message来标识错误。
如果completion timeout的severity是non-fatal的,并且requester 选择了通过发送一个新的请求尝试recovery,requester必须首先把当前的错误当做Avisroy Non-Fatal的错误处理。支持AER的requester通过发送ERR_CORmessage来标识这个错误。

常见的CPU的Completion timeout value
CPU型号 | Code name | Cap: Completion Timeout Ranges Supported | Ctrl: Completion Timeout Value |
11th Gen Intel(R) Core(TM) i7-11700K | ABC | 50us-50ms | |
12th Gen Intel(R) Core(TM) i5-12600K | Alder Lake | ABC | 50us to 50ms |
Intel(R) Xeon(R) Silver 4309Y | ABC | 260ms-900ms | |
Intel(R) Xeon(R) Gold 6130 | BCD | 260ms-900ms | |
Intel(R) Xeon(R) Gold 6430 | Sapphire Rapids | ABC | 260ms to 900ms |
AMD Ryzen 7 5700G | ABCD | 65ms-210ms |
PCIe spec强烈推荐completion timeout的时间不要少于10ms。按照经验,intel CPU一般会设置在65ms-210ms(sandy bridge)或者下一档次260ms-900ms(Ivy bridge及其之后的微架构)。


Intel CPU的架构和timer
intel CPU不同代的CPU微架构改变很大,下面是sky lake的CPU架构。

在sky lake CPU中有非常多的timer(见下图table6-30),每个timer对应不同sub-modules的超时时间。其中一个sub-moudule叫做IIO,PCIe错误仅仅是IIO中的一种错误,RootPort的completion timeout只是PCIe错误中的,IIO后面还有一个Cbo的TOR timeout和Core的3-strike。如果CPU的RAS是银河系的话,RootPort的completion timeout只是地球,仅仅是CPU RAS中的沧海一粟。






sky lake CPU中有个CHA(caching home agent)模块,该模块内有个Cbo的模块,在CBo内部有个TOR的模块,其全称是 table of request,TOR用来track pending CBo transaction。sky lake CPU的MCE的一种叫做TOR timeout就是说这个模块中的transaction超时了。
Purley platform fault coverage
由于CPU内部每个timer计算超时的起始时间点不同,CPU操作都是流水线的,再加上PCIe是spilt transaction协议,不用等上一笔request返回completion,只需要completer返回ACK或者NCK,CPU(requester)就可以发起下一笔请求,并且Non post、post、completion之间是有order要求的,这样会导致大量的transaction的累积效应和反压。因此,尽管Root Port的completion timeout的超时时间(通常都是几百毫秒级别的)小于MCE的时间(通常都是秒级别的)。在外设异常的场景,completion timeout仍然无法保证CPU访问外设时不出现MCE。
如果RootPort出现completion timeout的错误,应该去读header log reg或者抓trace,来看看是否是访问外设导致的,如果是访问外设导致,则需要分析是RootPort的completion timeout value设置不合理,还是switch 路由问题,或者外设响应缓慢。如果不做分析,也不管CPU架构和其他的几个timer的大小,贸然把RootPort的completion timeout改大。当外设异常时,可能会掩盖RootPort的completion timeout错误,但是这种做法可能会导致TOR timeout或者3-strike。