特权级别与栈

特权级别与栈

Content #

通过调用门实施特权级之间的控制转移时,可以使用jmp far 指令,也可以使用 call far 指令。如果是后者,会改变当前特权级CPL。因为栈段的特权级必须同当前特权级保持一致,因此,还要切换栈,即,从低特权级的栈切换到高特权级的栈。

比如,一个特权级为3 的程序必须使用自己的3 特权级栈工作。当它通过调用门进入0 特权级的代码段执行时,当前特权级由3 变为0。此时,栈也要跟着切换,从3 特权级的栈切换到0 特权级的栈。这主要是为了防止因栈空间不足而产生不可预料的问题,同时也是为了防止栈数据的交叉引用。

为了切换栈,每个任务除了自己固有的栈之外,还必须额外定义几套栈,具体数量取决于任务的特权级别。

  1. 0 特权级任务不需要额外的栈,它自己固有的栈就足够使用,因为除了调用返回外,不可能将控制转移到低特权级的段;
  2. 1 特权级的任务需要额外定义一个描述符特权级DPL 为0 的栈,以便将控制转移到0 特权级时使用;
  3. 2 特权级的任务则需要额外定义两个栈,描述符特权级DPL 分别是0 和1,在控制转移到0 特权级和1 特权级时使用;
  4. 3 特权级的任务最多额外定义3 个栈,描述符特权级分别是0、1 和2,在控制转移到0、1 和2 特权级时使用。

这些额外的栈,一般会由操作系统加载程序时自动创建。其描述符位于任务自己的LDT 中。同时,还要在任务的TSS 中登记,原因是,栈切换是由处理器固件自动完成的,处理器需要根据TSS 中的信息来完成这一过程。

任务状态段TSS的格式图所示,在TSS 内,从偏移4~24 处登记有特权级 0 到2 的栈段选择子,以及相应的ESP 初始值。任务自己固有的栈信息则位于偏移量为56(ESP)和80(SS)的地方。任务寄存器TR 总是指向当前任务的任务状态段TSS,其内容为该TSS 的基地址和界限。在切换栈时,处理器可以用TR 找到当前任务的TSS,并从TSS 中获取新栈的信息。

From #