2.1 OVERVIEW OF THE SYSTEM-LEVEL ARCHITECTURE
IA-32 与 IA32-e 模式
图中的实线箭头表示线性地址,虚线表示段选择器,虚线箭头表示物理地址
2.1.1 Global and Local Descriptor Tables
全局描述符表 (GDT)
-
GDT是一个全局的段描述符表,它存储在系统内存中的一个固定位置。通常,GDT被加载到内存中的一个特殊寄存器中,这个寄存器被称为全局描述符表寄存器 (Global Descriptor Table Register, GDTR)。
-
GDT包含了系统中所有进程所需的段描述符,这些段描述符定义了各种段的属性。这些属性包括段的基地址、段的大小、特权级别(Ring)、访问权限、段类型等。
-
GDTR寄存器包含了GDT的线性地址和界限信息。通过加载GDTR寄存器,处理器可以获得对GDT的访问权。
-
操作系统在启动时负责初始化GDT,并将其基地址和界限加载到GDTR寄存器中。这样,处理器就可以使用GDT中的段描述符来访问内存。
-
每个段描述符都包含了访问权限信息,指定了谁可以访问该段以及如何访问。这些权限包括特权级别(Ring)、读写权限、执行权限等。
局部描述符表 (LDT)
-
LDT是一个与每个进程关联的段描述符表。与GDT不同,每个进程都可以拥有自己的LDT,这为进程级别的隔离提供了一定的灵活性。
-
LDT允许每个进程定义自己的段描述符,这些描述符定义了进程特定的段,如代码段、数据段等。
-
每个任务(进程)都有一个关联的LDT描述符。这个LDT描述符的信息存储在一个特殊寄存器中,称为局部描述符表寄存器 (Local Descriptor Table Register, LDTR)。
-
当处理器执行任务切换时,它会加载LDTR寄存器,从而指向相应任务的LDT。
-
LDT通常在多任务操作系统中使用,用于在不同的进程之间进行隔离。每个进程都可以定义自己的LDT,使其拥有独立的段描述符表,这有助于保护一个进程的内存空间免受其他进程的干扰。
2.1.2 System Segments, Segment Descriptors, and Gates
系统段 (System Segments)
系统段是GDT(全局描述符表)中的一类特殊段,它们用于存储系统信息和控制特定的操作。这些段对操作系统和处理器的内部运行起着重要作用。
比如:
- 全局描述符表寄存器 (GDTR): 存储了GDT的基地址和界限信息。当处理器需要访问GDT时,它使用GDTR来定位GDT的位置。
- 任务状态段 (TSS): TSS是一种系统段,用于存储任务(进程)的上下文信息,如通用寄存器、段寄存器和堆栈指针。它在任务切换中起关键作用。
段描述符 (Segment Descriptors)
段描述符是一种数据结构,用于描述段的属性。每个段描述符包含了关于一个段的重要信息,包括但不限于基地址、段大小、特权级别、段类型、读写权限等。
属性信息:
- 基地址 (Base Address): 段在内存中的起始地址。
- 段大小 (Segment Size): 段的大小,以字节为单位。
- 特权级别 (Privilege Level): 描述段的特权级别(通常是0-3,0表示最高特权级别)。
- 段类型 (Segment Type): 指定段的类型,例如代码段、数据段、系统段等。
- 读写权限 (Read/Write Permissions): 指定谁可以读取和写入该段。
门 (Gates)
概述:
门是一种特殊的数据结构,用于实现控制转移。它们允许处理器从一个特定的执行点跳转到另一个执行点,通常用于中断和异常处理,以及任务切换。门允许受保护的控制转移,这意味着可以在不同的特权级别之间进行切换,从而提供了一定程度的系统安全性和隔离。
- 中断门 (Interrupt Gate): 用于处理中断请求,它将控制传递给中断处理程序。
- 陷阱门 (Trap Gate): 与中断门类似,但不会禁用中断,通常用于陷阱例程。
- 调用门 (Call Gate): 用于在不同特权级别之间进行子程序调用。
- 任务门 (Task Gate): 用于任务切换,允许从一个任务切换到另一个任务。
在IA-32e模式下(64位模式),任务门不再被支持。任务切换在这种模式下使用不同的机制。
当特权级别更改时,堆栈段选择器不会从TSS中读取。相反,它们被设置为NULL,这是因为IA-32e模式下的任务切换方式与传统方式不同。
2.1.3 Task-State Segments and Task Gates
任务状态段 (TSS):
任务状态段 (TSS) 是一种系统段,用于存储处理器在执行任务(进程)时的状态信息。包括通用寄存器、段寄存器、堆栈指针和一些特殊寄存器(如EFLAGS和EIP)的值。
-
任务切换:当操作系统决定切换到不同的任务时,它会加载新任务的TSS,以便处理器能够恢复新任务的状态。
-
任务切换可能是由外部事件触发的,如定时器中断,也可以是由操作系统内部决策引发的,例如进程切换。
-
每个TSS与特定的特权级别(通常是0-3,0表示最高特权级别)相关联。任务切换时,处理器会从当前特权级别切换到新任务的特权级别。
-
保护和隔离:TSS的存在有助于保护不同任务之间的内存空间,因为不同任务的TSS存储在不同的地址空间中,确保了任务之间的隔离性。
任务门 (Task Gate):
任务门 (Task Gate) 是GDT(全局描述符表)中的特殊段描述符,用于在不同任务之间进行切换。任务门包含了指向TSS的偏移量(TSS段在GDT中的偏移地址)以及目标任务的特权级别信息。
- 任务切换:当要执行任务切换时,处理器会使用任务门来指定目标任务。任务门包含了目标TSS的位置信息,以及要切换到的目标特权级别。
- 处理器会跳转到任务门,并从任务门中获取目标TSS的地址,然后加载该TSS,最终实现任务切换。
- 特权级别的切换:任务门还允许在不同特权级别之间进行任务切换。例如,从用户态(Ring 3)切换到内核态(Ring 0)时,任务门可以指定目标特权级别为0。
- 安全性和隔离:任务门的使用可以确保任务切换是受保护的,不允许不合法的任务切换。这有助于维护系统的安全性和隔离性。
2.1.4 Interrupt and Exception Handling
中断和异常是处理器用来应对外部事件和程序错误的机制。它们允许处理器在运行时停止当前执行的任务,执行特定的处理程序,然后在处理完成后恢复原来的执行流程。
中断(Interrupt )
- 中断是一种外部事件的通知机制,它通常由硬件设备或其他外部源触发。例如,硬件中断可以是键盘输入、鼠标点击、磁盘I/O等。
- 当中断发生时,处理器会立即停止当前执行的指令流,保存当前上下文,并跳转到与该中断相关的中断处理程序。
异常 (Exceptions)
- 异常是由程序错误或异常情况引发的事件。这些异常包括除零错误、页故障(如缺页异常)、非法指令、越界访问等。
- 异常是通过程序执行期间检测到的,处理器会捕获并触发与异常相关联的异常处理程序。
中断描述符表 (IDT)
中断描述符表 (Interrupt Descriptor Table, IDT) 是一个系统数据结构,它存储了中断和异常处理程序的入口点地址。每个中断或异常都在IDT中有一个条目。
- 每个IDT入口包括了中断或异常的处理程序的地址(称为中断服务例程,ISR)以及相关的描述符类型和特权级别等信息。
- 当中断或异常发生时,处理器根据IDT中的条目来确定要执行的处理程序。
中断向量
- 中断向量是一个唯一的标识符,用于表示IDT中的特定条目。不同的中断或异常有不同的中断向量。
- 处理器使用中断向量来查找IDT中的相应入口,以确定要执行的处理程序。
中断和异常处理流程:
-
当中断发生时,处理器会暂停当前执行的任务,保存当前上下文(包括寄存器状态和程序计数器值),并跳转到IDT中相应中断向量的处理程序。
中断处理程序通常执行与中断相关的操作,然后返回到原来的执行流程。 -
异常处理与中断处理类似,但通常用于处理程序错误。当异常发生时,处理器会停止当前执行的指令,保存上下文,并跳转到IDT中相应异常向量的处理程序。
异常处理程序通常会尝试纠正异常或终止进程,具体取决于异常的类型和操作系统的策略。
2.1.5 Memory Management
内存管理的主要任务包括分配、释放和保护内存区域,以及实现地址转换和缓存控制。它还涵盖了内存的组织、优化和回收。
内存管理同时涉及物理内存(RAM)和虚拟内存(通过磁盘上的交换文件实现)。虚拟内存扩展了可用内存,允许多个程序同时运行,而不必担心物理内存的限制。
内存管理机制
-
分页机制 (Paging):分页是一种内存管理机制,将物理内存和虚拟内存划分为固定大小的页。操作系统负责维护页表,将虚拟内存页映射到物理内存页。分页机制允许操作系统实现内存保护、内存共享和虚拟内存。
-
分段机制 (Segmentation):分段是另一种内存管理机制,将内存划分为不同的段,每个段具有不同的属性。例如,代码段、数据段、堆栈段等。
分段机制允许不同的程序区域具有不同的访问权限,提供了更精细的内存控制。 -
虚拟内存:虚拟内存是一个抽象的内存管理概念,它允许程序使用比物理内存更大的内存地址空间。虚拟内存通过将不常用的内存页存储到磁盘上的交换文件中来扩展物理内存。
Page Map Level 4 (PML4):
PML4是IA-32e架构中的内存管理单元之一,用于虚拟内存到物理内存的映射。它是分页机制的一部分,扩展了传统的分页表结构。
-
层级结构:PML4位于分页机制的最顶层,以下分别是Page Directory Pointer Table (PDPT),Page Directory (PD),和Page Table (PT)。PML4允许操作系统和硬件更灵活地管理大内存地址空间,以及实现更高级别的内存隔离。
-
地址映射:PML4将虚拟地址映射到物理地址。每个PML4条目对应一个区域的虚拟地址范围,将其映射到相应的物理页帧上。
2.1.6 System Registers
控制寄存器 (Control Registers)
-
CR0寄存器包含了各种控制标志位,用于控制处理器的基本行为。其中一些标志位包括:
分页开关(PG):启用或禁用分页机制。
保护模式开关(PE):进入或退出保护模式。
协处理器(FPU)开关:启用或禁用浮点处理单元。
内存写保护(WP):启用或禁用内存写保护。 -
CR2寄存器存储了最近一次引发页面故障(如缺页异常)的线性地址。操作系统使用它来识别和处理内存访问问题。
-
CR3寄存器存储了页目录表的物理地址,用于启用分页机制。它允许操作系统切换不同任务的地址空间。
-
CR4寄存器包含一些额外的控制标志位,用于控制处理器的高级功能,如页大小扩展、物理地址扩展等。
调试寄存器 (Debug Registers):
-
DR0-D3 这些寄存器用于设置断点。当程序执行到指定地址时,处理器会触发一个断点异常,允许调试器或监视程序检查程序状态。
-
DR6寄存器用于指示当前断点的状态。它包含了断点引发的异常类型以及其他相关信息。
-
DR7寄存器用于配置调试寄存器。它允许设置断点的条件、长度和访问类型等。
其他系统寄存器:
2.1.7 Other System Resources
除了上述寄存器,还有其他一些系统寄存器,如任务寄存器(Task Register,TR)和全局描述符表寄存器(GDTR)等。
2.2 MODES OF OPERATION
IA-32支持三种操作模式和一种准操作模式:
- 保护模式——这是处理器的本地操作模式。它提供了与现有软件基础的丰富架构特征、灵活性、高性能和向后兼容性。
- 实时地址模式——这种操作模式提供了英特尔 8086 处理器的编程环境,有一些扩展(例如切换到受保护或系统管理模式的能力)。
- 系统管理模式 (SMM) - SMM 是所有 IA-32 处理器的标准架构特征,从 Intel386 SL 处理器开始。该模式提供了一个操作系统或执行,具有透明机制来实现电源管理和OEM分化特征。
从实模式切换到保护模式
-
加载全局描述符表 (GDT): 保护模式需要使用GDT来描述各种段,包括代码段和数据段。在切换到保护模式之前,需要创建并加载GDT。
-
设置控制寄存器 (Control Registers): 控制寄存器如CR0和CR3需要进行相应的设置,以启用分页(开启PG标志)和设置CR3以指向新的页目录表。
-
重新加载段寄存器:在实模式下,段寄存器(如CS、DS、ES、SS等)存储的是段选择符,而在保护模式下,它们存储的是段描述符的索引值。因此,在切换到保护模式时,需要重新加载这些段寄存器以指向新的段描述符。
-
设置堆栈: 保护模式需要一个堆栈来存储函数调用和中断处理的返回地址以及局部变量。因此,需要设置一个适当的堆栈段和堆栈指针(通常是SS和ESP寄存器)。
-
清除中断允许位 (IF): 在实模式下,中断是启用的,但在保护模式下,默认是禁用的。因此,在切换到保护模式后,通常需要将IF标志位清零,以启用中断。
-
跳转到保护模式代码:一旦上述修改完成,操作系统可以通过跳转指令(如JMP指令)切换到保护模式代码段,开始执行保护模式下的程序。
从保护模式切换到实模式
-
加载全局描述符表 (GDT): 在切换回实模式之前,需要重新加载GDT,以便在实模式下继续使用正确的段描述符。
-
禁用分页: 实模式不需要分页机制,所以需要将CR0的PG标志位禁用,以停用分页。
-
重新加载段寄存器:由于实模式下使用的是段选择符,因此需要重新加载段寄存器以恢复实模式下的段选择符。
-
设置堆栈: 在实模式下也需要一个堆栈,所以需要设置正确的堆栈段和堆栈指针。
-
清除中断允许位 (IF): 在实模式下,中断是默认启用的,所以需要将IF标志位设置为1,以允许中断。
-
跳转到实模式代码:一旦上述修改完成,操作系统可以通过跳转指令(如JMP指令)切换到实模式代码段,开始执行实模式下的程序。
切换模式通常是操作系统内核的一部分,并且需要非常小心地管理寄存器和内存,以确保正确的切换和恢复。实模式通常用于启动计算机和操作系统引导过程,而保护模式用于执行用户和内核代码。
2.3 SYSTEM FLAGS AND FIELDS IN THE EFLAGS REGISTER
标志寄存器 EFLAGS
标志寄存器EFLAGS包含了一系列标志位,用于反映处理器的状态和执行结果。
-
ZF (Zero Flag): 当结果为零时被置位,用于判断操作结果是否为零。
-
SF (Sign Flag): 当结果为负数时被置位,用于表示操作结果的符号。
-
OF (Overflow Flag): 当运算结果溢出时被置位,用于检测有符号整数运算的溢出。
-
CF (Carry Flag): 当无符号整数运算产生进位时被置位,用于检测进位。
-
PF (Parity Flag): 当结果的二进制表示中有偶数个1时被置位,用于奇偶校验。
-
AF (Adjust Flag): 用于辅助进位,通常在BCD(二进制编码十进制)运算中使用。
-
TF (Trap Flag): 当设置时,可以用于单步调试,使处理器逐条执行指令。
-
IF (Interrupt Enable Flag): 当设置时,允许外部中断。
-
DF (Direction Flag): 用于指示字符串操作的方向(向上或向下)。
2.4 MEMORY-MANGAGEMENT REGISTERS
2.4.1 Global Descriptor Table Register (GDTR)
GDTR寄存器存储全局描述符表(GDT)的地址。GDT包含系统中所有的段描述符,用于内存访问控制。
2.4.2 Local Descriptor Table Register (LDTR)
LDTR寄存器存储局部描述符表(LDT)的地址。LDT通常与每个任务(进程)相关联,允许任务拥有独立的段描述符表。
2.4.3 Interrupt Descriptor Table Register(IDTR)
IDTR寄存器存储中断描述符表(IDT)的地址。IDT包含了中断和异常处理程序的入口点。
2.4.4 Task Register (TR)
TR寄存器存储任务寄存器的选择符。任务寄存器用于多任务操作系统中,它指向当前任务的TSS(任务状态段)。
2.5 CONTROL REGISTERS
参见2.1.6节
2.6 EXTENDED CONTROL REGISTERS (INCLUDING XCR0)
-
XCR0是扩展控制寄存器中最为重要的一个,它用于启用和配置高级处理器特性,主要是指向AVX(高级矢量扩展)和SSE(流式SIMD扩展)指令集的使用。这些特性包括高级浮点运算、SIMD操作和高级矢量处理。
-
除XCR0外,还存在一些未来可能用于其他高级特性的XCR寄存器,目前尚未广泛使用。
2.7 SYSTEM INSTRUCTION SUMMARY
-
LGDT (Load Global Descriptor Table)指令用于加载全局描述符表 (GDT) 的地址和界限值到GDTR寄存器。GDT包含了系统中所有的段描述符,用于内存访问控制。通过LGDT指令,操作系统可以更新GDT,以允许新的段描述符用于内存保护和管理。
-
SGDT (Store Global Descriptor Table)指令用于将GDTR寄存器中的全局描述符表 (GDT) 地址和界限值存储到指定的内存位置。这通常用于操作系统中的一些调试和诊断操作。
-
LIDT(Load Interrupt Descriptor Table)指令用于加载中断描述符表 (IDT) 的地址和界限值到IDTR寄存器。IDT包含了中断和异常处理程序的入口点。通过LIDT指令,操作系统可以更新IDT,以注册新的中断处理程序或修改现有的中断处理程序。
-
SIDT(Store Interrupt Descriptor Table)指令用于将IDTR寄存器中的中断描述符表 (IDT) 地址和界限值存储到指定的内存位置。这可用于操作系统中的一些调试和诊断操作。
-
LLDT(Load Local Descriptor Table)指令用于加载局部描述符表 (LDT) 的选择符(描述符表的索引值)到LDTR寄存器。LDT通常与每个任务(进程)相关联,允许任务拥有独立的段描述符表。LLDT指令通常在任务切换时使用。
-
SLDT(Store Local Descriptor Table)指令用于将LDTR寄存器中的局部描述符表 (LDT) 的选择符存储到指定的内存位置。这通常用于操作系统中的一些调试和诊断操作。
-
LTR (Load Task Register)指令用于加载任务寄存器 (TR) 中的任务选择符,该任务选择符指向任务状态段(TSS)。任务寄存器和TSS用于多任务操作系统中的任务切换。
-
STR (Store Task Register)指令用于将任务寄存器 (TR) 中的任务选择符存储到指定的内存位置。这通常用于操作系统中的一些调试和诊断操作。