7

我正在阅读 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 缓存,则将请求放入 Line Fill Buffer
  6. Line Fill Buffer 将无效读取请求转发到 L2
  7. 一些缓存接收到无效读取并发送其缓存行
  8. 存储缓冲区将其值应用于传入的缓存行
  9. 呃?行填充缓冲区将条目标记为无效

在此处输入图像描述

问题

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

2 回答 2

10

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

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

行填充缓冲区主要处理L1 缓存中未命中的加载和存储。本质上,它是从 L1 高速缓存到内存子系统其余部分的路径,并处理高速缓存行大小的单元。如果加载或存储命中 L1 缓存1,我们不希望 LFB 参与其中。像 Skylake 这样的英特尔芯片的 LFB 条目要少得多,可能只有 10 到 12 个。

我的描述中的事件顺序是否正确?

八九不离十。以下是我将如何更改您的列表:

  1. 存储指令被解码并拆分为存储数据和存储地址微指令,它们被重命名、调度并为它们分配存储缓冲区条目。
  2. 存储微指令以任何顺序或同时执行(这两个子项可以以任一顺序执行,主要取决于哪个首先满足其依赖关系)。
    1. 存储数据uop 将存储数据写入存储缓冲区。
    2. 存储地址 uop 进行 VP 转换并将地址写入存储缓冲区。
  3. 在所有旧指令退出的某个时刻,存储指令退出。这意味着该指令不再是推测性的,并且可以使结果可见。此时,存储仍保留在存储缓冲区中,称为高级存储。
  4. 存储现在一直等到它位于存储缓冲区的头部(它是最旧的未提交存储),此时它将提交(成为全局可观察的)到 L1,如果关联的缓存行存在于 L1 中MESIF 修改或独占状态。(即这个核心拥有这条线)
  5. 如果该行未处于所需状态(完全丢失,即缓存未命中,或存在但处于非排他状态),则必须从内存子系统:这会为整行分配一个 LFB,如果尚未分配一个。这是一个所谓的所有权请求(RFO),这意味着内存层次结构应该以适合修改的独占状态返回行,而不是只适合读取的共享状态(这会使存在于任何其他私有缓存)。

将共享转换为独占的 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。

于 2020-04-10T15:27:31.287 回答
0

当 uops 到达分配器时,在 PRF + Retirement RAT 方案(从 SnB 开始)中,分配器会在必要时咨询前端 RAT (F-RAT) 以重命名 ROB 条目(即,当写入架构寄存器时(例如rax) 被执行)它在 ROB 的尾指针处分配给每个 uop。RAT 在 PRF 中保留一个空闲和正在使用的物理目标寄存器 (pdsts) 的列表。RAT 返回要使用的空闲物理寄存器编号,然后 ROB 将它们放在相应的条目中(在 RRF 方案中,分配器向 RAT 提供要使用的 pdsts;RAT 无法选择,因为 pdsts要使用的对象本来就位于 ROB 的尾部指针处)。RAT 还使用分配给它的寄存器更新每个体系结构寄存器指针,即它现在指向包含程序顺序中最新写入数据的寄存器。同时,ROB 在预留站 (RS) 中分配一个条目。在存储的情况下,它将在 RS 中放置一个存储地址 uop 和一个存储数据 uop。

一旦在 RS 中分配了这些微指令,RS 就读取其源操作数的物理寄存器并将它们存储在数据字段中,同时检查 EU 回写总线以查找与源 PR(物理寄存器)相关的 ROB 条目和回写数据,因为它们被写回 ROB。然后,RS 安排这些微指令在它们拥有所有已完成的源数据时分派到存储地址和存储数据端口。

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

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

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

分配器已经为该 ROB 条目分配了 SBID 和 SAB / SDB 中的相应条目(STA+STD 微指令被微融合到一个条目中),它们缓冲来自 RS 的 AGU / TLB 中分派执行的结果。商店位于 SAB / SDB 中,对应的条目具有相同的条目号。(SBID),它将它们链接在一起,直到 MOB 被退休单元通知哪些存储已准备好退休,即它们不再是推测性的,并且在指向 ROB 索引的 ROB 条目重试指针的 CAM 匹配时通知它/ID 包含在 SAB / SDB 条目中(在每个周期可以引退 3 uop 的 uarch 中,有 3 个引退指针指向 ROB 中的 3 个最旧的未引退指令,并且只有 ROB 就绪位模式 0,0 ,1 0,1,1 和 1,1, 1 允许退出指针 CAM 匹配继续)。在这个阶段,他们可以在ROB中退休(称为'retire / complete local')并成为高级存储并用高级位(STA的Ae位,STD的De位)标记,并慢慢调度到L1d缓存,只要 SAB/SDB/PAB 中的数据有效。

L1d 缓存使用 SAB 中的线性索引对 tags 数组中的一个集合进行解码,该集合将包含使用线性索引的数据,并在下一个循环中使用与 SBID 具有相同索引值的相应 PAB 条目来比较物理带有集合中的标签的标签。PAB 的全部目的是允许对存储进行早期 TLB 查找以隐藏 dTLB 未命中的开销,而它们在等待成为高级时什么都不做,并允许在存储实际上仍处于推测状态时进行推测性页面遍历。如果存储是立即高级的,那么这个早期的 TLB 查找可能不会发生,它只是被分派,这就是 L1d 缓存将解码标记数组集并并行查找 dTLB 并绕过 PAB 的时候。记住虽然它可以 t 在执行 TLB 转换之前退出 ROB,因为可能存在 PMH 异常代码(页面错误,或在执行页面遍历时需要设置读取的访问/脏位),或者当 TLB 需要时出现异常代码通过它在 TLB 条目中设置的访问/脏位写入。完全有可能对存储的 TLB 查找始终发生在此阶段,并且不会与设置的解码并行执行(与加载不同)。当 PAB 中的 PA 变为有效(在 SAB 中设置了有效位)并且它在 ROB 中准备好退休时,存储变为高级。完全有可能对存储的 TLB 查找始终发生在此阶段,并且不会与设置的解码并行执行(与加载不同)。当 PAB 中的 PA 变为有效(在 SAB 中设置了有效位)并且它在 ROB 中准备好退休时,存储变为高级。完全有可能对存储的 TLB 查找始终发生在此阶段,并且不会与设置的解码并行执行(与加载不同)。当 PAB 中的 PA 变为有效(在 SAB 中设置了有效位)并且它在 ROB 中准备好退休时,存储变为高级。

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

当 RFO 完成并且 LFB 中的一个位表示它有权写入该行时,该存储变得全局可见,这意味着 LFB 将在下一次探听无效或驱逐时连贯地写回(或者在命中的情况下,当数据写入该行)。在发生未命中的情况下,在获取行之前将其写入 LFB 时,它不被视为全局可见(与在命中时退出的高级负载或 L1d 缓存分配 LFB 时的高级负载不同),因为可能存在由其他内核发起的其他 RFO,这些 RFO 可能在当前内核的请求之前到达 LLC 切片控制器,如果一个SFENCE当前内核已基于此版本的“全局可见”退休而退休-至少这为处理器间中断提供了同步保证。全局可见的是,如果负载发生在另一个核心上,存储的数据将被另一个核心读取的那一刻,而不是在一小段时间之后,在此之前旧值仍将被其他核心读取的那一刻。存储由 L1d 高速缓存在分配 LFB 时完成(或在发生命中时将它们写入行)并从 SAB / SDB 退出。当所有先前的存储都从 SAB / SDB 中退出时,这就是store_address_fence(not store_address_mfence) 及其相关联store_data_fence的可以分派到 L1d 的时间。序列化 ROB 指令流也更实用LFENCE,而SFENCE/MFENCE不要因为它可能会导致 ROB 中的全局可见性延迟很长并且没有必要,这与立即退休的高级负载不同,所以为什么LFENCE选择栅栏同时序列化指令流是有道理的。SFENCE/MFENCE在所有分配的 LFB 成为全局可见之前,不要退休。

行填充缓冲区可以处于 3 种模式中的一种:读、写或写组合。我认为写行填充缓冲区的目的是将多个存储组合到同一行的数据到 LFB 中,然后当行到达时,用从 L2 获取的数据填充无效位。可能在这个阶段,它被认为已完成,因此写入在批量和一个周期之前得到满足,而不是等待它们被写入行中。只要它现在保证被写回缓存以响应另一个内核的 RFO。LFB 可能会一直保持分配状态,直到它需要被释放,从而可以稍微更快地满足对同一行的后续读取和写入。读取行缓冲区可以更快地服务读取未命中几个周期,因为它在行填充缓冲区中立即可用,但将其写入缓存行然后从中读取需要更长的时间。当内存是一个写组合缓冲区时分配USWC类型并允许立即满足写入并立即将其全部刷新到 MMIO 设备,而不是具有多个 core->PCIe 事务并具有多个 PCIe 事务。WC 缓冲区还允许从缓冲区进行推测性读取。通常,在 UC 内存上不允许进行推测性读取,因为读取可能会改变 MMIO 设备的状态,而且读/写需要很长时间,以至于当它完成时,它将不再是推测性的,因此可能不值得额外交通?LFB 可能是 VIPT(VIPT/PIPT 在 intel 上是相同的,而 V 是 intel 上的线性地址);我想它可能有物理和虚拟标签来消除进一步的 TLB 查找,但是当物理页面迁移到新的物理地址时必须协商一些东西。

于 2021-01-26T08:51:35.130 回答