如何查询TLB缓存的层数,以防某些x86供应商决定提供3层TLB?
在所有当前的AMD处理器上,叶子0x2仅返回Intel处理器的TLB信息。在所有当前的Intel处理器上,没有一个单独的数字告诉你TLB层数。确定层数的唯一方法是枚举所有与TLB相关的cpuid叶子或子叶。以下算法适用于支持cpuid指令的所有当前Intel处理器(包括Ice Lake,Goldmont Plus和Knights Mill)。
- 检查当 EAX 设置为 0x2 时,执行
cpuid
后返回的四个寄存器 EAX、EBX、ECX 和 EDX 中是否存在值为 0xFE 的数据。
- 如果不存在值为 0xFE 的数据,则枚举四个寄存器中的所有字节。根据英特尔手册第二卷(编号 325383-070US)中的表 3-12,将有一个或两个描述符用于缓存 4KB 翻译的数据 TLB。英特尔手册使用以下不同名称来表示可能缓存数据访问翻译的 TLB:Data TLB、Data TLB0、Data TLB1、DTLB、uTLB 和 Shared 2nd-Level TLB。如果有两个这样的描述符,则层级数为两个。具有更多 TLB 数量的描述符是第二级 TLB 的描述符。如果只有一个这样的描述符,则层级数为一。
- 如果存在值为 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。
我将讨论一些基于InstLatx64的cpuid
转储的示例。在启用超线程的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中使用的名称。
edx
得到的信息。 - St.Antariocpuid
漏洞? - St.Antario