保护模式5:特权级
文章目录
对于Intel的CPU, 关于这个特权级转换, 套用小胡的话说, 有点罗嗦..
当前特权级(CPL):
当前执行程序或任务的特权级存在于已装载的CS, SS描述符中的0和1位中.
描述符特权级(DPL):
段或者门的特权级,存在于段或者门描述符中.的DPL中. 同时描述不同的类型时还有不同的含义:
数据段: DPL指明了访问该段的最小特权级, CPL <= DPL才可以访问
_非一致代码段(_不使用调用门): DPL指明了访问该段应该有的特权级, CPL == DPL, 没有其他大于等于或者什么的说法. 必须相等
调用门:和数据段相同
通过调用门访问一致代码段或者非一致代码:段CPL >= DPL才可以访问. 和数据段完全相反.
TSS:同数据段
请求特权级(RPL):
存在于段选择子的0和1位中, 一般来说访问一个段时, 如果CPL <= DPL, 这时候RPL就会取代CPL.
访问数据段时的特权检查:
为了访问数据段,必须将段选择子装入DS,FS, GS, SS. 如果在数值上(DPL >= CPL)and(DPL >= RPL )和那么就可以装入, 否则产生(#GP)
访问代码段中的数据:
有时候我们需要访问代码段中的数据, 可以采用以下几种方法.
1:将一个非一致的, 可读代码段选择子装入数据段寄存器
2:将一个一致的, 可读代码段的段选择子装入数据段寄存器.(可读的代码段可以装入DS, ES, FS, GS )
3:使用CS前缀来强制访问选择子已经装入CS寄存器的可读代码段
装入SS寄存器时的特权检查:
当选择子装入SS段寄存器时, 所有的特权级必须与CPL一致, (CPL == DPL ) and(CPL == RPL), 否则(#GP)
代码段间转移的特权检查:
目标转移中直接包含转移的选择子和偏移:
跳转到非一致代码段(C=0):在数值上(CPL == DPL ) and( RPL <= RPL ),否则(#GP), 当CS装入一个非一致代码段选择子时不改变CPL
跳转到一致代码段(C=1):在数值上(CPL >= DPL ) RPL废弃, 否则(#GP), 对于一致代码段, DPL代码调用例程对该代码段进行访问时需要的特权级的最低数值. 当CS装入一个一致代码段选择子时也不改变CPL.
通过调用门的转移:
对于通过调用门的转移, CALL指令和JMP指令是不同的, 而且调用门中涉及的 CPL(当前特权级), RPL(调用门选择子欲跳转的选择子), DPL(调用门描述符中的), DPL(目标代码段描述符中的).另外目标代码段中的C标记还有影响.
CALL: CPL <= 调用门DPL; RPL <= 调用门DPL
目标是一致代码段(c=1):DPL <= CPL
目标是非一致代码段(C=0):DPL <= CPL
JMP: CPL <= 调用门DPL RPL <= 调用门DPL
目标是一致代码段(C=1):DPL <= CPL
目标是非一致代码段(C=1):DPL == CPL
调用门中的DPL规定来访问该描述符的最大特权级数值, 要访问该调用门 (CPL <= DPL)and(CPL <= DPL), 也就是特权级比较高, 数值比较小.
如果调用门中的检查通过, 接下来检查代码段描述符和CPL, 此外CALL, 和JMP是不一样的, 只有CALL指令可以转移到特权级, 也就是数值更小的非一致代码段上,也就是说CALL可以跳转到DPL <= CPL的代码段上, JMP不行. JMP只可以跳转到DPL == CPL上面..
如果调用特权级更高的非一致代码段, CPL就降级为目标代码段的DPL上, 逻辑上来说是升级来, 数值变小了. 这时候会发生特权级变换, 切换到相应的特权级上面. 但是如果跳转的是一致代码段, 那么CPL不变, 堆栈也不切换
前面讲了CALL, 那么ret返回的时候是个什么款式呢? 其实是这样的.首先ret只能够返回到较低的特权级上面. 数值比较大的特权级, 和CALL对应. 那么如果确定返回的特权级是什么级别呢? 是和CS中的存放的RPL进行对比的, 如果CS中的RPL的数值>CPL, 也就是RPL数值大CPL数值小, 那么就执行跨段返回. 这时候还要特权级检查.
从调用例程的栈上装入CS和EIP寄存器, 做特权级检验, 然后跳过堆栈中的参数.. 然后检查DS, ES, FS, GS, 如果在返回到的特权级是不可访问的, 那么装入NULL.然后返回
通过TSS直接进行任务切换:
当段间转移指令的段选择子指向一个可用的TSS描述符时,正常情况下就发生特权级转移,目标任务的入口由目标任务TSS内的CS:EIP指定, 而jmp call内的偏移将丢弃. 另外如果如果是CALL指令, 则返回地址和外层堆栈指针并不压栈. 在访问TSS的时候采用与访问数据段相同的规则做特权级检测, CPL <= DPL, TSS描述符内的DPL规定了可用访问该描述符的最外层特权级, 这个和调用门是一样的,在数值上, (CPL <= DPL )and( RPL <= DPL ), 只有条件满足才进行任务切换
通过任务门进行任务切换:
当段间转移指令的段选择子指向一个任务门的时候,从当前任务切换到由任务门的选择子所指示的TSS描述符对应的任务, 这样jmp call内的偏移被丢弃, 任务门内的偏移也没有意义. 访问任务门的规则也是和访问数据段的规则是一致的, 在数值上(CPL <= DPL ), 任务门的DPL也是规定了访问该任务门的最外层特权级, 也就是说在数值上(CPL <= DPL)and(RPL <= DPL )以上检测通过的话, 就差不多了, 对于任务门指向的TSS描述符的DPL不做检测, 直接进行切换
差不多就这些吧. 通过其他形式的转移回头再添加!
文章作者 忆杰
上次更新 2011-09-18