我们说过,x64架构的处理器兼容实地址模式,当它工作在实地址模式的时候,就相当于一个快速的8086处理器。在实地址模式下,访问内存之前需要先加载逻辑段地址到段寄存器。
如图2-6所示,逻辑段地址是16位的,处理器将它乘以16,形成20位的段地址。访问内存的时候,处理器用这个段地址加上指令中的16位有效地址,形成20位的地址,并在左侧加0扩展到32位。
图2-6 实地址模式的内存访问
在输出物理地址时,如果实际的物理地址位数大于32,则左侧加0,扩展到实际的物理地址位数。物理地址多少位,取决于执行当前程序的处理器,可能是32根、36根或者更多。不管x64架构的处理器实际上多少根地址线,在实地址模式下,通常来说只能访问1MB物理内存。
x64架构的处理器兼容保护模式,当它工作在保护模式的时候,就相当于一个快速的32位处理器。如图2-7所示,在保护模式下,段寄存器用来选择一个段描述符,然后从描述符中取出段的32位线性基地址。
图2-7 保护模式下的内存访问
访问内存的时候,处理器用这个32位的线性基地址加上指令中的32位有效地址,形成32位的线性地址。如果处理器没有开启分页,则线性地址就是物理地址。但是我们已经知道,处理器的地址线可能多于32根。此时,处理器输出这个地址时,左侧加0,扩展到实际的物理地址位数。当然,如果处理器本身只有32根地址线,则不用扩展。
如果处理器开启了分页功能,则32位线性地址还要经页部件转换才能得到物理地址。我们已经学过传统的4KB分页模式,这是最简单、最基本的分页模式。技术在进步,处理器也在更新换代。为了访问更大的内存空间,分页功能也在不断变化,即使是在传统的保护模式下,也已经从最早的4KB分页模式变成现在的多种分页模式。这些新的分页模式我们还没有学过,没有关系,从下一节开始,我们先回顾最早的4KB分页模式,然后了解这些新的分页模式。
在传统的保护模式下,段部件输出32位的线性地址。如果开启了分页,则还需要用页部件将线性地址转换为物理地址。
页部件支持多种分页方式,比如我们已经学过32位4KB分页方式。如图2-8所示,在这种分页方式下,32位线性地址可以转换为32位物理地址。
传统的32位4KB分页技术是两级的,分为两个层次和级别,也就是通过页目录表和页表来完成。页目录表和页表都必须各自占用一个4KB的物理页。换句话说,页目录表和页表的尺寸都是4KB。
在处理器内,控制寄存器CR3保存着当前任务的页目录表的物理地址。在进行地址转换时,处理器通过CR3找到当前任务的页目录表。
在页目录表内,每个表项叫作页目录项,长度是32位的,4字节。所以,在页目录表内可以包含1024个页目录项。为了完成地址转换,处理器用线性地址的高10位乘以4作为表内偏移,从页目录表中选择一个页目录项。
通过页目录项,可以生成并得到32位的页表物理地址。有了这个物理地址,处理器就可以找到并访问页表。在页表内,每个表项叫作页表项,长度是32位,4字节,所以在页表内可以包含1024个页表项。于是,处理器用线性地址的中间10位乘以4作为表内偏移,从页表中选择一个页表项。
图2-8 32位4KB分页方式
通过页表项,可以生成并得到32位的物理页地址,我们要访问的代码和数据就包含在这个物理页中,线性地址的低12位就是代码或者数据在页内的偏移位置。于是,处理器用32位的页地址,加上12位的页内偏移,就是转换后的32位物理地址。
显然,转换后的物理地址和转换前的线性地址一样,都是32位的。这意味着,即使处理器拥有超过32根的地址线,拥有超过4GB的物理内存,在这种分页方式下也只能使用物理内存最低端的4GB。
我们很清楚,受处理器架构的影响,在保护模式下也只能生成32位的线性地址。这是IA-32架构的天然局限性,不可改变。
在开启分页的情况下,线性地址用于访问虚拟内存。由于线性地址是32位的,所以虚拟内存是4GB。当然了,在进行实际的内存访问之前,我们必须用页目录表和页表建立虚拟内存和物理内存之间的映射。也就是将虚拟内存中的段拆分,并映射到物理内存中的页。
映射关系建立之后,段部件发出32位线性地址,用于访问虚拟内存中的数据。但是实际上,这个线性地址被送往页部件,并转换为数据在物理内存中的地址。
在早期的处理器上,只有32根地址线。所以页部件的转换是一对一的,输入32位的线性地址,输出32位的物理地址。此时,虚拟内存和物理内存是一样大的,都是4GB。
这里还有另一个方面的问题:在保护模式下,每个任务都有自己独立的4GB虚拟内存空间,但是要通过分页机制映射到同一个物理内存。物理内存只有4GB,不可能将所有任务的4GB虚拟内存都完整地映射到4GB物理内存。相反,这种映射是按需进行的,并且还要用磁盘来执行页面的换入换出,这就是我们已经学过并且非常熟悉的虚拟内存管理技术。
问题在于,随着任务越来越多,越来越大,4GB物理内存开始捉襟见肘。毕竟,用4GB物理内存来映射所有任务的4GB虚拟内存,肯定是越来越吃力,磁盘交换肯定是越来越频繁。于是后面的处理器增加了地址线,使处理器的物理内存容量大大增加。地址线的增加不需要太多,比如增加到36根或者40根就足够了,实际可以访问的物理内存是巨大的。
但是,IA-32架构决定了线性地址只能是32位的,每个任务的虚拟内存也只能是4GB。即使增加了物理内存,也不可能提升每个任务可以访问的物理内存数量。
注意,我们的目标并不是为了解决单个任务的内存限制问题,每个任务还是只能使用32位的线性地址,还是只能访问4GB的虚拟内存,并且充其量也只能映射为4GB的物理内存。
但是,为所有任务服务的物理内存容量增加了。如此一来,就可以最大限度地将每个任务的虚拟内存映射到物理内存,甚至,在任务很少的时候,每个任务的4GB虚拟内存都可以完整地映射到物理内存,从而大大降低磁盘交换的频次。
最终,页部件的任务是,将32位线性地址转换为大于4GB的物理地址,或者说转换为大于32位的物理地址。只有这样,任务的虚拟内存才能映射到物理内存中的任意位置,而不是只能映射到低端4GB。
显然,处理器需要使用新的分页技术,新的分页技术可以将每个任务的4GB虚拟内存映射到物理内存中的任意位置,即使物理内存远大于4GB。
为了将每个任务的4GB虚拟内存映射到物理内存中的任意位置,即,将32位线性地址转换为36位或者40位物理地址,我们需要使用传统模式下的32位4MB分页技术。如图2-9所示,这种分页技术只使用一个页目录表,而不再使用页表。
图2-9 传统的32位4MB分页方式
在页目录表内,每个页目录项依然是32位的,4字节。所以,在页目录表内可以包含1024个页目录项。为了完成地址转换,处理器用线性地址的高10位乘以4,作为表内偏移,从页目录表中选择一个页目录项。
32位4MB分页方式下的页目录项可以生成一个与处理器地址线匹配的物理地址,长度可以是32位或者一直到40位。最典型的通常是36位或者40位。
生成的物理地址用来访问最终的物理页,它包含了我们要访问的代码和数据,线性地址的低22位就是代码或者数据在页内的偏移位置。2的22次方正好是4MB,所以线性地址的低22位做页内偏移正好合适。
到这一步,你可能非常疑惑,新的页目录项有什么特殊,居然可以生成超过32位的物理地址呢?
来看一下传统32位4MB分页技术的页目录项,如图2-10所示。和从前一样,P是存在位,为0表示当前页目录项无效,为1表明有效;RW是读写特权位;U/S位是管理员和用户位;PWT是页级通写位;PCD是页级高速缓存禁止位;A是已访问位;D是脏位,指示该表项是否已经被处理器引用过;G是全局位,以后再说;PAT与内存类型有关,以后再说。
图2-10 32位4MB分页方式的页目录项
在这里面,我们重点关注页物理地址。在这幅图中,位21是保留的。但实际上保留位的数量并不固定,是可以改变的,所以并不一定只有位21,这要取决于处理器的最大物理地址M。
举个例子来说,如果处理器有36根地址线,那么,M等于36,在这个表项中,从位21到位17都是保留的,剩下的位16到位13,存放页物理地址的位35到位32。
页物理地址的位31到22保存在表项的位22到31。那么,剩余的低22位在哪里指定呢?由于页的尺寸是4MB,所以,页的物理地址必须是4MB对齐的。这样的话,页物理地址的低22位必须为全0。既然为全0,就不需要在页目录项中指定,处理器在生成页物理地址时,自动用0补全即可。
最后,我们要看到这种分页方式的局限性。在页目录项中,位13到位20的这一段长度有限,最多只能提供8个比特。所以,最大只能生成40位的物理地址。要知道,后面的处理器有52根地址线,这种分页方式又落后了。
截至目前,我们应该已经明白了32位分页技术发展的目标,目标就是充分利用物理内存,让更多的物理内存为更多的任务服务。虽然每个任务只有4GB虚拟内存,也只能映射为4GB物理内存,但映射之后的页面却可以分布在物理内存中的任意位置。如此一来物理内存就可以为更多的任务服务。
我们知道,32位4MB分页技术只能使用最多40根地址线,最多只能利用1TB的物理内存。由于新的处理器拥有超过40根地址线,比如有52根地址线,这就需要发明新的分页技术。
先来回顾一下32位4KB和4MB分页方式,这两种分页方式都有页目录表和页表,页目录项和页表项的长度是32位的,折合4字节。同时,页目录表和页表的尺寸都是固定的4KB。所以,页目录表和页表都只能容纳1024个表项。
为了访问全部的页目录项,需要使用线性地址中的10个比特,因为2的10次方正好是1024;为了访问全部的页表项,同样需要使用线性地址中的另外10个比特。
但是,这种分页方式的问题在于,页目录项和页表项只有32位,无法容纳更大的物理地址。为此,IA-32架构引入了物理地址扩展(Physical Address Extension,PAE)技术。
在PAE分页方式下,每个页目录项和页表项扩展到64位,也就是8字节。但是,页目录表和页表的尺寸是固定的,4KB,只能占用一个自然页。如此一来,在页目录表和页表内,都只能有512个表项。512个表项,只需要线性地址中的9个比特就能访问。
现在我们来看传统模式下的32位PAE-4KB分页技术。之所以称之为传统的32位分页技术,是因为被转换的线性地址是32位的。如图2-11所示,这种分页方式用来管理4KB的页面,所以,和往常一样,32位线性地址的低12位是页内偏移。
图2-11 传统的32位PAE-4KB分页技术原理
和往常一样,在页表内,页表项用来指定页的物理地址及属性。我们说过,在PAE分页方式下,页表项的长度是64位的,用来指定和生成m位的页物理地址。在这里,m是应用此分页方式的处理器的物理地址位数,比如52。如果处理器有52根地址线,则可以用页表项生成一个52位的物理地址。用此地址加上12位页内偏移量,就可以访问页内的代码和数据。
和往常一样,页目录表内的页目录项用来指定和生成m位的页表物理地址。由于页目录项和页表项的尺寸都是64位的,所以,在页目录表和页表内都只能容纳512个表项,各自需要用线性地址中的9位来选择页表项以及页目录项。9加9加12一共是30个比特,在32位线性地址中还剩下2个比特。
为此,PAE分页方式引入另一个表,叫作页目录指针表。它只有4个表项,叫作页目录指针项。顾名思义,每个表项都相当于一个指针,指向不同的页目录表。换句话说,每个页目录指针项都用来保存页目录表的m位物理地址。
来看一下传统32位PAE-4KB分页方式下的页目录指针项,如图2-12所示。页目录指针项长64位,我们分成两段显示。
图2-12 传统32位PAE-4KB分页方式的页目录指针项
在图中,M是应用此分页方式的处理器的物理地址位数。在表项中,位M到位63是保留的,保留位有多少,取决于M的数值。如果处理器有52根地址线,则保留位是从位52到63。
在表项中,从位12到位M-1的这一部分,是页目录表物理地址的位M-1到位12。那么页目录表物理地址的位0到位11在哪里呢?在这里没有体现。原因很简单,页目录表在内存中必须是4KB对齐的,所以其物理地址的低12位是全0,用不着在这里登记。
再来看传统32位PAE-4KB分页方式下的页目录项,如图2-13所示。页目录项长64位,我们分成两段显示。其中,AVL是软件可用的位;NX是执行禁止位,若是1,则禁止从此表项关联的页中取指令和执行指令。
图2-13 传统32位PAE-4KB分页方式的页目录项
在表项中,从位12到位M-1的这一部分是页表物理地址的位M-1到位12。M是应用此分页方式的处理器的物理地址位数。页表物理地址的位0到位11没有在表中体现,页表在内存中必须是4KB对齐的,所以其物理地址的低12位是全0,不用在这里登记。
最后来看传统32位PAE-4KB分页方式下的页表项,如图2-14所示。页表项是64位的,我们分成两段显示。在表项中,从位12到位M-1的这一部分是页物理地址的位M-1到位12,M是应用此分页方式的处理器的物理地址位数。页物理地址的位0到位11没有在表中体现,页在内存中必须是4KB对齐的,所以其物理地址的低12位是全0,没有,也用不着在这里登记。
图2-14 传统32位PAE-4KB分页方式的页表项
这一课我们来看传统模式下的32位PAE-2MB分页技术。之所以称之为传统的32位分页技术,是因为被转换的线性地址依然是32位的。
如图2-15所示,这种分页方式用来管理2MB的页面,所以需要使用32位线性地址的低21位作为页内偏移。如此一来,32位线性地址还剩下11位。其中,高2位用来访问页目录指针表,中间9位用来访问页目录表。换句话说,在这种分页方式下,只使用页目录指针表和页目录表,不需要页表。
图2-15 传统的32位PAE-2MB分页技术原理
在页目录指针表内,最多可以有4个页目录指针项,每个页目录指针项是64位的,用来指定和生成m位的页目录表物理地址。在这里,m是应用此分页方式的处理器的物理地址位数。如果处理器有52根地址线,则生成52位的页目录表物理地址。
在页目录表内最多可以有512个页目录项,每个页目录项的长度是64位,用来指定和生成m位的页物理地址。如果处理器有52根地址线,则生成52位的页物理地址。
传统32位PAE-2MB分页方式下的页目录指针项和PAE-4KB分页方式下的页目录指针项相同,没有变化(见图2-12)。
来看传统32位PAE-2MB分页方式下的页目录项,如图2-16所示。页目录项是64位的,我们分成两段显示。其中,AVL是软件可用的位,被处理器忽略;NX是执行禁止位,若是1,则禁止从此表项关联的页中取指令和执行指令。
图2-16 传统32位PAE-2MB分页方式的页目录项
在表项中,从位21到位M-1的这一部分是2MB页物理地址的位M-1到位21。M是应用此分页方式的处理器的物理地址位数。页物理地址的位0到位20没有在表中体现,原因很简单,页是2MB的,低21位必须是全0,这样就可以用线性地址的低21位当页内偏移。既然页物理地址的低21位都是0,就用不着在这里登记。