购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.8 x64架构的系统表和系统描述符

我们学过保护模式,所以知道在IA-32架构的处理器上需要四个系统表,分别是全局描述符表GDT、中断描述符表IDT、局部描述符表LDT和系统状态段TSS。在x64架构的处理器上,依然支持这四个系统表,而且它们的尺寸没有变化,但是功能和用法上略有出入。

首先来看全局描述符表GDT,在x64架构下,全局描述符表GDT的尺寸和功能与传统的IA-32架构一致。全局描述符表GDT只有一个,用来保存关乎系统全局功能的描述符。

接着来看局部描述符表LDT,在x64架构下,局部描述符表LDT的尺寸和功能与传统的IA-32架构一致,而且每个任务都有一个,用来保存每个任务自己的段描述符。

再来看中断描述符表IDT,在x64架构下,中断描述符表IDT的尺寸和功能与传统的IA-32架构一致。中断描述符表在整个系统中只有一个,在保护模式下用来保存中断门、陷阱门和任务门。在IA-32e模式下不再支持硬件任务切换,所以不再支持任务门。

最后来看任务状态段TSS,在x64架构下,任务状态段TSS的尺寸与传统的IA-32架构一致。在保护模式下,TSS用来保存每个任务自己的状态,并用于任务切换;在IA-32e模式下,TSS的功能被简化,仅用于中断和特权级转移时的栈切换。

我们学过描述符的分类,描述符分存储器的段描述符和系统描述符。存储器的段描述符包括代码段描述符和数据段描述符;系统描述符包括系统的段描述符和门描述符。系统的段描述符包括LDT描述符和TSS描述符,而门描述符则包括调用门、中断门、陷阱门和任务门。

在x64架构下,存储器的段描述符都有哪些变化,前面已经做了说明,现在重点介绍一下系统描述符的变化情况。

在x64架构的IA-32e模式下,有些系统描述符被扩展到64位,也就是从原来的8个字节扩展到16字节,以容纳和提供64位的线性地址。

具体来说,LDT描述符和TSS描述符在兼容模式下保持不变(与保护模式相同),但是在64位模式下扩展到64位;调用门、中断门和陷阱门在IA-32e模式(包括兼容模式和64位模式)下,扩展到64位。

在IA-32e模式(包括兼容模式和64位模式)下,不再支持任务门,因为不再支持硬件任务切换。

有关64位系统描述符是如何扩展的,包括它们的组成细节,后面用的时候再详细介绍。

2.8.1 x64架构的GDTR

我们知道,GDT是全局描述符表,它位于内存中,是一个非常重要的数据结构,用来保存各种描述符。在x64架构下,GDT依然是需要的,而且依然非常重要。同时,处理器内部的GDTR寄存器依然用来指向GDT。

我们知道,GDTR由两部分组成,分别是表基地址部分和表界限部分。表基地址部分保存着GDT的线性基地址;表界限部分保存着GDT的长度。在传统的IA-32架构下,表基地址部分是32位的。但是,如图2-26所示,在x64架构下,GDT的表基地址部分已经扩展到64位。不过,表界限部分依然是16位的,所以,GDT的最大尺寸依然是64KB,这一点没有改变。

图2-26 x64架构的GDTR和IDTR

x64架构的处理器兼容保护模式。在传统的保护模式下,只能使用表基地址的低32位。原因很简单,传统的老程序,包括老的操作系统,依然是按32位保护模式执行的,以这些老程序的视角看来,GDTR还是那个老的GDTR,表基地址部分只有32位。

相反,在IA-32e模式下,使用全部的64位表基地址,这样就可以在64位线性地址空间中的任何位置安装GDT。注意,为了在访问GDT时不损失性能,GDT的线性基地址最好按8字节对齐,也就是这个地址能够被8整除。

GDTR在x64架构下的扩展对运行在兼容模式下的老程序没有任何影响,因为它们并不直接与GDT和GDTR打交道。GDT和GDTR由操作系统设置,操作系统和处理器会处理好底层的一切。

GDTR很简单,只包括表基地址部分和表界限部分。为了加载GDTR,需要使用lgdt指令从指定的内存位置加载这两部分数据即可。相反,sgdt将GDTR中的基地址和界限值保存到指定的内存位置。

但是,在处理器的不同工作模式下,这两条指令的执行效果也不相同:在任何16位或者32位模式(如实地址模式、保护模式和兼容模式)下,加载或者保存的是32位的基地址和16位的界限值,总共6字节;在64位模式下,加载或者保存的是64位的基地址和16位的界限值,总共10字节。注意,在64位模式下,加载的基地址必须符合扩高形式,否则产生一般保护异常#GP。

2.8.2 x64架构的IDTR

我们知道,IDT是中断描述符表,它位于内存中,是一个非常重要的数据结构,用来保存中断门、陷阱门和任务门。任务门在IA-32e模式下不再支持。在x64架构下,IDT依然是需要的,而且依然非常重要。同时,处理器内部的IDTR寄存器依然用来指向IDT。

我们知道,IDTR由两部分组成,分别是表基地址部分和表界限部分。表基地址部分保存着IDT的线性基地址;表界限部分保存着IDT的长度。

在传统的IA-32架构下,表基地址部分是32位的,但是,如图2-26所示,在x64架构下,表基地址部分已经扩展到64位。不过,表界限部分依然是16位的,所以,IDT的最大尺寸依然是64KB,这一点没有改变。

x64架构的处理器兼容并支持传统的保护模式。在传统的保护模式下,只能使用表基地址的低32位。原因很简单,传统的老程序,包括老的操作系统,依然是按32位保护模式执行,以这些老程序的视角看来,IDTR还是那个老的IDTR,表基地址部分只有32位。

相反,在IA-32e模式下,使用全部的64位表基地址,这样就可以在64位线性地址空间中的任何位置安装IDT。注意,为了在访问IDT时不损失性能,IDT的线性基地址最好按8字节对齐,也就是这个地址能够被8整除。

IDTR在x64架构下的扩展对运行在兼容模式下的老程序没有任何影响,因为它们并不直接与IDT和IDTR打交道。IDT和IDTR由操作系统设置,操作系统和处理器会处理好底层的一切。

IDTR很简单,只包括表基地址部分和表界限部分。为了加载IDTR,需要使用lidt指令从指定的内存位置加载这两部分数据即可。相反,sidt将IDTR中的基地址和表界限保存到指定的内存位置。

但是,在不同的处理器工作模式下,这两条指令的执行效果也不相同:在任何16位或者32位模式(如实地址模式、保护模式和兼容模式)下,加载或者保存的是32位的基地址和16位的界限值,总共6字节;在64位模式下,加载或者保存的是64位的基地址和16位的界限值,总共10字节。注意,在64位模式下,加载的基地址必须符合扩高形式,否则产生一般保护异常#GP。

2.8.3 x64架构的LDT描述符和LDTR

我们知道,LDT是局部描述符表,它位于内存中,是一个非常重要的数据结构,用来保存每个任务自己的段描述符。在x64架构下,LDT依然是需要的。同时,处理器依然用自己内部的LDTR寄存器指向当前任务的LDT。

我们知道,LDTR是16位的,用来保存LDT描述符的选择子。同时,在它背后还有三个不可见的部分,分别是LDT基地址部分、LDT界限部分和LDT属性部分。一旦改变了LDTR中的选择子,则处理器从全局描述符表GDT中选择对应的LDT描述符,并将相关内容加载到LDT基地址、LDT界限和LDT属性这三个不可见的部分,这样就可以快速地访问指定的LDT。

在传统的IA-32架构下,表基地址部分是32位的,但是,如图2-27所示,在x64架构下,表基地址部分已经扩展到64位。不过,其他部分则保持原来的长度,没有改变。

图2-27 x64架构的LDTR和TR

x64架构的处理器兼容保护模式。在保护模式下,只能使用表基地址的低32位。原因很简单,传统的老程序,包括老的操作系统,依然是按32位保护模式执行的,以这些老程序的视角看来,LDTR还是那个老的LDTR,表基地址部分只有32位。

相反,在IA-32e模式下,使用全部的64位表基地址,这样就可以在64位线性地址空间中的任何位置安装LDT。注意,为了在访问LDT时不损失性能,LDT的线性基地址最好按8字节对齐,也就是这个地址能够被8整除。

操作LDTR寄存器的指令是lldt和sldt。lldt指令用来向LDTR寄存器加载一个LDT描述符选择子,这导致处理器从GDT中找到指定的LDT描述符,并从描述符中加载基地址、界限值和属性这三部分内容到LDTR的隐藏部分。最后,LDTR就指向LDT。

在保护模式和兼容模式下,lldt指令从GDT中加载传统的32位LDT描述符;在64位模式下,lldt指令从GDT中加载64位LDT描述符,而且描述符中的LDT线性基地址必须符合扩高形式,否则产生一般保护异常#GP。

sldt指令将LDTR寄存器中的16位LDT描述符选择子保存到指定的通用寄存器或指定的内存位置。

2.8.4 x64架构的TSS描述符和TR

我们知道,TSS是任务状态段,它位于内存中,在传统的保护模式下用来保存每个任务自己的状态数据,并用来支持硬件任务切换。在新的IA-32e模式下,硬件任务切换不再支持,但是TSS依然存在,依然是需要的。同时,处理器依然用自己内部的任务寄存器TR指向TSS。

我们知道,任务寄存器TR是16位的,用来保存TSS描述符的选择子。同时,在它背后还有三个不可见的部分,分别是TSS基地址部分、TSS界限部分和TSS属性部分。一旦改变了TR中的选择子,则处理器从全局描述符表GDT中选择对应的TSS描述符,并将相关内容加载到TSS基地址、TSS界限和TSS属性这三个不可见的部分,这样就可以快速地访问当前任务的任务状态段TSS。

在传统的IA-32架构下,表基地址部分是32位的,但是,如图2-27所示,在x64架构下,表基地址部分已经扩展到64位。不过,其他部分则保持原来的长度,没有改变。

x64架构的处理器兼容保护模式。在保护模式下,只能使用表基地址的低32位。原因很简单,传统的老程序,包括老的操作系统,依然是按32位保护模式执行,以这些老程序的视角看来,TR还是那个老的TR,表基地址部分只有32位。

相反,在IA-32e模式下,使用全部的64位表基地址,这样就可以在64位线性地址空间中的任何位置安装TSS。注意,为了在访问TSS时不损失性能,TSS的线性基地址最好按8字节对齐,也就是这个地址能够被8整除。

操作TR寄存器的指令是ltr和str。ltr指令用来向TR寄存器加载一个TSS描述符选择子,这导致处理器从GDT中找到指定的TSS描述符,并从描述符中加载基地址、界限值和属性这三部分内容到TR的隐藏部分。最后,TR就指向TSS。

在保护模式和兼容模式下,ltr指令从GDT中加载传统的32位TSS描述符;在64位模式下,ltr指令从GDT中加载64位TSS描述符,而且描述符中的TSS线性基地址必须符合扩高形式,否则产生一般保护异常#GP。

str指令将TR寄存器中的16位TSS描述符选择子保存到指定的通用寄存器或指定的内存位置。 xI3jWCReSP1XD7i96JYYal2yRc8kyAeIFPeu+Gbgoy/UxDXvVshy1AWI7ymWVo1S

点击中间区域
呼出菜单
上一章
目录
下一章
×

打开