✨ 1. 初识LN
Lightweight Notification(LN),顾名思义,轻量级通知。PCIe 4.0时正式引入,并在PCIe 6.0中被移除。LN协议允许EP登记主存中的Cacheline,利用EP端的Cache来降低系统带宽需求并降低时延。
所谓登记Cacheline是指 ① EP把主存指定位置的Cacheline的内容copy一份放到EP本地,② 主机记录其主存某Cacheline被某EP关注了。若主机或其他设备更新了主存中被登记的Cacheline,硬件会通知该EP其关注的这条Cacheline已被更新,EP请停止使用你本地的Cacheline备份,再用的话麻烦再次申请登记。
✨ 2. 当初为啥要加入LN?
LN是一种能够满足几类关键应用模型的简单协议,其复杂度最小,成本最低。LN有其优点,所以PCI-SIG才考虑把LN写入到PCIe规范中。
PCIe系统中采用LN协议有以下潜在优点:
减小I/O带宽及时延。对于一些EP经常访问的主机内存地址,EP可以把对应地址的Cacheline缓存到EP本地,这样每次直接到本地Cacheline去取即可,而不用每次都同PCIe链路去读取主机内存,从而减小PCIe系统的带宽需求,也能够降低访问时延。
轻量级信令。采用LN协议的主机软件只在Cacheline发生变动时才给EP发送Cacheline更新的消息,而非发送可编程IO(PIO)操作,减少了软件开销,也避免了复杂的同步及流控问题。
动态设备相关。虚拟机驱动通过主内存结构与设备间的通信(无PIO)使客户迁移及虚拟机主机在VIO-Direct IO间动态切换更为简便。
✨ 3. LN协议深度剖析
3.1 支持LN协议的PCIe系统结构
LN协议中有两个较为关键的组件:LN Requester (LNR) 及 LN Completer (LNC)。LNR是EP中发送LN读写请求及接收LN Message的客户子系统,LNC是主机端接收LN读写请求及发送LN Message的服务子系统。
典型的支持LN协议的系统包括以下几部分:主处理器、主存、主机Fabric、RP、Switch及EP。下图是一个LN系统示意图(图1),其中EP X、EP Z及RCIEP 0各有一个LNR,RC为LNC。
图1 支持LN协议的PCIe系统结构示例
3.2 LN协议基本操作
LN协议包括两种基本操作:LN Read 和 LN Write。LN Read和LN Write可以理解为EP读写主存,同时把主存该Cacheline对应的数据在EP端留个备份。LN Read是一种存储器读请求,LN Write是一种存储器写请求,LN Completion是一种Completion消息,跟其常规TLP的唯一不同是其TLP头标中的LN位为1。
LN协议允许多个LNR同时登记同一条Cacheline,单个LNR的LN协议操作示意图如下图所示(图2),左侧为LN Read,右侧为LN Write。
图2 LN协议基本操作
3.2.1 LN Read
LN Read基本操作步骤如下:
1️⃣ LNR发送LN Read给LNC,请求登记一条主存Cacheline。
2️⃣ LNC回复该Cacheline的LN Completion给该LNR,并记录该LNR登记了该Cacheline。LNR所在的EP会把LN Completion所携带的Cacheline数据存储在本地Cache。
3️⃣ 若该Cacheline有更新或Cacheline注销,LNC发送LN Message给LNR。
3.2.2 LN Write
LN Write基本操作步骤如下:
1️⃣ LNR发送LN Write给LNC,请求写主存的Cacheline。
2️⃣ LNC记录该LNR登记了该Cacheline(LNC收到LN Write不回LN Completion)。
3️⃣ 若该Cacheline有更新或Cacheline注销,则发送LN Message给LNR。
⚠️注意:带有LNR的EP任何时候都可以发生LN Write,而不用关心其他LNR有没有登记该Cacheline。
3.3 LN协议规则
3.3.1 LN基本规则
LN协议遵循以下规则:
LN协议允许多个LNR同时登记相同的Cacheline。当该Cacheline发生变化时,LNC可以选择给各个受影响的LNR单独发送LN Message,也可以选择给受到影响的LNR所在的PCIe Hierarchy Domain发送广播LN Message。
若LNR在登记了某Cacheline之后再次发送针对该Cacheline的LN读写请求,当LNC回复LN Message时,LNR并不知道该LN Message是针对当前LN请求还是针对早前的LN读写请求。
LNC在发送完LN Message之后,除非LNR再次发送了LN读写请求,否则LNC不会再次发送LN Message。也就是说,一次LN请求仅对应一次通知。
单条LN Message可用于指示某LNR所有已登记Cacheline全被注销,用LN Message种的Notification Reason(NR)字段来指示。这种Message可以采用Directed或Broadcast的路由方式进行发送。
LNC可以设置一个上限,规定某条Cacheline最多可以被多少LNR登记。若登记该Cacheline的LNR数目在上限范围内,由于数量不多,LNC通常发送Directed LN Message;一旦超出上限,LNC发送Broadcast LN Message。当然把这个上限设置为0是允许的,这样每次回复LN Message都采用广播的形式。
LNC可以规定其可以登记的Cacheline数目上限,若LNC收到了Cacheline的登记申请,但该LNC没有精力同时跟踪这么多Cacheline,那么该LNC可以注销一些比较老的Cacheline登记信息来释放资源。
3.3.2 LN登记管理
鉴于LNC可以规定其登记Cacheline的最大数目,每个LNR的LNR能力结构内都应提供一种机制来约束该LNR最大登记Cacheline数目,以供软件取用。如有必要,该字段应该是软件可配置的。
LNC登记资源上限可以是高度可定制化的,比如根据集合相关性、最大集合数目、主存资源的不同集合等因素来设定。
LNC可以通过LN Message来告知LNR其关注的Cacheline已被注销,LNR同样可以告知LNC注销其Cacheline登记。为了管理LNR Outstanding登记的数量,LNR可以通过发送length为0的LN Write来注销LNC中相关Cacheline登记。
LNC接收到LNR的Cachelind登记请求后,可以对请求不予响应。但一旦响应,就必须确保登记的Cacheline地址是4KB对齐的,且登记的Cacheline粒度不能小于4KB。LNR在发送主存某区域的Cacheline登记请求前是不知道这段地址是否支持Cache登记的,为获取该信息,LNR可以发送LN Read请求到该区域内的任意Cacheline,看是否会收到LN Comletion,如果正确收到了LN Completion,表示可登记。若LNR仅仅是想确认这块区域是否可登记,而非真正登记,那么LNR可以发送长度为0的LN Read。
3.3.3 LN 事务排序
LN事务排序遵循以下规则:
LN Read的排序要求跟存储器读请求的排序要求相同。
LN Write的排序要求跟存储区写请求的排序要求相同。
LN Completion的排序要求跟存储器读请求Completion的排序要求相同。
LN Message的排序要求跟转发请求PR的排序要求相同。
对于给定的Cacheline,若LNC在更新该Cacheline之后才收到LN Read请求,LNC发送LN Completion和LN Message的顺序未作规定。
对于给定的Cacheline,若LNC收到的LN Read触发了注销LN Message,LNC发送LN Completion和LN Message的顺序未作规定。
对于跟单的Cacheline,若LNC在更新该Cacheline之后才收到LN Write并触发了注销LN Message,LNC发送这两笔LN Message的顺序未作规定。
对于不同的Cacheline,LNC可以以任意顺序发送LN Message。
3.4 LN协议总结
LN协议总结如下:
除非另有说明,所有存储器读请求的要求均适用于LN Read。
LN Read一次锁定不能访问超过一条Cacheline的范围,如果超出,该请求会被LNC当成CA处理(除非Completer去干其他高优先级的事去了)。长度为0的LN Read是允许的。
若LNC把LN Read处理为不可纠正错误或非致命错误,LNC不能登记该Cacheline。
LNC应把长度为0的LN Read当作对于存储区域的探针进行处理,如果该区域支持登记,那么回复LN Completion的TLP头标中LN位为1,但LNC不能真的登记该Cacheline。LNC需支持4KB对齐且粒度大于4KB的Cacheline登记能力。
LN Read的排序及流控规则与存储器读请求相同。
除非另有说明,所有存储器读请求完成消息的要求均适用于LN Completion。
若完成者为LNC,且目标存储区域接收了登记,LNC应给LN Read回复一笔LN Completion,即TLP头标中LN位为1;否则返回的Completion LN位应为0。注意:Poisoned Completion完成状态也为Successful Completion。
LN Completion的排序及流控规则同常规Completion相同。
除非另有说明,所有存储器写请求的要求均适用于LN Write。
LN Write一次锁定不能访问超过一条Cacheline的范围,如果超出,该请求会被LNC当成CA处理(除非completer去干其他高优先级的事去了)。长度为0的LN Write是允许的。
若LNC把LN Read处理为不可纠正错误,LNC不能登记该Cacheline的通知服务。根据具体配置,LNC可能会把被污染的LN Write当作不可纠正错误、非致命错误或可屏蔽错误处理。
LNC应把长度为0的LN Write当作对于既有登记服务的注销进行处理,若LN Write对于地址的Cacheline本就未登记,则继续保持未登记状态。
LN Write的排序、流控及数据污染规则与存储器写请求相同。
不论LN Read还是LN Write,其地址类型必须是AT字段所指定的地址类型(转换或未转换)。AT域具体采用啥值,跟系统是否采用了TA有关。(详情参考ATS服务详解)
若采用了TA,地址应为转换后的地址。LNR应支持ATS以采用转换后的地址。
若系统未采用TA,地址因为给默认地址或为转换的地址。
若检测到违例,LNC应把对应请求到最CA处理。