64位Linux下的地址映射

IA32-e模式下地址映射

之前写过,32位Linux虚拟地址映射,讨论了在CPU 80386下的虚拟地址映射。

看过博主的《Linux内核在x86_64 CPU中地址映射》,对32位和64位下地址映射的区别做了一些总结。


---------------------------------------------------------------------------

1. x86_64CPU中逻辑地址(段式)映射

    x86_64段式地址过程和x86一致,即各段起始地址都是0,区别在于段大小不再是4G

    在 x86-64 下,处理器默认 CS, DS, ES, SS的段基址为 0,所以下面就不讨论逻辑地址到线性地址的转换了,因为基址为0,经过运算后线性地址和逻辑地址是一样的。

    分页过程会将 48-bit 的线性地址转换为 52-bit 的物理地址, 可以看出虽然是 64bit 的操作系统但在处理器层面并没有提供 2^64 大小的访问范围。48-bit 线性地址可以有以下 3 种映射分配


2.x86_64CPU中线性地址(页式)映射



具体分析如下:

(1)线性地址是48位

    x86_64线性地址不是64bit,物理地址也不是64位,Intel当前CPU最高物理地址是52bit,但实际支持的物理内存地址总线宽度是40bit。


        x86CPU仅支持64位虚拟地址中的48位。对于用户模式地址,64位中的虚拟地址高16位的地址总被设置为0x0;对于内核模式地址,总被设置为0xF.

为什么64位虚拟地址只能使用48位呢?

        由于x86_64处理器硬件限制。x86_64处理器地址线只有48条,故而导致硬件要求传入的地址48位到63位地址必须相同。最初AMD规定,只有虚拟地址的最低48位才会在地址转换(页表查询)时被使用。48位地址空间在AMD推出64位时是非常大的,即使对于现在来说也基本够用。48位的虚拟地址转换成物理地址需要4级页表。

(2)页面映射分为4级

    4K页面下, 48位线性地址分为5段,位宽度分别是9、9、9、12。映射的方法为页表查找。

    即可管理的地址空间为2^48 = 256T。而在32地址模式下,该值仅为2^32 = 4G。

    另外64位地址时支持的物理内存最大为64T而在32位地址时最大支持的物理内存为64G(开启PAE选项)。

(3)CR3寄存器保存最高一级表的起始物理地址

(4)每个表项的大小为8字节


长模式(IA32-e模式)

    x86-64兼容CPU可以运行在多种模式之下,除了熟悉的实模式,保护模式,还有长模式等,在长模式下,处理器完全执行64位指令,使用64位地址空间(物理内存的寻址能力却没有被完全扩展到64位,因为目前的众多CPU在其寿命期限之内都没有机会见识到如此巨大的内存)和64操作数。因此,为了降低制造成本,目前的CPU被限制在略少于64位寻址。

  • 长模式下cpu屏蔽了段机制,简化了应用程序的内存管理,提高了单个寄存器的运算位数,并引入了一系列的新指令集和前缀(比如rex),使得合理优化过的64位程序比32位程序效率要高一些。
  • 长模式下引入了rip相对寻址机制,使得“位置无关代码”的实现更容易而且更快。


注:x86_64下HIGHMEM是没有定义的,用户空间默认从高端内存分配所需内存,虽然x86_64没有高端内存也没有关系,内核设计了适当的回退机制,用户空间一样可以在低端内存分配内存,只不过需要二次映射,浪费一点效率。

而在32位下虚拟地址空间的内核空间中,存在ZONE_HIGH(高端内存),用于Linux在32位系统下映射高于1G的内存,这块区域一般为128M大小。


-----------------------------------------------------------------------------------------------

参考资料:

X86/X64处理器体系结构及寻址模式

Linux内核在x86_64 CPU中地址映射



猜你喜欢

转载自blog.csdn.net/hhhanpan/article/details/80548687