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

5
英特尔和AMD的文档表示,在64位模式下,实际上只有48位可用于虚拟地址,而48到63位必须复制第47位(符号扩展)。据我所知,所有当前的CPU都是这样实现的,但理论上没有任何禁止在未来的实现中扩展可用空间(这不会破坏二进制兼容性)。
是否有一种标准的编程方式可以确定有意义的位数?(例如某些特定的CPUID,与物理地址相同)
我知道在实践中,48位对于任何合理的应用程序和操作系统来说已经足够了,我的问题是理论上的。
1个回答

8

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

算法如下:

  1. 检查cpuid的最大扩展E值,使用CPUID.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个物理和逻辑地址位。

来自Intel的符号CPUID.X:R B表示

  • Xcpuid之前要放入eax的值。
  • 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!

注:Haswell是英特尔公司推出的一款处理器系列。


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