操作系统篇之-通过调用门和TSS进行不同特权级之间的代码跳转

前面几篇文章我们知道了有很多段,GDT段、LDT段等,通过jmp或者call进行直接代码段间转移我们比较熟悉。但是那只限于同样特权级别的代码段之间跳转。要知道,在IA32的分段机制中,操作系统代码的特权级总共有4个,从高到低分别是0,1,2,3。数字越小代表的特权级别越大。
   处理器通过识别下面3种特权级进行特权级检验:
    CPL(Current PrivilegeLevel):当前执行的程序或者任务的特权级。
    DPL(Descriptor PrivilegeLevel):表示段或者门的特权级。
    RPL(Requested PrivilegeLevel): RPL是通过段选择子的第0位和第1位表现出来的。
   如果目标是非一致代码段,要求CPL必须等于目标段的DPL,同时要求RPL小于等于DPL;如果目标是一致段代码段,则要求CPL大于等于目标段的DPL,RPL此时不做检查。当转移到一致代码段中后,CPL会被延续下来,而不会变成目标代码段的DPL。也就是说,通过jpm和call所能进行的代码段间转移是非常有限的,对于非一致代码段,只能在相同特权级代码段之间转移。遇到一致代码段也最多能从低到高,而且CPL不会改变。如果想自由的进行不同特权级之间的转移,显然需要其他方式:运用门描述符或者TSS(TSS的使用是因为进行段间转移时堆栈需要作一些特殊处理)。
   利用调用门可以实现从低优先级代码访问高优先级代码。
    优先级切换中堆栈处理步骤:
1)准备调用门
2)加载TSS,因为总共有4个优先级(ring0~3),所以每个优先级下面都对应一个堆栈。加载了TSS,就能够根据目标优先级而从TSS中获取想对应的堆栈地址
3)临时性保存当前,未切换前的SS_old和ESP_old的值
4)根据目标优先级从TSS中获取对应的对应得堆栈地址SS_new和ESP_new,并加载。(因为CPU只有一个SS和一个ESP寄存器,所以,所谓的加载,只是把新的SS_new和ESP_new的地址赋给CPU的SS和ESP寄存器)
5) 将已经临时保存的SS_old和ESP_old的值保存到新堆栈中。
6)将当前的CS_old和EIP_old保存入新堆栈
7)加载调用门中指定的新的CS和EIP,开始执行被调用者过程。
    优先级切换返回过程堆栈处理步骤:
1)加载被调用者堆栈上的CS_old和EIP_old
2)加载SS_old和ESP_old,切换到调用者堆栈,被调用者的SS_new和ESP_new被丢弃

你可能感兴趣的:(osdev)