点击查看精选 CXL 系列文章
点击进入【芯片设计验证】社区,查看更多精彩内容
声明:
- 作者主页:【MangoPapa的CSDN主页】。
- ⚠️ 本文首发于CSDN,转载或引用请注明出处【https://mangopapa.blog.csdn.net/article/details/132647075】。
- ⚠️ 本文目的为 个人学习记录 及 知识分享。因个人能力受限,存在协议解读不正确的可能。若您参考本文进行产品设计或进行其他事项并造成了不良后果,本人不承担相关法律责任。
- ⚠️ 若本文所采用图片或相关引用侵犯了您的合法权益,请联系我进行删除。
- 欢迎大家指出文章错误,欢迎同行与我交流 ~
- 邮箱:[email protected]
- 直达博主:loveic_lovelife 。(搜索或点击扫码)
文章目录
- 0. 前言
- 1. Req
-
- 1.1 Read
- 1.2 Read0
- 1.3 Write
- 1.4 Read0-Write
- 2. Rsp
- 3. Data
- 4. Q&A
- 5. 参考
0. 前言
为了实现 Host 和 Device 之间的缓存一致性,CXL.cache 提供了 D2H、H2D 两个方向的 Cache 管理,每个方向均有 3 个 Channel:Req、Rsp 及 Data。每个 Channel 由细分为多种 Message,如下图所示。本文对 D2H 方向各 Message 的含义进行解释。
1. Req
D2H Req 主要用以 Device 访问 Host Memory,HDM-D Host Bias 时也用以访问 Device Memory。D2H Req 分为 4 类共 15 种请求,分类如下:
- Read ,包括 RdCurr、RdOwn、RdShared、RdAny 共 4 种;
- Read0 ,包括 RdOwnNoData、CLFlush、CacheFlushed 共 3 种;
- Write ,包括 DirtyEvict、CleanEvict、CleanEvictNoData、WOWrInv、WOWrInvF、WrInv 共 6 种;
- Read0-Write ,包括 ItoMWr、WrCur 共 2 种。
每笔 D2H Req 可以得到 0/1/2 笔 Rsp 以及最多 64B 的 Cacheline Data。在发起 CXL.cache D2H 请求之前,Device 需要知道所访问地址对应的主机物理地址(Host Physical Address,HPA),HPA 需要 Device 通过 CXL.io 向 Host 发送 ATS 请求来获得。
Device 在给 Host 发送 CXL.cache Req 之前,需要获得 Host 的物理地址。物理地址在此之间通过 CXL.io 的 ATS 从 Host 获得。若 ATS Cpl 中指示当前 HPA 不支持 Cache 访问,那就不能发起该 HPA 的 D2H Req。如果请求的地址为 Device 本地 HDM 范围,该 HPA 可以通过 ATS 获得,也能通过其他方式获得。还没完成,开放状态,等待 SSWG 支持 Bypass HDM 范围的 ATS。
Cacheline 空满时的操作:新数据进来时,优先选择处于 Invalid 状态的 Cacheline。如果选择其他状态的 Cacheline,要先进行数据置换,当被置换掉的 Cacheline 数据再次被访问到时就发生了 Cache Miss。
1.1 Read
Read 请求用以 Device 读取 Host Memory 或 HDM 的 Host Bias 区域,且只有 Device 要访问的地址在 Device Cache 内没有 Hit 或没有备份时才能向 Host 发起 D2H Req。Read 请求的目标为一整条 Cacheline 的完整数据,BE 全 1,且需要 Host 返回读数据,一笔 Read 对应(0/1 笔 GO)+64B Data。
只有在 Host 有足够 Credit 来接收该请求且 Device 有 Buffer 接收 Host 反馈回来的 64B 数据的前提下才能发送 D2H Read 请求。发出 Read 请求后,Device 以 CQID 为 Flag 在 Device 端创建 Entry,该 Entry 在收全 Rsp+Data 之前一直保持 Active。Host 收到 Req 后提取 CQID 并在接下来的 H2D Rsp/Data 中反射回来,Device 依据该 CQID 将 Rsp 及 Data 路由至相关 Entry。
几种 Read 请求介绍如下:
-
RdCurr ,Device 访问 Host Memory 的数据,但不改变其在任何 Cache 现有状态(既不改变 Device Cache 也不改变 Host Cache 及其他 Peer Cache)。Host 收到该请求后 无需通过 GO 反馈 Cacheline 状态 ,直接回复 Data 即可。Host 端的 Snoop Flilter 也无需跟踪 Device 内的该 Cacheline。若 Device Cache 内该 Cacheline 处于 Invalid 状态,Device 收到 Data 后也不能放进 Cache,仍然保持 Invalid 状态。
-
RdOwn ,Device 访问 Host Memory 的数据且要求独享该 Cacheline(M/E 状态)。Host 收到 RdOwn 请求后,会将 Peer Cache 中该 Cacheline 给 Invalidate 掉,正常情况下反馈 GO-E 或 GO-M 及该 Cacheline 的最新数据,Device 获得最新数据及该 Cacheline 的独享权限。如果反馈的为 GO-E,说明该 Cacheline 内的数据与 Host Memory 一致,Device 可以在不写回的情况下 E->I;如果反馈的为 GO-M,说明该 Cacheline 内的数据为最新但还没写回到 Host Memory,相当于直接把 Peer Cache 内的脏数据替换到了 Device Cache,Device 在 Invalid 该 Cacheline 之前必须把脏数据写回 Host Memory。非正常情况下(出错等),Host 会反馈 GO-I 或 GO-Err,同时反馈全 1 的数据,该数据 Device 不可用,Device 应能识别并处理该情况。
-
RdShared ,跟 RdOwn 类似,区别在于 Device 希望跟 Peer Cache 共享该 Cacheline。正常情况下 Host HA 处理完一致性问题后,反馈 GO-S+Data 给 Device,至此 Device Cache 获得了该 Cacheline 的最新数据及 Shared 权限。异常情况下处理情况跟 RdOwn 一致。
-
RdAny ,该请求相当于 RdOwn 及 RdShared 的合集,其不苛求任何特定特定的 Cacheline 状态,独享也行共享也罢,Clean 数据也行 Dirty 数据也行,错误状态下 GO-I、GO-Err 也不在话下。
1.2 Read0
D2H Read0 用以 Device Cache 向 Host 请求指定 Cacheline 的 Exclusive 权限或通知相关 Cacheline 的状态、操作,但不需要 Host 反馈数据。
Read0 包含的几种子请求释义如下:
- RdOwnNoData ,Device Cache 向 Host 请求指定 Cacheline 的 Exclusive 权限,但不需要 Host 反馈数据。只有当访问的地址在 Device Cache 内 Cache Miss 或 Cache Hit 但处于 Shared 状态的前提下才能发起该请求。若 Device Cache 内该 Cacheline Hit 且已经处于 M 或 E 状态,则无需也不能发送该请求。该请求跟 RdOwn 的区别在于其无需 Host 返回 Data,RdOwn 返回的 Rsp 可以为 GO-M/E/I/Err,但是 RdOwnNoData 只有 GO-E/Err。该请求常用于 Device 写数据操作中,在写之前先获取 Cacheline 的独享权限。Device Cache 只能完整修改 64B Cacheline,不支持部分修改。如果想要部分写,需要用 RdOwn 把数据都回来,跟要该的字段 Merge 在一起后进行完整写。
- CLFlush ,Cacheline Flush,通常用于 HDM-D Host Bias Mode 下,Device 请求 Host Flush 掉 Host Cache 内属于 HDM 区域的 Cacheline,即 Host Cache 相关数据写回 Device Memory。Host Cache 在将数据写回后反馈 GO-I。
- CacheFlushed ,注意这里的"ed",该请求为 Device 发给 Host 的指示信号,指示 Device 内所有 Cacheline 均被 Flush 了且处于 Invalid 状态了,没有处于 MES 状态的 Cacheline 了。Host 在收到该消息后,可以指导其 Snoop Filter 停止对 Device Cache 的 Snoop 操作,然后反馈 GO-I 给 Device。只有 Device Cache 内的所有 Cacheline 均 Flush 完毕(收到 Flush 完毕的 Rsp 了)才能发送 CacheFlushed 消息。
1.3 Write
D2H Write 请求用以 Device 写 Host Memory 或 HDM 的 Host Bias 区域,可大致分为两类:*Evict 及*WrInv*,*Evict 是 P 类型的,*WrInv*是 NP 类型的。
D2H Write 几种请求介绍如下:
- CleanEvict ,Device 驱逐 Device Cache 内一条存有干净数据的 Cacheline(处于 E/S 状态),Host 收到请求后回复 GO_WritePull 或 GO_WritePull_Drop。若 Device 收到的 Rsp 为 GO_WritePull,Device 将数据写到 Host;若收到 GO_WritePull_Drop,Device 直接丢弃该数据(数据没有变,Host 通知 Device 直接丢掉吧,没必要写过来了)。
- DirtyEvict ,Device 驱逐 Device Cache 内一条存有脏数据的 Cacheline(处于 M 状态)。正常情况下 Host 反馈 GO_WritePull,Data 不能被 DeviceDrop。若 Host 反馈的为 GO-Err_WritePull,Device 仍需写数据到 Host,但数据会被 Host 丢掉,Device 应能够处理该情况。
- CleanEvictNoData ,跟 CleanEvict 相比,该请求没有写数据的操作,通常用以指示 Host Snoop Filter 停止对 Cacheline 的 Snoop。Host 收到请求后停止对该 Cacheline 的 Snoop 并直接反馈 GO-I 给 Device。
- WrInv ,采用强内存顺序,Device Cacheline Invalid 前提下 Device 向 Host Memory 或 HDM 写数据,数据长度可以为 0~64B。Host 收到请求后反馈 WritePull,Device 进一步将 Data 发送给 Host,Host 反馈 GO-I 结束流程。
- WOWrInv ,采用弱内存顺序,通常在 Device Cacheline Invalid 前提下用以 Device 写 Host Memory。该请求带有 Byte Enable 信息,支持 Device 向 Host 写入 0~63B 数据。Host 会反馈 Fast_GO_WritePull,Device 收到 Fast_GO_WritePull 后写数据。若 Host 反馈的为 GO-Err_WritePull,Device 写给 Host 的数据会被 Host 丢掉,Device 应能够处理该情况。对于 Host-attached Memory,Host 写 Host Memory 完成之后反馈 ExtCmp。
- WOWrInvF ,跟 WOWrInv 比,该请求携带了完整的 64B Data,没有 Byte Enable 字段。
上文简单提到,*Evict 是 P 类型的,*WrInv*是 NP 类型的,此外还有以下区别:*Evict 用以驱逐 Device Cache 内的一整条(64B)有效(非 I)的 Cacheline,或者说把 Device Cache 内的数据写回 Host Memory(不能是 Device Memory,因为 Evict 仅适用于 Host Memory 区域)并 Invalidate 该 Cacheline;相较于*Evict,*WrInv*写操作是在 Device Cache Miss(I 状态)的情况下直接把数据写到 Memory 里且支持 Host Memory 和/或 Device Memory。对于*Evict,Host 收到请求之后反馈 GO、Device 发出数据之后就可以结束写操作,而*WrInv*要求 Host 反馈 WritePull/FasgGo_WritePull->Device 写数据到 Memory -> Host 反馈 GO-I/ExtCmp 之后才算结束。
此外再做几点总结:
- Evict 驱逐操作一般(Spec 用语为 Expected,而非 Must)用于 Host-attached Memory。如果是 HDM,Device 内部就可以操作,不用知会 Host。
- 从支持的数据长度看,*Evict*为 64B,WrInv 为 0~64B,WOWrInv 为 0~63B,WOWrInvF 为 64B。
- 以上几种写请求中,WrInv 采用的是 SO 强内存顺序,WOWrInv、WOWrInvF 采用的是弱内存顺序。
- Evict 和 WOWrInv 的区别:Evict 采用强内存顺序,WOWrInv 采用弱内存顺序。若内存顺序的写请求,Host 反馈的为 Fast_GO_WritePull,且 Host 收到数据后会返回 ExtCmp。
1.4 Read0-Write
D2H Read0-Write 可以认为是 Read0+Write 的一套组合拳。在 Device Cache Miss 的前提下,Device 向 Host 申请指定 Cacheline 的 Exclusive 权限,把数据放到该 Cacheline 并置为 Modified,然后自动把该 Modified 的 Cachelines 数据送到 Host(写到 Memory 或 Host Cache),最终将 Device 内当前 Cacheline Invalidate 掉。
D2H Read0-Write 几种请求介绍如下:
- ItoMWr ,Device 获取 Host Cacheline 的独占权限并写入数据。写入的地方为 Cache,如果 Cache Miss 则创建 Cacheline,Cache Hit 则直接写入。Host 收到请求后反馈 GO_WritePull,然后 Device 写入数据。Host 收到 Read0-Write 跟 DirtyEvict 的反馈方式是一样的。(没怎么理解该应用场景)
- WrCur ,CXL 2.0 及之前版本称为 MemWr,跟 ItoMWr 相似。如果 Cacheline Hit,那跟 ItoMWr 相同;未 Hit,则直接写到 Memory。
2. Rsp
D2H Rsp 用以响应 H2D 方向的 Snoop 请求,有两大作用:① 指示 Device Cache 相关 Cacheline 的状态;②指示是否有数据返回。
D2H Rsp 共 7 种:
- RspIHitI ,表示 Host 访问的 Cacheline 在 Device 中不存在。
- RspVHitV ,表示 Host 访问的 Cacheline 在 Device 中存在且状态未改变,Device 中至少有一份该 Cacheline 的副本。SnpCur 的响应。
- RspIHitSE ,表示 Host 访问的 Cacheline 在 Device 中存在且 Clean(SE),但现在被 Invalidate 了,Host 可以独享该 Cacheline。
- RspSHitSE ,表示 Host 访问的 Cacheline 在 Device 中存在且 Clean(SE),现在 Shared 了,Host 不能独享该 Cacheline。
- RspSFwdM ,Host 监听的 Cacheline 由 M->S,接下来 Device 可能会将其置为 I。该消息之后 Device 紧接着反馈 64B Data 将脏数据写回。
- RspIFwdM ,Host 监听的 Cacheline 由 M->I。该消息之后 Device 紧接着反馈 64B Data 将脏数据写回。
- RspVFwdV ,Host 监听的 Cacheline 处于 M/E 状态,Device 将数据写回但 Cacheline 状态不发生变化。SnpCur 的响应。
3. Data
一方面用于 D2H Write 的写数据,一方面用于回应 H2D 的 Req。
Bogus Data 相关解读: 《对CXL.cache 伪数据(Bogus Data)的解读》。
4. Q&A
- HDM-D Host->Device Bias 时,为什么不建议用 CLFlush/GO-I 的方案?
对于 HDM-D 区域,如果 Device 想要将某个地址由 Host Bias 转为 Device Bias,不能依赖于 CLFlush/GO-I,而应采用 RdOwnNoData/GO-E。为什么?一来 CLFlush+GO-I 的方案仅是把 Host Cacheline 内的数据 Flush 掉了并 Invalidate 了,Device 没有获得该 Cacheline 的独享权限,如果此时 Peer Cache 内存在该 Cacheline 的 Shared 副本,Host Snoop Filter 依然会对该 Cacheline 进行 Snoop。二来,采用 RdOwnNoData+GO-E 的方案 Device Cache 能够获得该 Cacheline 的独享权限,Device 无需通知 Host 即可修改 Device 侧的 Cacheline,Device 在获取独享权限后再更改 Bias Table 为 Device Bias。
5. 参考
- CXL Base Spec, r3.0
- 理解弱内存顺序模型- 知乎 (zhihu.com)
- Weak vs. Strong Memory Models_weak memory models_sparkliang 的博客-CSDN 博客
精选往期 CXL 协议系列文章,请查看【 CXL 专栏】
⬆️ 返回顶部 ⬆️