中断子系统(1)--- 异常中断

一、异常

计算机通常按照软件的执行流进行顺序执行和跳转,但有时会需要中断正常的执行流程去处理其他任务,可以触发这一过程的事件统称为异常。

1、异常分类

从来源来看,异常可分为以下 6 种。

1 )外部事件:来自 CPU 核外部的事件,来自处理器内部其他模块或者处理器外部的真实物理连线也称为中断。中断的存在使得CPU能够异步地处理多个事件。在操作系统中,为了避免轮询等待浪费CPU时间,与IO相关的任务通常都会用中断方式进行处理。中断事件的发生往往是软件不可控制的,因此需要一套健全的软硬件机制来防止中断对正常执行流带来影响。

2 )指令执行中的错误:执行中的指令的操作码或操作数不符合要求,例如不存在的指令、除法除以0 、地址不对齐、用户态下调用核心态专有指令或非法地址空间访问等。这些错误使得当前指令无法继续执行,应当转到出错处进行处理。

3 )数据完整性问题:当使用ECC等硬件校验方式的存储器发生校验错误时,会产生异常。可纠正的错误可用于统计硬件的风险,不可纠正的错误则应视出错位置进行相应处理。

4 )地址转换异常:在存储管理单元需要对一个内存页进行地址转换,而硬件转换表中没有有效的转换对应项可用时,会产生地址转换异常。

5 )系统调用和陷入:由专有指令产生,其目的是产生操作系统可识别的异常,用于在保护模式下调用核心态的相关操作。

6 )需要软件修正的运算:常见的是浮点指令导致的异常,某些操作和操作数的组合硬件由于实现过于复杂而不愿意处理,寻求软件的帮助。

2、异常处理

异常处理的流程包括异常处理准备、确定异常来源、保存执行状态、处理异常、恢复执行状态并返回等。主要内容是确定并处理异常,同时正确维护上下文环境。异常处理是一个软硬件协同的过程,通常 CPU 硬件需要维护一系列控制状态寄存器(域)以用于软硬件之间的交互。寄存器包括下列:

CRMD 保存当前处理器核特权等级、全局中断使能、监视点使能和地址翻译模式

PRMD 例外前模式信息,当出发例外时,硬件将此时处理器核的特权等级、全局中断使能、监视点使能保存到此寄存器中,用于例外返回时恢复处理器核现场

ECFG 此寄存器用于控制例外和中断入口计算方式以及中断的局部使能位

ESTAT 此寄存器记录例外状态,包括触发例外的一二级编码以及中断状态

EENTYR 该寄存器用于配置普通例外和中断的入口地址

ERA 记录了普通例外处理完毕后的返回地址

BADI 记录出错指令

BADV 记录出错的虚拟地址

下面对异常处理流程的五个阶段进行介绍:

1> 异常处理准备,当异常发生时, CPU 在转而执行异常处理前,硬件需要进行一系列准备工作。

a、记录被异常打断的指令的地址(记为EPTR),(这里涉及精确异常的概念,指发生任何异常时,被异常打断的指令之前的所有指令都执行完,而该指令之后的所有指令都像没执行一样。在实现精确异常的处理器中,异常处理程序可忽略因处理器流水线带来的异常发生位置问题。异常处理结束后将返回EPTR所在地址,重新执行被异常打断的指令)。    <硬件处理设置ERA寄存器>

b、调整CPU的权限等级(通常调整至最高特权等级)并关闭中断响应。在指令系统中,当异常发生时,硬件会将CSR.PLV置0以进入最高特权等级,并将CSR.CRMD的IE域置0以屏蔽所有中断输入。    <硬件处理设置CRMD寄存器>

c、硬件保存异常发生现场的部分信息。在  指令系统中,异常发生时会将 CSR.CRMD中的 PLV 和 IE 域的旧值分别记录到 CSR.PRMD 的 PPLV 和 PIE 域中,供后续异常返回时使用。    <硬件处理设置PRMD寄存器>

d、记录异常的相关信息。异常处理程序将利用这些信息完成或加速异常的处理。最常见的如记录异常编号以用于确定异常来源。在  指令系统中,这一信息将被记录在 CSR.ESTAT的 Ecode 和 EsubCode 域,前者存放异常的一级编号,后者存放异常的二级编号。除此以外,有些情况下还会将引发异常的指令的机器码记录在 CSR.BADI 中,或是将造成异常的访存虚地址记录在CSR.BADV 中。  <硬件处理设置ESTAT、BADI、BADV寄存器>

2> 确定异常来源,将不同的异常进行编号,其异常处理程序入口地址采用 “入口页号与页内偏移进行按位逻辑或”的计算方式,入口页号通过CSR.EENTRY配置,每个普通异常处理程序入口页内偏移是其异常编号乘以一个可配置间隔(通过CSR.ECFG 的 VS 域配置)。通过合理配置EENTRY和ECFG控制状态寄存器中相关的域,可以使得不同异常处理程序入口地址不同。

3> 保存执行状态。在操作系统进行异常处理前,软件要先保存被打断的程序状态,通常至少需要将通用寄存器和程序状态字寄存器的值保存到栈中。

4> 处理异常。跳转到对应异常处理程序进行异常处理。

5> 恢复执行状态并返回。在异常处理返回前,软件需要先将前面第3个步骤中保存的执行状态从栈中恢复出来,在最后执行异常返回指令。(之所以要采用专用的异常返回指令,是因为该指令需要原子地完成恢复权限等级、恢复中断使能状态、跳转至异常返回目标等多个操作)。在中,异常返回的指令是ERTN ,该指令会将CSR.PRMD的PPLV和PIE域分别回填至CSR.CRMD的PLV和IE域,从而使得CPU的权限等级和全局中断响应状态恢复到异常发生时的状态,同时该指令还会将CSR.ERA中的值作为目标地址跳转过去。 X86的IRET指令有类似效果。


3、异常嵌套的处理

在异常处理的过程中,又有新的异常产生,这时就会出现异常嵌套的问题。当产生异常嵌套时,需要保存被打断的异常处理程序的状态,这会消耗一定的栈资源,因此无限的异常嵌套是无法容忍的。异常嵌套通常基于优先级,只有优先级更高的异常才能进行嵌套,低优先级或同优先级的异常只能等待当前异常处理完成,系统支持的优先级级数就是异常嵌套的最大层数。

在指令系统中,异常嵌套时被打断的异常处理程序的状态的保存和恢复主要交由软件处理,这就需要保证异常处理程序在完成当前上下文的保存操作之前,不会产生新的异常,或者产生的新异常不会修改当前需要保存的上下文。这两方面要求仅通过异常处理程序开发人员的精心设计是无法完全保证的,因为总有一些异常的产生原因是事先无法预知的,如中断、机器错、TLB 重填等。为此需要设计硬件机制以保证这些情况发生时不至于产生嵌套异常,或即使产生嵌套异常也能保证软件可以获得所要保存上下文的正确内容。

例如,可以在跳转到异常入口的过程中关闭全局中断使能以禁止中断异常发生,还可以在发生嵌套异常的时候将可能被破坏而软件又来不及保存的上下文信息由硬件暂存到指定的控制状态寄存器或内存区域。

二、中断

异常处理的流程是通用的,但有两类异常出现的机会确实比其他类型大很多。一类是地址转换异常,当片内从虚地址到物理地址的地址转换表不包含访问地址时,就会产生缺页异常,另一类常见的异常就是中断,中断在外部事件想要获得 CPU 注意时产生。由于外部事件的不可控性,中断处理所用的时间较为关键。在嵌入式系统中, CPU 的主要作用之一就是处理外设相关事务,因此中断发生的数量很多且非常重要。

1、中断级联

中断从系统中各个中断源传递到处理器主要有两种形式:中断线和消息中断。用中断线传递是最简便直接的方式。当系统的中断源不多时,直接连到处理器引脚即可。若中断源较多,可使用中断控制器汇总后再与处理器引脚相连。由于连线会占用引脚资源,一般只在片上系统 (System On Chip, 简称 SoC) 中才会给每个外设连接单独的中断线,板级的中断线一般采用共享的方式。比如 PCI 上有四根中断线,供所有的设备共享。中断处理程序在定位到哪根中断线发生中断后,逐个调用注册在该中断线的设备中断服务。

指令系统支持中断线的中断传递机制,共定义了 13 个中断,分别是:

1 个核间中断( IPI ), 1 个定时器中断( TI ), 1 个性能监测计数溢出中断( PMI ), 8 个外部硬中断( HWI0~HWI7 ), 2 个软中断( SWI0~SWI1 )。
其中所有中断线上的中断信号都采用电平中断,且都是高电平有效。当有中断发生时,这种高电平有效中断方式输入给处理器的中断线上将维持高电平状态直至中断被处理器响应处理。无论中断源来自处理器核外部还是内部,是硬件还是软件置位,这些中断信号都被不间断地采样并记录到 CSR.ESTAT 中 IS 域的对应比特位上。

这些中断均为可屏蔽中断,除了 CSR.CRMD中的全局中断使能位 IE 外,每个中断各自还有其局部中断使能控制位,在 CSR.ECFG 的 LIE 域中。当CSR.ESTAT 中 IS 域的某位为 1 且对应的局部中断使能和全局中断使能均有效时,处理器就将响应该中断,并进入中断处理程序入口处开始执行。

用中断线方式传递中断有一些限制。首先是扩展性不够强,在搭建较复杂的板级系统时会引入过多的共享,降低中断处理的效率。其次,中断处理过程需要通过查询中断控制器以及设备上的状态寄存器来确认中断和中断原因,中间有较长的延迟,同样不利于提高效率。在多处理器平台中,高性能外设(如万兆网卡)对中断处理的性能有更高的要求,需要实现多处理器的负载均衡、中断绑定等功能,传统的中断线方式难以做到。而这正好是消息中断的长处。

消息中断以数据的方式在总线上传递。发中断就是向指定的地址写一个指定的数。相比总线外增加专门的中断线的 “ 带外 ” ( Side‐Band) 传输形式,消息中断在 “ 带内 ”(In‐Band )传输。增加中断时不需要改动消息传递的数据通路,因而有较高的扩展性和灵活性,也为更高程度的优化提供了可能。比如一个设备可以申请更多的中断号,使中断处理程序无须查询设备状态,只根据中断号就能知道应当做什么处理。

2、中断向量化

指令系统默认支持向量化中断 4 ,其 13 个线中断各自具有独立的中断处理程序入口地址。在指令系统中,中断被视作一类特殊的异常进行处理,因此在具体计算中断处理程序入口地址时将 SWI0 ~ IPI 这 13 个中断依次 “ 视作 ” 异常编号 64 ~ 76 的异常,用异常处理程序入口地址的统一计算方式进行计算。向量化中断的好处之一是省去了中断处理程序开头处识别具体中断源的开销,可以进一步加速中断的处理。

X86 指令系统支持的向量化中断方案更复杂一些,其在地址空间的指定位置处存放中断向量表( IVT ,实模式下默认为 0 地址)或中断描述符表( IDT ,保护模式),中断向量表中存放中断入口地址的段地址和偏移量,中断描述符表还包含权限等级和描述符类别的信息。 X86 的向量化中断机制最多可支持 256 个中断和异常, 0~19 号为系统预设的异常和 NMI , 20~31 是 Intel 保留的编号, 32号开始可用于外部中断,详细的实现可参考 Intel 相关手册。

3、中断优先级

在支持多个中断源输入的指令系统中,需要规范在多个中断同时触发的情况下,处理器是否区别不同来源的中断的优先级。当采用非向量中断模式的时候,处理器通常不区别中断优先级,此时若需要对中断进行优先级处理,可以通过软件方式予以实现,其通常的实现方案是:

1 )软件随时维护一个中断优先级( IPL ),每个中断源都被赋予特定的优先级。

2 )正常状态下, CPU 运行在最低优先级,此时任何中断都可触发。

3 )当处于最高中断优先级时,任何中断都被禁止。

4 )更高优先级的中断发生时,可以抢占低优先级的中断处理过程。

当采用向量中断模式的时候,处理器通常不可避免地需要依照一套既定的优先级规则来从多个已生效的中断源中选择一个,跳转到其对应的处理程序入口处。 指令系统实现的是向量中断,采用固定优先级仲裁机制,具体规则是硬件中断号越大优先级越高,即 IPI 的优先级最高,TI 次之, ⋯ , SWI0 的优先级最低。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值