Thursday, July 31, 2008

总结一下最近看的IA32 Protected Mode

历史
从80386开始,Intel的x86系列处理器有了"保护模式"
至此,x86运行在三种模式上:
Real Mode: 兼容8086的模式。即20根地址线,没有提供保护措施,采用 aa:bb 的段寻址方法,最大1M内存。
Protected Mode: 新的模式,32位地址线,支持4G内存。提供0-3共4个特权级,支持分页机制。
Virtual 8086 Mode: 在Protected Mode下模拟8086的工作模式。

开机过程
当按下电源,BIOS经过加电自检(post,power on self test)后,搜寻引导盘的0道0扇,即第一个512B的地方,执行这里的代码。
一般在这里存放bootloader。

Bootloader
一般分为两个stage。第一个stage是自我引导过程,即大概经过了"进入保护模式->读入stage2代码->交付给stage2代码运行"
第二个stage则是bootloader的主程序,一般提供多os的引导。

保护模式
1.进入保护模式
开机时是运行在实模式下的,比如通过一些初始化工作才能进入保护模式,必须做的工作大概有:(不一定要按顺序)
1) 准备GDT:包括编写GDT以及选择子
2) 用lgdt指令加载gdtr
3) 打开A20地址线允许超过20b的寻址
4) 关中断
5) 设置cr0的PE位
6) 跳转进入32位的代码,进入保护模式

2.关于GDT
保护模式下的寻址与实模式差很远.它是使用GDT来完成的.GDT = Global Descriptor Table,用于存储各段的基址,长度,属性。
32b的寻址与16b一样,也是通过段:偏移来完成的。然而段寄存器保存的不是段基址,而是选择子selector。
选择子指向GDT中的表项,这些表项包含有一个段的基址,长度,属性。

因此,这样则提供了第一层保护:该段代码只能按照属性访问基址+长度范围内的内存。
段属性作为对一个段各个方面的定义规定和限制了段的行为和性质。

3.关于LDT
与GDT很类似,也是用来描述段结构的。使用LDT可以模拟多个任务,使各个任务独立。
添加一个LDT的步骤为:
1) 添加一个32b的代码段
2) 增加一个段保存一个LDT
3) 在GDT中添加一个描述符用以描述LDT,同时也要定义相应的选择子
4) 添加新添的描述符的初始化代码
5) 使用lldt加载ldtr
6) jmp跳转到局部任务

4.特权级
共有0-3个特权级,0级最高,是操作系统内核级别,1,2次之,是服务级别,3最低,是普通应用程序级别.
处理器通过复杂的步骤检查特权级,以保护任务跳转时的合法性: 禁止非法的跳转以及访问.这又为系统的运行提供了一层保护.

不同特权级代码段之间的转移
从高到低:使用ret/retf完成
从低到高:使用 call gate(调用门) 完成

其中调用门也是类似段描述符的GDT表项

5.分页
分页基址非常重要,提供了很多现代OS重要的功能基础.
1) 线性地址(平坦地址空间)
每个程序看起来都是运行在一个具有4GB平坦线性地址空间的机器中.
使得编写程序,调试程序简单了许多. 掩盖了真实内存与运行时内存之间的差异. 减轻了程序员的负担.

2) 虚拟内存
使得每个程序可以使用远大于物理内存的4GB内存. 注意是每个程序,而不是所有程序共享.
这样使得系统能完成多任务的功能.

6.分页机制详解
首先要理解物理地址,线性地址,逻辑地址.
逻辑地址(logical address) : 表现为16b段选择子:32b偏移,用于描述计算线性地址
线性地址(linear address): 形如0x00000000的地址,是程序眼中看到的地址,共4GB
物理地址(physical address): 真实的在物理内存中的地址

当没有开启分页机制时,线性地址就是物理地址。开启了分页机制后,还必须经过转换才能得到真实物理地址。

分页机制下寻址模式为:
通过逻辑地址的16b段选择子读取出段描述符,获得段基址,加上32b偏移,得到线性地址。
然后线性地址通过分页机制计算出物理地址。

分页机制下,线性地址看作 10b+10b+12b的组合。转换使用二级页表。
第一级是页目录,大小为4KB,每个表项占4B,共1024项
第二级是页表,大小为4MB,每个表项占4B,共1024项,因为有1024个页表,因此一共为4*1024*1024B=4MB
其中高10b是页目录地址,中10b是页表地址,最后12b是偏移,这个过程描述为:
通过高10b得到页目录表项,从中读取出页表地址(第几个页表)
然后通过中10b得到页表表象,从中读取出页地址(第几个页表项)
然后把页地址加上偏移,得到真实地址。

以上假设每个页大小为4KB。其中页目录以及页表都具有一个基址。
分页机制的开关位于CR0寄存器的PG位。
CR3寄存器负责存储页目录基地址。

7.保护模式下的中断与异常
中断与异常是类似的,中断产生的原因是硬件发生请求或者程序主动发出中断调用。
异常产生的原因是运行时检测到错误,如除数为0,保护违例,页错误等。
但是它们的处理手段类似的,都是通过一个PIC(Programmable Interrupt Controller)
向CPU发送中断信号。
总的来说,都是软件或者硬件发生了某种情形而通知CPU的行为。
区别于实模式,保护模式下的中断使用IDT(Interrupt Descriptor Table)来代替实模式的中断向量表。
IDT的作用是将每一个中断向量和一个描述符对应起来。


No comments: