提问者:小点点

存储缓冲区和行填充缓冲区如何相互交互?


我正在阅读MDS攻击论文RIDL: Rogue In-Flight Data Load。他们讨论了Line Fill Buffer如何导致数据泄漏。关于RIDL漏洞和负载的“重放”问题讨论了漏洞利用的微架构细节。

读了这个问题后,我不清楚的一件事是,如果我们已经有一个存储缓冲区,为什么我们需要一个行填充缓冲区。

John McCalpin在WC-buffer如何与LFB相关中讨论了存储缓冲区和行填充缓冲区是如何连接的?在英特尔论坛上,但这并没有让我更清楚。

对于存储到WB空间,存储数据一直保留在存储缓冲区中,直到存储退役后。一旦退役,数据可以写入L1数据缓存(如果该行存在并且有写入权限),否则为存储未命中分配一个LFB。LFB最终会收到缓存行的“当前”副本,以便可以将其安装在L1数据缓存中,并将存储数据写入缓存。合并、缓冲、排序和“捷径”的细节不清楚…与上述合理一致的一种解释是,LFB充当缓存大小的缓冲区,存储数据在发送到L1数据缓存之前在其中进行合并。至少我认为这是有道理的,但我可能忘记了一些事情……

我最近才开始阅读乱序执行,所以请原谅我的无知。这是我对存储如何通过存储缓冲区和行填充缓冲区的想法。

  1. 在前端安排存储指令。
  2. 它在存储单元中执行。
  3. 存储请求被放入存储缓冲区(地址和数据)
  4. 从存储缓冲区向缓存系统发送无效读取请求
  5. 如果它未命中L1d缓存,则将请求放入行填充缓冲区
  6. 行填充缓冲区将无效的读取请求转发到L2
  7. 一些缓存接收无效读取并发送其缓存行
  8. 存储缓冲区将其值应用于传入的缓存行
  9. 呃?行填充缓冲区将条目标记为无效

  1. 如果存储缓冲区已经存在以跟踪超出存储请求,为什么我们需要行填充缓冲区?
  2. 事件的顺序在我的描述中是否正确?

共2个答案

匿名用户

如果存储缓冲区已经存在以跟踪超出存储请求,为什么我们需要行填充缓冲区?

存储缓冲区用于按顺序跟踪存储,在它们停用之前和停用之后,但在它们提交到L1缓存2之前。存储缓冲区在概念上是一个完全本地的东西,并不真正关心缓存未命中。存储缓冲区以各种大小的单个存储的“单位”处理。像Intel Skylake这样的芯片有50个条目的存储缓冲区。

行填充缓冲区主要处理L1缓存中未命中的加载和存储。本质上,它是从L1缓存到内存子系统其余部分的路径,并处理缓存行大小的单位。如果加载或存储命中L1缓存1,我们不期望LFB参与其中。像Skylake这样的Intel芯片的LFB条目要少得多,可能为10到12个(Skylake的测试点为12个)。

事件的顺序在我的描述中正确吗?

非常接近。以下是我如何改变你的名单:

  1. 存储指令被解码并拆分为存储数据和存储地址uops,它们被重命名、调度并为它们分配了一个存储缓冲区条目。
  2. 存储uops以任何顺序或同时执行(两个子项可以按任一顺序执行,主要取决于哪个依赖项首先得到满足)。
    1. 存储数据uop将存储数据写入存储缓冲区。
    2. 存储地址uop进行V-P转换并将地址写入存储缓冲区。

    将共享转换为独占的RFO仍然需要等待响应,以确保所有其他缓存都使其副本无效。对这种无效的响应不需要包含数据副本,因为此缓存已经有一个。它仍然可以称为RFO;重要的部分是在修改行之前获得所有权。6.在未命中场景中,LFB最终会返回该行的全部内容,该行被提交到L1,挂起的存储现在可以提交3

    这是该过程的粗略近似。某些或所有芯片上的某些细节可能不同,包括不太了解的细节。

    举个例子,在上述顺序中,直到商店到达商店队列的头部,才会获取商店未命中行。实际上,商店子系统可能会实现一种RFO预取,其中检查商店队列是否有即将到来的商店,如果L1中不存在这些行,则提前开始请求(对L1的实际可见提交仍然必须按顺序、在x86上或至少“好像”按顺序发生)。

    因此,请求和LFB使用可能最早在步骤3完成时发生(如果RFO预取仅在存储退役后适用),或者甚至可能最早在2.2完成时发生,如果初级存储需要预取。

    作为另一个例子,第6步描述了从内存层次结构返回的行并提交到L1,然后存储提交。有可能挂起的存储实际上与返回的数据合并,然后写入L1。也有可能即使在未命中的情况下,存储也可以离开存储缓冲区,只需在LFB中等待,释放一些存储缓冲区条目。

    1对于命中L1缓存的存储,有一个建议是LFB实际参与其中:每个存储在提交到缓存之前实际上进入了一个组合缓冲区(可能只是一个LFB),这样一系列针对同一缓存行的存储在缓存中合并,只需要访问L1一次。这没有得到证明,但无论如何,它不是LFB主要用途的一部分(更明显的是,我们甚至不能真正判断它是否正在发生)。

    2在停用之前保存存储的缓冲区可能是两个完全不同的结构,具有不同的大小和行为,但在这里我们将它们称为一个结构。

    3所描述的场景涉及未命中的存储在存储缓冲区的头部等待,直到相关行返回。另一种场景是将存储数据写入用于请求的LFB,并且可以释放存储缓冲区条目。这可能允许在未命中时处理一些后续存储,但要遵守严格的x86排序要求。这可能会增加存储MLP。

匿名用户

一旦这些uops在RS中被分配,RS读取其源操作数的物理寄存器并将它们存储在数据栏中,同时检查欧盟写回总线中与这些源PR(物理寄存器)相关的ROB条目和写回数据,因为它们正在被写回ROB。RS然后安排这些uops,以便在它们拥有所有完整的源数据时调度到存储地址和存储数据端口。

然后分派uops-存储地址uop到AGU,AGU生成地址,将其转换为线性地址,然后将结果写入SAB。我认为在PRF R-RAT方案中,存储根本不需要PR(这意味着在这个阶段ROB不需要发生写回),但是在RRF方案中,ROB条目被迫使用它们的嵌入式PR并且所有内容(ROB/RS/MOB条目)都由它们的PR号标识。PRF R-RAT方案的好处之一是ROB,因此飞行中uops的最大数量可以扩展,而不必增加PR的数量(因为会有不需要任何指令),并且所有内容都由ROB条目编号解决,以防条目没有识别PR。

存储数据直接通过存储转换器(STC)到达SDB。一旦它们被调度,它们就可以被释放以供其他uops重用。这可以防止更大的ROB受到RS大小的限制。

然后将地址发送到dTLB,然后将dTLB输出的物理标签存储在L1d缓存的PAB中。

然后它检查线路的状态。如果是共享线路,物理地址将被发送到RFO中的相干域(写入时始终为RFO),当它拥有该行的所有权时,它将数据写入缓存。如果该行不存在,则为该缓存线路分配一个LFB,存储数据存储在其中,并向L2发送请求,然后L2将检查L2中线路的状态,并在环IDI接口上启动读取或RFO。