为什么x86-64系统只有48位虚拟地址空间?


97

在书中,我读到以下内容:

32位处理器具有2 ^ 32个可能的地址,而当前的64位处理器具有48位地址空间

我的期望是,如果它是64位处理器,则地址空间也应该是2 ^ 64。

所以我想知道限制的原因是什么?


11
这本书一定是在专门讨论AMD64体系结构(x86-64)的当前实现。仅使用低阶48位。不过,这不是硬件限制-所有64位都可用。
科迪·格雷

7
确定这本书总是一个好主意。
Henk Holterman

1
我猜物理地址线不是免费的(至少需要16个额外的CPU引脚)。而且我还不知道有任何硬件可以在同一处理器上用物理RAM芯片填充48位空间。当这变得可行时,我确定AMD将添加缺少的16针:)
Torp

7
即使The 32-bit processors have 2^32 possible addresses不一定,也可以存在32位cpu,但只有24个“引脚”可用于寻址内存。例如68EC020(更便宜的68020版本)是32位的CPU,但具有24位用于寻址存储器。
ShinTakezou 2011年

21
64位物理寻址存在一个非常实际的问题,虚拟内存页面大小太小。这使得在每个上下文切换上都有巨大的页面目录和极其昂贵的TLB缓存刷新。从4KB页面移动到4MB页面是一种选择,但与当前操作系统非常不兼容。
汉斯·帕桑

Answers:


134

因为这就是所有需要的东西。48位为您提供256 TB的地址空间。好多啊。您不会很快看到一个系统需要更多的系统。

因此,CPU制造商采取了捷径。他们使用的指令集允许完整的64位地址空间,但是当前的CPU仅使用低48位。另一种选择是浪费晶体管来处理更大的地址空间,这是多年以来不需要的。

因此,一旦我们接近48位的限制,就只需要释放处理全部地址空间的CPU即可,但是它不需要对指令集做任何更改,也不会破坏兼容性。


118
640kb足够任何人使用。

7
亲爱的,您还在运行8088系统吗?

23
@bdares:比喻不好。8088/8086足弓的指令集内置了640k的限制。只有制作新的ISA(386)才有可能打破障碍。另一方面,x86_64支持ISA中的所有64位。只是当代的硬件无法充分利用它们...
R .. GitHub停止帮助ICE

16
@R。实际上,CPU的限制是一兆字节。IBM PC为内存映射的外围设备,BIOS等指定了一部分。其他一些8088/8086设计(如果有内存,则为Zenith Z100)为外围设备等指定了较少的部分,为应用程序指定了更多部分。
杰里·科芬,

25
lwn.net/SubscriberLink/655437/9a48cd3e7a8cbe8a <-回复三年后,我们已经达到了这些限制:) HP Machine将拥有320TB的内存,由于48个内存,它们无法将其提供为固定地址空间位寻址限制。
agam

18

关于总线大小和物理内存的任何答案都有些错误,因为OP的问题是关于虚拟地址空间而不是物理地址空间。例如,所谓的对386的类似限制是对他们可以使用的物理内存的限制,而不是对虚拟地址空间的限制,虚拟地址空间始终是完整的32位。原则上,即使只有几MB的物理内存,您也可以使用完整的64位虚拟地址空间。当然,您可以通过交换来完成,或者对于要在大多数地址处映射同一页面的特殊任务(例如某些稀疏数据操作)来执行此操作。

我认为真正的答案是AMD只是便宜而已,希望现在没人会在意,但我没有引用。


14
“便宜”我想你的意思是不添加永不使用的引脚,不为不使用的晶体管占用芯片空间,并利用释放的空间使现有指令更快?如果那很便宜,我就进去!
Olof Forshell

80386允许2 * 4096个选择器,每个选择器最多包含4GB内存(总计32TB)。80286允许2 * 4096个选择器,每个选择器最多包含64KB(1GB)。
Olof Forshell

非线性分段黑客在我的书中不算作地址空间。便携式软件无法利用它们。
R .. GitHub停止帮助ICE,

@R ..-我认为便携式软件的定义是可以。:-)例如,C ++禁止将指针比较到不同的数组中,以便它们可以位于单独的4GB段中。
Bo Persson

如果您的编译实际上生成了巨大的指针并为每个内存取消引用加载了一个段寄存器,则可以。但是实际上,这太慢了,相反,每个人都使用小型内存模型和__far(或更糟糕的是FAR/ far!)指针...
R .. GitHub停止帮助ICE

10

阅读Wikipedia文章的限制部分:

PC不能包含4 PB的内存(由于当前内存芯片的大小,如果没有其他限制),但是AMD设想了大型服务器,共享内存群集以及在可预见的将来可能会达到此目的的其他物理地址空间使用,以及52位物理地址为扩展提供了足够的空间,而不会产生实现64位物理地址的成本

也就是说,此时无法实现完整的64位寻址,因为我们无法构建可以完全利用这样的地址空间的系统-因此,我们选择了对于当今(以及未来)系统非常实用的东西。


这4 PB中的4个来自哪里?如果我们要说的是64条地址线,那么我们应该以32位地址线(即4 GB)使地址空间的平方结束。平方那我们应该有16个,而不是4 PB。我想念什么吗?
Olof Forshell

1
它来自当前的物理限制(52位)-关键是我们无法在PC中放置足够的RAM来支持此受限范围,更不用说完整的64位地址空间需要什么了。
Damien_The_Unbeliever

9

宽度不内部本地寄存器/操作需要被反映在外部地址总线宽度。

假设您有一个64位处理器,只需要访问1 MB的RAM。仅需要20位地址总线。为什么不使用所有多余的额外引脚的成本和硬件复杂性呢?

摩托罗拉68000就是这样。内部32位,但具有23位地址总线(和16位数据总线)。CPU可以访问16 MB的RAM,并且要加载本机数据类型(32位)需要进行两次内存访问(每个访问16位数据)。


1
但是68000被认为是“ 16/32位” cpu,而不是“完整的” 32位cpu,因此可以说它在过去的16位上还有优势。我以68020为例,因为它的低成本68EC020版本仅24位用于地址,尽管68020是“完整”的32位CPU ... +1代表了这个出色的处理器系列!
ShinTakezou 2011年

@ShinTakezou:说实话,80386SX是16位CPU(因为它具有类似于80286的地址空间)还是32位(因为它具有80386DX的内部体系结构)?一个人可以像您所做的那样说,但另一个人(这个人)说“内部才是最重要的”-您可以在那引用我。
Olof Forshell

@Olof我认为,在“内存”(即外部世界)的上下文中,外部才是最重要的,因此68000是16位CPU(需要2个“步骤”才能读取32位数据):D
ShinTakezou

@ShinTakezou:即使在现代处理器中,内存上下文(甚至是缓存)也始终在cpu本身外部。8088在内部与8086相同,尽管它与8086的16条相比有8条数据总线。我不认为您可以明显看到8088应该与Z80、8080、8085等归为同一类。在这种情况下,数据总线的宽度问题似乎微不足道
Olof Forshell

我根本不是这个问题的专家,所以我对我没有什么明显的了解。我只想注意到有必要对过去进行更严格的调整,因为人们可能认为68000仍然是“旧时的”处理器,因此它的地址空间被限制为小于32位,这似乎是“自然的”;而68020可以为32位,因此68EC020的存在及其局限性清楚地表明,它的选择不是因为“或“此时间”),但要考虑其他因素(例如,如果有64个引脚没有真正的优势,则可以使其更便宜),这或多或少是该答案的理由。
ShinTakezou 2011年

7

还有一个更严重的原因,不仅仅是在CPU地址路径中保存晶体管:如果增加地址空间的大小,则需要增加页面大小,增加页面表的大小或具有更深的页面表结构(即是翻译表的更多级别)。所有这些都增加了TLB丢失的成本,这会损害性能。


1
英特尔提议将5级分页方案从当前的48位扩展到57位。(与当前x86-64页表相同,每级9位/ 4k页)。每级使用10或11位将需要更改页面遍历硬件,因此这可能不是用于大内存的最佳设计,但这是对双模CPU的明智扩展,它还需要支持4的最大性能。当前格式的级别表。
彼得·科德斯

当然,对于2M或1G的大页面,从顶层到大页面表条目的页面表只有4到3层,而不是页面目录指针。
彼得·科德斯

6

从我的角度来看,这是页面大小导致的。每个页面最多包含4096/8 = 512个页面表条目。而2 ^ 9 = 512。因此9 * 4 + 12 = 48。


4

要回答原始问题:不需要添加超过48位的PA。

服务器需要最大的内存量,因此让我们尝试更深入地研究。

1)最大(常用)服务器配置是8套接字系统。8S系统只不过是8个服务器CPU,它们通过高速一致的互连(或简称为高速“总线”)连接起来,形成一个节点。那里有更大的集群,但它们之间相距甚远,我们在这里谈论的是常用配置。请注意,在实际使用中,2套接字系统是最常用的服务器之一,而8S通常被认为是非常高端的服务器。

2)服务器使用的主要内存类型是字节可寻址的常规DRAM内存(例如DDR3 / DDR4内存),内存映射的IO-MMIO(例如附加卡使用的内存)以及用于配置的配置空间系统中存在的设备。第一种类型的存储器通常是最大的类型(因此需要最大数量的地址位)。一些高端服务器也会根据系统的实际配置使用大量的MMIO。

3)假设每个服务器CPU可以在每个插槽中容纳16个DDR4 DIMM。最大容量为256GB的DDR4 DIMM。(根据服务器的版本,每个插槽可能的DIMM数量实际上少于16个DIMM,但为示例起见,请继续阅读)。

因此,每个插槽理论上可以具有16 * 256GB = 4096GB = 4 TB。对于我们的示例8S系统,DRAM大小最大为4 * 8 = 32 TB。这意味着寻址此DRAM空间所需的最大位数为45(= log2 32TB / log2 2)。

我们将不介绍其他类型的内存(MMIO,MMCFG等)的详细信息,但是这里的要点是,对于当今拥有最大类型的DDR4 DIMM(256 GB)的8插槽系统,最“需求”的类型的内存DIMM)仅使用45位。

对于支持48位(例如WS16)的OS,还有(48-45 =)3个剩余位。这意味着,如果仅将低45位用于32TB DRAM,我们仍然有2 ^ 3倍的可寻址内存,可用于MMIO / MMCFG,总共有256TB的可寻址空间。

因此,总结一下:1)48位物理地址足以支持当今最大的系统,这些系统“已满载”了大量的DDR4以及大量其他需要MMIO空间的IO设备。确切地说是256TB。

请注意,这个256TB的地址空间(= 48位物理地址)不包括SATA驱动器之类的任何磁盘驱动器,因为它们不是地址映射的一部分,它们仅包括可字节寻址的内存,并且已公开给操作系统。

2)CPU硬件可以选择实现46位,48位或> 48位,具体取决于服务器的生成。但是另一个重要因素是操作系统可以识别多少位。如今,WS16支持48位物理地址(= 256 TB)。

对于用户而言,这意味着,即使一个服务器具有可以支持> 48位寻址的超大型大型服务器CPU,但是如果您运行的操作系统仅支持48位PA,则您只能利用256 TB的内存。

3)总而言之,有两个主要因素可以利用更高数量的地址位(=更多的存储容量)。

a)您的CPU硬件支持多少位?(这可以由Intel CPU中的CPUID指令确定)。

b)您正在运行什么操作系统版本以及它可以识别/支持多少位PA。

(a,b)的最小值将最终确定系统可以利用的可寻址空间量。

我写此回复时没有详细研究其他回复。另外,我没有详细研究MMIO,MMCFG的细微差别以及地址映射结构的整体。但我确实希望这会有所帮助。

感谢,英特尔公司服务器平台架构师Anand K Enamandram


这个问题询问的是48位虚拟地址空间的大小(要求虚拟地址是规范的)。您确实需要比物理位更多的虚拟位,因此上半部分内核可以将所有物理内存映射到单个地址空间(它是自己的或用户空间)中。就像您说的那样,HW只需要实现DRAM控制器+ MMIO可以使用的尽可能多的PA位,并且可以使用x86-64页表格式中的任意数字,最高为52位限制。(为什么在64位中,虚拟地址比物理地址(52位长)短4位(长48位)?
Peter Cordes

1
4级页表格式还强加了48位VA限制,直到HW + SW支持57位VA的PML5页表为止。无论如何,这是一个有用的答案,但似乎贴在错误的问题下。我不确定是否有更好的地方,所以我想我们可以把它留在这里,希望可以进行编辑以添加标头,以表达有关PA vs. VA的信息。
彼得·科德斯

2

许多人有这种误解。但是,如果您仔细阅读本文,我向您保证,读完本文后,您所有的误解都会消失。

说一个32位或64位处理器并不表示它应该分别具有32位地址总线或64位地址总线!...我再说一遍!

32位处理器意味着它具有32位ALU(算术和逻辑单元)...这意味着它可以在32位二进制操作数上运行(或者简单地说是具有32位的二进制数),类似地64位处理器可以在64位二进制上运行操作数。因此,使用32位或64位处理器并不意味着可以安装最大内存量。它们只是显示操作数有多大...(比喻,您可以想到一个10位的计算器可以计算最多10位的结果...它不能给我们11位或任何其他更大的结果...尽管它是以十进制表示,但是为了简单起见,我在讲这个类比)...但是您要说的是地址空间,即最大可直接接口存储的内存(RAM)。RAM' 最大可能的大小由地址总线的大小决定,而不是数据总线的大小,甚至不是定义处理器大小(32/64位)的ALU的大小。是的,如果处理器具有32位“地址总线”,则它能够寻址2 ^ 32字节= 4GB的RAM(或者对于64位,它将为2 ^ 64)...但是说32位或64位处理器具有与该地址空间无关(地址空间=它可以访问内存的距离或RAM的最大大小),并且仅取决于其ALU的大小。当然,数据总线和地址总线的大小可能相同,然后似乎32位处理器意味着它将访问2 ^ 32字节或4 GB内存...但这只是一个巧合,而且不会相同对所有人.... 例如,英特尔8086是16位处理器(因为它具有16位ALU),因此,正如您所说的,它应该已经访问了2 ^ 16字节= 64 KB的内存,但这不是事实。它可以访问最多1 MB的内存以拥有20位地址总线...。如果您有任何疑问,可以用Google搜索:)

我想我已经阐明了我的观点。现在来问您的问题...因为64位处理器并不意味着它必须具有64位地址总线,因此在64位处理器中具有48位地址总线没有任何问题...他们将地址空间缩小以降低设计和制造的成本。...因为没有人会使用如此大的内存(2 ^ 64字节)...如今2 ^ 48字节已绰绰有余。


我认为您的观点很明确,关于您所说的16位8086 CPU有一点我不理解:16位CPU如何处理20位地址?它是否通过两步操作来处理?即使地址总线为20位宽度,一旦到达CPU,寄存器宽度显然也只能占用16位...它们如何做到这一点?
程序员

2
嗯...两步操作。段寄存器仅包含高16位。然后将其乘以10H,使其变为20位,然后将偏移量相加。
hafiz031

1

至少在Intel 64中仅使用了64位VA的低阶48位是不正确的。使用的高16位有点。

英特尔 ®64 和IA-32体系结构软件开发人员手册中的3.3.7.1节“规范寻址说:

规范地址必须将第63至48位设置为零或一(取决于位47是零还是一)

因此,位47至位63构成一个全为1或全为0的超位。如果地址不是规范形式,则实现应会出错。

在AArch64上,这是不同的。根据ARMv8指令集概述,它是一个49位VA。

AArch64内存转换系统支持49位虚拟地址(每个转换表48位)。虚拟地址从49位进行符号扩展,并存储在64位指针中。可选地,在系统寄存器的控制下,64位指针的最高8位可以保存一个“标签”,当用作加载/存储地址或间接分支的目标时,该标签将被忽略


1
只有低48位有效,但是硬件会检查它是否正确符号扩展为64位。IDK为什么他们不指定零扩展名;也许他们想使检查高半地址和低半地址的方法更加方便(只需检查符号位)。或者,也许是为了避免使2 ^ 48边界变得特殊,因此顶部附近的地址可以方便地适合32位符号扩展常量。我认为后者更有可能。
彼得·科德斯

无论如何,当前的硬件规范检查阻止了软件对标记指针使用忽略的位,这些标记将在将来的硬件上中断,因此它是该机制的一部分,可以在需要时扩展将来的硬件。(由于非易失性存储器直接连接到物理和虚拟地址空间,因此可能比预期的要早。)
Peter Cordes

我在Core i5上的Linux上的procfs说它已映射到7ffd5ea41000-7ffd5ea62000。根据上述“规范”规则,该地址范围是有意义的。位48-63为0,使其成为正确的规范地址。Linux源码中的一些地址有些奇怪。在include / asm / pgtable_64_types中,它说#define __VMALLOC_BASE _AC(0xff92000000000000,UL)。这不是规范的地址。这样的地址将从0xffff8开始。邓诺为什么。
奥尔森主义者'17

是的,IIRC Linux将规范范围的下半部分用于用户空间,并且(主要)将高端部分用于仅内核映射。但是有些内核内存会导出到用户空间,例如[vsyscall]页面。(这可能是导出诸如当前PID之类的内容,所以它getpid()纯粹是用户空间。也gettimeofday()可以仅在内核导出的用户空间+比例因子中使用rdtsc。尽管我认为[vdso]其中有些是在顶部附近的)下半部分。)
彼得·科德斯

IDK做什么__VMALLOC_BASE。大概不直接使用。
彼得·科德斯

0

CPU主要根据其数据总线大小以及其大部分实体(内部体系结构)被认为是“ N位”:寄存器,累加器,算术逻辑单元(ALU),指令集等。例如:较旧的摩托罗拉6800(或Intel 8050)CPU是8位CPU。它具有8位数据总线,8位内部体系结构和16位地址总线。


  • 尽管N位CPU可能具有除N尺寸实体以外的其他实体。例如6809在6800之上的改进(它们都是具有8位数据总线的8位CPU)。在6809中引入的重要增强功能包括使用两个8位累加器(A和B,可以组合成一个16位寄存器D),两个16位索引寄存器(X,Y)和两个16位堆栈指针。

以摩托罗拉68000/68020为例已经有一个答案。这个问题确实是关于x86-64的,而不是旧的8/16位CPU。对于x86-64,主要因素之一是,较宽的虚拟地址将需要更深的页表,而对于您正在谈论的旧芯片,则不存在该因素。
彼得·科德斯

数据总线宽度不必匹配寄存器或ALU宽度。例如,P5 Pentium具有64位数据总线(保证对齐的64位加载/存储是原子的),但是寄存器/ ALU仅32位(集成FPU除外,在以后的Pentium MMX中为SIMD) ALUs。)
彼得·科德斯

OP写道:“我的期望是,如果它是64位处理器,则地址空间也应该是2 ^ 64。” ........您写道:“这个问题实际上是关于x86-64的,而不是旧的8/16位CPU”。........我想您错过了OP问题的实质。OP问题是错误假设的结果,即64位CPU应该具有64位地址总线。关于ALU,我写了很大一部分实体。不是所有的人。
阿米特·G

通过重新发布此评论来停止向我发送垃圾邮件。是的,由于您所描述的原因,OP当然是错误的,但我指出您的答案似乎犯了类似的错误。您说“ 并因此占了很大一部分实体:寄存器和累加器,算术逻辑单元(ALU)... ”,这听起来像是在说那些东西与数据总线宽度匹配。短语“很大一部分”意味着您是在说哪些部分,而不是有时仅适用于那些部分。
彼得·科德斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.