x86-64:规范地址和实际可用范围

Giu*_*ini 5 x86 assembly x86-64 virtual-address-space address-space

英特尔和AMD文档说,对于64位模式,实际上只有48位可用于虚拟地址,并且从48到63的位必须复制第47位(符号扩展)。据我所知,目前所有的CPU都是以这种方式实现的,但从理论上讲,没有任何事情可以扩展以后的实现中的可用空间(这不会破坏二进制兼容性)。

有没有一种标准的方法来以编程方式确定有意义的位数?(即某些特定的CPUID,就像物理地址一样)。

我知道实际上48位对于任何合理的应用程序和OS来说已经绰绰有余;我的问题是理论上的。

Mar*_*oom 7

是的,CPUID.80000008H:EAX[7:0]如果支持,您可以使用。

算法如下:

  1. 检查最大扩展é的价值cpuidCPUID.80000000h.EAX
  2. 如果E > = 80000008h,则使用 CPUID.80000008H:EAX[7:0]物理地址位数。
    CPUID.80000008H:EAX[15:8]线性地址位数。
  3. 如果不是CPUID.1:EDX.PAE(位6),则CPU具有36个物理地址位和32个线性地址位。
  4. 否则,CPU具有32个物理和逻辑地址位。

英特尔的符号CPUID.X:R B表示

  • Xeax之前要输入的值cpuid
  • R感兴趣的输出寄存器。
  • B格式为[upper:lower]的位域,或格式为.bitname的命名位。

AMD将虚拟:物理地址的最大限制设置为63:52。
尽管物理地址空间的大小可以不同,但​​是当前的实现通常是48:40。


可以使用NASM编译的示例代码

BITS 64

GLOBAL max_phy_addr
GLOBAL max_lin_addr


SECTION .text


max_phy_addr:
 push rbx


 mov eax, 80000000h
 cpuid

 cmp eax, 80000008h
 jae .fromCpuid

 mov eax, 1
 cpuid

 mov eax, 32
 shr edx, 4
 and edx, 4

 add eax, edx

 pop rbx
 ret

.fromCpuid:

 mov eax, 80000008h
 cpuid

 movzx eax, al

 pop rbx
 ret


max_lin_addr:
 push rbx

 mov eax, 80000000h
 cpuid

 cmp eax, 80000008h
 jae .fromCpuid

 mov eax, 1
 cpuid

 mov eax, 32

 pop rbx
 ret

.fromCpuid:

 mov eax, 80000008h
 cpuid

 movzx eax, ah

 pop rbx
 ret
Run Code Online (Sandbox Code Playgroud)

并与C程序(例如

#include <stdio.h>

long max_phy_addr();
long max_lin_addr();

int main()
{
   printf("Phy: %llu\nLin: %llu\n", max_phy_addr(), max_lin_addr());
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

我刚刚发现我的Haswell是48:39!