## 8.3 保护和I/O(Protection and I/O)
有两种机制用于I/O保护:
1、 FLAGS里的IOPL字段定义了使用I/O指令的特权级。
2、 TSS段里的I/O许可位图定义了使用I/O地址空间的特权级。
这些机制只在保护模式下工作,包含虚拟8086模式。在实模式中他们不会起作用。在实模式中,I/O空间没有任何保护。任何子程序可执行I/O指令。任意I/O端口都是可以被I/O指令寻址的。
### 8.3.1 I/O 特权级(I/O Privilege Level)
处理I/O的指令应该被限制执行,但不在特权级0执行I/O指令也是需要的。所以,处理器用了标志寄存器里的两位来存储I/O的特权级(IOPL)。IOPL定义了要执行I/O指令所需要的特权级。
以下指令只有当CPL <= IOPL时才可以执行:
![](https://box.kancloud.cn/2016-03-06_56dbfdae027fd.gif)
这些指令被称作“敏感指令”,因为他们对I/O敏感的。
为了执行敏感指令,子程序必须执行在至少小于或等于(数值上)IOPL(CPL <= IOPL)的特权级。任何没有足够特权级的程序执行I/O指令时将引起通用保护异常。
因为每个任务都有自已的标志寄存器,每个程序都有不同的IOPL。一个任务如果主要任务是完成I/O操作的话(设备驱动程序)可以让IOPL为3,所以他的任何子程序都可以执行I/O。其它一些程可以把IOPL设成0或1,只让特权级高的子程序可以执行I/O。
一个任务只有通过POPF指令才能改变IOPL。但是,这样的改变是特权级的。只有在特权级0执行的程序才可以改变IOPL。不够特权级的程如果试图更改IOPL的话,不会产生任何异常,而IOPL只是保持不变。
一条POPF指令可以用来副加的开中断和关中断。但是,通过POPF来改变IF标志位也是特权级的。一个想通过POPF指令来改变IF标志的程序,必须要执行在到少IOPL的特权级上(数值上小于或等于)。同样,不够特权级的试图更改并不会产生任何异常,而IF只是保持不变。
### 8.3.2 I/O 许可位图(I/O permission Bit Map)
直接指定处理器I/O地址空间的I/O指令是IN,INS,OUT,OUTS。80386可以有选择性的把一些I/O地址空间访问设成陷阱。允计这样做的数据结构是在TSS段(请看图8-2)中的I/O 许可位图(I/O Permission Bit Map)I/O许可位图是一个位向量。位图的大小是可变的,这个值存放在TSS段中。处理器通过TSS中的位图基址来定位这个位图。I/O位图基址是一个16位宽的字段,包含了I/O许可位图的偏移。位图的上限也是TSS段的上限。
在保护模式下,当遇到一条I/O指令时(IN,INS,OUT,或OUTS),处理器首先检查是否CPL<=IOPL。如果是的话,I/O操作可以继续。如果不是的话,处理器检查I/O许可位图。(在虚拟8086模式,处理器不管IOPL而直接查看位图,参看第15章)
位图中的每一位都对应着一个I/O端口字节地址。例如,端口41的位可以在I/O位图基址+5,位偏移1,处找到。处理器会检测I/O指令访问到的每个字节,以看是否允许访问。例如,一个双字操作,将测试4位,对应着4个连续的字节地址空间。如果任一个测试是置位的,处理器引发一个通用保护异常。如果所有的测试都有为0,I/O操作被允许。
没有必要为所有的I/O地址设置I/O许可位图。没有被覆盖到的I/O地址空间,将被假设该位图对应位已设置为1。例如,如果TSS界限等于I/O位图基址+31的话,前256的端口被映射。对于更大的端口号作的I/O操作将引起异常。
如果I/O映射位图基址大于或等于TSS界限的话,TSS段则没有I/O许可位图,所以只要当CPL>IOPL时,所有的I/O操作将引起异常。
因为I/O许可位图在TSS段中,不同的任务有不同的映射位图。操作系统可以通过修改一个任务的TSS段中的I/O许可位图,来为某个任务分配端口,
![](https://box.kancloud.cn/2016-03-06_56dbfdae13033.gif)
- 第一章 80386介绍
- 1.1 该手册的组织结构
- 1.2 其他文献
- 第二章 编程基本模型
- 2.1 存储器组织和段
- 2.2 数据类型
- 2.3 寄存器
- 2.4 指令格式
- 2.5 操作数选择
- 2.6 中断和异常
- 第4章 系统寄存器
- 4.1 系统寄存器 (System Registers)
- 4.2 系统指令 (System Instructions)
- 第五章 内存管理
- 5.1 分段地址转换(Segment Translation)
- 5.2 分页地址转换(Page Translation)
- 5.3 混合分段和分页地址转换(Combining Segment and Page Translation)
- 第六章 内存管理
- 6.1 为什么要保护(Why Protection?)
- 6.2 80386保护机制概述(Overview of 80386 Protection Mechnaisms)
- 6.3 段级保护(Segment-Level Protection)
- 6.4 页级保护(Page-Level Protection)
- 6.5 混合分页和分段保护(Combining Page and Segment Protection)
- 第7章 多任务(Multitasking)
- 8.1 I/O 寻址(I/O Addressing)
- 7.1 任务状态段(Task State Segment)
- 7.3 任务寄存器(Task Register)
- 7.4 任务门描述符(Task Gate Descriptor)
- 7.5 任务切换(Task Switching)
- 7.6 任务链(Task Linking)
- 7.7 任务寻址空间(Task Address Space)
- 第8章 输入 输出
- 8.2 I/O 指令(I/O Instructions)
- 8.3 保护和I/O(Protection and I/O)
- 第9章 异常和中断(Exceptions and Interrupts)
- 9.1 识别中断(Identifying Interrupts)
- 9.2 允许和禁止中断(Enabling and Disabling Interrupts)
- 9.3 同时发生的中断和异常的优先级(Priority Among Simultaneous Interrupts and Exceptions)
- 9.4 中断描述符表(Interrupt Descriptor Table)
- 9.5 IDT 描述符(IDT Descriptors)
- 9.6 中断任务和中断子程序(Interrupt Tasks and Interrupt Procedures)
- 9.7 出错码(Error Code)
- 9.8 异常条件(Exception Conditions)
- 9.9 异常总结(Exception Summary)
- 9.10 出错码总结(Error Code Summary)
- 第10章 初始化(Initialization)
- 10.1 复位后处理器状态(Processor State After Reset)
- 10.2 实模式初始化(Software Initialization for Real-Address Mode)
- 10.3 切换到保护模式(Switching to Protected Mode)
- 10.4 保护模式初始化(Software Initialization for Protected Mode)
- 10.5 初始化示例
- 10.6 TLB测试
- 第十四章 80386实地址模式
- 14.1 物理地址构成
- 14.2 寄存器和指令
- 14.3 中断和异常处理
- 14.4 进入和离开实地址模式
- 14.6 实地址模式异常
- 14.7 与8086的不同
- 14.8 与80286实地址模式的不同