2.1.2 ATS地址转换完成
TA在收到地址转换请求之后,需要给Device/Function反馈转换结果。Device/Function收到TA反馈的ATS转换完成包后会根据完成状态更新其ATC或将该地址标记为不存在,并依据完成结果进一步发送经过/未经地址转换的存储器读写请求。
1) ATS地址转换完成帧格式
转换完成TLP头标如下图所示。
- Cpl.Status: 地址转换完成状态。000b -> 成功;001b -> 不支持的请求(UR),TA地址转换失败。Device/Function收到该状态后需关闭ATC,且在重新开启ATC之前不应发送任何已转换地址的内存访问请求;010b -> 配置请求重传(CRS),若Device/Function收到该状态,需将其当作畸形包处理;100b -> CA,TA出现异常导致其无法处理该转换请求;其他 -> 预留,若 Device/Function收到该完成状态,当UR处理。只有在状态为000b时才表示地址转换成功,该头标后边紧跟data包,否则没有data包。
- Byte Count:
- Lower Address:
- TC: Cpl/CplD的TC应与该地址的转换请求TC值相同。
若TA无法对Device/Function要求转换的地址进行转换,TA会回复Cpl,此时Byte Count及Lower Address域需要置0,但实际应用中不建议采用这两个域中的值做任何判断。若ATS地址转换成功,在completion消息包后应紧跟携带有转换后地址的数据包CplD,其格式如下图所示。
各域的解释如下表:
补充解释:
- Translated Address:Device/Function收到CplD后,若W=0且R=0,或U=1,则Device/Function不能使用当前转换地址。一旦转换地址缓存进ATC,Device/Function不能通过除地址转换作废协议以外的任何方式修改或删除ATC中该地址Entry。在开启ATS之前或收到转换CplD之前,不能通过任何方式填充ATC。开启ATS能力之前的ATC中的内容在开启了ATS后不也能直接使用,要么忽略不用,要不通过invalid协议将其作废,要使用的话需重新发送地址转换请求。
- S:值0b表示4096Byte,为1的话,需要继续看地址bit[62:12]的值,bit[12]=1 -> 8096byte,bit[12]=1 & bit[13]=0 -> 16384byte,以此类推,参照图。bit[63:12]全为1时的行为尚未定义。若该size值比STU小,应将该笔TLP视为UR。该规则同样适用于invalidate完成TLP,bit[63:12]全为1时表示invalid所有ATC中的内容。
- U:对于命令缓存等复用率很高的地址,将转换后的地址存入ATC,每次访问的时候直接发送转换后地址能够提升效率;但是对于数据缓存等复用率很低的地址,数据变化较频繁,地址映射变化也频繁,这样当地址映射发生变换的时候,TA就可以不用发送该地址的invalid给ATC。但是,当U=1或W/R=1时,ATC可以对该地址的U/W/R/Exe/Priv/S进行缓存,若该地址的这些属性发生变动,TA仍然需要发送invalid给ATC。
注意:地址转换完成TLP可以设置其Attr为宽松排序来提升整体性能。
2)有多笔地址转换的转换完成的情况
通过设置转换请求TLP头标的Length域,ATC可以在一次地址转换请求中请求TA返回多笔连续虚地址的地址转换。在地址转换请求size(完成长度*4)不大于最大读请求size(或RCB)前提下,Length可设置为所请求转换长度的两倍。若Device/Function请求多笔转换,在不超过转换请求数量的情况下TA可返回一笔或多笔转换结果,即便是TA返回的转换包少于请求的数量,也不视为出错。
若转换完成包含多笔地址转换数据,所有的转换结果中size必须相同,且相邻地址转换数据对应的虚地址应该是连续的。
若转换数据的R=0且W=0,TA需设置size域及转换后地址域的低bit位设置合适的值。
一次成功的ATS地址转换完成应包含至少一笔CplD,转换完成包中每一笔转换地址都在地址转换请求的范围内。
若转换完成CplD的Byte Count值大于Length值的四倍,则意味着需要额外的转换完成CplD才能结束当前的转换完成事务。
若转换完成CplD的Byte Count域值等于Length域值的四倍,该CplD意味着其对应转换请求的结束。此时,若Byte Count和Lower Address的和不是RCB的多(>=1)倍,说明当前CplD是这多笔转换完成包序列的最后一笔CplD。若此前没有收到过该地址转换请求的其他CplD,则表明出现错误(请求了多笔只收到一笔,当让是出错了),此前收到的转换结果应全部丢弃。
注意⚠️⚠️📢📢:若干一次请求了多笔地址转换,实际返回的地址转换完成包数量有可能笔请求的多(CplD序列被拆分),也有可能比请求的少(CplD被截短)。有诸多原因会使TA截短CplD,例如Device、Function请求对一段地址范围的地址进行转换,但只有部分有效,TA就会将无效的部分截去,只留有效的部分并返回CplD,此时有效地址转换的CplD不会报错。有诸多原因会使TA拆分转换完成CplD,例如地址转换请求的地址范围跨越了RCB边界,TA就会将一笔请求完成拆成两笔CplD进行发送。
✨2.2 ATS地址转换作废协议(ATS Invalidation)
如果TA发现其本地某个地址映射发生变化,其需告知Device/Function无需继续在ATC中维护该虚地址Entry。TA通过给Device/Function发送一笔或多笔带有作废地址信息的地址转换作废请求来关闭ATC中该虚地址Entry,单笔作废请求对应至少一笔作废完成包。以单笔地址转换作废请求及作废完成为例,ATS地址转换作废操作如下图所示。
ATS地址转换作废动态流程有以下三步:
- 系统软件更新TA的地址转换表ATPT后,TA发送对应地址的转换作废请求给Device/Function;
- Device/Function收到来自TA的地址转换作废请求后,将其ATC指定虚地址Entry清除(但也不能立即清除)。但Device/Function不必立即清除其ATC中的对应entry;
- Device/Function在确保发送队列中所有使用待作废转换后地址TLP传输到TA之后,反馈作废完成包给TA。作废完成TLP中的ITAG应与其作废请求中的ITag保持一致(仅针对单笔Cpl,多笔Cpl的ITag Vector可以合并)。
2.2.1 ATS地址转换作废请求
如前文所述,当TA端地址映射发生变动时,其需要将这种变动告知ATC,使ATC中的相应地址变换作废。TA通过发送地址转换作废请求给ATC来保证ATPT及ATC地址映射的一致性。地址转换作废请求TLP的头标格式如图所示。
地址转换作废请求是带有64bit数据载荷的消息MsgD,其数据载荷中有携带有待作废的地址范围的起始值。地址转换作废请求TLP头标可采用任意TC值。作废请求中Itag值范围为0~31,用以对发出去的作废请求加以区分。在收到某笔作废请求的请求完成之前,该笔作废请求使用的ITag不允许重复使用。
若ATC在收到的作废请求size小于STU,ATC可以将其当作UR处理,也可以不全作废地址范围为大于等于STU。Device/Function在收到作废请求后需要在~1分钟(+50%-0%)之内回复完成,否则ATPT会通报等待作废完成超时并释放该作废请求使用的ITag。
作废请求的数据载荷TLP格式如下图所示。S域用以指明要作废的地址范围,使用方法与转换请求S域相同。Glocal Invalidate域是全局invalidate标志位,决定ATC是否将该作废请求应用到所有的PASID。地址位bit[63:12]全为1时表示invalid所有ATC中的内容。
2.2.2 ATS地址转换作废完成
Device/Function完成TA的地址转换作废操作后回复作废完成消息给TA。作废完成消息TLP格式如下图所示。
地址转换作废完成包是基于ID路由的消息事务,Requester ID是该ATC所在的Function ID,Device ID是发送作废请求的TA ID,其值与作废请求的Requester ID相同。考虑到一个ATC仅对应一个TA,ATC可以在其收到的第一笔作废请求中提取出Request ID作为完成事务的Device ID,接下来的每次作废完成包中都采用该ID作为Device ID,而不必每次都重新提取,从而提升系统传输性能。
完成计数域CC表示针对当前作废请求ATC需要反馈的作废完成包的数量,CC域为0时表示要发送8笔响应。TA端应能收集这些作废完成包并根据CC及ITag判断某笔作废请求是否成功完成。
作废完成包可以采用任意TC值进行发送,其值与作废请求包的TC无关。
ITag Vector用以表明该作废完成包对应哪笔作废请求,ITag Vector域与作废请求包中的Itag值相呼应。比如作废请求包中ITag值为a,则作废完成包 ITag Vector的bit[a]应为1,其余位为0。对于仅ITag Vector不同但TC、CC、requester ID完全相同的多笔作废完成包,也可应将这几笔作废完成包的ITag Vector或在一起,从而合并成为一笔作废完成包。
如果某Device/Function不支持ATS却收到了地址转换作废请求,该Device/Function会将其作为UR处理。带有ATS能力的Device/Function,即便其ATS没有开启,也应能够接收作废请求并回复作废完成。
注意⚠️⚠️📢📢:
ATC回应作废完成之前必须确定一下几件事:
- 所有新发起的请求不能使用旧的已经作废掉的转换地址;
- 发送队列中所有采用旧的已作废转换地址的outstanding读请求必须已经完全发送完毕或者被废弃;
- 发送队列中所有采用旧的已转换地址的outstanding转发写请求必须已经被全部发至TA。若ATC不知道写请求是否到达TA,则ATC需采用与写请求相同TC发送作废完成包,有多少笔TC不同的写请求就采用与该笔写请求相同的TC发送多少笔作废完成包,通过相同TC事务间的PCIe事务排序规则来确保写请求能够先于作废完成包达到TA。这些作废完成包的CC值应相同。
2.2.3 ATS地址转换作废流控(Invalidate Flow Control)
对于不同的设计,其cache结构及排队策略也不同,这也意味着地址作废包的时延及吞吐量不同,这就难免出现TA发送作废请求的速率超出ATC的服务速率情况。当TA发送作废请求的速率超出ATC的服务速率时,由于其流控机制的信用量耗尽,会阻塞TA继续发送作废请求,这也会阻塞其他采用相同流控信用量的事务,从而影响性能。为避免这种情况的发生,可在TA端软件设计更高级的流控机制。
为了实现流控,ATC必须在反压之前及时公布其作废请求事务的信用余量。
在以下几种情况时,可以不开启地址作废流控:
- Device/Function有能力处理以最大速率达到的作废请求;
- Device/Function极少出现反压的情况,出现反压对性能影响也可以忽略不计;
- Device/Function能够在不反压的情况下缓存下所有发过来的作废请求。
✨2.3 ATS协议存在的问题及解决办法
ATS服务最大的问题在于它是基于信任的,是ATC自己声称它发出的地址是经过翻译还是没有经过翻译的。如果ATC生成这个地址已经翻译,就可以越过IOMMU的隔离。这个问题可以通过ACS来保护,ACS能够决定一个TLP能够正常路由、阻塞或重定向,可以在桥上禁止ATS消息。
🔥 3. PCIe ATS配置
所有支持ATS的Function扩展配置空间中必须有ATS扩展能力结构,如下图所示。
ATS扩展能力结构分为3部分:
- PCIe扩展能力头标,用以表明该Function具有的能力;
- ATS控制寄存器,表明该ATS invalidate queue的深度、是否支持页对齐、是否支持全局invalidate、是否支持宽松排序;
- ATS能力寄存器,用以设置STU及启用ATS。
分别如下图所示。
📖 参考
- PCI Express Base Specification Revision 5.0 Version 1.0 (22 May 2019)
- PCI Express Technology - Comprehensive Guide to Generation 1.x, 2.x and 3.0. Mike Jacson, Ravi Budruk, MindShare, Inc.
- PCI-SIG, Address Translation Services(PPT)
- Address Translation Services Revision 1.1, January 26, 2009
- ARM系列 – SMMU(一)
- ARM系列 – SMMU(二)
- IOMMU原理分析以及在Linux中初始化
- PCIe/SMMU ATS analysis note
- Introduction to PCIe Access Control Services
- PCIe SR-IOV:为什么需要SR-IOV
- Linux source code