`
spartan1
  • 浏览: 360351 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

ucore-project4: interrupt--x86 cpu复习

 
阅读更多

离上次更新ucore工程已经过去6天了。这几天工作比较忙,经常加班,回家一般23点多了。另外x86 cpu知识忘得差不多了,优先级切换、段式、页式内存访问和保护等记不起来,project4也没法继续做下去。周末终于有时间把x86文档啃了一下(25366821-pentium4-V3A-System-Programming-Guide.pdf),终于又捡起来些。

 

这是以前学习x86时记的一些东东,重新翻出来,发现还比较有用。更新了一些内容,记在这里,以备查阅:

 

段式保护规则:
1·当一个segment selector载入段寄存器时,才会触发段式保护。

 

2·CPL:进程的当前优先级,是CS寄存器中的段选择子(segment selector)的优先级,不一定等于当前代码段的优先级;
   RPL:是一个选择子(可能是某个段寄存器中的)的优先级;
   DPL:描述符优先级,是descriptor中的优先级,对于用户描述符,是用户段的段优先级,对于系统描述符,是系统段或各种门的优先级。

 

3·访问一个段中的“数据”时,只有使用的数据段寄存器(cs/ds/es/fs/gs)中的RPL和CPL(cs中的优先级)都比该段的DPL高或相等时才可以。这里的“优先级高”说的是优先级从数值上说小于DPL。

 

4·堆栈段的段优先级DPL、堆栈段寄存器SS的请求优先级RPL,必须等于进程的当前优先级CPL。

 

5·跨段调用时,如果目标代码段是不一致的(nonconforming),CPL必须等于目标代码段的优先级DPL,而RPL优先级必须等于或高于CPL,否则触发通用保护异常。当selector载入CS后,不会改变当前优先级CPL,即使RPL优先级比CPL高,也不会改变CPL,从而跳转后的CPL仍然是老的CPL(也是跳转后当前代码段的CPL)。

 

6·跨段调用时,如果目标代码段是一致的(conforming),将不检查RPL,CPL的优先级必须低于或等于目标段的优先级DPL,否则会触发通用保护异常。当selector载入CS后,老的CPL不会随着新的DPL而改变。一致代码段适合数学库以及异常处理函数,这些代码支持应用程序调用,同时又不访问被保护的系统资源。

 

7·绝大多数代码段都是不一致的(nonconforming),这些代码只能在同优先级的代码中调用,除非使用调用门(call gate)。

 

8·call gate用于让程序切换不同的当前优先级,通常只在操作系统内部使用优先级保护机制时使用。

 

9·call gate只在GDT或LDT中存在,在IDT中没有。

 

10·访问call gate时,通过call 0x70:0或jmp 0x70:0这种方式来访问,其中0x70是选择子,用于选择门
描述符,而偏移值可以为任意值(这里是0)。

 

11·使用调用门时,对于call指令,CPL和RPL必须优先级高于等于门的DPL;目标代码段,不论其是否是一致的,其DPL都必须高于等于CPL。
即,通过call 优先级低于或等于自己的调用门,可以访问优先级高于或等于自己的代码;调用后,CPL变为不一致的目标代码段的DPL,此时需要切换堆栈;对于一致的目标代码段,CPL不变。

 

12·使用调用门时,对于jmp指令,CPL和RPL必须优先级高于等于门的DPL;目标代码段如果是一致的,其DPL必须高于等于CPL,如果是不一致的,其DPL必须等于CPL。即,对于jmp指令,使用不使用门一个样。

 

13·除了return,cpu不允许高优先级代码直接跳转到低优先级代码

 

14·堆栈切换时,低优先级的栈指针和指令指针(都是全指针,即远指针)将保存到新栈上。

 

总结:正常情况下,调用和跳转只能在同优先级的代码段中进行。要跳转到高优先级代码中,必须使用门(调用门、中断门和异常门);要跳转到低优先级代码中,必须使用返回(ret)。跳转到高优先级代码中时,栈要相应切换,此时低优先级的栈和代码位置都保存在高优先级栈中。而这些栈都保存在当前task的TSS中,所以即使不用cpu的task能力,也要至少创建一个TSS,用以切换优先级时可以顺利找到新优先级代码的栈。而在ret时,除了修改CS/EIP外,还会修改SS/ESP,同时如果有参数传递的话,还会同时把两个栈上的指针值进行调整。

可以看出,call和ret指令在具有优先级切换的情况下,cpu要做的事变得复杂了很多。


问题:
为什么栈优先级必须和CPL一致?
a、保护高优先级代码免于栈溢出;
b、防止高优先级代码读写低优先级的栈数据

 

页式保护规则:
1·页目录项和页表项中有两个位用于保护规则:U/S位(用户/管理者位)和R/W位(读写位)。
当U/S = 0时,这一项对应的页表或页处于管理者模式,否则处于用户模式
当R/W = 0时,这一项对应的页表或页是只读的,否则是可读可写的。

 

CPL决定当前进程的优先级:
当CPL=0、1、2时,处于管理者模式,此时可以访问所有的页面,当CR0的WP(写保护)位清空时,可以读写所有页面,不论其读写标记是啥。
当CPL=3时,处于用户模式,此时只能读用户模式的所有页面,写用户模式的可读可写页面,不能访问任何管理者模式的页面。

 

x86保护模式下cpu在执行时,总是处于某个task的上下文中执行。这个task的状态由TSS段指定,由TR寄存器索引(TSS描述符只能位于GDT中),这样TR就是类似CS/DS/ES/FS/GS一样的段寄存器,其内保存了一个selector,同时隐藏部分缓存了descriptor的内容。

 

一个task在某一时刻可以在各种优先级中执行,优先级切换时,堆栈需要切换,切换的堆栈也在TSS中指定。x86的TSS的第一个word是一个指向前一个task的selector,所以task可以组成一个task链表,task是不能重入的。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics