从 Intel 上的 CPUID 结果了解 TLB

Understanding TLB from CPUID results on Intel

我正在探索 cpuid 指令的叶 0x02 并提出了几个问题。有一个 table in the documentation 描述了 cpuid 结果对 TLB 配置的意义。他们在这里:

案例 1

56H TLB Data TLB0: 4 MByte pages, 4-way set associative, 16 entries
[...]
B4H TLB Data TLB1: 4 KByte pages, 4-way associative, 256 entries

是不是说TLB只有2级?如果某些 x86 供应商决定提供 3 级 TLB,如何查询 TLB 缓存的级别数?

案例 2

57H TLB Data TLB0: 4 KByte pages, 4-way associative, 16 entries
[...] 
B4H TLB Data TLB1: 4 KByte pages, 4-way associative, 256 entries

这里的“4-way associative”只是一个错字,意思是“4-way set associative”吗?

案例 3

55H TLB Instruction TLB: 2-MByte or 4-MByte pages, fully associative, 7 entries
[...]
6AH Cache uTLB: 4 KByte pages, 8-way set associative, 64 entries
6BH Cache DTLB: 4 KByte pages, 8-way set associative, 256 entries

DTLB是Data TLB吗? uTLB 是什么意思? uops-TLB?这里考虑哪个 TLB 缓存级别?

案例 4

C1H STLB Shared 2nd-Level TLB: 4 KByte/2MByte pages, 8-way associative, 1024 entries

这是否意味着在那种情况下第 2 级 TLB 由所有内核共享?那么当没有明确指定时,TLB 缓存核心是私有的吗?

How to query the number of levels of TLB cache in case some x86 vendor decides to provide 3 levels of TLB?

叶 0x2 可能 return TLB 信息仅在 Intel 处理器上。它保留在所有当前的 AMD 处理器上。在所有当前的 Intel 处理器上,没有一个数字可以告诉您 TLB 级别的数量。确定层数的唯一方法是枚举所有 TLB-related cpuid 叶或子叶。以下算法适用于所有当前支持 cpuid 指令的英特尔处理器(包括 Ice Lake、Goldmont Plus 和 Knights Mill):

  1. 检查EAX、EBX、ECX和EDX这四个寄存器中的任何一个是否存在值0xFEreturn当cpuid执行时EAX设置为叶子0x2。
  2. 如果0xFE不存在,则枚举四个寄存器中的所有字节。根据 Intel 手册第 2 卷(编号 325383-070US)的 Table 3-12,将有一个或两个可以缓存 4KB 翻译的数据 TLB 描述符。 Intel 手册对可能缓存数据访问转换的 TLB 使用以下不同名称:Data TLB、Data TLB0、Data TLB1、DTLB、uTLB 和 Shared 2nd-Level TLB。如果有两个这样的描述符,那么级别数就是两个。 TLB 编号较大的描述符是second-level TLB 的描述符。如果只有一个这样的描述符,则级别数为一个。
  3. 如果0xFE存在,需要从cpuid叶子0x18获取TLB信息。枚举所有有效子叶,直到最大有效子叶数。如果至少有一个子叶的 EDX 的至少两个有效位等于 11,则 TLB 级别数为 2。否则,TLB层数为1。

Ice Lake 和 Goldmont Plus 处理器的 TLB 信息存在于叶子 0x18 中。此叶子在编码 TLB 信息方面提供了更大的灵活性。所有其他当前 Intel 处理器的 TLB 信息都存在于叶子 0x2 中。我不知道 Knights Mill(如果有人可以访问 Knights Mill,请考虑共享 cpuid 转储)。

确定 TLB 级别的数量不足以完全描述级别之间的关系。当前的英特尔处理器实现了两种不同的 2 级 TLB 层次结构:

  • second-level TLB 可以缓存数据加载(包括预取)、数据存储和指令获取的转换。 second-level TLB 在这种情况下被调用 "Shared 2nd-Level TLB."
  • second-level TLB 可以缓存数据加载和存储的转换,但不能缓存指令获取。在这种情况下,second-level TLB 被称为以下任何一种:数据 TLB、数据 TLB1 或 DTLB。

我将根据来自 InstLatx64cpuid 转储讨论几个示例。在启用超线程的 Haswell 处理器之一上,叶 0x2 在四个寄存器中提供以下信息:

76036301-00F0B5FF-00000000-00C10000

没有 0xFE,因此 TLB 信息存在于此叶本身中。根据Table 3-12:

76: Instruction TLB: 2M/4M pages, fully associative, 8 entries
03: Data TLB: 4 KByte pages, 4-way set associative, 64 entries
63: Data TLB: 2 MByte or 4 MByte pages, 4-way set associative, 32 entries and a separate array with 1 GByte pages, 4-way set associative, 4 entries
B5: Instruction TLB: 4KByte pages, 8-way set associative, 64 entries
C1: Shared 2nd-Level TLB: 4 KByte/2MByte pages, 8-way associative, 1024 entries

其他字节与 TLB 无关。

与Intel优化手册(编号248966-042b)的Table2-17相比有一处出入。 Table2-17提到4KB条目的指令TLB有128个条目,4路关联,在两个超线程之间动态分区。但是 TLB 转储说它是 8 路关联的,只有 64 个条目。对于 128 项的 4 路 ITLB 实际上没有编码,所以我认为手册是错误的。不管怎样,C1表明有两个TLB级别,第二级缓存数据和指令翻译。

在其中一个 Goldmont 处理器上,叶 0x2 在四个寄存器中提供以下信息:

6164A001-0000FFC4-00000000-00000000

这里是TLB-relevant字节的解释:

61: Instruction TLB: 4 KByte pages, fully associative, 48 entries
64: Data TLB: 4 KByte pages, 4-way set associative, 512 entries
A0: DTLB: 4k pages, fully associative, 32 entries
C4: DTLB: 2M/4M Byte pages, 4-way associative, 32 entries

4KB页有两个数据TLB,一个有512个条目,另一个有32个条目。这意味着处理器有两级 TLB。第二层称为 "Data TLB",因此它只能缓存数据翻译。

Table优化手册的19-4提到Goldmont中的ITLB支持大页,但是TLB信息中没有这个信息。数据TLB信息与手册Table19-7一致,只是"Data TLB"和"DTLB"分别称为"DTLB"和"uTLB",在手册。

Knights Landing 处理器之一上,叶 0x2 在四个寄存器中提供以下信息:

6C6B6A01-00FF616D-00000000-00000000
6C: DTLB: 2M/4M pages, 8-way set associative, 128 entries
6B: DTLB: 4 KByte pages, 8-way set associative, 256 entries
6A: uTLB: 4 KByte pages, 8-way set associative, 64 entries
61: Instruction TLB: 4 KByte pages, fully associative, 48 entries
6D: DTLB: 1 GByte pages, fully associative, 16 entries

所以有两个TLB级别。第一个包含用于不同页面大小的多个结构。用于 4KB 页面的 TLB 称为 uTLB,用于其他页面大小的 TLB 称为 DTLB。第二级TLB称为DTLB。这些数字和名称与手册中的 Table 20-3 一致。

Silvermont 处理器提供以下 TLB 信息:

61B3A001-0000FFC2-00000000-00000000
61: Instruction TLB: 4 KByte pages, fully associative, 48 entries
B3: Data TLB: 4 KByte pages, 4-way set associative, 128 entries
A0: DTLB: 4k pages, fully associative, 32 entries
C2: DTLB: 4 KByte/2 MByte pages, 4-way associative, 16 entries

此信息与手册一致,除了2. 我认为应该说“4 MByte/2 MByte”而不是“4 KByte/2 MByte”。这可能是手册中的错字。

Intel Penryn 微架构是一个示例,其中 TLB 信息使用名称 TLB0 和 TLB1 来指代第一级和第二级 TLB:

05: Data TLB1: 4 MByte pages, 4-way set associative, 32 entries
B0: Instruction TLB: 4 KByte pages, 4-way set associative, 128 entries
B1: Instruction TLB: 2M pages, 4-way, 8 entries or 4M pages, 4-way, 4 entries
56: Data TLB0: 4 MByte pages, 4-way set associative, 16 entries
57: Data TLB0: 4 KByte pages, 4-way associative, 16 entries
B4: Data TLB1: 4 KByte pages, 4-way associative, 256 entries

较旧的 Intel 处理器具有 single-level TLB 层次结构。例如,这里是 Prescott:

的 TLB 信息
5B: Data TLB: 4 KByte and 4 MByte pages, 64 entries
50: Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 64 entries

所有 Intel 80386 处理器和部分 Intel 80486 处理器都包含 single-level TLB 层次结构,但不支持 cpuid 指令。在早于 80386 的处理器上,没有分页。如果您希望上述算法适用于所有 Intel x86 处理器,您还必须考虑这些情况。可以找到标题为 "Processor Identification and the CPUID Instruction," 的英特尔文档编号 241618-025 here,在第 7 章中讨论了如何处理这些情况。

我将讨论一个示例,其中 TLB 信息出现在叶 0x18 而不是叶 0x2 中。正如我之前所说,在 0x18 中存在 TLB 信息的现有英特尔处理器只有 Ice Lake 和 Goldmont Plus 处理器(可能还有 Knights Mill)。 Ice Lake 处理器的叶 0x2 转储是:

00FEFF01-000000F0-00000000-00000000

有一个0xFE字节,所以TLB信息存在于更强大的叶子0x18中。子叶 0x18 的子叶 0x0 指定最大有效子叶为 0x7。这是子叶 0x0 到 0x7 的转储:

00000007-00000000-00000000-00000000 [SL 00]
00000000-00080007-00000001-00004122 [SL 01]
00000000-0010000F-00000001-00004125 [SL 02]
00000000-00040001-00000010-00004024 [SL 03]
00000000-00040006-00000008-00004024 [SL 04]
00000000-00080008-00000001-00004124 [SL 05]
00000000-00080007-00000080-00004043 [SL 06]
00000000-00080009-00000080-00004043 [SL 07]

英特尔手册描述了如何解码这些位。每个有效的子叶描述一个单一的 TLB 结构。如果 EDX 的最低有效五位不全为零,则子叶是有效的(即描述 TLB 结构)。因此,子叶 0x0 无效。接下来的七个子叶都是有效的,这意味着 Ice Lake 处理器中有 7 个 TLB 描述符。 EDX 的最低有效五位指定 TLB 的类型,接下来的三位指定 TLB 的级别。通过解码子叶位得到以下信息:

  • [SL 01]:描述了一个 first-level 指令 TLB,它是一个 8 路全关联缓存,能够缓存 4KB、2MB 和 4MB 页面的转换.
  • [SL 02]:最低5位表示数字5,根据最新版本的手册(卷2),这是一个保留编码。其他位指定一个 16 路完全关联的 TLB,并且能够缓存所有页面大小的转换。英特尔在优化手册的 Table 2-5 中提供了有关 Ice Lake 中 TLB 的信息。最接近的匹配表明保留编码 5 最有可能表示用于数据存储转换的 first-level TLB。
  • [SL 03]:最低5位表示数字4,根据最新版本的手册也是保留编码。与 Table 2-5 的最接近匹配表明它代表了一个 first-level TLB,用于可以缓存 4KB 翻译的数据加载。路数和套数匹配Table2-5。
  • [SL 04]:类似于子叶 0x3。与 Table 2-5 最接近的匹配表明它代表了一个 first-level TLB,用于数据加载,可以缓存 2MB 和 4MB 的翻译。路数和套数匹配Table2-5。
  • [SL 05]:类似于子叶 0x3。与 Table 2-5 的最接近匹配表明它代表一个 first-level TLB,用于可以缓存 1GB 翻译的数据加载。路数和套数匹配Table2-5。
  • [SL 06]:描述了一个second-level统一的TLB,由8路128组组成,能够缓存4KB、2MB、4MB页面的翻译。
  • [SL 07]:描述了一个second-level统一的TLB,由8路128组组成,能够缓存4KB和1GB页面的翻译。

Table2-5其实提到只有一个统一的TLB结构,但是有一半路只能缓存4KB、2MB、4MB页的翻译,另一半只能缓存翻译4KB 和 1GB 页面。所以second-level TLB的TLB信息和手册是一致的。但是指令TLB的TLB信息与Table2-5不一致。手册可能是正确的。在 TLB 信息转储中,4KB 页面的 ITLB 似乎与 2MB 和 4MB 页面的 ITLB 混淆了。

在 AMD 处理器上,first-level 和 second-level TLB 的 TLB 信息分别在叶子 8000_0005 和 8000_0006 中提供。更多信息可以在 AMD 手册第 3 卷中找到。早于 K5 的 AMD 处理器不支持 cpuid,其中一些处理器包含 single-level TLB。因此,如果您关心这些处理器,则需要一种替代机制来确定 TLB 是否存在。 Zen 2 在两个 TLB 级别都增加了 1GB 支持。有关这些 TLB 的信息可以在叶 8000_0019.

中找到

AMD Zen 有一个 three-level 指令 TB 层级according to AMD。这是我所知道的第一个使用 three-level TLB 层次结构的核心微体系结构。很可能这也是 AMD Zen+ 和 AMD Zen 2 的情况(但我找不到证实这一点的 AMD 来源)。 L0 ITLB 上似乎没有记录 cpuid 信息。因此,您可能必须检查处理器是 AMD Zen 还是更高版本,并为这些处理器手动提供 L0 ITLB 信息(所有页面大小的 8 个条目,可能是完全关联的)。

Is "4-way associative" here just a typo meaning that "4-way set associative"?

这不是错字。这些术语是同义词,并且都常用。

Does DTLB stand for Data TLB? What does uTLB mean? uosp-TLB? Which TLB cache level is considered here?

DTLB 和 uTLB 都是数据 TLB 的名称。 DTLB 名称用于 first-level 和 second-level TLB。 uTLB 名称仅用于 first-level 数据 TLB,是 micro-TLB.

的缩写

Does this mean that in that case the 2-nd level TLB is shared among all cores? So when not specified explicitly is the TLB cache core private?

术语"shared"在这里的意思是"unified",因为数据和指令翻译都可以被缓存。 Intel 应该称它为 UTLB(大写 U)或 Unified TLB,这是现代叶子 0x18 中使用的名称。

正在将我的评论收集到一个答案中。 Hadi 的回答更直接地回答了更多的问题,但希望这是关于 TLB 的有用背景,可以帮助您理解为什么这样设计以及它的含义。

您可以查看已知的微体系结构详细信息,以帮助检查您对 cpuid 结果 的解释。例如,https://www.7-cpu.com/cpu/Skylake.html and https://www.realworldtech.com/haswell-cpu/5/ 有关于那些 Intel uarches 的详细信息。其他来源包括英特尔的优化手册,也许还有 Agner Fog 的微架构指南。 IDK 为什么有人说“设置”关联而其他人不说;这并不重要 AFAIK。

(在某些情况下,应用常识推理什么是合理的设计。令人惊讶的结果 可能 是正确的,但需要更多检查。)

Does it mean that there are only 2 levels of TLB?

是的,主流 x86 CPUs 仍然“只”使用 2 级 TLB,第 2 级被统一(instruction/data 翻译)。

第一级拆分 L1iTLB(与前端提取阶段紧密耦合)和 L1dTLB(与 load/store 单元紧密耦合)。统一二级TLB

在当前的 Intel CPUs 上,我想我已经读到 L2TLB 基本上是一个受害者缓存,但我可能记错了,因为我还没有找到确认。如果那是真的,页面遍历器结果只被添加到需要它的 L1 TLB,只有在从 L1iTLB 或 L1dTLB 驱逐后才移动到 L2TLB。我忘记了它们是否是排他性的(即交换条目以确保没有重复),但我不这么认为。无论如何,如果 L2TLB 实际上是一个受害者缓存:将代码和数据保存在同一页中仍然可以触发代码和数据的单独页面遍历,因为代码的 iTLB 未命中不会将结果放在 dTLB 可以看到的任何地方想念,不是马上。至少 page-table 数据本身将在 L1d 缓存中,如果访问时间很近,页面 walker 可以快速访问它。

Does this mean that in that case the 2nd level TLB is shared among all cores? So when not specified explicitly is the TLB cache core private?

TLB 始终是每个内核私有的,即使您愿意,在设计共享条目的方法时也存在重大问题。

与内存内容不同,翻译和 invlpg 失效是每个内核私有的。每个逻辑核心都有自己的指向顶级页面目录的 CR3 指针。 有时多个核心是同一进程的 运行 线程,因此它们具有相同的 CR3,但有时则不同。跨内核共享 TLB 的价值有限,除非 x86 ISA 系统编程细节使用跨内核全局 PTE 的概念进行扩展,而不仅仅是一个内核上的 CR3 更改。 (那些跨 CR3 更改的条目适用于始终保持内核虚拟地址 space 映射的内核,但语义是根据每个内核的行为定义的,而不是真正全局的。)IIRC,PCID(进程上下文ID) 的东西还假设 ID 是每个核心私有的,所以即使这样也无助于实现共享。请注意,启用 Meltdown 缓解后,进入内核确实会更改页面 table,因此即使是常见的现实生活用例也不理想。

所以无论如何,根据现有的 ISA 规则标记共享 TLB 条目以保持正确性存在大量潜在的复杂性。启用超线程后,Sandybridge 甚至在逻辑核心之间静态分区小页面 L1iTLB,并复制大页面 L1iTLB (Kanter, RealWorldTech).

此外,这不是提高性能的最佳方法。离开核心到共享资源往往很慢;例如L3 数据缓存访问是多个周期。 TLB 条目可以从页面重建-table 本身可以由 L3 数据缓存缓存的数据。(以及私有 L2 和 L1d 缓存;Hardware page-walk fetches through the data caches on PPro and later (有趣的事实:与绕过其片上缓存的 P5 Pentium 不同)。

与其脱离核心(延迟可能类似于 L3 缓存)来检查假设的共享 L3TLB(可能仍未命中),重建 TLB 条目更有意义使用本地页面遍历硬件。 Skylake 添加了第二个硬件页面遍历器,使其可以并行处理两个 TLB 未命中(或推测性填充);这可能比共享 L3TLB 更有帮助,即使在具有大量共享工作集的同一进程的所有核心 运行 线程的最佳情况下也是如此。如果 page-table 数据必须来自 off-core,则将 page-table 中的数据处理到 TLB 条目中可能只占总周期的一小部分。

缓存页面-table 数据(如更高级别的页面目录条目) 页面步行者中也有帮助,我认为在实践中已经完成。因此,页面遍历可能只需要通过数据缓存获取底部 2 级。

TL:DR:从现有的私有+共享数据缓存中快速读取硬件页面遍历,以及推测性 TLB 预取,解决了共享 TLB 可能存在的相同问题,并有助于提高单独的性能-处理案例。 还避免了 许多 问题。

与共享的 L3TLB 相比,添加更多/更好的页面遍历硬件可以帮助更多案例。


Does DTLB stand for Data TLB? What does uTLB mean? uops-TLB? Which TLB cache level is considered here?

是的,DTLB = 数据 TLB。

uTLB不能用于uop缓存;在 Intel CPUs 上,uop 缓存实际上是寻址的,因此它不需要 TLB。 (不确定 Ryzen 的 uop-cache 有什么作用,但您正在查看 Intel 文档)。

从大小和其他方面,我们可以看出它也不是Unified L2TLB。 (虽然从 Hadi 的回答来看,UTLB 似乎在某些情况下可能意味着统一,即组合或共享数据和指令)

我发现https://software.intel.com/en-us/vtune-amplifier-help-utlb-overhead好像不是说UTLB=一级数据TLB。也许它的意思是“微型 TLB”,如 small/fast 只有几个条目的 TLB,而不是更大的 L2TLB。

Hadi 发现在某些 Silvermont 系列 CPU 上,“uTLB”用于 4k 页面,而 DTLB 用于其他页面大小。似乎“微型 TLB”才是正确的解释方式。


I also found https://wikichip.org/wiki/intel/microarchitectures/kaby_lake resource regarding TLB. There is a Note: STLB is incorrectly reported as "6-way" by CPUID leaf 2 (EAX=02H). Kaby Lake erratum KBL096 recommends software to simply ignore that value. which is actually 12-way associative. cpuid bug for all Kaby Lake cpus?

是的,这是一个CPU错误,CPU通过CPUID报告了错误的信息;这就是为什么 KBL096 是 CPU 错误,而不是使用 cpuid.

的软件中的错误

如果此类软件遵循正常规则,它会得到与 KBL 实际拥有的结果不匹配的结果。英特尔建议软件对此进行特殊处理,并简单地打印已知的正确结果,而不是 cpuid 数据指示的结果。