Orange'S:一个操作系统的实现

保护模式

Posted by BINBIN Blog on November 1, 2019

保护模式I/O

毫无疑问,对I/O 的控制权限是很重要的内容,保护模式对此也做了限制,用户进程如果不被许可是无法进行IO操作的。 这种限制通过两个方面实现的,它们就是IOPL 和 I/O许可位图。

IOPL

前面代码提到IOPL ,它是IO 保护机制的关键之一,位于寄存器eflags的第12、13位,如图所示:

指令in、ins、out、outs、cli、sti只有在CPL<= IOPL时候才能执行!

这些指令被称为I/O 敏感指令。如果低特权级的指令试图访问这些I/O指令将会导致常规保护错误(#GP)。

可以改变IOPL 的指令是popf 和 iretd,但是只有运行在ring0的程序才能将其改变。 运行在低特权级下的程序无法改变IOPL,书上说是你可以试试改,但是IOPL 不会变化,还是保持原样的。

指令popf也能改变IF (好像执行了cli和sti指令)。 所以popf也变成了I/O 敏感指令。只有CPL<=IOPL时,popf才能改变IF,否则IF 将维持原值,不会产生任何异常。

I/O许可位图

前面章节的TSS 的知识中,有一个图上面提到了“ I/O 位图基址”,它是一个以TSS的地址为基址的偏移,指向的便是I/O许可位图。

为什么叫位图,是因为它的每一位表示一个字节的端口地址是否可用。如果某一位为0,则表示此位对应的端口号可以用,为1则不可用。由于每一个任务都可以有单独的TSS,所以每一个任务可以有它单独的I/O许可位图。

比如,一个任务的TSS 是这样的:


1 [SECTION .tss3]
2 LABEL_TSS3:
3            ...
4 			DD 		SelectorLDT3    ; LDT
5			DW 		0				; 调试陷阱标志
6			DW 		$ - LABEL_TSS3 + 2 ; 指向I/O 许可位图
7		times 12 DB  0FFh				; 端口 00h -- 5fh
8           DB		11111101b 			; 端口 60h -- 67h,只允许端口61h的操作
9			DB      0FFh 				; I/O 许可位图结束标志
10 TSS3Len     equ      $ - LABEL_TSS3

由于I/O 许可位图开始有12字节内容为0FFh,即有12 X 8 = 96位被置为1,所以从端口00h 到 5Fh 共有96个端口地址对此任务不可用。同理,接下来的1字节只有第1位(从0开始数)是0,表示这一位对用的端口 (61h) 可用!

I/O 许可位图必须以0FFh结尾,代码第9行就是这样做的!

如果I/O位图基址大于或等于TSS 段界限,就表示没有I/O 许可位图,如果CPL <= IOPL ,则所有I/O 指令都会引起异常。

I/O 许可位图的使用使得即便在同一特权级别下不同的任务有不同的I/O 访问权限。

保护模式小结

  • 在GDT LDT 以及IDT中,每一个描述符都有自己的界限和属性等内容,是对描述符所描述对象的一种限定和保护
  • 分页机制中的PDE 和 PTE都含有R/W以及U/S 位。提供页级保护。
  • 页式存储的使用使应用程序使用的线性地址空间而不是物理地址,于是物理地址就被保存起来了。
  • 中断不再像实模式一样使用,也提供特权检验等内容
  • I/O指令不再随便使用,于是端口被保护起来。
  • 在程序运行过程中,如果遇到不同特权级间的访问情况,会对CPL、RPL、DPL、IOPL等内容进行非常严格的检验,同时可能伴随堆栈的切换,这都对不同层级的程序进行了保护!