关于CPL/RPL/DPL的疑惑

CPL:当前任务特权(Current Privilege Level)

表示当前正在执行的代码所处的特权级。CPL保存在CS中的最低两位,是针对CS而言的。

RPL:请求特权级RPL(Request Privilege Level)

RPL保存在选择子的最低两位。

DPL:描述符特权(Descriptor Privilege Level)

存储在描述符中的权限位,用于描述代码的所属的特权等级,也就是代码本身真正的特权级。一个程序可以使用多个段(Data,Code,Stack)也可以只用一个code段等。正常的情况下,当程序的环境建立好后,段描述符都不需要改变——当然DPL也不需要改变,因此每个段的DPL值是固定。

以上是网上随处可搜的说明, 之前一直不理解, 为什么会有 CPL/RPL之分, 后来看了  https://bbs.pediy.com/thread-92921.htm   上面的回答,才算是理解了.

举个例子:

这个call调用,就是明显需要加载选择子,寻找描述符的过程

只要这样理解,   实际上的比较, 实在加载选择子之前的, 因为如果校验不通过, 是不允许加载的,  所以  ,CS != Selector != DPL  (是不一定等于,而不是一定不等于,也就是说, 这是三个明显不同的东西, 之前一直以为, 是需要把selector加载到CS后,才比较的,所以一直认为,CPL一定== RPL,产生了纠结)

call 0x08:0             // 这是一个 call-gate (使用调用门)

那么:

processor 会做:

1、根据选择子 0x08 在 GDT 中寻找 descriptor

2、processor 检查 descriptor 的 Type 是什么?
  这里设为是 call-gate descriptor

3、processor 进行权限检查:

(1) RPL = 00, 因为: selector = 0x08
(2) CPL = 03,(这里设为 03)

(3) DPL 这里要分为两种 DPL:
  分别是: call gate descriptor 的 DPL,表示为 DPLg
                   code segment descriptr 的 DPL,表示为 DPLs
-------------------------------------------------------------------------------

processor 检查:
(1)RPL <= DPLg  且 CPL <= DPLg: 表示当前的运行级别和选择子级别比调用门符级别要高。

  因此:调用门符级别必须设为低权限级别,即在这里必须为 DPLg = 3

(2)如果使用的是 call 指令无论代码是 conforming 还是 non-conforming,只要
   CPL >= DPLs

    都会成功。

4、processor 检查通过后,进行加载 selector 到 CS 中
   
    CS.selector  =  selector

5、更新 CS 寄存器的内部缓存

(1)    CS.slector.RPL = DPLs           // 目标代码的运行级别
(2)       CS 的 descriptor 结构用 code segment descriptor 来更新

原文地址:https://www.cnblogs.com/davytitan/p/13827044.html