本文用于汇总整理Intel80386的多任务支持功能,
参考文献:
- 《INTEL 80386 programmer's reference manual 1986》
本文是系列文章《Intel80386知识总结》的一部分。
===================================================================
1. 任务信息的管理机构
1.1 TSS
处理器把维护一个任务所需的所有信息都保存在一个特殊的段中:Task State Segment(TSS)。TSS的结构如下图所示:
TSS中的字段可以分为两组,一组是每次任务切换时都会更新的动态字段,另一组是只读的静态字段。动态字段包括:
- 通用寄存器保存字段:EAX、ECX、EDX、EBX、ESP、EBP、ESI、EDI
- 段寄存器保存字段:ES、CS、SS、DS、FS、GS
- 标志位寄存器保存字段:EFLAGS
- 指令指针保存字段:EIP
- 前一个任务的TSS选择符
静态字段包括:
- 任务LDT的选择符
- 寄存器PDBR的保存字段
- CPL为0~2时的堆栈段选择符,共3个
- T bit:Debug trap bit,等于1时,在每次任务切换时处理器都会产生一个调试异常
- I/O Map base:I/O用
1.2. TSS描述符
即指向TSS的段描述符,其结构如下所示:
TSS描述符TYPE字段中的B bit是TSS的忙标志位,当TYPE字段=9时,表示该任务为非繁忙任务,当TYPE字段=11时,表示该任务为繁忙任务。i386的任务是不可重入的,处理器可以通过检查任务的B bit发现任务是否繁忙。TSS描述符的LIMIT字段必须大于等于103,大于103是允许的,可以系统软件被用来存储一些相关信息。
TSS描述符只能被保存在GDT中,通过TI=1的选择符访问TSS选择符会造成异常。不能直接通过把TSS描述符载入数据段寄存器来修改其中的内容,只能通过载入另一个指向TSS的数据段描述符来修改TSS。
1.3. TR寄存器
TR寄存器给出了当前任务的TSS,通过TR寄存器访问TSS的路径如下图所示:
1.4. 任务门
i386提供任务门机制作为间接的受保护的访问TSS的方式,其结构如下所示:
其中,SELECTOR字段指向TSS描述符,SELECTOR字段中的RPL是不被使用的,同时,当使用任务门时,TSS描述符中的DPL失效,优先级保护规则为:选中任务门所用的选择符RPL和CPL都必须小于等于任务门的DPL。
一个TSS只有唯一的TSS描述符与其对应,却可以有多个任务门同时指向对应的TSS。TSS描述符和任务门形成了多任务管理的两层架构:
2. 任务的切换
2.1 切换流程
- 检查当前任务是否有权切换到目标任务:TSS描述符或者是调用门的DPL必须小于等于CPL和调用门选择符的RPL
- 检查目标TSS描述符的PRESENT字段是否为1,LIMIT字段是否合法,否则产生异常。异常将在切换前的任务上下文中。
- 保存当前任务的执行现场:保存寄存器EAX、ECX、EDX、EBX、ESP、EBP、ESI、EDI、ES、CS、SS、DS、FS、GS、EFLAGS到TSS。把当前指令(造成任务切换的指令)的下一条指令地址保存到TSS。
- 在TR寄存器中载入目标任务的TSS描述符,并设置其Busy bit。
- 从新任务的TSS中恢复现场,并继续执行
在上述过程中要完成的保护检查一览:
序号 | 检查内容 | 异常类型 |
1 | Incoming TSS descriptor is present | NP |
2 | Incoming TSS descriptor is marked not-busy | GP |
3 | Limit of incoming TSS is greater than or equal to 103 | TS |
4 | LDT selector of incoming task is valid | TS |
5 | LDT of incoming task is present | TS |
6 | CS selector is valid | TS |
7 | Code segment is present | NP |
8 | Code segment DPL matches TS Code segment CS RPL | TS |
9 | Stack segment is valid | GP |
10 | Stack segment is present | SF |
11 | Stack segment DPL = CPL | SF |
12 | Stack-selector RPL = CPL | GP |
13 | DS, ES, FS, GS selectors are valid | GP |
14 | DS, ES, FS, GS segments are readable | GP |
15 | DS, ES, FS, GS segments are present | NP |
16 | DS, ES, FS, GS segment DPL ≥ CPL (unless these are conforming segments) | GP |
其中,异常类型的含义为:
- NP = Segment-not-present exception
- GP = General protection fault
- TS = Invalid TSS
- SF = Stack fault
2.2 任务返回链
TSS的back-link字段和EFLAGS寄存器的NT(Nested Task)标志位共同提供了i386的任务返回链机制。当由任务A切换至任务B的时候,处理器会在任务B的TSS中设置back-link字段,指向任务A的TSS选择符,同时设置任务B的EFLAGS寄存器中的NT位=1。当任务B释放控制流的时候,处理器首先检查EFLAGS的NT位是否为1,若为1则读取任务B TSS中的back-link字段自动返回。在系统运行的过程中返回链的长度可以无限增长,TSS描述符的Busy位保护了在返回链中没有环。同时,在多处理器环境下,Busy位还可以保护一个任务不被多个处理器同时执行。下表总结了Busy位,NT位和Back-link字段的具体行为逻辑: