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

时间:2016-09-09 16:35:38

标签: assembly x86 x86-64 virtual-address-space address-space

英特尔和AMD的文档称,对于64位模式,虚拟地址实际上只有48位可用,而48到63位必须复制第47位(符号扩展)。据我所知,所有当前的CPU都以这种方式实现,但没有(理论上)禁止在未来的实现中扩展可用空间(这不会破坏二进制兼容性)。

是否有一种标准方式以编程方式确定有意义的位数? (即某些特定的CPUID,如物理地址所发生的那样)。

我知道实际上48位对于任何合理的应用程序和操作系统都是足够的;我的问题是理论上的。

1 个答案:

答案 0 :(得分:5)

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

算法如下:

  1. 使用cpuid检查CPUID.80000000h.EAX的最大扩展 E 值。
  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个物理和逻辑地址位。
  5. 来自英特尔的符号,CPUID.X:R B表示

    • X eax之前输入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
    

    与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;
    }
    

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