Write-Combining Buffer 位于何处? x86

Where is the Write-Combining Buffer located? x86

Write-Combine 缓冲区是如何物理连接的?我看过说明许多变体的框图:

它是否依赖于微架构?

在现代 Intel CPUs 中,写入组合由 LFB(行填充缓冲区)完成,也用于来自 L1 <-> L2 的其他待处理传输。每个核心都有 10 个(自 Nehalem 以来)。 (Transfers between L2 and L3 use different buffers, called the "superqueue").

这就是为什么英特尔建议在进行 NT 存储时避免过多的其他流量,以避免因分配 LFB 的需求负载而导致过早刷新部分填充的 LFB。 https://software.intel.com/en-us/articles/copying-accelerated-video-decode-frame-buffers

LFB 的 "inside" 连接到 L1d、存储缓冲区和加载端口。

LFB 的 "outside" 可以与 L2 通信或(可能在 L2 的帮助下)通过环形总线/网格到达内存控制器,或用于 NT 预取的 L3.对于 L3 和内存来说,脱离核心可能没有太大区别;只是在核心之间的环网/网状互连上发送的不同类型的消息;在 Intel CPUs 中,内存控制器是 just another stop on the ring bus (in the "system agent), like other cores with their slices of L3. L1 LFB 真的 直接连接到环形总线,并且请求不放进入 L2 的数据可能仍会通过 L2 超级队列缓冲区到达环形总线/网格。这似乎是可能的,因此每个内核只需要在环形总线上存在一个点,L2 和 L1 之间的仲裁发生在内核内部。


NT 存储数据 直接从存储缓冲区进入一个 LFB,并探测 L1d 以查看它是否需要先驱逐该行。

正常存储数据 在从 L1d 逐出时进入 LFB,为正在分配的新行腾出空间或响应来自另一个想要读取的核心的 RFO那条线。

L1d 中未命中的正常加载(和存储)需要缓存来获取该行,它还会分配一个 LFB 来跟踪传入行(以及对 L2 的请求) .当数据到达时,它会直接发送到等待它的加载缓冲区,同时将其放入 L1d。 (在 CPU 体系结构术语中,参见 "early restart" and "critical word first":缓存未命中只会阻塞,直到需要的数据到达,缓存行的其余部分到达 "in the background"。)你(和 CPU Intel 的架构师)绝对不希望 L2 命中延迟包括将数据放入 L1d 并再次取出。

NT从WC内存加载(movntdqa)直接从LFB读取;数据根本不会进入缓存。 LFB 已经连接到加载端口以提前重启正常负载,因此我认为 SSE4 能够添加 movntdqa 而无需在硅片上增加很多额外成本。不过,它的特殊之处在于未命中只会直接从内存中填充 LFB,绕过 L3/L2/L1。 NT 存储已经需要 LFB 才能与内存控制器通信。

写缓冲区在不同的处理器中可以有不同的用途或不同的用途。此答案可能不适用于未具体提及的处理器。我想强调的是 "write buffer" 一词在不同的上下文中可能有不同的含义。此答案仅针对 Intel 和 AMD 处理器。

Intel 处理器上的写入组合缓冲区

每个缓存可能伴随有零个或多个行填充缓冲区(也称为填充缓冲区)。 L2 的填充缓冲区集合称为超级队列或超级队列(超级队列中的每个条目都是一个填充缓冲区)。如果高速缓存在逻辑内核或物理内核之间共享,则关联的填充缓冲区也在内核之间共享。每个填充缓冲区可以保存一个缓存行和描述缓存行的附加信息(如果它被占用),包括缓存行的地址、内存类型和一组有效位,其中位数取决于缓存行的粒度跟踪缓存行的各个字节。在早期的处理器中(例如 Pentium II),只有一个填充缓冲区能够进行写合并(和写折叠)。随着处理器的更新,行缓冲区和能够写入组合的行缓冲区总数稳步增加。

从 Nehalem 到 Broadwell,每个 L1 数据缓存都包含 10 个填充缓冲区。 Core 和 Core2 每个物理内核有 8 个 LFB。根据this, there are 12 LFBs on Skylake. @BeeOnRope has observed that there are 20 LFBs on Cannon Lake. I could not find a clear statement in the manual that says LFBs are the same as WCBs on all of these microarchitectures. However, this article一位来自英特尔的人写的说:

Consult the Intel® 64 and IA-32 Architectures Optimization Reference Manual for the number of fill buffers in a particular processor; typically the number is 8 to 10. Note that sometimes these are also referred to as "Write Combining Buffers", since on some older processors only streaming stores were supported.

我认为LFB这个词最早是由Intel在Intel Core微架构中引入的,在Intel Core微架构上,8个LFB也都是WCB。基本上,英特尔当时偷偷把 WCB 改名为 LFB,但此后并没有在他们的手册中明确这一点。

同一句话还说,术语 WCB 用于较旧的处理器,因为它们不支持流式加载。这可以解释为 LFB 也被流加载请求使用 (MOVNTDQA)。然而,第 12.10.3 节说流式加载将目标行提取到称为流式加载缓冲区的缓冲区中,这在物理上显然不同于 LFBs/WCBs.

以下情况使用行填充缓冲区:

(1) 在高速缓存中加载未命中(请求或预取)时分配填充缓冲区。如果没有可用的填充缓冲区,加载请求会不断堆积在加载缓冲区中,这可能最终导致发布阶段停滞。在加载请求的情况下,分配的填充缓冲区用于临时保存来自内存层次结构较低级别的请求行,直到它们可以写入缓存数据数组。但是高速缓存行的请求部分仍然可以提供给目标寄存器,即使该行尚未写入高速缓存数据阵列。根据Patrick Fay (Intel):

If you search for 'fill buffer' in the PDF you can see that the Line fill buffer (LFB) is allocated after an L1D miss. The LFB holds the data as it comes in to satisfy the L1D miss but before all the data is ready tobe written to the L1D cache.

(2) 填充缓冲区在可缓存存储上分配给 L1 缓存,目标行未处于允许修改的一致性状态。我的理解是,对于可缓存存储,只有 RFO 请求保存在 LFB 中,但要存储的数据在存储缓冲区中等待,直到目标行被提取到为其分配的 LFB 条目中。 Intel 优化手册第 2.4.5.2 节中的以下语句支持这一点:

The L1 DCache can maintain up to 64 load micro-ops from allocation until retirement. It can maintain up to 36 store operations from allocation until the store value is committed to the cache, or written to the line fill buffers (LFB) in the case of non-temporal stores.

这表明如果目标行不在 L1D 中,则可缓存存储不会提交给 LFB。换句话说,存储必须在存储缓冲区中等待,直到将目标行写入 LFB,然后在 LFB 中修改该行,或者将目标行写入 L1D,然后修改该行在 L1D.

(3) 填充缓冲区被分配到 L1 缓存中不可缓存的写入组合存储上,而不管该行是否在缓存中或其一致性状态。在单个 LFB 中,可以组合和折叠对同一缓存行的 WC 存储(多次写入同一行中的同一位置将使程序顺序中的最后一个存储在它们变得全局可观察之前覆盖之前的存储)。当前在 LFB 中分配的请求之间不维护顺序。因此,如果有两个 WCB 在使用中,则无法保证哪个将首先被逐出,无论存储的顺序与程序顺序无关。这就是为什么 WC 存储可能变得无序地全局可见,即使所有存储都按顺序退出提交(尽管 WC 协议允许 WC 存储无序提交)。此外,WCB 不会被窥探,因此只有当它们到达内存控制器时才变得全局可见。可以在 Intel 手册 V3 的第 11.3.1 节中找到更多信息。

some AMD processors 使用与非临时存储的填充缓冲区不同的缓冲区。 P6(第一个实现 WCB)和 P4 中也有一些 WCB 缓冲器专用于 WC 内存类型(不能用于其他内存类型)。在 P4 的早期版本中,有 4 个这样的缓冲区。对于支持超线程的 P4 版本,当启用超线程并且两个逻辑核心都是 运行ning 时,WCB 在两个逻辑核心之间静态分区。然而,现代英特尔微体系结构竞争性地共享所有 LFB,但我认为每个逻辑核心至少保留一个可用以防止饥饿。

(4) L1D_PEND_MISS.FB_FULL的文档表明UC stores分配在相同的LFBs中(不管该行是否在缓存中或其一致性状态).与可缓存存储一样,但与 WC 不同的是,UC 存储未组合在 LFB 中。

(5) 我通过实验观察到来自 INOUT 指令的请求也在 LFB 中分配。有关详细信息,请参阅:How do Intel CPUs that use the ring bus topology decode and handle port I/O operations.

附加信息:

填充缓冲区由缓存控制器管理,缓存控制器连接到其他级别的其他缓存控制器(或 LLC 的内存控制器)。当请求命中缓存时,不会分配填充缓冲区。因此,在缓存中命中的存储请求直接在缓存中执行,而在缓存中命中的加载请求直接由缓存提供服务。当从缓存中逐出一行时,不会分配填充缓冲区。逐出的行被写入它们自己的缓冲区(称为写回缓冲区或逐出缓冲区)。这是 Intel 的 patent,讨论了 I/O 写入的写入梳理。

我有一个 运行 与我描述的非常相似的实验 以确定是否分配单个 LFB,即使同一行有多个负载。事实证明,确实如此。第一次加载到写回 L1D 缓存中未命中的行会为其分配一个 LFB。以后对同一缓存行的所有加载都将被阻止,并且会在相应的加载缓冲区条目中写入一个块代码,以指示它们正在等待该 LFB 中保存的同一请求。当数据到达时,L1D 缓存向加载缓冲区发送一个唤醒信号,并且在该行上等待的所有条目都被唤醒(畅通)并安排在至少一个加载端口可用时发送到 L1D 缓存.显然,内存调度程序必须在未阻塞的负载和刚刚从 RS 分派的负载之间进行选择。如果在所有等待的负载有机会得到服务之前,线路由于某种原因被逐出,那么它们将再次被阻塞,并且将再次为该线路分配一个 LFB。我没有测试商店的情况,但我认为无论操作是什么,都会为一行分配一个 LFB。 LFB 中的请求类型可以从预取到请求加载到推测 RFO 到需要时请求 RFO。我还根据经验发现,在刷新管道时,在错误预测的路径上从 uops 发出的推测请求不会被删除。它们可能会降级为预取请求。我不确定。

AMD 处理器上的写入组合缓冲区

我之前根据 article 提到,有一些 AMD 处理器使用与非临时存储的填充缓冲区分开的缓冲区。我引用文章:

On the older AMD processors (K8 and Family 10h), non-temporal stores used a set of four “write-combining registers” that were independent of the eight buffers used for L1 data cache misses.

"on the older AMD processors" 部分让我很好奇。这在较新的 AMD 处理器上有变化吗?在我看来,这在所有更新的 AMD 处理器上仍然适用,包括最新的 Family 17h 处理器 (Zen)。 WikiChip article on the Zen mircoarchitecture includes two figures that mention WC buffers: this and this. In the first figure, it's not clear how the WCBs are used. However, in the second one it's clear that the WCBs shown are indeed specifically used for NT writes (there is no connection between the WCBs and the L1 data cache). The source for the second figure seems to be these slides1. I think that the first figure was made by WikiChip (which explains why the WCBs were placed in an indeterminate position). In fact, the WikiChip article does not say anything about the WCBs. But still, we can confirm that the WCBs shown are only used for NT writes by looking at Figure 7 from the Software Optimization Guide for AMD Family 17h Processors manual and the patent 用于 Family 17h 处理器的加载和存储队列。 AMD 优化手册指出,现代 AMD 处理器中每个内核有 4 个 WCB。我认为这适用于 K8 和所有后来的处理器。不幸的是,关于扮演 Intel 填充缓冲区角色的 AMD 缓冲区没有任何说法。


1 Michael Clark, A New, High Performance x86 Core Design from AMD, 2016.

一级缓存中有多个缓冲区。

This patent 给出以下缓冲区类型:

  • 监听缓冲区(服务于 M/E 状态监听来自其他内核的缓冲区(读取/RFO))
  • 写回缓冲区(为 M 状态从 L1 逐出提供服务的缓冲区)
  • 行填充缓冲区(服务可缓存 load/store L1 未命中的缓冲区)
    • 读取缓冲区(服务 L1 读取可缓存临时负载的未命中)
    • 写入缓冲区(服务 L1 可缓存临时存储的写入未命中)
    • 写入组合行填充缓冲区(不确定,似乎与本专利中的写入组合专用缓冲区相同)
  • 专用缓冲区(缓冲区服务不可缓存 loads/stores 并且 'dedicated' 用于从内存中获取而不是 L2(但仍通过 L2 传递请求),并且不填充缓存行)
    • 非写入组合专用缓冲区(服务 UC loads/stores 和 WP 存储)
    • 写入组合专用缓冲区(服务 USWC loads/stores)

该专利表明,这些都可以是同一个物理缓冲区的功能,或者它们可以在物理上是分开的,并且每个功能都有一组缓冲区。在 Intel 上,Skylake 上的 12 个 LFB 可能是全部,逻辑功能在它们之间共享类型或状态字段。在一些实施例中,行填充缓冲区还可以处理 USWCloads/stores。在一些实施例中,专用缓冲区可以处理错过 L1 的可缓存 non-temporal (NT) loads/stores(这样它们就不会 'fill' L1d 缓存,顾名思义,利用 NT防止缓存污染的提示)。

'Write combining buffer' 这里暗示了 USWC 内存 / non-temporality 和固有的弱排序和不可缓存性,但实际的词 'write combining' 并不暗示任何这些东西,可能只是一个其自身的概念,其中对同一存储缓冲区的常规写入未命中被压缩并按程序顺序写入同一行填充缓冲区。 A patent suggests such functionality, so it is probable that regular temporal write buffers that aren't marked WC probably have a combining functionality. Related:

x86-64 优化手册声明(大量赠品):

On a write miss to the first-level cache, it allows multiple stores to the same cache line to occur before that cache line is read for ownership (RFO) from further out in the cache/memory hierarchy. Then the rest of line is read, and the bytes that have not been written are combined with the unmodified bytes in the returned line. Store ordering and visibility are also important issues for write combining. When a write to a write-combining buffer for a previously-unwritten cache line occurs, there will be a read-for-ownership (RFO). If a subsequent write happens to another write combining buffer, a separate RFO may be caused for that cache line. Subsequent writes to the first cache line and write-combining buffer will be delayed until the second RFO has been serviced to guarantee properly ordered visibility of the writes. If the memory type for the writes is write-combining, there will be no RFO since the line is not cached, and there is no such delay.

这是术语 'write combining buffer' 用于描述具有纯粹组合能力的常规写入缓冲区的明显证据,其中保持了强排序。我们现在还知道,不仅仅是 non-temporal 存储到分配写入组合缓冲区的任何内存,而是所有写入(因为 non-temporal 存储不发出 RFO)。缓冲区用于在发生 RFO 时组合写入,以便可以完成存储并释放存储缓冲区条目(如果它们都写入同一缓存行,则可能是多个)。无效位表示当缓存行到达 E 状态时要合并到缓存行中的位。一旦该行出现在高速缓存中,LFB 就可以转储到高速缓存,并且之后对该行的所有写入要么直接写入高速缓存行,要么它可以保持分配以进一步加速 reads/writes 直到释放条件发生(例如它需要用于其他目的或 RFO 到达线路,这意味着它需要写回线路)

所以现在看来​​,所有缓冲区都可以是任何类型的逻辑缓冲区,所有逻辑写缓冲区都是 write-combining 缓冲区(除非 UC)并且缓存类型决定了缓冲区的处理方式weak/strong 排序以及是否执行 RFO 或是否将其写回缓存。 LFB中的缓存类型,要么来自TLB(从PMH获取缓存类型,PMH分析PTE、PAT MSR和MTRR MSR,计算出最终的缓存类型),要么缓冲后的SAB(Store Address Buffer)推测性 TLB 查找的结果。

所以现在有6种缓冲区:

  • 写入组合 LFB(WB 写入未命中/预取)
  • 读取 LFB(从 UC 和 USWC 以外的任何地方读取未命中/预取)
  • 写入组合专用缓冲区(WP 写入、WT 写入未命中、USWC read/write、NT read/write 到除 UC 以外的任何地方)
  • 专用缓冲区(UC read/write)
  • 监听缓冲区
  • 驱逐写回缓冲区

这些缓冲区由物理地址索引,并与 L1 缓存并行扫描,如果它们包含有效数据,则可以更快、更有效地满足 read/write 命中,直到它们在释放条件发生时被释放.我认为“10 LFB”值是指可用于前两个目的的缓冲区数。 L1d 写回有一个单独的 FIFO 队列。

我们不要忘记缓存类型的优先顺序:

  • UC(英特尔E位)
  • USWC (PAT)
  • UC(MTRR)
  • UC (PAT)
  • USWC(MTRR)(如果与WP或WT组合(PAT/MTRR):逻辑与或非法:默认为UC)
  • UC- (PAT)
  • WT WP (PAT/MTRR)(在此等级中组合 MTRR 会产生逻辑和内存类型;在此等级上组合 MTRR 和 PAT 会产生逻辑和(英特尔); AMD(非法:UC))
  • 白平衡 (PAT/MTRR)

此处的MTRR包括默认类型,其中范围未被MTRR映射。 MTRR 是 MTRR 解决了任何冲突或默认值后产生的最终类型。首先,默认值被解析为 UC 并与任何 UC MTRR 排名相同,然后将任何冲突的 MTRR 组合成最终的 MTRR。然后将此 MTRR 与 PAT 和 E 位进行比较,优先级最高的成为最终内存类型,尽管在某些情况下,它们是非法组合,会导致创建不同的类型。没有UC-MTRR.

缓存类型的描述(时间):

  • UC(强不可缓存)。不允许推测性读取和写入组合。强烈订购。
  • UC-(弱不可缓存)与 UC 相同,只是它是 PAT 的较低优先级 UC
  • 允许 USWC(Uncacheable Speculative Write Combining)推测和写入组合。不缓存读取和写入。相对于其他读取和写入,读取和写入都变得弱有序。
  • WT(直写)读取是可缓存的,其行为类似于 WB。命中 L1 缓存的 WT 写入同时更新 L1 缓存和外部存储器,而未命中 L1 缓存的 WT 写入仅更新外部存储器。允许推测性读取和写入组合。强烈订购。
  • WP(写保护)读取是可缓存的,并且表现得像 WB。写入不可缓存并导致行无效。允许推测性读取。强烈订购。
  • WB(回写)一切都是允许的。强烈订购。

缓存类型说明(non-temporal):

  • NT UC 无差异(UC 覆盖)
  • 我认为NT USWC和USWC没什么区别
  • NT WT 我认为这与 NT WB 的行为相同。 Seems so.
  • NT WP 我不确定 WP 是否会覆盖 NT 提示以仅写入或读取。如果它不覆盖读取,那么读取很可能表现得像 NT WB。
  • NT WB 在答案顶部的专利中,NT 读取可以命中 L1 缓存,并且它使用有偏见的 LRU 策略来减少污染(这类似于强制集合的树 PLRU 指向该方式)。读取未命中的行为类似于 USWC 读取未命中,并且分配了写入组合专用缓冲区,它导致 LLC 或其他内核或套接字中的任何别名行在从内存读取行之前被写回内存,并且读取也是弱排序的。它是特定于现代英特尔 CPU 上发生的 NT WB 读取的实现——NT 提示可以完全忽略,它的行为类似于 WBsee full discussion). Write hits in L1 cache in some implementations 可以将写入与 L1 中的行合并使用强制 PLRU,以便接下来将其逐出(作为 WB),或者写命中导致逐出,然后分配写组合专用缓冲区,就好像有未命中一样,写回 USWC(使用 WCiL(F)) 在释放条件上。写入未命中分配一个专用的写入组合缓冲区,并在释放时作为 USWC 写回内存,但如果该未命中导致 L2 命中,则写入组合缓冲区立即或在释放时写入 L2条件,这要么导致立即从 L2 逐出,要么强制 PLRU 位,因此它是下一次逐出。进一步 reads/writes 该行继续由缓冲区满足,直到它被释放。NT 写入是弱排序的。 L1/L2 中未处于 M/E 状态的写入命中可能仍导致 WiL 使当前和其他套接字上的所有其他核心无效以获得 E 状态,否则,它只是使该行无效,当最终创建 USWC 存储时,LLC 检查是否有任何其他核心当前或远程套接字需要失效。

如果完整的 USWC 存储(操作码 WCiLF)命中 LLC 缓存,Cbo 发送 IDI 无效(出于某种原因使 IDI 操作码无效(as part of egress request in the IPQ logical queue of the TOR) sent by Cbo is undocumented) to all cores with a copy and also always sends a QPI InvItoE,无论是否存在 LLC 未命中或不,根据 SAD 交错规则发送到正确的归属代理。只有过滤器中的所有核心都响应了无效并且归属代理也响应了,存储才会发生;在它们响应之后,Cbo 发送 WrPull_GO_I(代表 Write Pull with globally observed notification and Invalidate Cache Line)从 L2 发送数据并将数据发送到 home。如果部分 USWC 存储 WCiL 在 LLC 缓存中命中,同样会发生,除非该行现在在 LLC 切片中进行了修改(从 SnpInv 如果该行仅存在于一个核心中,它发送而不是无效 - 我猜它确实这样做并且不只是发送普通的无效对于 WCiL 就像它对 WCiLF) 所做的那样,或者一直在 LLC 中修改,Cbo 在执行写启用之前对归属代理执行 WBMtoI/WbMtoIPtl USWC 商店的位回写 WcWrPtl。 PAT 在虚拟地址上运行,因此可能会出现别名,即同一物理页面可能有e 多种不同的缓存策略。据推测,WP write 和 UC read/write 别名也有相同的行为,但我不确定。

核心superqueue是L2和L3之间的接口。 SQ 也称为 'off core requests buffer',任何非核心请求都称为任何已到达 SQ 的 request。虽然,我相信分配条目是为了在 L1 写回时填充 L2,这并不是真正的 'request'。因此,当 L1D 写回挂起 FIFO 请求缓冲区已满时,可能会发生 OFFCORE_REQUESTS_BUFFER.SQ_FULL,这表明如果该缓冲区已满,则无法分配 SQ 中的另一个条目,这表明条目已在 SQ 中分配,并且该缓冲区位于同时。对于 LFB,在 L2 命中时,数据直接提供给 LFB,否则在未命中时,如果分配 SQ 条目并在从两个 32B IDI 事务中获取的数据写入 SQ 时提供给 LFB。进一步的 L2 未命中可以击中 SQ 并被压缩到相同的条目 (SQ_MISC.PROMOTION)。

RFO 意图从存储缓冲区开始,如果它以 M 或 E 状态命中 L1d 缓存,则执行写入并结束 RFO。如果该线路处于 I 状态,则分配一个 LFB 并且 RFO 传播到 L2,如果处于 M 或 E 状态(当 M 线路被写回 L2 时,它会变成 M​​ 状态)那里关于L3)。如果它是 I 状态/不存在,则它在 SQ 中分配,并且 RFOItoM 数据包传播到处理地址范围的相应 LLC 切片 Cbo。然后,Cbo 切片使用窥探过滤器使其他核心无效,这涉及向核心发送无效请求(或窥探无效(SnpInv),如果它仅存在于一个核心中——它也会获取数据,因为Cbo 不知道这是否被修改)。 Cbo 一直等待,直到它收到来自核心的无效确认(以及修改后的数据)。然后 Cbo 向请求核心的 SQ 表明它现在具有独占访问权。它可能会提前确认这一点,因为 Cbo 可能必须从内存控制器中获取数据,因此它可以提前确认数据不存在于任何其他内核中。 SQ 将此信息传播到 L1d 缓存,这会导致在 LFB 中设置全局观察位,高级存储现在可以从 SAB/SDB 退出以释放其条目。当数据最终到达时,它会传播到 LFB,在那里它被合并到无效位中,然后根据该地址的释放条件或由于 LFB 资源限制将其写入缓存。

如果 WB 行存在于 L1 中但处于 S 状态,则在写入该行之前,它可能会或可能不会分配 LFB 以合并存储。如果它在 L1 中无效/不存在,则将 LFB 分配给合并存储。然后,如果线路存在于 L2 但处于 S 状态,则将 WiL 数据包发送到 LLC 切片(它只需要使其他内核无效)。然后它通知请求核心的 SQ 它现在可以将其转换到 E 状态。此信息被传播到 L1d 缓存,在 LFB 资源约束的该地址发生释放条件之前,现在可以将 LFB 合并到缓存中。

ItoM is used instead of an RFO when it's assumed that the full line is going to be written to so it doesn't need a copy of the data already in the line, and it already has the data if it's in any other state (S, E, M). A theoretical StoI i.e. a WiL is the same thing as an RFO, same for E, all except for I, where ItoM and RFO differs in that the LLC doesn't need to send the data to the core for an ItoM. The name emphasises only the state changes. How it knows the whole line is going to be written to by stores I dont know.. maybe the L1d cache can squash a bunch of sequential senior stores in the MOB all at once while it allocates a LFB, because the RFO is sent immediately upon allocation I thought (and then retires them all once the RFO arrives). I guess it has some further time for stores to arrive in the LFB (L2 lookup) before the opcode has to be generated. .

我假设RFO IDI数据包不需要区分请求锁定RFO、预取RFO、请求常规RFO(non-prefetch),以对应Xeon 5500 core events,但可能对于优先级目的(优先于预取的需求流量),否则只有核心需要知道这个信息,这要么编码在 RFO 中,要么有单独的未记录的操作码。 PrefRFO 由核心发送以预取到 LLC。

L1i 表面上缺少填充缓冲区意味着填充缓冲区的主要好处是一个存储和组合存储的位置,并且可以更快地释放存储缓冲区条目。由于 L1i 不执行任何存储,因此没有必要这样做。我本以为它确实仍然读取了 LFB,以便它可以在填充缓存时或之前提供丢失的数据,但后续读取不会加速,因为我认为缓冲区是 PIPT 并且它们的标签与缓存并行扫描。读取 LFB 还将压缩读取以指向 LFB 并防止多次查找,并通过跟踪 LFB MSHR 中的当前未命中来防止缓存阻塞,因此很可能存在此功能。