Linux操作系统基础 Intel32位系统架构总览

来源:互联网 发布:办公软件培训学校 编辑:程序博客网 时间:2024/05/18 00:37

前言

         说是Linux操作系统基础,其实应该是Intel IA-32架构,但是以学习Linux操作系统为目的,故而称为《Linux操作系统基础》。本部分开始主要讲解80x86保护模式下基本概念,最主要的参考资料为Intel开发手册第三卷《系统编程指南》和赵炯的《Linux内核完全剖析》,最开始部分会直接翻译《系统编程指南》,当然不是逐字逐句的翻。

         本来想从中断开始写的,后来发现要把中断相关知识写出来必需要先明白分段机制,而分段机制和分页机制属于内存管理,内存管理之前还有一些最基本的概念比如标志寄存器、控制寄存器、内存寻址模式、地址变换、IDT、GDT等。所以先给出一个总体概念描述,然后再详细解释,循序渐进。基本概念看起来最头痛,但它是后续学习的基础,不好好理解基本概念,以后将会举步维艰,磨刀不误砍柴工。

         这一节将对Intel 32位系统架构中涉及的一些最基本的概念做概要介绍,在以后的博文中做具体阐述。如图1为Intel 32位系统架构总览。


图1

系统架构总览

全局描述符表(GDT)和局部描述符表(LDT)

       在保护模式下,所有内存访问都是通过全局描述符表(Global Descriptor Tables)或者局部描述符表(LocalDescriptor Tables)定位的,如图1所示。表的成员为段描述符(segment descriptors),段描述提供段基地址、段限长、段属性(段访问权限)、段类型和其它信息。每一个段描述符都有一个段选择符(segment select)与之对应,一个段选择符提供一个GDT或IDT的索引、一个指向标志TI(决定段选择符指向GDT还是IDT)和访问权限信息(请求特权级RPL)。

         为了访问段中的一个字节,必需提供一个段选择符和偏移值,段选择符提供了一种由段描述符到段访问的方法,处理器从段描述符中获取线性空间中的段基地址,段基地址再加上偏移值就确定了字节所在位置。访问数据段、代码段和堆栈段都是使用这种机制,提供的段必须是CPU的CPL(current privilege level)所接受的(CPL是当起可执行的代码段的保护级别)。

         GDT的线性基地址存储在GDT寄存器(GDTR)中;LDT的线性基地址存储在LDT寄存器(LDTR)中。

系统段、段描述符和门

       除了代码段、数据段和堆栈段是构成程序运行的环境外,系统架构还定义了两个系统段:任务状态段(task-state segement)和LDT。GDT不认为是段,因为它不通过段选择符或者段描述符访问。TSSs和LDTs都有相应的段描述符定义它们。

         系统架构还定义了一个特别的描述符集,称为门:调用门(call gates)、中断门(interrupt gates)、陷阱门(trap gates)和任务门(task gates)。这些门为运行在不同特权级的系统程序和处理程序提供保护。例如,一个对调用门的调用可以提供与当前代码段特权级相同或者数字更低(特权更高)的程序代码段的访问,也就是说程序的代码段特权级大于等于当前代码段特权级才可以访问。为了通过调用门访问程序,调用程序必需提供调用门选择符,然后由处理器通过调用门完成一个访问权限的检查——通过比较调用门的当前特权级和调用门指向的目标代码段的特权级。假如允许访问目标代码段,处理器从调用门中获取目标代码段的段选择符和段偏移。如果调用需要改变特权级,处理器也切换到目标特权级堆栈中。新栈的段选择符由当前运行的特务的TSS中获得。调用门使得在16位和32位代码段中转换变得更容易。

任务状态段(TSS)和任务门(taskgates)

  TSS定义了任务执行环境的状态。这些状态包括通用寄存器,段寄存器,标志寄存器,EIP寄存器以及三个堆栈段的段选择符(三个特权级0,2,3各一个)。TSS还包括一个LDT的段选择符,这个LDT把当前任务和页表基地址联系起来。

         保护模式下所有程序运行在任务上下文中(称为当前任务)。当前任务的TSS段选择符存放在任务寄存器(task register)中,最简单切换任务的方法就是通过call或jump 指令到新任务。这里新任务的TSS段选择符由call或jump指令提供。在任务切换过程中,处理器完成以下操作:

1.        在当前TSS中存储当前任务的状态。

2.        加载带有新任务段选择符的任务寄存器。

3.        通过GDT中段描述符访问新TSS。

4.        从新TSS加载新任务的状态到通过寄存器、段寄存器、LDTR、控制寄存器CR3(页表基地址)、EFLAGS标志寄存器和EIP寄存器中。

5.        开始执行新任务。

  任务也可以通过任务门访问。任务门和调用门类似,只不前者是对TSS的访问(通过段选择符),后者是对代码段的访问。

中断和异常处理

  外部中断、软中断和异常是通过IDT处理的。IDT存储提供访问中断和异常处理程序的门描述符的集合。和GDT类似,IDT也不是段。IDT的线性基地址存储在IDTR(中断门描述符表寄存器)中。

  IDT中的门描述符可分为:中断门、陷阱门和任务门。为了访问中断或异常处理程序,处理器首先接收一个中断向量(中断号),中断向量可以由内部硬件、外部中断控制器或者软件指令(比如INT,INTO,INT 3,BOUND)获得。中断向量提供IDT表的一个索引。假如选择的门描述符是中断门或陷阱门,相关的处理程序访问非常类似于通过调用门调用程序;假如选择的门描述符是任务门,处理程序是通过任务切换访问的。

内存管理

    系统架构支持直接物理寻址和虚拟内存(通过分页实现)。当使用直接物理地址时,一个线性地址就是一个物理地址;当使用分页时,所有的代码段、堆栈段、和系统段(包括GDT和IDT)可以将最近访问的页驻留在内存而分页(这句翻不太来)。物理内存中的页(有时称为页框)包含两种类型的系统数据结构:页目录和页表。两种数据结构都在物理内存中(见图1)。页目录的物理基地址存储在操作寄存器CR3中。一条页目录包含页表的物理基地址,访问权限和内存管理信息。一条页表包含页框的物理基地址,访问权限和内存管理信息。

         为了使用这种分页机制,一个线性地址被分为三部分:页目录,页表和页框。系统可以有一个或者多个页目录。例如,每个任务可以有它自己的页目录。

系统寄存器

         为了帮助处理器初始化和控制系统操作,系统架构提供存储系统标志的EFLAGS寄存器和几个系统寄存器:

l  系统标志和IOPL域在EFLAGS寄存器中,控制任务和运行模式切换、中断处理、指令跟踪他访问权限。

l  控制寄存器(CR0、CR2、CR3和CR4)包含多种标志和数据域来控制系统级操作。这些寄存器中的其它标志表示支持在操作系统和执行时的特别的处理能力。

l  debug调试寄存器允许在调试程序和系统软件时设置中断。

l  GDTR、LDTR和IDTR寄存器包括他们各自表的线性基地址和表的大小。

l  任务寄存器包含当前任务的TSS线性基地址和大小。

l  特别的模型寄存器。

其它系统资源

         除了在前面提到的系统寄存器和数据结构外,系统架构还提供以下额外的资源:

l  操作系统指令。比如LGDT、SGDT用来操作GDTR寄存器。

l  性能监控计数器。

l  内部高速缓存和缓冲区。

         性能监控计数器是用来记录处理器事件的事件计数器,比如指令解码数、中断接收数和高速缓存加载数。

         处理器提供一些内部高速缓存和缓冲区。高速缓存用来存储数据和指令,缓冲区用来存储类似于系统解码地址和应用程序段和等待执行的写操作。

 

参考:《Intel System ProgrammingGuide》

          《Linux内核完全剖析》赵炯编著

运行模式

         IA-32架构支持四种模式。

l  保护模式(Protected mode)这是处理器主要运行模式。在这种模式下可以提供最多的架构特性指令集,最高的性能以及向后兼容。

l  实地址模式(Real-address mode) 这种模式提供了8086处理器程序运行的环境,比如提供切换到保护模式和系统管理模式的能力。

l  系统管理模式(System management mode SMM)从Intel 386 SLCPU开始,SMM就成为所有IA-32 CPU的标准架构特性。这种模式为操作系统实现电源管理和OEM特性提供透明机制。SMM是通过外部系统中断pin(SMI#)激活的,系统中断pin 产生一个系统管理中断(SMI)。在SMM模式下,处理器通过保存当前运行程序或任务的上下文切换到单独的地址空间。然后特别的SMM代码透明的执行。当从SMM返回时,处理器把SMI之前的状态返回。

l  虚拟8086模式(Virtual8086 mode) 在保护模式下,处理器支持一个准操作模式模式叫虚拟8086模式。在这种模式下允许处理器在保护模式和多任务环境下执行8086程序。

如图2显示处理器在不同模式之前切换。

         系统加载或复位时CPU处于实模式。CR0寄存器的PE标志用于控制CPU工作在实模式或保护模式。

         EFLAGS寄存的VM标志用于决定CPU工作在保护模式还是虚拟8086模式。保护模式和虚拟8086之前的切换通常完成任务切换或者从中断或异常处理程序返回的一部分。

    每当处理器接收到SMI,就会从其它模式切换到SMM。当执行RSM指令时,处理器总是返回到SMI发生之前的模式。

图2

EFLAGS寄存器中的系统标志和域

   EFLAGS寄存器中的c系统标志和IOPL域控制I/O,可屏蔽硬件中断,调试,任务切换和虚拟8086模式,如图3所示。只有特权级代码(通常为操作系统代码)允许修改这些标志位。


图3

内存管理寄存器

    处理器提供四个内存管理寄存器(GDTR,LDTR,IDTR和TR),用于指定分段内存管理所使用的系统表的基地址,如图4所示。处理器为这些寄存的加载和存储提供了特别的指针。


图4

GDTR全局描述符表寄存器

    GDTR寄存器保存了GDT的32位线性基地址和16位表长度。基地址指定GDT中字节0在线性地址空间的地址;表长度指明GDT表的字节长度。

    LGDT和SGDT指令分别用来加载和存储GDTR寄存器。在CPU刚加电或复位时,线性基地址默认设为0,表长度设置为0FFFFH。在保护模式CPU初始化过程中,GDTR寄存器必须加载一个新值。

LDTR局部描述符表寄存器

  LDTR寄存器保存了LDT的32位基地址,16位段选择符,限长和描述符属性。基地址指定LDT段中字节0在线性地址空间的地址;段限长指明LDT段的字节长度。

    LLDT和SLDT指令分别用来加载和存储LDTR寄存器。GDT表中必须包含LDT的段段描述符。当通过LLDT指令加载段描述符到LDTR时:LDT的基地址,段限长和描述符表属性将自动的加载到LDTR。

    当发生任务切换时,新任务LDT的段选择符和段描述符自动的加载到LDTR中。在写入新的LDT信息到LDTR之前,LDTR不会自动保存旧的信息。

    当处理器刚加电或复位时,段选择符和基地址被默认设为0,段限长默认高为0FFFFH。

IDTR中断描述符表寄存器

   IDTR寄存器保存了IDT的32位线性基地址和16位表长度。基地址指定IDT中字节0在线性地址空间的地址;表长度指明IDT表的字节长度。LIDT和SIDT指令分别用来加载和存储IDTR寄存器。在CPU刚加电或复位时,线性基地址默认设为0,表长度设置为0FFFFH。在CPU初始化过程中,基地址和表长可以改变。

TR任务寄存器

   TR寄存器保存了当前任务TSS的32位基地址,16位段选择符,段限长和描述符属性。选择符引用GDT中的TSS描述符。基地址指定TSS中字节0在线性地址空间的地址;段限长指明TSS的字节长度。

   LTR和STR指令分别用来加载和存储TR寄存器的段选择符。LTR指令加载TR寄存器的段选择符时:TSS描述符的基地址,段限长和描述符属性自动加载到TR中。在CPU刚加电或复位时,基地址默认设为0,段限长设置为0FFFFH。

    当发生任务切换时,新任务的TSS段描述符和段选择符自动加载到TR寄存器中。在写入新的TSS信息到TR中之前,TR不会自动保存旧的信息。

控制寄存器

    控制寄存器(CR0,CR1,CR2,CR3和CR4)决定处理器的操作模式和当前执行任务的特性,如图5所示。。在32位模式和兼容模式下这些寄存器都是32的。

         通过MOV CRn 指令操作这些寄存器的。控制寄存器总述如下。

CR0——包含控制系统模式和处理器状态的系统控制标志。

CR1——保留。

CR2——包含导致页错误的线性地址。

CR3——包含页目录表的物理地址和两个标志(PCD和PWT)。CR3也被称为页目录基地址寄存器(PDBR)。它只有高20位是有效的;低12位被设置为0。因此页目录必须是4KB对齐。PCD和PWT标志控制处理器内部数据缓存区的页目录的高速缓存(它们不能控制查找缓冲区TLB的页目录信息)。

CR4——包含一组标志用于开启一些架构额外的选项,并且指明系统对某些处理器的兼容性。CR4可以通过mov指令读取和加载。在保护模式下,MOV指令允许控制CR4寄存器读取和加载(特权级0)。这种限制意味着应用程序或其它系统程序(运行在特权级1,2,3上)将不能读取的加载CR4寄存器。


图五

系统指令一览表

         系统指令操作系统级功能,比如加载系统寄存器,管理高速缓存,管理中断,设置设置寄存器。这些指令中的多数只能被操作系统或特权级为0的程序执行,其它可以被任何级别的程序执行。

         如下图列出了系统指令并且指示哪些可以被应用程序使用。


 

参考:《Intel SystemProgramming Guide》

          《Linux内核完全剖析》赵炯编著


0 0
原创粉丝点击