RISC-V特权架构 - 时钟中断处理

本文属于《 RISC-V指令集基础系列教程》之一,欢迎查看其它文章。

RISC-V 架构定义了,CSR 寄存器机器模式中断等待寄存器mip(Machine Interrupt Pending Registers),可以用于查询中断的等待状态。

在这里插入图片描述

支持的中断类型,主要有以下几种:

  • 外部中断:MEIP/SEIP/UEIP
  • 时钟中断:MTIP/STIP/UTIP
  • 软件中断:MSIP/SSIP/USIP

RISC-V 架构中,在机器模式、监督模式和用户模式下,均有对应的时钟中断,分别为MTIP、STIP、UTIP。

对于初学者来讲,涉及到的mie,mstatus,midelege等寄存器,是如何使用的,可能理解的比较模糊,希望经过本节的介绍,能够拨开迷雾。
本文主要,以时钟中断为例,对中断的触发、查询、委托、处理,整个流程进行介绍。

1 MTI中断处理

MTI(Machine Timer Interrupt),即机器模式时钟中断
时钟中断,是由本地中断控制器(‌CLINT)‌管理的,‌属于本地中断的一种。‌

1.1 触发中断

MTI中断的触发,是依靠一个计时器,以及一对寄存器来完成的,即mtime和mtimecmp。

  • mtime 用于反映当前计时器的计数值
  • mtimecmp 用于设置计时器的比较值

当mtime 中的计数值,大于或者等于mtimecmp 中设置的比较值时,计时器便会产生时钟中断。产生中断后,需要固件/软件,重新写mtimecmp 寄存器的值,使其大于mtime 中的值,从而将计时器中断清除。

RISC-V 架构,并没有将这一对寄存器,定义为CSR寄存器。而是定义为存储器地址映射(Memory Address Mapped)的系统寄存器,具体的存储器映射(Memory Mapped)地址RISC-V 架构并没有规定,而是交由SoC系统集成者实现。

以上描述的是单核时的情形,若为多核,原理是相同的。CLINT的时钟中断,亦可以发送给每个核,如下图所示:

在这里插入图片描述

CLINT中,定义了与核数相同的mtimecmp寄存器,如下图所示:

在这里插入图片描述

一个mtimecmp 对应一个核,计数值使用同一个mtime寄存器,mtime与所有mtimecmp比较,可以分别对每个核,触发时钟中断。
时钟中断触发后,硬件会自动将mip.MTIP=1。

MTI中断触发、查询、处理,完整流程图,如下所示:

在这里插入图片描述

1.2 查询mie.MTIE与mip.MTIE

  • mie.MTIE == 1:表示使能MTI中断
  • mip.MTIE == 1:表示MTI中断处于等待响应状态

要让某中断被处理,则该中断对应的mie.XXIE和mip.XXIP必须为1,只有满足这个条件,才会进入处理逻辑。

此外,下面,还需要根据,当前运行的模式,来查询全局中断使能状态,以及委托。

1.3 若运行在M模式下

在这里插入图片描述

  • mstatus.mie == 0:表示禁用M模式下中断;故不处理任何中断,异常可以正常处理,不受影响。
  • mstatus.mie == 1:表示使能M模式下中断,故可以继续处理。

由于mideleg.MTIP始终为0,因此MTI中断,永远无法被委托给S模式。
即无论运行在何种模式下,M模式时钟中断(mip.MTIP),只能在M模式下处理。

所以,通常,会在MTIP的中断处理函数中,通过注入的方式将mip.STIP置1,以及midelege.STIP置1,以便下一次进入S模式时,以委托方式在S模式下处理mip.STIP中断。

不能忘记,每次时钟中断处理都要更新 mtimecmp 寄存器,否则时钟中断信号,就不会被清除。

1.4 若运行在S模式下

在这里插入图片描述

  • mstatus.sie == 0:表示禁用S模式下中断;由于mideleg.MTIP为0,无法委托至S,故陷入M处理中断。
  • mstatus.sie == 1:表示使能S模式下中断,由于mideleg.MTIP为0,无法委托至S,故陷入M处理中断。

若运行在M模式下,只有在全局中断使能位mstatus.mie置位时,才会处理中断。
如果在S模式下,触发了M模式的中断(MTIP),此时无视mstatus.mie直接响应,即:
运行在低权限模式下,高权限模式的全局中断使能位一直是enable状态。

1.5 若运行在U模式下

在这里插入图片描述

由于mideleg.MTIP为0,无法委托至S,故只能陷入M处理中断。

此处,就像是上面S模式介绍的一样,亦不关心mstatus.mie全局中断使能状态。

2 STI中断处理

STI(Supervisor Timer Interrupt),即监管模式时钟中断
时钟中断,是由本地中断控制器(‌CLINT)‌管理的,‌属于本地中断的一种。‌

2.1 触发中断

在早期的RISC-V规范中,仅有mtime和mtimecmp寄存器,因此时钟中断触发时,默认写入mip.MTIP=1,而非mip.STIP=1。
我们知道mip.MTIP,只能在M下处理,这就导致想要在S下处理时钟中断,变得比较麻烦。

所以,这里就有2个方法:

  • 软件注入mip.STIP

    通常,会在mip.MTIP的中断处理函数中,通过注入的方式将mip.STIP置1,以及midelege.STIP置1,以便下一次进入S模式时,以委托方式在S模式下处理mip.STIP中断。

  • 通过stimecmp,触发mip.STIP

    由于 mtimecmp 只能在 M 模式下访问,对于 S/HS 模式下的内核需要通过 SBI 才能访问,会造成较大的中断延迟和性能开销。为了解决这一问题,RISC-V 新增了 Sstc 拓展支持,S模式扩展为HS模式,新增了 stimecmp 。当 time>=stimecmp (HS)时会产生 timer 中断,不再需要通过 SBI 陷入其他模式。

STI中断触发、查询、处理,完整流程图,如下所示:

在这里插入图片描述

2.2 查询mie.STIE与mip.STIE

  • mie.STIE == 1:表示使能STI中断
  • mip.STIE == 1:表示STI中断处于等待响应状态

要让某中断被处理,则该中断对应的mie.XXIE和mip.XXIP必须为1,只有满足这个条件,才会进入处理逻辑。

此外,下面,还需要根据,当前运行的模式,来查询全局中断使能状态,以及委托。

2.3 若运行在M模式下

在这里插入图片描述

  • mstatus.mie == 0:表示禁用M模式下中断;故不处理任何中断,异常可以正常处理,不受影响。
  • mstatus.mie == 1:表示使能M模式下中断,故可以继续处理。
    • 如果mideleg.STIP == 0,表示不委托给S处理,故陷入M进行处理。
    • 如果mideleg.STIP == 1,表示委托给S处理,故不在M处理,下次进入S时,尝试在S下处理。

2.4 若运行在S模式下

在这里插入图片描述

  • mstatus.sie == 0:表示禁用S模式下中断。
    • 如果mideleg.STIP == 0,表示不委托给S处理,故陷入M进行处理。
    • 如果mideleg.STIP == 1,表示委托给S处理,但是这里,由于S模式全局中断被禁用,因此即便委托,也不会处理任何中断。
  • mstatus.sie == 1:表示使能S模式下中断。
    • 如果mideleg.STIP == 0,表示不委托给S处理,故陷入M进行处理。
    • 如果mideleg.STIP == 1,表示委托给S处理,这里S模式全局中断使能,因此,可以陷入S处理中断。

2.5 若运行在U模式下

在这里插入图片描述

  • 如果mideleg.STIP == 0,表示不委托给S处理,故陷入M进行处理。
  • 如果mideleg.STIP == 1,表示委托给S处理,这里,由于运行在低优先级U下,要切换到高优先级S处理中断,因此不关心mstatus.sie全局中断开关状态,默认为enable。所以,这里可以陷入S处理中断。

3 知识总结

3.1 中断处理逻辑

经过对MTI和STI中断的处理分析,发现两者的查询处理逻辑,其实是一样的。

对于RISC-V支持的,主要中断类型:

  • 外部中断:MEIP/SEIP/UEIP
  • 时钟中断:MTIP/STIP/UTIP
  • 软件中断:MSIP/SSIP/USIP

其处理流程,总结为以下几个步骤(以XXI中断为例):

  • mie.XXIE == 1 && mip.XXIP == 1:检查确保XXI中断使能,且该中断被触发
  • 根据运行模式,检查全局中断开关
    • M模式: 检查mstatus.mie
      • mstatus.mie == 0:禁用M全局中断,不处理
      • mstatus.mie == 1:使能M全局中断,继续检查委托
        • mideleg.XXIP == 0:不委托,陷入M
        • mideleg.XXIP == 1:委托到S,陷入S
    • S模式: 检查mstatus.sie
      • mstatus.sie == 0:禁用S全局中断,继续检查委托
        • mideleg.XXIP == 0:不委托,陷入M
        • mideleg.XXIP == 1:委托到S,不处理
      • mstatus.sie == 1:使能S全局中断,继续检查委托
        • mideleg.XXIP == 0:不委托,陷入M
        • mideleg.XXIP == 1:委托到S,陷入S
    • U模式: 无需检查全局中断,只检查委托
      • mideleg.XXIP == 0:不委托,陷入M
      • mideleg.XXIP == 1:委托到S,陷入S

比如,换成机器模式外部中断MEI,也是一样的处理过程。

3.2 中断处理规则

  1. RISC-V架构所有模式的异常,在默认情况下,都跳转到M模式处理。
  2. 中断/异常委托的目的地,只能是S模式。也就是说,将mideleg中某中断置为1后,表示将该中断委托到S模式进行处理,且只能是S模式。
  3. 事实上,即使在mideleg中设置了,将S模式产生的时钟中断,委托给S模式,委托仍无法完成。因为,硬件产生的时钟中断,仍会发到M模式(mtime寄存器,是M模式的设备),所以,我们需要手动触发S模式下的时钟中断(注入mip.STIP)。
  4. 由于mideleg中MEIP、MTIP、MSIP这三类M模式中断,属于保留位域,默认值为0,也不可更改,因此对于这些中断均不能委托。
    在这里插入图片描述
    MEIP、MTIP、MSIP这3类中断,仅能在M模式下处理。
  5. 当运行在低权限模式下时,若需要陷入高权限模式处理中断,则高权限模式的全局中断使能位,默认一直是enable状态(即忽略mstatus.mie或sie的实际值)。
  6. 当处理中断时,mie、mip、mideleg三个寄存器中,判断的位域应该是相同的。比如:处理MTI中断时,应检查mie.MTIE && mip.MTIP && mideleg.MTIP,因mideleg.MTIP==0,故无法委托;而不能去检查mideleg.STIP,它是表示将STI中断,委托到S的位域。
    在这里插入图片描述 7. 在常见模拟器中,对于影子寄存器,通常只使用mie、mip、mstatus寄存器,而不使用uie/sie、uip/sip、sstatus。
  • uie、sie均为mie的子集,为影子寄存器,对应位域偏移与值,均相同;读取 uie/sie 的任何字段或写入其任何可写字段,都会导致 mie 中同名字段的读写。
  • uip、sip均为mip的子集,为影子寄存器,对应位域偏移与值,均相同;读写与上述特性相同。
  • sstatus为mstatus的子集,为影子寄存器,对应位域偏移与值,均相同;读写与上述特性相同。

更多关于中断处理的文档,可参考:

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百里杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值