为什么在x86-64架构中,虚拟地址比物理地址短4位(48位 vs. 52位)?

26
在书籍《底层编程:C语言、汇编和Intel® 64架构下的程序执行》中,我读到: 每个虚拟64位地址(例如我们在程序中使用的地址)由若干字段组成。实际上,地址本身只有48位宽;它被扩展为64位规范地址。其特点是左侧的17位相等。如果不满足这个条件,则在使用时立即被拒绝。然后,通过特殊的表将48位虚拟地址转换为52位物理地址。 为什么虚拟地址和物理地址之间会有4位的差异?

1
反问:为什么虚拟地址和物理地址应该具有相同的大小?20世纪80年代使用超过48k内存的8位计算机也使用了“内存分段”,这更或多或少意味着物理地址比虚拟地址位数更多。 - Martin Rosenau
3
@MartinRosenau,很抱歉您认为我的问题暗示了“我认为虚拟地址和物理地址应该具有相同的大小”。我的意图只是问一下为什么在那种情况下会有差异。我正在寻找类似于您评论中提到的内容,但与“现代PC”和64位寻址相关。 - user1785721
2
有趣的事实:如果您想要使用高16位进行标记指针,您可以在使用之前使用 shl rax,16 / sar rax,16 进行重新符号扩展。 (或者更好的是,让您的程序仅在规范范围的低半部分分配标记指针,这样您就可以只使用 and 或 BMI2 andn 来使地址规范化)。 更好的是,仅在虚拟地址空间的低4G中分配,以便您可以使用地址大小(0x67)前缀忽略高垃圾,或者在操纵指针时使用32位操作数大小进行自由零扩展。 - Peter Cordes
我猜想,如果/当硬件支持更宽的虚拟地址时,可能会出现与当前 mmap(MAP_32BIT) 等效的 mmap(MAP_48BIT) 标志,以便希望将高 16 用于自己目的的程序可以继续使用。仅使用高字节可能更安全,因为即使采用内存映射的非易失性存储(例如 DIMM 上的快于闪存的存储器),也不太可能在虚拟空间远远超过物理空间。 - Peter Cordes
2个回答

35

我相信你在谈论x86-64,我的答案基于该架构。


当操作在64位模式下时,CPU使用一种名为PAE-物理地址扩展的重新设计的功能将虚拟地址转换为物理地址。
最初发明的目的是在仍然使用32位指针的情况下突破4GiB限制,该功能涉及使用4个级别的表格。
每个表格都提供一个指向下一个表格的指针,最右边的表格给出物理地址的高位。要了解情况,请查看AMD64体系结构编程手册中的这张图片:

4-Level paging, PAE, in long mode

所有这些表背后的原理是“稀疏性”:将虚拟地址转换为物理地址的元数据非常庞大 - 如果我们仅使用4KiB页面,我们需要264-12=252个条目来覆盖整个64位地址空间。表允许采用稀疏方法,只有必要的条目才会在内存中填充。
该设计反映在虚拟地址如何被划分上(因此间接地反映在级别数量上),每个级别仅使用9位运行来索引表。从第12位开始,这样就得到了:级别1->12-20,级别2->21-29,级别3->30-38,级别4->39-47。
这解释了当前实现仅支持48位虚拟地址空间的限制。请注意,在使用逻辑地址的指令级别上,我们支持完整的64位地址。在分段级别上,即将逻辑地址转换为线性地址的部分,也提供了完整的支持。因此,限制来自PAE。
我个人的观点是,AMD急于成为第一个推出带有64位支持的x86 CPU的公司,并重用了PAE,通过新的间接级别来修补它,以将其翻译到48位。请注意,英特尔和AMD都允许未来的实现使用64位虚拟地址(可能需要更多表)。
然而,这两家公司都将物理地址的硬限制设置为52位。为什么?
答案仍然可以在分页工作方式中找到。
在32位模式下,每个表中的每个条目都是32位宽;低位用作标志(由于对齐要求使它们在翻译过程中无用),但高位全部用于翻译,提供32/32虚拟/物理翻译。
重要的是强调使用了所有32位,而其中一些较低的位未被用作标志,Intel将它们标记为“忽略”或“可用”,这意味着操作系统可以自由使用它们。

当Intel引入PAE时,他们需要4个更多的位(当时PAE是36位),逻辑上应该加倍每个条目的大小,因为这会创建比40位表项更有效的布局。
这给了Intel很多空余的空间,他们将其标记为保留(这可以在早期版本的Intel SDM手册中更好地观察到,像这样)。

随着时间的推移,条目中需要新的属性,其中最著名的是XD/NX位
保护密钥也是一个相对较新的功能,占据条目中的空间。 这表明,当前ISA不再可能实现完整的64/64位虚拟/物理翻译。

作为视觉参考,这是64位PAE表条目的格式:

Intel 64-bit PAE table entries

它表明64位物理地址不可能(对于大页面仍有一种方法可以解决,但考虑到位的布局,这似乎不太可能),但没有解释为什么AMD将限制设置为52位。
很难说。当然,物理地址空间的大小与硬件成本有关:更多引脚(尽管随着集成内存控制器,DDR规范复用了许多信号,这得到了缓解)和高速缓存/TLB中的更多空间。在这个问题(类似但不足以使其成为重复项)中,一个答案引用维基百科,而维基百科则声称引用了AMD的说法,声称AMD的工程师在考虑了效益和成本后将限制设置为52位。
我分享Hans Passant六年前写的内容:当前的分页机制不适用于完整的64位物理寻址,这可能是为什么英特尔和AMD都没有费心保留每个条目中的高位的原因。
两家公司都知道,随着技术接近52位的极限,它也将与当前形式非常不同。到那时,他们将设计更好的内存机制,因此避免了过度设计现有机制。

@Margaret:汉斯只是说4k页面太小了。如果非易失性存储的大型内存空间开始流行,我猜TLB将开始为1G巨页(目前在Skylake中为4x 1G条目完全关联)增加更多的条目,并且操作系统将允许用户空间使用1G巨页映射非易失性存储。我猜大多数数据库进程都需要一个或两个巨大的连续映射,而2级页表(使用1G巨页而不是PDPTE的有效深度)对此来说已经足够了,对吧?据我所知,当映射稀疏时,增加更多级别通常会有所帮助。 - Peter Cordes
1
@PeterCordes,确实,4KiB是有问题的。巨大页面绝对是唯一的出路。当我们达到2^52限制时,很难说未来会怎样,像GiB这样的大小甚至可能被认为是小的。个人认为,使用可直接访问TLB的软件行走表会是更好的方法(就像某些MIPS实现中发生的那样)。 - Margaret Bloom
@MargaretBloom:嗯,也许可以采用混合方法(使用PML4E中的位选择区域进行SW页面遍历)。除非我们完全摆脱4k/2M页面,否则硬件推测页面遍历与其他工作同时发生的价值太大了。当前的x86实现具有专用的页面遍历硬件;它不是一个占据管道的微码辅助工具,因此它可以在循环大数组时作为下一页预取的一部分发生。请参见https://dev59.com/UVwY5IYBdhLWcg3wwqA5。 - Peter Cordes
@PeterCordes 关于推测性和当前的硬件页行走,你说得很好。调侃一下:如果将来我们拥有了如此多的内存,我们可以毫不担心地分配几个 TiB 或 PiB 的进程,而不必担心它是否有效地使用了吗?一个扩大的 TLB 结合非常巨大的页面(谈论 TiB 或更多)将允许操作系统在创建时分配进程的所有内存。页面很少被交换出去。当然只是开玩笑 :) - Margaret Bloom
1
@MargaretBloom 对不起,是我理解错了。正如你所说的,它是9位:4 * 9位(每个索引)+12位(偏移量)=48位。 - user1785721
显示剩余8条评论

2
之前的回答说:
“当然,物理地址空间的大小会带来一些硬件成本:需要更多的引脚[...]和更多的缓存/TLB空间。”
这表明作者有一个误解:x86-64 CPU 实际上拥有足够的引脚来寻址252字节的 RAM。
实际上,从未发布过的任何CPU都没有接近那么多的物理地址空间。插座不支持它,因此也不需要在缓存或 TLB 中为其分配位。
地址空间为 52 位的唯一意义是,某些页表条目中的位被标记为保留(意味着操作系统必须将它们设置为0),而其他位被标记为忽略(意味着操作系统可以将它们用于自己的目的)。保留的位数恰好足以在未来将物理地址空间扩展到 252 字节,尽管原则上它们也可以被指定为其他角色。
将位指定为保留/忽略的权衡是:
  • 忽略的位数越少,操作系统可以存储的信息就越少,这可能会使它们在现今变得更慢。

  • 保留的位数越少,当物理地址空间的限制在几年后被达到时,页表条目格式可能再次需要改变。

32位x86 CPU多年来具有36位物理地址空间,因此物理地址空间可能比虚拟地址空间大,但在操作系统层面上是很麻烦的。我不相信有任何计划发布一个物理地址空间大于虚拟地址空间的x86-64 CPU。英特尔最近推出了5级分页,将虚拟地址空间增加到257字节。他们的白皮书说,英特尔处理器的物理地址大小由CPUID返回,EAX=80000008h:

支持Intel 64架构的处理器对于这个值最多枚举46。支持5级分页的处理器预计会枚举更高的值,最高可达52。

我从中了解到,目前他们没有计划更改页面表格格式以支持超过252字节的RAM,并且他们也没有计划支持大于虚拟地址空间四分之一的物理地址空间。后者是有道理的,因为只有一半的虚拟地址空间是为内核而设计的,如果全部填满RAM可能会不方便。

AMD的架构手册第二卷,版本3.38(2021年11月)表示:

“[T]he page-translation mechanism can be extended to support 52-bit physical addresses. [...] Currently, the AMD64 architecture supports 40-bit addresses in this mode, allowing up to 1 terabyte of physical-address space to be supported.”

AMD似乎还没有5级分页。


2
实际上,我不认为操作系统开发人员(特别是Linus Torvalds,他曾经抱怨过PAE有多糟糕)会喜欢回到内核没有足够的虚拟地址空间来映射所有物理RAM的时代。为什么4级分页只能覆盖64 TiB的物理地址 - Linux想要比DRAM多4倍的虚拟地址空间,并且不支持64位模式下的HIGHMEM。 - Peter Cordes

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