今天来学习一下X86中断与异常和控制寄存器

中断

中断通常是由CPU外部的输入输出设备(硬件)所触发的,供外部设备通知CPU有事情需要处理,因此又叫中断请求,英文为Interrupt Request。中断请求的目的是希望CPU暂时停止执行当前正在执行的程序,转去执行中断请求所对应的中断处理例程,中断处理程序由 IDT 表决定。

80x86 有两条中断请求线:非屏蔽中断线,NMI,全称NonMaskable Interrupt和可屏蔽中断线,INTR,全称Interrupt Require

可屏蔽中断

CPU 的 EFLAGS 有一个 IF 位,它表示了 CPU 当前是否接受可屏蔽中断请求,下面是 EFLAGS 寄存器的图解

IF 是第九位,权值为 0x200,这也就是为什么在用户态我们看到的 EFLAGS 值几乎都是 2xx,因为用户态几乎不允许把该位复位,复位该位需要特权指令 cli 来操作,而重新设置指令需要 sti 来操作。

IF = 1 的时候,可屏蔽中断请求可以被执行,IF = 0 的时候,可屏蔽中断会被屏蔽,不会被执行,不可屏蔽中断走的是 CPU 的NMI引脚,而可屏蔽中断走的就是INTR引脚。

在硬件级,可屏蔽中断是由一块专门的芯片来管理的,通常称为中断控制器。它负责分配中断资源和管理各个中断源发出的中断请求.为了便于标识各个中断请求,中断管理器通常用IRQ,全称为Interrupt Request,后面加上数字来表示不同的中断,例如在键盘设备中,可以看到键盘的请求是一号中断

不可屏蔽中断

不赘述了,就是 CPU 收到就必须立刻执行的事件,诸如CPU掉电,总线校验错误,内存校验错误,看门狗错误等,一旦发生了这些事件,硬件会向 CPU 的 NMI 引脚发送一个中断请求要求 CPU 立刻响应。不过大部分的 NMI 可能都表示着CPU生存周期的终结(出现的故障无法恢复),当然也有一些软件产生的 NMI 中断,可能在执行完事件处理程序之后,会允许 CPU 继续运行。

异常

异常通常是CPU在执行指令时检测到的某些错误,比如除0、访问无效页等。也可以看出,异常是 CPU 主动触发的,是在检测到一些指令不符合某些要求的时候触发的。而中断是由外部设备(中断源)向CPU请求的,是被动的。int n 虽然这个指令是中断(Interrupt)的缩写,但是它本质还是 CPU 主动触发了一个异常,就跟除法的时候检测到了被除数为零是差不多的。

异常处理

无论是由硬件设备触发的中断请求还是由CPU产生的异常,处理程序都在IDT表。常见的异常处理程序如下表所示:

错误类型 (IDT表)中断号
页错误 0xE
段错误 0xD
除零错误 0x0
双重错误 0x8

缺页异常

这是 CPU 主动触发的比较多的异常,当PDE/PTEP=0 时或当PDE/PTE的属性为只读但程序试图写入的时就会触发。一旦发生缺页异常,CPU会执行IDT表中的0xE中断处理程序,由操作系统来接管。

在 Windows 操作系统中,大家都听过 pagefile.sys,它占用空间很大并且无时无刻不被写入,以前问过一个很蠢的问题就是,这个文件是否能删?先来了解一下这个文件是干啥的,答:为了节省物理内存。由于程序局部性的原理,一个程序所占用的物理页,很可能只有一小部分的数据会被频繁读写或者执行,大部分数据可能都不会反复被使用,那么对于这样一部分的物理页,操作系统会选择将该物理页保存到外部文件,也就是这个 pagefile.sys,也就是这个物理页不会被挂上去了。但是当再一次需要使用的时候怎么办呢,此时找不到对应的物理页,CPU 报告一个缺页异常,调用 IDT 表的 0xE 中断程序去处理,发现这个虚拟内存事实上是有对应的物理内存,只是现在被交换到外部文件当中,那就重新指定一个物理页,把内容写回重新挂上,向CPU报告“这个虚拟内存已经被正确挂上了物理页,可以访问了”,那么CPU重新执行这条指令之后就不会报错了就接着运行。

可以说,缺页异常在操作系统中是无时无刻不在发生。就连刚申请的内存页,在不访问之前也是不会挂物理页的(即不实际占用内存),在第一次访问的时候会引发缺页异常,发现这个页是正确的,只是没被挂物理页,那么挂上物理页之后重新执行再返回。

控制寄存器介绍

控制寄存器(CR0、CR2、CR3、CR4)中有一些标志和数据域用于控制系统级操作,另外一些标志则专用来支持操作系统和管理程序,其中,CR1作保留目前不使用。

CR0

CR0寄存器中含有控制处理器操作模式和状态的系统控制标志,可以说它是总开关的集合体。如下图所示:

这里解释几个重要的位

  • PE位是启用保护模式(Protection Enable)标志。若PE = 1是开启保护模式,反之为实地址模式。这个标志仅开启段级保护,而并没有启用分页机制。若要启用分页机制,那么PEPG标志都要置位。
  • PG位是启用分页机制。在开启这个标志之前必须已经或者同时开启PE标志。PG = 0PE = 0,处理器工作在实地址模式下。PG = 0PE = 1,处理器工作在没有开启分页机制的保护模式下。PG = 1PE = 0,在PE没有开启的情况下无法开启PGPG = 1PE = 1,处理器 工作在开启了分页机制的保护模式下。
  • WP位对于Intel 80486或以上的CPU,是写保护(Write Proctect)标志。当设置该标志时,处理器会禁止超级用户程序(例如特权级0的程序)向用户级只读页面执行写操作;当CPL < 3的时候,如果WP = 0可以读写任意用户级物理页,只要线性地址有效。如果WP = 1可以读取任意用户级物理页,但对于只读的物理页,则不能写。

CR1

保留,暂不使用

CR2

当CPU访问某个无效页面时,会产生缺页异常,此时,CPU会将引起异常的线性地址存放在CR2中。

CR3

CR3含有存放页目录表页的物理地址,因此CR3也被称为PDBR(Page-Directory Base address Register,页目录基地址寄存器)。因此前面提到的,dirbase 就是 CR3 的值,事实上任务的切换也依赖于 CR3 寄存器。

CR4

Cr4的结构如下图所示:

VME用于虚拟8086模式。PAE用于确认是哪个分页,PAE = 1,是2-9-9-12分页,PAE = 010-10-12分页。PSE是大页是否开启的总开关,如果置0,就算PDE中设置了大页你也得是普通的页。

参考文献