特权级和调用门

转载 2016年08月30日 22:54:22

在IA32的分段机制中,总共有4个特权级别,从高到低分别是0、1、2、3。处理器通过识别下面3中特权级进行特权级检验

1.CPL(Current Privilege Level)CPL是当前执行的程序或者任务的特权级,它被存储在CS和SS的第0位和第1位上,通常情况下,CPL等于代码所在的段的特权级,但是有一个例外是如果在遇到一致代码段时,当处理器访问一个与CPL特权级不同的代码段时,CPL不会发生改变。

什么是一致码段呢?它其实是由段描述符数据结构中的属性字段决定的,“一致”的意思是当转移的目标是一个特权级更高的代码段时,当前的特权级会被延续下去,而向特权级更高的非一致代码段转移会引起常规保护错误,除非使用调用们或者任务门。而当目标代码段的特权级低的话,无论它是不是一致代码段,都不能通过call或者jmp转移进去。另外所以的数据段都是非一致的,这意味着不可能被低特权级的代码访问到,然而,与代码段不同的是,数据段可以被更高特权级的代码段访问,而不需要特定的门。

2.DPL(Descriptor Privilege Level) DPL表示段或者门的特权级,它被存储在段描述符或者门描述符的DPL字段中,当当前代码段试图访问一个段或者门时,DPL将会和CPL以及段或者门选择自的RPL相比较。DPL的比较分下面5种情况:

  • 数据段:DPL规定了可以访问此段的最低特权级
  • 非一致代码段(不使用调用门情况下):DPL规定了访问此段的特权级
  • 调用门:DPL规定了当前执行的程序或者任务可以访问此调用门的最低特权级(这个和数据段的规则是一致的)
  • 一致代码段和通过调用门访问的非一致代码段:DPL规定了可以访问此段的最高特权级
  • TSS:DPL规定了可以访问此TSS的最低特权级

3.RPL(Requested Privilege Level) RPL是通过段选择子的第0位和第1位表示出来的。处理器通过检查RPL和CPL来确认一个访问请求是否合法。

所以对数据段的访问比较简单,就是检验特权级,只要CPL和RPL都小于被访问的数据段的DPL就可以了

对程序段的访问比较复杂,程序从一个代码转移到另外一个代码之前,目标代码段的选择子会被加载到cs中,作为加载的一部分,处理器将检查描述符的界限、类型、特权级的内容。如果检验成功,cs将会被加载。

使用jmp或者call指令可以实现下列4种转移:

  • 目标操作数包含目标代码段的段选择子(直接转移)
  • 目标操作数指向一个包含目标代码段选择子的调用门描述符(间接转移)
  • 目标操作数指向一个包含目标代码段选择子的TSS(间接转移)
  • 目标操作数指向一个任务门,这个任务门指向一个包含目标代码段选择子的TSS(间接转移)

调用门:什么是调用门,它也是一种描述符,它的结构定义如下:

; 门

; usage: Gate Selector, Offset, DCount, Attr

;        Selector:  dw

;        Offset:    dd

;        DCount:    db

;        Attr:      db

%macro Gate 4

dw (%2 & 0FFFFh); 偏移 1(2 字节)

dw %1; 选择子(2 字节)

dw (%3 & 1Fh) | ((%4 << 8) & 0FF00h) ; 属性(2 字节)

dw ((%2 >> 16) & 0FFFFh); 偏移 2(2 字节)

%endmacro ; 共 8 字节

和段描述符的6个字节结构不一样,门是由8字节构成,这个描述符也是放置在GDT,LDT或者IDT中以供调用。门描述符分为4种:

  • 调用门
  • 中断门
  • 陷阱门
  • 任务门

门调用其实就是提供了一个入口地址,它可以实现的是不同特权级的代码之间的转移。下面介绍一下具体的过程:

假设我们想由代码A转移到代码B,运用一个调用门G,即调用门G中的目标选择子指向代码B的段,我们涉及这么几个要素:CPL、RPL、代码B的DPL(DPL_B)和调用门的DPL(DPL_G)。根据门调用的规则,A要调用G,则A的CPL和RPL要小于DPL_G,另外还要比较CPL和DPL_B,如果是一致代码段的话,要求DPL_B小于等于CPL,如果是非一致代码段的话,call指令要求DPL_B小于等于CPL,jmp指令要求DPL_B=CPL。

这里我不是特别清楚,可能是如果没有通过门调用,会直接比较RPL和DPL_B,因此门调用能够实现从低特权级到高特权级的转移。

TSS介绍:在进行call和jmp时候,必然要使用堆栈,然而由于不同的特权级会使用不同的堆栈,因此一个任务最多可能有4个堆栈,那么当转移指令在不同特权级之间变化的时候,压入堆栈的内容在另外一个特权级里面已经不是原来的堆栈了,对于这个问题,就引出了TSS(Task-State Stack)这个数据结构。这个数据结构中存在着ss2、esp2;ss1、esp1;ss0、esp0,转移过程如下:

  1. 根据目标代码的DPL从TSS中选择应该切换至哪个ss和esp
  2. 从TSS中读取新的ss和esp
  3. 暂时性地保存当前的ss和esp的值
  4. 加载新的ss和esp
  5. 将刚刚保存起来的ss和esp的值压入新栈
  6. 将当前的cs和eip压栈
  7. 加载调用门中指定的新的cs和eip。

所以,从上面的过程中我们可以知道,在进行特权级转移时,首先根据目标代码的DPL从TSS中取得对应的ss和esp,然后加载新的ss和esp,也就是使用新的堆栈,并把老的堆栈的信息压入新栈,以便返回时使用,然后再进行转移

 

 

 

下面说明代码段和数据段的访问:


一、代码段间跳转


1、普通(直接)跳转:

JMP Selector:0 或 CALL Selector:0

1)一致代码段(JMP&CALL)

要求:CPL>=DPL,RPL不作检查

特权变化:跳转后程序CPL=跳转前程序CPL

2)非一致代码段(JMP&CALL)

要求:CPL=DPL & RPL<=DPL

特权变化:跳转后程序CPL=目标代码段DPL


2、通过调用门跳转:

JMP 调用门Selector:0 或 CALL 调用门Selector:0 (注意:此时如果选择子后面跟着32位偏移量也不会被CPU使用,因为调用门描述符已经记录了目标代码的偏移)


step1: 要求:指示调用门的选择子的RPL<=门描述符DPL & 当前代码段的CPL<=门描述符的DPL。


只有满足以上条件时,CPU才会进一步从调用门描述符中读取代码段的选择子或地址偏移。而从调用门中读取代码选择子和地址偏移后,跟普通跳转又站在同一起跑线上了。

唯一不同的是CPU会将目标代码段RPL清0。此后需要分类讨论,如下:


step2:

1)一致代码段(JMP&CALL)  <------------------------------------------------------------------------------------------------------

要求:CPL>=DPL,RPL不作检查(因为RPL总被清0)                                                        |

特权变化:跳转后程序CPL=跳转前程序CPL                                                                        |

                                                                                                                                             比较

2)非一致代码段(JMP)                                                                                                                |

要求:CPL=DPL,RPL不作检查(因为RPL总被清0)                                                          |

特权变化:跳转后程序CPL=目标代码段DPL                                                                        |

3)非一致代码段(CALL)  <------------------------------------------------------------------------------------------------------------

要求:CPL>=DPL,RPL不作检查(因为RPL总被清0)

特权变化:跳转后程序CPL=目标代码段DPL(CPL>DPL的情况下,特权级发生跃迁)


二、访问数据段

数据段:特权级低->高:NO | 特权级高->低:YES | 特权级同级之间:YES


注意:

1、一致代码段:无论那种方式跳转到一致代码段,CPL都不会改变(不变化为目标代码段的DPL),也即加载目标代码段选择子时,只加载高14位,表示CPL的低2位保持不变。

因此,“一致”的意思就是——代码段被调用执行时,不使用自己描述符的DPL,而采用调用这特权级,CS的低2位保持不变(与“调用者保持一致”)

2、非一致代码段:无论采用哪种方式跳转到非一致代码段,CPL都发生变化,也即在加载目标代码段选择子时,将整个选择子放入到CS中。

3、为了访问调用门,调用者程序的特权级CPL必须小于或等于调用门的DPL。调用门段选择符的RPL也要同调用CPL一样遵守相同的规则,即RPL也必须小于或等于调用门的DPL

相关文章推荐

特权级和调用门

转自:http://blog.csdn.net/wjwbin1986/article/details/6144058            http://1025250620.iteye.com/b...

保护模式编程——保护的详尽意义:通过调用门转移特权级

保护模式及其编程——保护机制 摘要:在汇编语言的编程和操作系统的编写过程中,我们经常能听说到“保护模式”这个名词。为什么要叫“保护模式”呢?保护 二字的含义何在?本文主要探讨,“保护模式”下面各种具体...

通过retf和调用门实现特权级转换

不打算按别人的思路来,因为在我学的过程中上网查,发现网上的博客都是互相抄的,最终还是抄书的。Intel 64 和 IA-32架构处理器在进入保护模式之后,就会有一些列保护机制。其中出现了三个特别重要的...

80386保护模式--GDT,LDT,TSS,调用门,特权级转移,附pmtest5代码详解

教材选择一个操作系统的实现,作者于渊,看此书前最好了有汇编语言,保护模式下的汇编(参考清华杨季文的80X86汇编语言程序设计教程),C语言,计算机组成原理,微机接口,操作系统相关知识。 一、8038...
  • jltxgcy
  • jltxgcy
  • 2013年03月10日 11:14
  • 3752

一个操作系统的实现 不同特权级代码段之间的跳转 CPL DPL RPL 调用门

http://blog.csdn.net/begginghard/article/details/7262901 1、特权级 2、一致代码段和非一致代码段 3、DPL、RPL、CPL分别...

读书笔记_跨特权级调用

通常发起调用的函数和被调用的函数都是位于同一个特权级的代码中的,这种调用叫做同特权级调用,另一种情况是位于不同特权级代码段中的代码互相调用,被称为跨特权级调用。跨特权级调用通常是通过一个所谓的调用门(...

没有特权级变换的进程调度示例

  • 2009年12月02日 09:28
  • 348KB
  • 下载

jmp,call,ret,特权级转移,进程调度

jmp,call,ret,特权级转移,进程调度 ①jmp是不负责任的调度,不保存任何信息,不考虑会回头。跳过去就什么也不管了。 ②call,保存eip等,以便程序重新跳回。ret是call的逆过程...

专注于操作系统18之完整的特权级转换

在上一篇文章中,我们已经能从ring0级进入到ring3级,在这里我们将再加上从ring3级到ring0级。从ring3级到ring0级这需要使用在第十四篇文章中提到的调用门来实现。即在进入ring3...

不同特权级代码段之间的跳转(CPL DPL RPL之间的关系)

1、特权级 2、一致代码段和非一致代码段 3、DPL、RPL、CPL分别代表的含义,存储在什么位置,以及它们之间的关系 4、不同特权级数据段之间的访问规则 5、不同特权级代码段之间的转移 6...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:特权级和调用门
举报原因:
原因补充:

(最多只允许输入30个字)