本文主要是介绍【CXL协议-事务层之CXL.cache (3)】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
3.2 CXL.cache
3.2.1 概述
CXL.cache 协议将设备和主机之间的交互定义为许多请求,每个请求至少有一个关联的响应消息,有时还有数据传输。 该接口由每个方向的三个通道组成:
请求、响应和数据。 这些通道根据其方向命名,D2H(设备到主机)和 H2D(主机到设备)以及它们携带的事务、请求、响应和数据,如图 20 所示。独立通道允许不同类型的消息使用专用线路 并实现解耦和每线更高的有效吞吐量。
D2H 请求携带从设备到主机的新请求。 这些请求通常针对内存。 每个请求将接收零个、一个或两个响应以及最多一个 64 字节缓存行数据。 通道可能会受到背压而不会出现问题。 D2H 响应携带从设备到主机的所有响应。 设备对监听的响应指示该行留在设备高速缓存中的状态,并且可能指示数据正在返回到主机所提供的数据缓冲区。 它们可能仍会被暂时阻止链路层信用,但不应要求完成任何其他交易来释放信用。 D2H 数据将所有数据和字节使能从设备传送到主机。 数据传输可以由隐式(作为窥探的结果)或显式回写(作为缓存容量驱逐的结果)产生。 在所有情况下,都会传输完整的 64 字节缓存行数据。 D2H 数据传输必须取得进展,否则可能会发生死锁。 它们可能会被暂时阻止链路层信用,但不得要求完成任何其他交易来释放信用。
H2D 请求携带从主机到设备的请求。 这些是为了保持一致性的窥探。 数据可能会被返回以供窥探。 该请求携带任何返回数据应写入的数据缓冲区的位置。 H2D 请求可能会因设备资源不足而受到反压; 但是,资源必须释放,而不需要 D2H 请求才能取得进展。 H2D 响应携带排序消息并拉取写入数据。 每个响应都携带来自原始设备请求的请求标识符,以指示应将响应路由到何处。 对于写数据拉取响应,消息携带应写入数据的位置。 只能暂时阻止链路层信用的 H2D 响应。 H2D Data 为设备读取请求提供数据。 在所有情况下,都会传输完整的 64 字节缓存行数据。 H2D 数据传输只能暂时阻止链路层信用。
3.2.2 CXL.cache Channel Description(CXL.cache通道说明)
3.2.2.1 Channel Ordering
一般来说,所有 CXL.cache 通道必须彼此独立工作,以确保维持前进进度。 例如,由于从设备向主机发送给给定地址 X 的请求将被主机阻止,直到它收集到该地址 X 的所有监听响应为止,因此链接通道将导致死锁。
然而,在特定情况下,为了正确性,必须保持通道之间的顺序。 主机需要等待设备观察到在 H2D 响应上发送的全局排序 (GO) 消息,然后再发送针对同一地址的后续监听。 为了限制跟踪 GO 消息所需的缓冲量,主机假定在给定周期中通过 CXL.cache 发送的 GO 消息不能被稍后周期中发送的监听传递。
对于在单个通道内具有多个并发消息的事务(例如 FastGO 和 ExtCmp),设备/主机应假设它们可以按任何顺序到达。
对于在单个通道上具有预期顺序的多条消息的事务(例如,WrInv 的 WritePull 和 GO),设备/主机必须确保使用序列化消息正确观察它们(例如,WrInv 的 WritePull 和 GO 之间的数据消息,如图所示) 图 24)。
3.2.2.2 Channel Crediting
为了保持接口的模块化,不能对在通道上发送消息的能力做出任何假设,因为链路层信用可能并非始终可用。 因此,每个通道必须使用信用来发送任何消息并从接收者处收集信用返回。 在操作期间,接收者只要处理了消息(即释放缓冲区)就会返回信用。 不需要双方都记入所有信用,只要信用计数器饱和就足够了
当满的时候。 如果没有可用积分,发送者必须等待接收者返回积分。 下表描述了哪些通道必须耗尽才能维持前进进度,哪些通道可以无限期阻塞。
3.2.3 CXL.cache 线路说明
每个 CXL.cache 通道的每个字段的定义如下。
3.2.3.1 D2H Request
3.2.3.2 D2H Response
3.2.3.3 D2H Data
3.2.3.3.1 Byte Enable(字节使能)
尽管字节启用在技术上是数据头的一部分,但它不会与数据头字段的其余部分一起在 flit 上发送。 相反,仅当值不全为 1 时才将其作为数据块发送,如第 4.2.2 节中所述。 字节启用字段为 64 位宽,指示哪些字节对于所包含的数据有效。
3.2.3.4 H2D Request
3.2.3.5 H2D Response
3.2.3.6 H2D Data
3.2.4 CXL.cache Transaction Description(CXL.cache交易说明)
3.2.4.1 设备到主机的请求
3.2.4.1.1 设备到主机 (D2H) CXL.cache 请求语义
对于设备到主机的请求,有四种不同的语义:CXL.cache Read、CXL.cache Read0、CXL.cache Read0/Write 和 CXL.cache Write。 所有设备到主机 CXL.cache 事务都属于这四种语义之一,尽管给定语义内每种请求类型的允许响应和限制是不同的。
3.2.4.1.2 CXL.cache Read
CXL.cache 读取必须具有 D2H 请求信用,并在 D2H CXL.cache 请求通道上发送请求消息。 CXL.cache 读取请求需要零个或一个响应 (GO) 消息和数据消息,总计单个 64 字节缓存行数据。
响应(如果存在)和数据消息都定向到初始 D2H 请求数据包的 CQID 字段中提供的设备跟踪器条目。 设备条目必须保持活动状态,直到收到来自主机的所有消息。 为了确保转发进度,设备必须有一个保留的数据缓冲区,以便能够在请求发送后立即接受所有 64 字节的数据。 然而,该设备可能由于先前返回的数据未耗尽,暂时无法接受来自主机的数据。 一旦从主机接收到响应消息和数据消息,就可以认为事务已完成并且条目从设备中解除分配。
下图显示了完成 CXL.cache 读取所需的元素。 注意,响应(GO)消息可以在数据消息之前、之后或之间接收。
3.2.4.1.3 CXL.cache Read0
CXL.cache Read0 必须具有 D2H 请求信用并在 D2H CXL.cache 请求通道上发送消息。 CXL.cache Read0 请求收到响应消息,但没有数据消息。 响应消息针对初始 D2H 请求消息的 CQID 值中指示的设备条目。 一旦收到这些请求的 GO 消息,就可以认为它们已完成,并且条目从
设备。 主机不得为这些事务发送数据消息。 大多数特殊周期(例如 CLFlush)和其他杂项请求都属于这一类。
详情见表 18。
下图显示了完成 CXL.cache Read0 事务所需的元素。
3.2.4.1.4 CXL.cache Write(CXL.cache 写入)
在 D2H CXL.cache 请求通道上发送请求消息之前,CXL.cache Write 必须具有 D2H 请求信用。 一旦主机收到请求消息,就需要发送两个单独的或一个合并的 GO-I 和 WritePull 消息。
GO 消息绝不能在 WritePull 之前到达设备,但它可以在组合消息中同时到达。 如果事务需要发布语义,则可以使用组合的 GO-I/WritePull 消息。 如果事务需要非发布语义,则当全局观察非发布写入时,将首先发布 WritePull,然后发布 GO-I。
收到 GO-I 消息后,设备将从内存排序和缓存一致性角度考虑存储完成,放弃缓存行的监听所有权(如果 CXL.cache 消息是 Evict)。
WritePull 消息触发设备向主机发送总计 64 字节数据的数据消息,但可以设置任意数量的字节使能。
一旦设备接收到 GO-I 消息并发送了所需的数据消息,设备就认为 CXL.cache 写入事务已完成。 此时可以从设备中释放该条目。
一旦主机接收到所有 64 字节数据并发送了 GO-I 响应消息,就认为写入已完成。 所有设备写入和逐出都属于 CXL.cache 写入语义。
有关多个活动写入事务的限制的更多信息,请参阅“同一缓存行的多个逐出”部分。
图 23 显示了完成 CXL.cache 写入事务(与发布的行为匹配)所需的元素。 WritePull(或组合的 GO_WritePull)消息触发数据消息。 Snoops 和 WritePulls 有限制。 有关更多详细信息,请参阅“设备/主机监听/WritePull 假设”部分。
图 24 显示了 WritePull 是与 GO 分开的消息的情况(例如:强有序的不可缓存写入)。
图 25 显示主机 FastGO 加上 ExtCmp 对弱有序写入的响应要求。
3.2.4.1.5 CXL.cache Read0-Write Semantics(CXL.cache 读0-写语义)
在 D2H CXL.cache 请求通道上发送请求消息之前,CXL.cache Read0-Write 请求必须具有 D2H 请求信用。 一旦主机接收到请求消息,就需要发送一条合并的GO-I和WritePull消息。
WritePull 消息触发设备向主机发送数据消息,尽管可以设置任意数量的字节使能,但主机总共传输 64 字节的数据。
一旦设备接收到 GO-I 消息并发送了所有需要的数据消息,设备就认为 CXL.cache 读 0-写事务已完成。 此时可以从设备中释放该条目。
一旦主机接收到所有 64 字节数据并发送了 GO-I 响应消息,主机就认为读/写已完成。 ItoMWr 属于读0-写类别。
3.2.4.1.6 RdCurr
这些是来自设备的完整缓存行读取请求,用于获取最新数据,但不会更改任何缓存(包括主机)中的现有状态。 主机不需要跟踪发出 RdCurr 的设备中的缓存行。 RdCurr 获取数据但没有执行。 设备接收处于无效状态的行,这意味着它获得了该行的一次使用,并且无法缓存它。
3.2.4.1.7 RdOwn
这些是来自设备的完整高速缓存行读取请求,要求在任何可写状态下缓存行。 通常,RdOwn 请求接收处于独占 (GO-E) 或修改 (GO-M) 状态的线路。 处于修改状态的行不得被删除,并且必须写回到主机。
在错误情况下,RdOwn 请求可能会接收处于无效 (GO-I) 或错误 (GO-Err) 状态的线路。 两者都会返回 all1 的合成数据。 设备负责适当地处理错误。
3.2.4.1.8 RdShared
这些是来自设备的完整缓存行读取请求,用于在共享状态下缓存行。 通常,RdShared 请求接收处于共享 (GO-S) 状态的线路。
在错误情况下,RdShared 请求可能会收到处于无效 (GO-I) 或错误 (GO-Err) 状态的线路。 两者都会返回 all1 的合成数据。 设备负责适当地处理错误。
3.2.4.1.9 RdAny
这些是来自设备的完整缓存行读取请求,用于在任何状态下缓存行。
通常,RdAny 请求接收处于共享 (GO-S)、独占 (GO-E) 或修改 (GO-M) 状态的线路。 处于修改状态的行不得被删除,并且必须写回到主机。
在错误情况下,RdAny 请求可能会收到处于无效 (GO-I) 或错误 (GO-Err) 状态的线路。 两者都会返回 all1 的合成数据。 设备负责适当地处理错误。
3.2.4.1.10 RdOwnNoData
这些是获取地址字段中指示的高速缓存行地址的独占所有权的请求。 典型的响应是“独家”(GO-E)。
在错误情况下,RdOwnNoData 请求可能会接收处于错误 (GO-Err) 状态的线路。 设备负责适当地处理错误。
3.2.4.1.11 ItoMWr
该命令请求地址字段中指示的高速缓存行地址的独占所有权,并将高速缓存行自动写回主机。 该设备保证整条线路都会被修改,因此不需要将数据传输到设备。 典型的响应是 GO-I-WritePull,该响应在请求被授予所有权后发送。 设备不得保留线路的副本。
如果发生错误,则发送 GO-Err-WritePull。 设备将数据发送到主机,主机将数据丢弃。 设备负责适当地处理错误。
3.2.4.1.12 MemWr
该命令的行为类似于 ItoMWr,它以原子方式请求缓存行的所有权,然后将完整的缓存行写回结构。 然而,它与 ItoMWr 的不同之处在于数据的写入位置。 只有当命令命中缓存时,数据才会被写入那里; 如果未命中,数据将直接写入内存。 一旦请求被授予所有权,典型的响应是 GO-I-WritePull。 设备不得保留线路的副本。
如果发生错误,则发送 GO-Err-WritePull。 设备将数据发送到主机,主机将数据丢弃。 设备负责适当地处理错误。
3.2.4.1.13 ClFlush
这是对主机的请求,以使地址字段中指定的高速缓存行无效。
典型的响应是 GO-I,它将在内存中完成后从主机发送。
然而,如果核心已向属于高速缓存行的地址发出监视器,则主机可以继续跟踪处于共享状态的高速缓存行。 因此,设备不得依赖 CLFlush/GO-I 作为将缓存线从主机翻转到设备偏置模式的唯一且充分的条件。 相反,设备必须在更新其偏置表之前启动 RdOwnNoData 并接收 GO-E 的 H2D 响应,并且随后可以在不通知主机的情况下访问缓存行。
在错误情况下,ClFlush 请求可能会接收处于错误 (GO-Err) 状态的行。 设备负责适当地处理错误。
3.2.4.1.14 CleanEvict
这是向主机发出的请求,要求主机从设备中逐出完整的 64 字节独占高速缓存行。
通常,CleanEvict 接收 GO-WritePull 或 GO-WritePullDrop。 接收任何信号都意味着设备必须放弃对线路的监听所有权。 对于 GO-WritePull,设备将正常发送数据。 对于 GO-WritePullDrop,设备只是删除数据。
一旦设备发出此命令并且随后侦听地址,但在设备收到 GO-WritePull 或 GO-WritePullDrop 之前,设备必须在所有 D2H 数据消息中设置 Bogus 字段以指示数据现在已过时。
CleanEvict 请求还向主机保证设备不再包含该行的任何缓存副本。 对于任何给定的缓存行地址,设备中只有一个 CleanEvict 可能在 CXL.cache 上挂起。
CleanEvict 仅适用于主机连接的内存地址范围。 对于设备附加的内存范围,可以在设备内部完成等效操作,而无需向主机发送事务。
3.2.4.1.15 DirtyEvict
这是向主机发出的请求,要求主机从设备中逐出完整的 64 字节修改后的缓存行。
通常,DirtyEvict 从主机接收 GO-WritePull,此时设备必须放弃线路的监听所有权并正常发送数据。
一旦设备发出此命令并且随后侦听地址,但在设备接收到 GO-WritePull 之前,设备必须在所有 D2H 数据消息中设置 Bogus 字段以指示数据现在已过时。
DirtyEvict 请求还向主机保证设备不再包含该行的任何缓存副本。 对于任何给定的缓存行地址,设备中只有一个 DirtyEvict 可能在 CXL.cache 上挂起。
在错误情况下,将收到 GO-Err-WritePull。 设备将正常发送数据,主机将丢弃数据。 设备负责适当地处理错误。
DirtyEvict 仅适用于主机连接的内存地址范围。 对于设备附加的内存范围,可以在设备内部完成等效操作,而无需向主机发送事务。
3.2.4.1.16 CleanEvictNoData
这是设备更新主机的请求,在设备中删除了一条干净的线路。 此请求的唯一目的是更新主机中的任何监听过滤器,并且不会交换任何数据。
CleanEvictNoData 仅适用于主机连接的内存地址范围。 对于设备连接的内存范围,等效操作可以在设备内部完成,而无需向主机发送事务。
3.2.4.1.17 WORWrInv
这是用于写入组合类型存储的 0-63 字节的弱有序写入无效行请求。 可以设置字节使能的任意组合。
通常,WOWrInv 接收 FastGO-WritePull,后跟 ExtCmp。 收到 FastGO-WritePull 后,设备将数据发送到主机。 对于主机连接的内存,一旦内存中的写入完成,主机就会发送 ExtCmp。
在错误情况下,将收到 GO-Err-Writepull。 设备将正常发送数据,主机将丢弃数据。 设备负责适当地处理错误。 在所有情况下,主机在 GO-Err 之后仍会发送 ExtCmp。
3.2.4.1.18 WOWrInvF
与 WOWrInv(规则和流程)相同,但它是 64 字节的写入。
3.2.4.1.19 WrInv
这是0-64 字节的写无效行请求。 通常,WrInv 接收 WritePull,后跟 GO。 收到 WritePull 后,设备将数据发送到主机。 一旦内存中的写入完成(主机连接或设备连接),主机就会发送 GO。
在错误情况下,会收到 GO-Err。 设备负责适当地处理错误。
试用版
3.2.4.1.20 CacheFlushed
这是设备发送的指示,通知主机其缓存已刷新,并且不再包含任何处于共享、独占或修改状态的缓存行。 主机可以使用此信息清除其探听过滤器并阻止对设备的探听并返回 GO。 一旦设备收到 GO,就保证不会收到来自主机的任何监听,直到设备发送下一个可缓存的 D2H 请求。
对于针对设备连接内存的请求,如果该区域处于设备偏差中,则 CXL.cache 上预计不会有事务,因为设备可以在内部完成这些请求。 如果该区域处于主机偏置状态,下表显示了设备应如何预期响应。
无论偏置状态如何,针对设备连接内存的 CleanEvict、DirtyEvict 和 CleanEvictNoData 应始终由设备内部完成。 对于在 CXL.mem 上接收响应的 D2H 请求,与 CXL.cache 请求关联的 CQID 反映在 CXL.mem MemRdFwd 或 MemWrFwd 命令的标签中。 对于MemRdFwd,该行的缓存状态反映在MetaValue中字段如表 32 中所述。
3.2.4.2 Device to Host Response(设备到主机响应)
响应针对原始 H2D 请求消息中 UQID 字段中指示的主机条目。
3.2.4.2.1 RspIHitI
一般来说,这是当在任何缓存中都找不到该行时设备向探听器提供的响应。 如果设备返回 RspIHitI 进行监听,则主机可以假设该线路已从该设备清除。
3.2.4.2.2 RspVHitV
一般来说,这是当缓存中的行被命中并且没有发生状态更改时设备向探听器提供的响应。 如果设备返回用于监听的 RspVHitV,则主机可以假设该线路的副本存在于该设备的一个或多个位置。
3.2.4.2.3 RspIHitSE
一般来说,这是当至少一个高速缓存中的线路在干净状态下被击中且现在无效时,设备向探听器提供的响应。 如果设备返回一个用于监听的 RspIHitSE,则主机可以假设该线路已从该设备清除。
3.2.4.2.4 RspSHitSE
一般来说,这是当至少一个高速缓存中的线路在干净状态下被命中并且现在降级为共享状态时设备向窥探器提供的响应。 如果设备返回用于监听的 RspSHitSE,则主机应假定线路仍在设备中。
3.2.4.2.5 RspSFwdM
该响应向主机表明,在命中已修改状态的线路之后,正在侦听的线路现在在设备中处于 S 状态。 设备可能会选择将线路降级为无效。 此响应还向主机侦听跟踪逻辑指示 64 字节数据将在 D2H CXL.cache 数据通道上传输到原始侦听目的地 (UQID) 中指示的主机数据缓冲区。
3.2.4.2.6 RspIFwdM
(又名 HITM)此响应向主机指示,在命中已修改状态的线路后,正在侦听的线路现在在设备中处于 I 状态。 主机现在可以假设设备不再包含该行的缓存副本。 此响应还向主机侦听跟踪逻辑指示 64 字节数据将在 D2H CXL.cache 数据通道上传输到原始侦听目的地 (UQID) 中指示的主机数据缓冲区。
3.2.4.2.7 RspVFwdV
该响应表明设备正在将当前数据返回给主机并保持状态不变。 由于没有状态信息,主机必须仅将数据转发给请求者。
3.2.4.3 Host to Device Requests(主机到设备请求)
除了本地 H2D 请求积分外,来自主机的窥探不需要获得任何积分。 设备将始终在 D2H CXL.cache 响应通道上发送 Snoop 响应消息。 如果响应采用 RspFwd 格式,则设备必须通过 D2H 数据通道以 64 字节的数据进行响应,针对原始探听请求消息中的 UQID。 如果响应不是RspFwd,则主机在接收到所有监听响应消息后可以认为请求完成。 一旦针对非数据转发情况发送了响应,或者在发送了最后一个数据块并且发送了响应之后,设备可以停止跟踪窥探。
下图显示了完成 CXL.cache 监听所需的元素。 注意,主机可以按照与数据消息的任何相关顺序来接收响应消息。 对于 Snoop 数据传输,字节使能字段始终为全 1。
3.2.4.3.1 SnpData
这些是来自主机的针对线路的探听请求,这些线路旨在在请求者处以共享或独占状态缓存(仅当所有设备都以 RspI 响应时,独占状态才能在请求者处缓存)。 这种类型的窥探通常由数据读取请求触发。 接收此监听的设备必须使所有缓存行无效或将其降级为共享状态。 如果设备保存脏数据,则必须将其返回给主机。
3.2.4.3.2 SnpInv
这些是来自主机的对线路的探听请求,这些线路旨在被请求者授予所有权和独占状态。 这种类型的窥探通常由写请求触发。 接收此监听的设备必须使所有缓存行无效。 如果设备保存脏数据,则必须将其返回给主机。
3.2.4.3.3 SnpCur
此监听获取该行的当前版本,但不需要更改层次结构中的任何缓存状态。 它仅代表 RdCurr 请求发送。 如果设备以修改状态保存数据,则必须将其返回给主机。 缓存状态可以在设备和主机中保持不变,并且主机不应更新其缓存。
3.2.4.4 Host to Device Response(主机到设备响应)
3.2.4.4.1 WritePull
该响应告诉设备将写入数据发送到主机,但不更改线路的状态。 这用于 WrInv,其中在发送 GO-I 之前需要数据。 这是因为GO-I是I/O写入完成的通知。
3.2.4.4.2 GO
全局观察(GO)消息传达读请求是连贯的并且写请求是连贯且一致的。 它表明系统设备已观察到事务,并且 RspType 字段中编码的 MESI 状态指示应将与事务关联的数据放入请求者的缓存中的状态。 详情见表 14。
如果主机将修改状态返回给设备,则设备应对脏数据负责,并且不能在不将其写回主机的情况下丢弃该线。
如果主机向设备返回 Invalid 或 Error 状态,则设备必须最多使用该数据一次,并且不缓存该数据。 对读取和可缓存写入请求(例如,RdOwn 或 ItoMWr)的错误响应始终是中止条件的结果,因此修改后的数据可以安全地删除到设备中。
3.2.4.4.3 GO_WritePull
这是一个组合的 GO + WritePull 消息。 没有缓存状态传输到设备。
GO+WritePull 消息用于发布写入类型。
3.2.4.4.4 ExtCmp
此响应表明先前本地排序 (FastGO) 的数据已在整个系统中被观察到。 最重要的是,对内存的访问将返回最新的数据。
3.2.4.4.5 GO_WritePull_Drop
该消息与 Go_WritePull 具有相同的语义,只是设备不应向主机发送数据。 当主机确定不需要数据时,可以发送此响应来代替 GO_WritePull。 对于部分写入,永远不会发送此响应,因为始终需要传输字节使能。
3.2.4.4.6 Fast_GO
与GO类似,但仅表示该请求在本地被观察。 当事务在内存中完全可观察时,稍后会有 ExtCmp 消息。 未实现 Fast_GO 功能的设备可能会忽略此消息并等待 ExtCMP。
3.2.4.4.7 Fast_GO_WritePull
与 GO_WritePull 类似,但仅表示本地观察该请求。 当事务在内存中完全可观察时,稍后会有 ExtCmp 消息。
未实现 Fast_GO 功能的设备可能会忽略 GO 消息并等待 ExtCMP。 但必须始终为 WritePull 发送数据。 没有缓存状态传输到设备。
2.2.4.4.8 GO_ERR_WritePull
与 GO_WritePull 类似,但表示事务存在错误,应在设备中正确处理。 WritePull 必须将数据发送到 Host,Host 会丢弃数据。 没有缓存状态传输到设备(假定为错误)。 如果原始请求需要 ExtCmp,则仍会发送 ExtCmp。
3.2.5 Cacheability Details and Request Restrictions(可缓存性详细信息和请求限制)
这些详细信息和限制适用于所有设备。
3.2.5.1 GO-M 响应
来自主机的 GO-M 响应表明设备被授予修改数据的唯一副本。 设备必须缓存该数据并在完成后将其写回。
3.2.5.2 设备/主机 Snoop-GO-数据假设
当主机向设备返回 GO 响应时,期望到达与接收 GO 的请求相同地址的窥探将看到该 GO 的结果。 例如,如果主机发送 GO-E 请求 RdOwn 请求,随后立即对同一地址进行探听,则人们会期望设备将线路转换为 M 状态,并用 RspIFwdM 响应回复主机。
为了实现这一原则,CXL.cache链路层确保设备将在不同的时隙中接收两个消息,以使顺序完全明确。
当主机向设备发送探听时,要求在主机收到探听响应和所有隐式回写 (IWB) 数据之前,不会向设备中具有该地址的任何请求发送 GO 响应( 已收到响应窥探而转发的脏数据。
当主机针对读取类型请求向设备返回数据并且该请求的GO尚未发送至设备时,主机可以直到发送GO消息之后才向该地址发送探听。 由于新的缓存状态被编码在用于读取的响应消息中,因此在未接收到 GO 的情况下向地址发送探听,但在接收到数据后,对于设备来说,在这种情况下探听响应应该是什么是不明确的。
从根本上讲,与读取请求关联的 GO 也适用于随该请求返回的数据。 发送读取请求的数据意味着数据是有效的,这意味着即使 GO 尚未到达,设备也可以使用它。 GO 将稍后到达并通知设备缓存该行的状态(如果有的话)以及数据是否是错误条件的结果(例如命中设备不允许访问的地址区域)。
3.2.5.3 设备/主机监听/WritePull 假设
该器件要求主机不能在 CXL.cache 上同时激活 WritePull 和 H2D Snoop 到给定的 64 字节地址。 在主机接收到来自该地址的所有 WritePull 数据之前,主机可能不会启动对 64 字节地址的监听。
相反,在主机接收到对挂起写入地址的任何探听的探听响应(包括RspFwd情况下的数据)之前,主机不能启动用于写入的WritePull。 任何违反这些要求的行为都意味着 D2H 数据通道上的 Bogus 字段将不可靠。
3.2.5.4 CXL.cache 逐出上的监听响应和数据传输
为了监听缓存逐出(例如,DirtyEvict)并维持监听所有权从设备到主机的有序转移,CXL.cache 上的缓存逐出必须遵守以下协议。
如果设备 Evict 事务已在 CXL.cache D2H 请求通道上发出,但尚未处理来自主机的 WritePull,并且窥探命中 WB,则设备必须跟踪此窥探命中。 当设备开始处理WritePull时,设备必须在发送到主机的所有D2H数据消息中设置Bogus字段。 目的是向主机传达请求数据已作为 IWB 数据发送,因此来自 Evict 的数据可能已过时。
3.2.5.5 对同一地址的多次监听
主机一次只允许对给定设备的给定高速缓存行地址进行一次未完成的探听。 主机必须等待,直到它收到侦听响应和所有 IWB 数据(如果有),然后才能将下一个侦听发送到该地址。
3.2.5.6 对同一缓存行的多次读取
仅在以下特定情况下才允许对同一缓存行进行多个读取请求(可缓存或不可缓存),其中无论处理请求的顺序如何,主机跟踪状态都是一致的。 主机可以自由地对请求重新排序,因此设备负责在需要时对请求进行排序。 对于主机内存,允许多个 RdCurr 和/或 CLFlush。 对于这些命令,设备以 I 状态结束,因此设备缓存的主机跟踪不可能出现不一致的状态。 对于 2 类设备,除了 RdCurr 和/或 CLFlush 之外,设备附加内存还允许多个 RdOwnNoData(偏置翻转请求)。 这种情况是允许的,因为对于设备附加的内存,主机不会跟踪设备的缓存,因此主机中的重新排序不会在设备和主机之间创建不明确的状态。
3.2.5.7 同一缓存线的多次逐出
不允许对同一缓存行进行多次驱逐。 来自设备的所有逐出消息向主机保证被逐出的缓存行将不再存在于设备的缓存中。
因此,为同一缓存行发送另一个 Evict 且没有向该地址插入可缓存的 Read/Read0 请求是违反一致性的。
3.2.5.8 对同一缓存线的多个写请求
同一缓存行的多个 WrInv/WOWrInv/ItoMWr/MemWr 允许在 CXL.cache 上未完成。 主机或交换机可以自由地重新排序请求,并且设备可以以重新排序的方式接收相应的H2D响应。 然而,通常建议设备对给定的高速缓存行发出不超过一个未完成的写入请求,并且只要保证严格的排序,就将多个写入请求相继排序到同一高速缓存行。
3.2.5.9 正常全局观察(GO) 正常全局观察(GO)响应仅在主机保证该请求将拥有所请求的缓存行的下一个所有权之后发送。 请求的 GO 消息携带通过 MESI 状态允许的缓存行状态或指示数据只能使用一次以及是否发生错误。
3.2.5.10Relaxed Global Observation (FastGO)
FastGO 仅适用于不需要严格排序的请求。 一旦保证请求在套接字内(但不一定在系统中)拥有所请求的缓存行的下一个所有权,主机就可以返回 FastGO。 接收 FastGO 响应并需要完成消息的请求通常是写组合
内存类型和排序要求是,会有一个最终完成(ExtCmp)消息,表明该请求处于整个系统完全观察到的阶段。
3.2.5.11 逐出到设备附加内存
CXL.cache 上不允许设备逐出设备连接的内存。 设备仅允许向设备连接的内存发出 WrInv、WOWrInv*。
3.2.5.12 CXL.cache 上的内存类型
要在 CXL.cache 上发出请求,设备需要通过 CXL.io 上的 ATS 请求从主机获取主机物理地址 (HPA)。 由于内存类型限制,在 ATS 完成时,主机向设备指示 HPA 是否只能在 CXL.io 上发出,如第 3.1.6 节所述。 不允许设备向 CXL.cache 上的此类 HPA 发出请求。
3.2.5.13 一般假设
- 主机不会保留设备传送的 CXL.cache 请求的顺序。 对于顺序很重要的情况,设备必须维护请求的顺序。 例如,如果需要根据 MSI(在 CXL.io 上)对 D2H 内存写入进行排序,则由设备来实现排序。 这是通过 CXL.cache 上所有请求的非发布性质实现的。
- 主机选择的顺序对于读取和写入的传达方式将有所不同。 对于读取,全局观察 (GO) 消息传达所寻址的缓存行的下一个所有权; 数据消息传达相对于其他事务的排序。 对于写入,GO 消息传达该行的下一个所有权以及相对于其他事务的排序。
- 如果先前对该地址的读取接收到 GO-E 或 GO-M,则设备可以缓存所有权并在内部顺序写入该地址。
- 对于从设备读取,即使设备尚未收到数据响应,主机也会使用 GO 消息转移缓存行的所有权。
设备必须响应对已接收 GO 的缓存行的监听,但如果需要来自当前事务的数据(例如,写入该行的 RdOwn),则监听的数据部分将被延迟,直到收到数据响应。 - 主机不得针对设备已收到先前读事务的数据响应但尚未收到 GO 的地址发送探听。
参见第 3.2.5.2 节 - 写请求(Evict 除外),例如 WrInv、WOWrInv*、ItoMWr 和 MemWr 永远不会响应带有标记为 Bogus 的数据的 WritePulls。
- 主机不得向同一设备请求发送两个缓存行数据响应。
设备可以假设一次性使用所有权(基于请求)并开始处理设备在 GO 消息之前接收到的缓存行的任何部分。 最终状态信息将随 GO 消息一起到达,此时设备可以根据响应缓存该行或删除它。 - 对于给定的事务,H2D 数据传输必须以自然顺序出现在连续的数据包中,并且没有来自其他线路的交错传输。
- D2H 高速缓存行的数据传输必须以连续数据包的形式进行,不得与其他行交错传输。 数据必须按自然块顺序排列,即 64B 传输必须首先完成较低的 32B 一半,因为窥探始终是缓存行对齐的。
- 除了 D2H 响应通道中信用的可用性之外,D2H 响应中的设备监听响应不得依赖于任何其他通道或设备中的任何其他请求。 主机必须保证响应最终会得到服务并将积分返回到设备。
- 主机不得向某个地址发送第二次探听请求,直到收集到先前探听的所有响应以及所需的数据。
- 发往设备的 H2D 响应和 H2D 数据消息必须耗尽,无需任何其他事务才能取得进展。
- 对于内存中未实际修改的数据,主机不得返回 GO-M。
- 主机不得将未修改的数据写回内存。
- 除WOWrInv和WOWrInF外,所有其他写入都是强有序的
3.2.5.14 隐藏缓存状态规则
每当设备在 CXL.Cache 协议上发起新请求时,埋藏式缓存状态是指在设备的一致性引擎 (DCOH) 中注册的缓存行的状态,针对该缓存行发送特定请求。 埋藏缓存状态规则:
• 如果缓存行隐藏在修改、独占或共享状态,则设备不得对缓存行发出读取。
• 如果缓存行隐藏在修改或独占状态,则设备不得发出RdOwnNoData。 设备可以请求独占状态的所有权作为来自共享状态的升级请求
这篇关于【CXL协议-事务层之CXL.cache (3)】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!