玄铁C910异常与中断处理
异常
异常机制
异常(Exception)机制,即处理器核在顺序执行程序指令流的过程中突然遇到了异常的事情而中止执行当前的程序,转而去处理该异常,异常处理(包括指令异常和外部中断) 是处理器的一项重要功能,在某些异常事件产生时,用来使处理器转入对这些事件的处理。这些事件包括硬件错误、指令执行错误、用户程序请求服务等。
-
处理器遇到的“异常的事情”称为异常(Exception)。异常与中断的最大区别在于中断往往是一种外因,而异常是由处理器内部事件或程序执行中的事件引起的,譬如本身硬件故障、程序故障,或者执行特殊的系统服务指令而引起的,简而言之是一种内因。
-
与中断服务程序类似,处理器也会进入异常服务处理程序。
-
与中断类似,可能存在多个异常同时发生的情形,因此异常也有优先级,并且也可能发生多重异常的嵌套。
中断标记 | 异常向量号 | 描述 |
---|---|---|
0 | 0 | 未实现 |
0 | 1 | 取指令访问错误异常 |
0 | 2 | 非法指令异常 |
0 | 3 | 调试断点异常 |
0 | 4 | 加载指令非对齐访问异常 |
0 | 5 | 加载指令访问错误异常 |
0 | 6 | 存储/原子指令非对齐访问异常 |
0 | 7 | 存储/原子指令访问错误异常 |
0 | 8 | 用户模式环境调用异常 |
0 | 9 | 超级用户模式环境调用异常 |
0 | 10 | 保留 |
0 | 11 | 机器模式环境调用异常 |
0 | 12 | 取值页面错误异常 |
0 | 13 | 加载指令页面错误异常 |
0 | 14 | 保留 |
0 | 15 | 存储/原子指令页面错误异常 |
0 | >=16 | 保留 |
C910 异常处理步骤
以机器模式响应异常为例,其步骤如下:
异常相应
- 处理器保存PC 到mepc 中。
- 根据发生的异常类型设置 mcause,并更新 mtval 为出错的取指地址、存储/加载地址或者指令码。
- 将 mstatus 的中断使能位 MIE 保存到 MPIE 中,将 MIE 清零,禁止响应中断。
- 将发生异常之前的权限模式保存到 mstatus 的 MPP 中,切换到机器模式。
- 根据 mtvec 中的基址和模式,得到异常服务程序入口地址。处理器从异常服务程序的第一条指令处开始执
行,进行异常的处理。
异常返回
执行mret 指令可以实现异常返回。此时,处理器执行下列操作:
- 将 mepc 恢复到 PC。(mepc 保存的是发生异常的PC。通过调整 mepc,可以跳过发生异常的指令;如果不调整,
则重新执行发生异常的指令) - 将 mstatus.MPIE 恢复到 mstatus.MIE。
- 从 mstatus.MPP 恢复发生异常之前的权限模式。
中断
C910 中断处理步骤
以在机器模式响应中断为例,具体步骤为:
中断响应
- 第一步:处理器执行完当前指令,保存下一条指令的 PC 到 mepc 中。
- 第二步:设置mcause 的中断标记为1,将中断编号写入 mcause,并更新 mtval 为0。
- 第三步:将mstatus 的中断使能位MIE 保存到MPIE 中,将 MIE 清零,禁止响应中断。
- 第四步:将发生中断之前的权限模式保存到mstatus 的 MPP 中,切换到机器模式。
- 第五步(mtvec.Mode=0,直通中断):PC 从mtvec.Base 处取指令并执行。通常,取回的指令是一条跳转指令,
跳转至顶层处理函数。该函数通过分析mcause 获取中断编号,并调用该编号对应的处理函数。 - 第五步(mtvec.Mode=1,矢量中断):PC 从mtvec.Base + 4 * 中断编号处取指令并执行。通常,取回的指令是
一条跳转指令,跳转至相应中断的处理函数。
中断返回
执行mret 指令可以实现中断返回。此时,处理器执行下列操作:
- 将mepc 恢复到PC。(mepc 保存的是下一条指令的PC,所以无需调整)
- 将mstatus.MPIE 恢复到mstatus.MIE。
- 从mstatus.MPP 恢复发生中断之前的权限模式。
局部中断控制器(CLINT)
C910MP 实现了处理器核局部中断控制器(以下简称CLINT),是一个内存地址映射的模块,用于处理软件中断和
计时器中断。
软件中断
软件中断通过配置地址映射的软件中断配置寄存器进行控制。其中机器模式软件中断由机器模式软件中断配置寄存
器(MSIP)控制,超级用户模式软件中断由超级用户模式软件中断配置寄存器(SSIP)控制。
用户可通过将SIP 位置1 的方式,产生软件中断;可通过将SIP 位清 0 的方式,清除软件中断。其中CLINT 超
级用户模式软件中断请求,仅在对应核使能CLINTEE 位时有效。
机器模式下拥有修改访问所有软件中断相关寄存器的权限;超级用户模式下仅具有访问修改超级用户模式软件中断
配置寄存器(SSIP)的权限;普通用户模式没有权限。
计时器中断
在多核系统中仅存在一个 64 位系统计时器 MTIME,要求在always-on 电压域进行工作。系统计时器不可写,仅能通过reset 清0。系统计时器的当前值可通过读取 PMU 的 TIME 寄存器获取。
机器模式下拥有修改访问所有计时器中断相关寄存器的权限;超级用户模式下仅具有访问修改超级用户模式时钟计
时器比较值寄存器(STIMECMPL, STIMECMPH)的权限;普通用户模式没有权限。
全局中断控制器(PLIC)
上图1为 PLIC 的逻辑示意图,并非真正的硬件结构图。
如上图1所示,PLIC 理论上可以支持任意多个(具体硬件实现可以选择其支持的上限)中断源(Interrupt Source)。每个中断源可以是不同的触发类型,譬如电平触发(Level-triggered)或者边沿触发(Edge-triggered)等。
PLIC 为每个中断源分配了如下功能组件和参数。
- 闸口(Gateway)和IP
- 编号(ID)
- 优先级(Priority)
- 使能(Enable)
PLIC 中断源之闸口(Gateway)和 IP
如图1所示,PLIC 为每个中断源分配了一个闸口(Gateway),每个闸口都有对应的中断等待寄存器,其功能如下:
-
闸口将不同触发类型的外部中断转换成统一的内部中断请求。
-
对于同一个中断源而言,闸口保证一次只发送一个中断请求(Interrupt Requst)。如图1所示,中断请求经过闸口发送后,硬件将会自动将对应的IP寄存器置高。
-
闸口发送一个中断请求后则启动屏蔽,如果此中断没有被处理完成,则后续的中断将会被闸口屏蔽住。。
PLIC中断源之编号(ID)
PLIC为每个中断源分配了一个独一无二的编号(ID)。ID 编号0被预留,作为表示“不存在的中断”,因此有效的中断ID从1开始,C910 处理器支持最多1023个中断源采样。
中断标记 | 中断向量号 | 描述 |
---|---|---|
1 | 0 | 未实现 |
1 | 1 | 超级用户模式软件中断 |
1 | 2 | 保留 |
1 | 3 | 机器模式软件中断 |
1 | 4 | 未实现 |
1 | 5 | 超级用户模式计时器中断 |
1 | 6 | 保留 |
1 | 7 | 机器模式计时器中断 |
1 | 8 | 未实现 |
1 | 9 | 超级用户模式外部中断 |
1 | 10 | 保留 |
1 | 11 | 机器模式外部中断 |
1 | 16 | L1 数据缓存ECC 中断(如配置ECC) |
1 | 17 | 性能检测溢出中断(如配置性能检测单元) |
1 | 其他 | 保留 |
PLIC 中断源之优先级(Priority)
如图1所示,PLIC 的每个中断源均可以设置特定的优先级。
-
每个中断源的优先级寄存器应该是存储器地址映射的可读可写寄存器,从而使得软件可以对其编程配置不同的优先级。
-
PLIC 架构理论上可以支持任意多个优先级,硬件实现时可以选择具体的优先级个数。玄铁C910 支持 32 个级别的中断优先级。
-
优先级的数字越大, 则表示优先级越高。
-
优先级0意味着“不可能中断”,相当于将此中断源屏蔽。
当同时发生多个中断请求时,优先级按照下列顺序决定(从高到低):
- L1 ECC中断
- M态外部中断
- M态软件中断
- M态计时器中断
- S态外部中断
- S态软件中断
- S态计时器中断
- PMU溢出中断
- L1 ECC中断(被降级1)
- S态外部中断(被降级)
- S态软件中断(被降级)
- S态计时器中断(被降级)
- PMU溢出中断(被降级)
PLIC中断源之中断使能(Enable )
如图1所示,PLIC为每个中断目标的每个中断源均分配了一个中断使能寄存器。
IE寄存器是存储器地址映射的可读可写寄存器,从而使得软件可以对其编程。
- 如果IE寄存器被编程配置为0,则意味着此中断源对应此中断目标被屏蔽。
- 如果IE寄存器被编程配置为1,则意味着此中断源对应此中断目标被打开。
PLIC 中断完整流程
-
如果闸口没有被屏蔽,则中断源经过闸口发起中断请求(Interrupt Request)。 闸口发送一个中断请求后:硬件自动将其对应的IP寄存器置高; PLIC 硬件将对应中断源的闸口启动屏蔽,后续的中断将会被闸口屏蔽住。
-
如果经过PLIC 硬件仲裁后选中了该中断源,且其优先级高于中断目标的阈值, PLIC则向中断目标发起中断通知(Interrupt Noification)。
-
中断目标收到中断通知后,如果决定响应此中断,则使用软件向PLIC发起中断响应的读操作。作为响应反馈,PLIC 返回该中断源的中断ID。同时,硬件自动将其对应的IP寄存器清零。
-
中断目标收到中断ID之后,可以通过此ID得知其需要响应的具体外部中断源。然后进入该外部中断源对应的具体中断服务程序(Interrupt Service Routine)中进行处理。
-
待彻底完成了中断处理之后,中断目标使用软件向PLIC发起“中断完成”的写操作,写入要完成的中断ID。同时,PLIC硬件将对应中断源的闸口解除屏蔽,允许其能够发起下一次新的中断请求。
🎁
🍟
🚄
中断降级指的是:将超级用户模式或用户模式下的相应中断委托给超级用户模式中断处理程序执行,避免了切换处理器工作模式带来的性能损失。 ↩︎