异常和中断处理

IA-32中异常和中断的处理

  1. 引导程序被读到内存后,开始执行引导程序,以装入操作系统内核,并对GDT,IDT等进行初始化,系统启动后,进入保护模式。
  2. IA-32中,每条指令执行后,下条指令的逻辑地址(虚拟地址)由CS和EIP指示 实地址模式下:指令地址=cs<<4+IP
  3. 每条指令执行过程中,CPU会根据执行情况判定是否发生了某种内部异常事件,并在某条指令执行结束时判定是否发生了外部中断请求(由此可见,异常事件和中断请求的检测都是在某一条指令执行过程中进行的,显然有硬件完成)
  4. 在CPU根据CS和EIP取下条指令之前,会根据检测的结果判断是否进入中断响应阶段(异常和中断的响应也都是在某一条指令执行过程中或执行结束时进行的,显然也由硬件完成)

IA-32中异常和中断响应过程

首先介绍一些名词,用下面的图片。
段描述符表:
IA-32处理器把所有段描述符按顺序组织成线性表 放在内存中,称为段描述符表。分为三类:全局描述符表GDT,局部描述符表LDT和中断描述符表IDT。GDT和IDT在整个系统中只有一张,而每个任务 都有自己私有的一张局部描述符表LDT,用于记录本任务中涉及的各个代码段、数据段和堆栈段以及本任务的使用的门描述符。

中断描述符表(Interrupt Descriptor Table, IDT )是保护模式下用于存储中断处理程序入口的表,当CPU 接收一个中断时,需要用中断向量在此表中检索对应的描述符,在该描述符中找到中断处理程序的起始地址,然后执行中断处理程序。
中断描述符表中有什么呢?表中不仅仅有中断描述符,还可以有任务门描述符和陷阱门描述符
在这里插入图片描述
中断发生后, eflags 中的 NT 位和 TF 位会被置0 。如果中断对应的门描述符是中断门,标志寄存器 eflags中的IF位被自动置0 ,避免中断嵌套,即中断处理过程中又来了个新的中断,这是为防止在处理某个中断的过程中又来了个相同的中断,即同一种中断未处理完时又来了一个,这会导致一般保护性( GP )异常。这表示默认情况下,处理器会在无人打扰的方式下执行中断门描述符中的中断处理例程。若中断发生时对应的描述符是任务门或陷阱门的话, CPU 是不会将IF位清0因为陷阱门主要用于调试,它允许 CPU 响应更高级别的中断,所以允许中断嵌套。而对任务门来说,这是执行 一个新任务,任务都应该在开中断的情况下进行,否则就独占 CPU 资源,操作系统也会由多任务退化成单任务了。
TF 表示 Trap Flag ,也就是陆阱标志位,这用在调试环境中,当TF 时表示禁止单步执行,也就是说,进入中断后将 TF 直为 ,表示不允许申断处理程序单步执行
NT位表示 Nest Task Flag,即任务嵌套标志位,也就是用来标记任务嵌套调用的情况。任务嵌套调用是指CPU 将当前正执行的旧任务挂起,转去执行另外的新任务. iret 指令有两个功能, 一个是从中断返回,另外一个就是返回到调用自己执行的那个旧任务. 对同一条iret指令, CPU是如何知道该从中断返回昵,还是返回到旧任务继续执行呢?这就用到 NT 位了,当 CPU 执行 iret 时,它会去检查 NT 位的值,如果 NT 位为1,这说明当前任务是被嵌套执行的,因此会从自己 TSS 中“上一个任务 TSS 的指针”字段中获取旧任务,然后去执行该任务。如果 NT 位的值为0 ,这表示当前是在中断处理环境下,于是就执行正常的中断退出流程

内核中的TSS段记录了每个进程的状态信息,例如,每个进程对应的页表,task和mm等结构信息,内核栈的栈顶信息:SS:ESP等

IA-32中异常和中断响应过程
  • 处理器根据中断向量号定位中断门描述符
    确定中断类型号i,从IDTR指向的IDT中取出第i个表象的IDTi
    根据IDTi中段选择符,从GDTR指向的GDT取出相应段描述符,得到对应的异常或中断处理程序所在段的 DPL、基地址等信息。Linux下中断门和陷阱门对应的即为内核代码段,所以DPL为0,基地址为0。
  • 处理器进行特权级检查
    若CPL<DPL或编程异常 IDTi 的 DPL<CPL,则发生13号异常。Linux下,前者不会发生。后者用于防止恶意程序模拟 INT n 陷入内核进行破坏性操作。
    若CPL≠DPL,则从用户态换至内核态,以使用内核栈。切换栈的步骤:
    • 读 TR 寄存器,以访问正在运行的用户进程的 TSS段;
    • 将 TSS段中保存的内核栈的段选择符和栈指针分别装入寄存器 SS 和 ESP,
    • 然后在内核栈中保存原来用户栈的 SS 和 ESP。
  • 执行中断处理程序。
    若是故障,则将发生故障的指令的逻辑地址写入 CS 和 EIP,以使处理后回到故障指令执行。其他情况下,CS 和 EIP 不变,使处理后回到下条指令执行。
    在当前栈中保存 EFLAGS、CS 和 EIP 寄存器的内容(断点和程序状态)
    异常产生了一个硬件出错码,则将其保存在内核栈中。
    将IDTi中的段选择符装入CS(CS中为异常处理程序或中断服务程序的基地址),IDTi中的偏移地址装入EIP,它们是异常处理程序或中断服务程序第一条指令的逻辑地址(Linux中段基址=0)
    下个时钟周期开始,从CS:EIP所指处开始执行异常或中断处理程序!

在这里插入图片描述

IA-32中异常和中断的返回过程

中断或异常处理程序最后一条指令是IRET。CPU在执行IRET指令过中完成以下工作

  1. 从栈中弹出硬件出错码(保存过的话)、EIP、CS和EFLAGS
  2. 检查当前异常或中断处理程序的CPL是否等于CS中最低两位,若则说明异常或中断响应前、后都处于同一个特权级,此时,IRET指令完成操作;否则,再继续完成下一步工作。
  3. 从内核栈中弹出SS和ESP,以恢复到异常或中断响应前的特权级程所使用的栈。
  4. 检查DS、ES、FS和GS段寄存器的内容,若其中有某个寄存器的选择符指向一个段描述符且其DPL小于CPL,则将该段寄存器清0。是为了防止恶意应用程序(CPL=3)利用内核以前使用过的段寄存(DPL=0)来访问内核地址空间。
    执行完IRET指令后,CPU回到原来发生异常或中断的进程继续
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值