首页
论坛
课程
招聘
[求助]RPL保存在选择子里,那么CPL是保存在哪里的?
2009-7-6 10:18 6198

[求助]RPL保存在选择子里,那么CPL是保存在哪里的?

2009-7-6 10:18
6198
谁能讲讲?还有rpl,DPL,CPL之间的相互关系,最好也能一并讲讲.

[2022冬季班]《安卓高级研修班(网课)》月薪三万班招生中~

收藏
点赞0
打赏
分享
最新回复 (9)
雪    币: 2059
活跃值: 活跃值 (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
书呆彭 活跃值 6 2009-7-6 19:51
2
0
其实这个很简单的逻辑,首先你心里要明白descriptor与selector代表的都是一个内存段(segment):

Descriptor描述一个segment,既然叫描述符,它自然就有一些字段用来描述这个段的属性(DPL)。

而selector是用来访问内存的,比如DS用来访问数据段,SS访问堆栈段。selector它的一部分字段用来指出要使用哪个descriptor(换言之,就是要访问哪一个内存段),还有一部分字段,用来表明“我有什么特权来访问这段内存(RPL)”。

而CS与SS中的RPL,就是被称为CPL。因为CPU执行指令,必须要读指令,实际上就是访问CS段中EIP偏移量的内存。因此,CS选择子的特权就代表了“我有多大权力去运行这段代码”,也就是当前特权级(CPL),正因为执行的代码(CODE)的特权也就代表了当前任务(TASK)的特权。至于SS,因为堆栈的特殊性,代码的执行与堆栈密切相关,特别是诸如retn之类的指令,是有可能改变程序执行流程的,因此要求堆栈具有足够的特权。

你把指令执行当成“访问CS:[EIP]内存”,于是就很清楚了:

CPU只是执行“你有足够的特权去访问这个segment的内存吗”这个简单的判断而已。

(其实上面说的有些并不准确,但不防这么理解,接触的时间长了,自然就明白了)
雪    币: 211
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
骑猪到处跑 活跃值 2009-7-7 09:31
3
0
谢谢楼上的版主,
还有一个问题,是在<<自动动手写操作系统>>那本书的63页讲的, 说处理器通过检查RPL和CPL来确认一个访问请求是否合法, 即便提出访问请求的段有足够的特权级,如果RPL不够也是不行的, 
到这里,我不明白的是目标选择子不就是代表目标描述符吗,目标选择子里的的PRL为什么还要和目标描述符里的DPL相比较呢?我感觉目标有一个特权就够了,为什么还要多此一举呢?
雪    币: 2059
活跃值: 活跃值 (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
书呆彭 活跃值 6 2009-7-7 22:06
4
0
选择子不代表描述符!选择子用来选择描述符,但你选择了并不表示就给你了。

实际情况是,当程序往断寄存器中装载选择子时,处理器检查选择子中的RPL与DPL,如果特权不够,将直接触发保护异常!

而当特权检查通过时,才会将描述符中的基址与限装入SHADOW寄存器,不过我在书上没有看到装入的特权级是RPL还是DPL,个人猜测应该是RPL。

实际访问内存时,硬件只使用SHADOW寄存器的内容,如果不重新装载(哪怕是用原来的值)段寄存器,SHADOW寄存器中的内容就不发生变化。也就是说,修改GDT中的描述符,没有重新装载段寄存器之前是不生效的
雪    币: 211
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
骑猪到处跑 活跃值 2009-7-9 09:01
5
0
选择子不就是描述符表里的某一个描述符的偏移吗?
感觉上 选择子就是和描述符一一对应的,这是我以前的理解,以前我一直认为,选择了某一个选择子,就是选择了某一个描述符,现在楼上所说的,和我以前的理解不一样。现在脑子有点转不过来。

另外,在CS等装入选择子时,对于在shadow高速缓冲寄存器里,特权级装入的是PRL还是DPL的问题,
先看一下高速缓冲里面保存的是什么

段寄存器 段基地址 段界限 段属性 存在性 特权级 已存取 粒度 扩展方向 可读性 可写性 可执行 堆栈大小 一致特权

这里把段选择子和描述符全部缓存起来了。段选择子里面有CPL,描述符里面有DPL,这里面还有一些模糊的地方。
雪    币: 211
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
骑猪到处跑 活跃值 2009-7-9 09:07
6
0
可能这样,在装入高速缓冲寄存器后,CS里面以及高速缓冲寄存器的CS里面的存的是CPL,也就是目标描述符里的DPL值(非一致代码段的情况)。这代表了当前运行的特权级。而在高速缓冲寄存器里面的描述符寄存器里面存的还是DPL。不知道这样理解对不对?!

在书上看到这样一段话:
对于使用调用门的段间调用指令CALL,情形就不同了。由于已置RPL=0,所以可认为RPL<=DPL的条件总能满足。对于一致代码段,在满足CPL>=DPL时发生无特权级变换的转移。对于非一致代码段,当CPL=DPL时,仍发生无特权级变换的转移;当CPL>DPL时,就发生向内层特权级变换的转移,将调用门中的选择子和偏移装入CS和指令指针EIP中,并使CPL保持等于DPL,同时切换到内层堆栈。
雪    币: 695
活跃值: 活跃值 (76)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
mik 活跃值 4 2009-7-9 21:59
7
0
好好的看一看我写的那个贴子吧:

http://linux.chinaunix.net/bbs/thread-1052389-1-1.html
雪    币: 695
活跃值: 活跃值 (76)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
mik 活跃值 4 2009-7-9 22:31
8
0
还是在这回复你吧:

如下指令:

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 来更新
雪    币: 211
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
骑猪到处跑 活跃值 2009-7-10 11:02
9
0
楼上的有一点没讲清楚。

4、processor 检查通过后,进行加载 selector 到 CS 中
   
    CS.selector  =  selector
那CS.selector.RPL的值是多少?
雪    币: 2059
活跃值: 活跃值 (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
书呆彭 活跃值 6 2009-7-10 20:20
10
0
mik出手,就是不同凡响,讲得真清楚。

感谢mik,这里原来我也没有搞明白,现在才知道。

回楼上: CS.slector.RPL = DPLs ,也就是目标代码的权限。因为这里的descriptor是个CALL GATE,因此有DPLg与DPLs两个特权级,DPLg是门的特权级,DPLs是“穿过”门后的代码段的特权级。
游客
登录 | 注册 方可回帖
返回