从Intel的CPUID结果理解TLB

6

我正在研究cpuid指令的叶子0x02,并想到了一些问题。文档中有一个表格(请点击),其中描述了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仅有两个级别?如果某个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路关联”是否只是笔误,实际意思为“4路关联”?

案例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是否代表数据TLB?uTLB是什么意思?指的是uops-TLB吗?这里考虑的是哪个TLB缓存级别?

案例4

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

这是否意味着在这种情况下,第二级TLB会在所有核心之间共享?因此,当未明确指定时,TLB缓存是否为核心私有?

2
是的,主流的x86 CPU仍然“只”使用2级TLB,第二级是统一的(指令/数据)。没有共享(在核心之间)的第三级,就像读/写数据缓存一样。您可以独立于CPUID查找您实际查看的CPU,例如https://www.7-cpu.com/cpu/Skylake.html或https://www.realworldtech.com/haswell-cpu/5/。我不知道为什么有些人说“设置”关联,而其他人则没有;据我所知,这并不重要。 - Peter Cordes
@PeterCordes 信息不完整。在我的 CPU 上,似乎只有一级指令 TLB(关于第二级的信息没有)。或者第二级 TLB 被用于数据和指令共享,根据我从 edx 得到的信息。 - St.Antario
1
是的,正如我所说,并且就Skylake(包括Kaby Lake)提供给您的链接所述,L2TLB是统一的。只有L1iTLB和L1dTLB是分离的。 - Peter Cordes
3
如果条目数大于路数,那么它总是采用集关联方式。 X(路数)* Y(组数)= X*Y 条目。 - rustyx
1
@PeterCordes 我也发现了关于TLB的资源。有一个注释:CPUID叶子2(EAX=02H)错误地报告STLB为“6路”。Kaby Lake勘误KBL096建议软件忽略该值,实际上是12路关联。所有Kaby Lake CPU的cpuid漏洞? - St.Antario
显示剩余3条评论
2个回答

11
如何查询TLB缓存的层数,以防某些x86供应商决定提供3层TLB?
在所有当前的AMD处理器上,叶子0x2仅返回Intel处理器的TLB信息。在所有当前的Intel处理器上,没有一个单独的数字告诉你TLB层数。确定层数的唯一方法是枚举所有与TLB相关的cpuid叶子或子叶。以下算法适用于支持cpuid指令的所有当前Intel处理器(包括Ice Lake,Goldmont Plus和Knights Mill)。
  1. 检查当 EAX 设置为 0x2 时,执行 cpuid 后返回的四个寄存器 EAX、EBX、ECX 和 EDX 中是否存在值为 0xFE 的数据。
  2. 如果不存在值为 0xFE 的数据,则枚举四个寄存器中的所有字节。根据英特尔手册第二卷(编号 325383-070US)中的表 3-12,将有一个或两个描述符用于缓存 4KB 翻译的数据 TLB。英特尔手册使用以下不同名称来表示可能缓存数据访问翻译的 TLB:Data TLB、Data TLB0、Data TLB1、DTLB、uTLB 和 Shared 2nd-Level TLB。如果有两个这样的描述符,则层级数为两个。具有更多 TLB 数量的描述符是第二级 TLB 的描述符。如果只有一个这样的描述符,则层级数为一。
  3. 如果存在值为 0xFE 的数据,则需要从 cpuid leaf 0x18 中获取 TLB 信息。枚举所有有效的子叶,直到最大有效子叶号码。如果至少有一个子叶的 EDX 的最后两位等于 11,则层级数为两个。否则,层级数为一。
Ice Lake和Goldmont Plus处理器的TLB信息在叶子0x18中。该叶子提供了更灵活的编码TLB信息的方式。所有其他当前的Intel处理器的TLB信息都在叶子0x2中。我不知道Knights Mill的情况(如果有人可以访问Knights Mill,请考虑共享cpuid转储)。
确定TLB级数并不足以完全描述它们之间的关系。当前的Intel处理器实现了两个不同的2级TLB层次结构:
- 第二级TLB可以缓存数据加载(包括预取),数据存储和指令获取的翻译。在这种情况下,第二级TLB称为“共享第二级TLB”。 - 第二级TLB可以缓存数据加载和存储的翻译,但不能缓存指令获取的翻译。在这种情况下,第二级TLB称为以下任何一种:数据TLB,数据TLB1或DTLB。

我将讨论一些基于InstLatx64cpuid转储的示例。在启用超线程的Haswell处理器中,叶子0x2在四个寄存器中提供以下信息:

76036301-00F0B5FF-00000000-00C10000

这个叶子节点中没有0xFE,因此TLB信息在该叶子节点本身中存在。根据表格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

其他字节与TLBs无关。
与英特尔优化手册(编号248966-042b)的表2-17相比,存在一个差异。表2-17提到4KB条目的指令TLB具有128个条目,4路关联,并在两个超线程之间动态分区。但是TLB转储显示它是8路关联且只有64个条目。实际上没有编码用于具有128个条目的4路ITLB,因此我认为手册是错误的。无论如何,C1显示存在两个TLB级别,第二个级别缓存数据和指令翻译。
在其中一个Goldmont处理器上,叶0x2在四个寄存器中提供以下信息:
6164A001-0000FFC4-00000000-00000000

以下是与TLB相关的字节的解释:
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。第二级称为“数据TLB”,因此它只能缓存数据翻译。
优化手册的表19-4提到Goldmont中的ITLB支持大页面,但在TLB信息中没有这些信息。数据TLB信息与手册的表19-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。这些数字和名称与手册中的表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

这份信息与手册一致,除了C2。我认为它应该说“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

旧的英特尔处理器具有单层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处理器包括单级TLB层次结构,但不支持cpuid指令。在低于80386的处理器中,不存在分页。如果您希望上面的算法适用于所有Intel x86处理器,则还必须考虑这些情况。Intel文档号为241618-025,标题为“处理器识别和CPUID指令”,可以在此处找到,在第7章中讨论了如何处理这些情况。

我将讨论一个示例,其中TLB信息存在于叶子0x18而不是叶子0x2中。正如我之前所说,唯一具有TLB信息存在于0x18的现有Intel处理器是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]: 描述了一个一级指令TLB,它是一个8路全关联高速缓存,能够缓存4KB、2MB和4MB页面的翻译。
  • [SL 02]: 最低的五位表示数字5,这是根据最新版本的手册(第2卷)保留的编码。其他位指定了一个16路全关联的TLB,能够缓存所有页面大小的翻译。英特尔在优化手册的表2-5中提供了有关Ice Lake中TLB的信息。最接近的匹配显示,保留编码5很可能代表数据存储翻译的一级TLB。
  • [SL 03]: 最低的五位表示数字4,这也是根据最新版本的手册保留的编码。与表2-5的最接近匹配表明,它代表了一个可以缓存4KB翻译的数据加载的一级TLB。路数和集数与表2-5相匹配。
  • [SL 04]: 类似于子叶0x3。与表2-5的最接近匹配表明,它代表了一个可以缓存2MB和4MB翻译的数据加载的一级TLB。路数和集数与表2-5相匹配。
  • [SL 05]: 类似于子叶0x3。与表2-5的最接近匹配表明,它代表了一个可以缓存1GB翻译的数据加载的一级TLB。路数和集数与表2-5相匹配。
  • [SL 06]: 描述了一个由8路和128组成的二级统一TLB,能够缓存4KB、2MB和4MB页面的翻译。
  • [SL 07]: 描述了一个由8路和128组成的二级统一TLB,能够缓存4KB和1GB页面的翻译。

表2-5实际上提到只有一个统一的TLB结构,但是一半的路只能缓存4KB、2MB和4MB页面的翻译,而另一半只能缓存4KB和1GB页面的翻译。因此,第二级TLB的TLB信息与手册一致。然而,指令TLB的TLB信息与表2-5不一致。手册可能是正确的。4KB页面的ITLB似乎与TLB信息转储中的2MB和4MB页面的ITLB混淆了。

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

AMD Zen有一个三级指令TLB层次结构根据AMD的说法。这是我所知道的第一个使用三级TLB层次结构的核心微架构。很可能在AMD Zen+和AMD Zen 2上也是如此(但我找不到确认这一点的AMD来源)。没有关于L0 ITLB的文档化cpuid信息。因此,您可能需要检查处理器是否为AMD Zen或更高版本,并为这些处理器手动提供L0 ITLB信息(所有页面大小的8个条目,可能是完全关联的)。

这里的“4路关联”只是打字错误,意思是“4路组关联”吗?

这不是打字错误。这些术语是同义词,两者都常用。

DTLB代表数据TLB吗?uTLB是什么意思?uosp-TLB?这里考虑了哪个TLB缓存级别?

DTLB和uTLB都是数据TLB的名称。DTLB名称用于一级和二级TLB。uTLB名称仅用于一级数据TLB,缩写为微型TLB。
“共享”在此处的意思是“统一”,即可以缓存数据和指令翻译。英特尔应该称之为UTLB(大写U)或统一TLB,这是现代叶子0x18中使用的名称。

具有更多TLB号码的描述符是第二级TLB的描述符。我在“0x02”叶子的文档中没有注意到这样的内容。它在其他地方有记录吗? - St.Antario
1
@St.Antario 不是的。对于4KB页面,第二级缓存具有更多的条目比第一级缓存更自然。这在所有当前的英特尔和AMD x86处理器上都是正确的,并且将来可能会继续保持这种情况。这是一种简单、快速和正确的确定哪个描述符是用于第二级TLB的方法。另一方面,“cpuid”工具实际上无法在叶子0x02中区分一级和二级TLB。它只会按照手册中显示的表3-12中所示的描述打印出来。某些编码明确地描述为“2级TLB”... - Hadi Brais
2
但是我在我的答案中展示了第二个TLB可能被称为其他名称的示例。顺便说一下,在叶子0x18中,第一级和第二级TLB的编码是不同的,因此没有必要诉诸这样的黑客行为。这是叶子0x18的优点之一。将来,如果添加第三级TLB,则可能会通过0x18中的新编码来描述它。 - Hadi Brais

5

将我的评论整理成一个答案。Hadi的回答更直接地回答了更多问题,但这里提供关于TLB的有用背景,帮助您理解为什么它被设计成这样以及其含义。

您可以查找已知的微架构细节,以帮助检查您对cpuid结果的解释。例如,https://www.7-cpu.com/cpu/Skylake.htmlhttps://www.realworldtech.com/haswell-cpu/5/有关于那些Intel uarches的详细信息。其他来源包括Intel的优化手册,也许是Agner Fog的微体系结构指南。我不知道为什么有些人说“set”联想,而其他人则没有;在我看来,这并不重要。

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

这是否意味着只有2级TLB?

是的,主流的x86 CPU仍然只使用两级TLB,第二级是统一的(指令/数据翻译)。
第一级是分离的L1iTLB(紧密耦合于前端获取阶段)和L1dTLB(紧密耦合于加载/存储单元)。第二级TLB是统一的。
在当前的Intel CPU上,我想我读到过L2TLB基本上是一个受害者缓存,但是我可能记错了,因为我没有找到确认。如果这是真的,那么页面行走器的结果只会添加到需要它的L1 TLB中,只有在从L1iTLB或L1dTLB驱逐后才会移动到L2TLB。我忘记它们是否是互斥的(即交换条目以确保没有重复),但我认为不是。无论如何,如果L2TLB实际上是一个受害者缓存:将代码和数据保留在同一页中仍然可以触发代码和数据的单独页面行走,因为代码的iTLB miss不会立即将结果放在任何可以被dTLB miss看到的地方。至少页面表数据本身将在L1d缓存中,其中页面行走器可以快速访问,如果访问在时间上彼此接近。
这是否意味着在这种情况下,第二级TLB是所有核心共享的?因此,当未明确指定时,TLB缓存是核心私有的吗?
TLB始终是每个核心私有的,即使您想要共享条目,设计一种共享方式也存在重大问题。
与内存内容不同,翻译和invlpg失效是每个核心私有的。每个逻辑核心都有自己的CR3指针,指向顶级页目录。有时,多个核心运行相同进程的线程,因此它们具有相同的CR3,但有时并非如此。除非x86 ISA系统编程细节扩展了跨核心全局PTEs的概念,否则跨核心共享的TLB将具有有限的价值。(那些跨CR3更改的条目旨在为保持内核虚拟地址空间始终映射的内核提供服务,但语义是以每个核心为基础定义的,而不是真正全局的。)我IRC,PCID (进程上下文ID) 也假设ID是每个核心私有的,因此即使使用它也无法实现共享。请注意,启用Meltdown缓解后,进入内核会更改页面表,因此常见的实际用例也不理想。
无论如何,标记共享的TLB条目以根据现有ISA规则维护正确性存在巨大的潜在复杂性。启用超线程后,Sandybridge甚至在逻辑核之间静态分区小页面L1iTLB,并复制大页面L1iTLB (Kanter, RealWorldTech)。
此外,这不是提高性能的最佳方法。访问共享资源时,离开核心往往会变慢;例如,L3数据缓存访问需要多个周期。TLB条目可以从页表数据中重新构建,而页表数据本身可以由L3数据缓存缓存。(还可以通过私有的L2和L1d缓存进行缓存; Hardware page-walk fetches through the data caches on PPro and later(有趣的事实:与P5 Pentium不同,后者绕过了其芯片上的缓存))。

与其去检查一个假想的共享L3TLB(可能仍然会错过)并且离开核心(延迟可能类似于L3缓存),重新构建具有本地页行走硬件的TLB条目更加合理。 Skylake添加了第二个硬件页行走器,可以同时处理两个TLB未命中(或者是推测填充);即使在所有内核运行带有大量共享工作集的同一进程线程的最佳情况下,这应该比共享L3TLB更有帮助。如果必须从离核心的位置获取页表数据,则将页面表数据转换为TLB条目可能只占总周期的一小部分。

将页面表数据(例如较高级别的页面目录条目)缓存在页行走器中也有所帮助,并且在实践中已经实现。因此,例如通过数据缓存,页面行走可能只需要获取底部2级。

简而言之:快速的页行走硬件从现有的私有+共享数据缓存中读取,并且进行推测性的TLB预取,解决了共享TLB可能出现的问题,同时提高了单独进程情况下的性能。还避免了许多问题。

添加更多/更好的页面遍历硬件将有助于更多情况,比共享L3TLB更加有效。
DTLB代表数据TLB。uTLB不能用于uop缓存;在英特尔CPU上,uop缓存是虚拟寻址的,因此不需要TLB。(不确定Ryzen的uop-cache的作用,但您正在查看英特尔文档)。 从大小和其他内容可以看出,它不是统一的L2TLB。 (尽管从Hadi的答案中,似乎UTLB在某些情况下可能表示统一的,即组合或共享数据和指令) 我发现https://software.intel.com/en-us/vtune-amplifier-help-utlb-overhead,似乎并没有说UTLB =一级数据TLB。也许它的意思是“微型TLB”,即只有几个条目的小型/快速TLB,与更大的L2TLB相比。
Hadi发现在某些Silvermont系列的CPU中,“uTLB”用于4k页面,而DTLB用于其他页面大小。看起来“微型TLB”是正确的解释方式。
我还发现了关于TLB的https://wikichip.org/wiki/intel/microarchitectures/kaby_lake资源。有一个注释: CPUID leaf 2(EAX = 02H)错误地将STLB报告为“6路”。Kaby Lake勘误KBL096建议软件忽略该值,实际上是12路关联。这是所有Kaby Lake CPU的cpuid错误吗?
是的,这是CPU通过CPUID报告错误信息的CPU错误;这就是为什么KBL096是CPU勘误,而不是使用cpuid的软件中的错误。
如果这样的软件遵循正常规则,它将得到与KBL实际不符的结果。英特尔建议软件特殊处理此问题,并简单地打印已知的正确结果,而不是cpuid数据所示的结果。

手册上说:“EAX寄存器中的最低有效字节(AL寄存器)将始终返回01H。软件应忽略此值,不将其解释为信息描述符。”但是接下来的一个要点是“每个寄存器的最高有效位(第31位)指示该寄存器是否包含有效信息(设置为0)或保留(设置为1)”。你能想象把EAX的LSB作为特殊情况的原因吗?我想这可能是出于历史原因,所以我会简单地将EAX的LSB清零,并像处理所有其他寄存器一样处理它。 - St.Antario
@zerocool:iTLB 用于指令获取,dTLB 用于数据加载/存储执行单元。因此有这些名称。请参见 Is TLB used at all in the instruction fetching pipelineVIPT Cache: Connection between TLB & Cache?。特别注意 https://www.realworldtech.com/haswell-cpu/2/ 中的 L1iTLB 与 https://www.realworldtech.com/haswell-cpu/5/ 中的 L1dTLB 的位置。 - Peter Cordes
@zerocool:接近了,但是缓存翻译(页表项)与缓存内容是不同的。无论是否命中L1d缓存,您始终需要dTLB将代码获取从虚拟地址翻译为物理地址。也许你首先不知道什么是TLB? https://en.wikipedia.org/wiki/Translation_lookaside_buffer 是我在谷歌上搜索“TLB”得到的第一个结果。 - Peter Cordes
@zerocool:TLB缓存PDE/PTE遍历结果,因此对于大多数访问,不必完全执行。它不能加速单个页面遍历,但可以减少页面遍历的频率。因此,在那个意义上,它减少了在遍历PDE和PTE时花费的总时间。(尽管页面遍历可以与CPU中的其他事物并行发生,并且可以通过推测性TLB预取来触发,以希望避免TLB未命中或减少其成本,因此理论上您实际上可以使页面遍历器大部分时间处于活动状态,而不会减慢执行速度。) - Peter Cordes
让我们在聊天中继续这个讨论 - zerocool
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接