【问题标题】:How lea and 48 bit addressing works ( x86_64 ) and confusion with 57 bit addresseslea 和 48 位寻址如何工作 (x86_64) 以及与 57 位地址的混淆
【发布时间】:2022-08-21 04:05:42
【问题描述】:
所以我所知道的是,x86_64 上的每个虚拟地址空间都可以通过 48/57 寻址来访问。因此,在 48 位寻址中,您使用 0-0x7FFFFFFFFFFF 访问低 47 位(128TB),使用 0xFFFF800000000000-0xFFFFFFFFFFFFFFFF 访问高 47 位,那么 57 位寻址怎么样?处理器是使用 lea(加载有效地址)自动计算,还是操作系统必须手动计算(尤其是在将内核模式空间放在这个 128TB 的高地址空间上时)。我的想法对吗?
标签:
x86
kernel
x86-64
memory-address
osdev
【解决方案1】:
CPU 要求地址已经正确地从 48 位或 57 位符号扩展为 64 位(也称为“规范”),具体取决于是否在控制寄存器中启用了 5 级分页。
当它们实际用于访问内存时会发生此检查。 lea 没有这样做,它只是寻址模式的“偏移”部分的移位和加法指令。lea 与规范地址要求没有交互,因此对于Using LEA on values that aren't addresses / pointers? 来说是安全的
检查也发生在 branch/call/ret/etc 中。指示,前他们更新 RIP。如果一条指令尝试设置非规范 RIP,则该指令会出现 #GP(0) 异常。相比之下,跳转到未映射的页面会成功,但随后您会收到带有新地址的#PF 页面错误。 (这是有道理的;它可能不是无效的页面错误,操作系统可能只需要分页一些代码,或者如果数据已经在某个地方,则只需连接页表。)检测非规范地址也不需要 TLB 检查。
如果启用 PML5,则检查仅适用于与第 57 位(位 #56)匹配的虚拟地址的高 64-57 = 7 位。新的 CPU 支持它,但除非您的系统实际上需要那么多虚拟地址空间,否则启用操作系统没有意义。 (通常是因为你有大量的 RAM。)页表的额外级别减慢了每个 TLB 未命中,并且更多地由操作系统管理。
除非您使用即将推出的使 CPU 忽略高位的 AMD UAI (Upper Address Ignore) 功能,或者最近的 Intel LAM(线性地址掩码)硬件功能,该功能使 CPU 仅检查最高位与最重要的位(#47 或 #56) ,而不是介于两者之间的位。
这些功能允许标记指针,而无需手动重做符号或零扩展。 (用户空间可以在普通操作系统上使用零扩展,因为他们知道内核不会在高半部分给他们地址。)
有关在没有 LAM / UAI 的情况下执行此操作的详细信息,请参阅 Using the extra 16 bits in 64-bit pointers。 (或启用 PML5 的系统上的高 7 位。)