riscv中的异常简介

处理器在执行的过程中,除了分支类型的指令之外,很多其他的情况也可以打断程序的执行,这些情况统称为异常(exception);

不同的指令集体系中,异常包括的内容也不尽相同,可以概括地将异常分为下面几种。

  • 处理器的外部事件引起的异常,这种类型的异常其实更多时候被称做中断(interrupt)
    • 因为发生在处理器的外部,中断本质上和处理器中执行的指令没有必然的关系,处理器在执行的任何阶段都有可能接收到中断,因此也称做是异步的异常;
  • VA->PA转换的异常;
    • TLB miss;
    • page fault;
    • 访问了一个受保护的page;
  • 指令自身引起的错误,例如:
    • 未定义的指令、用户态下的非法指令、整数运算时的溢出、访问存储器的地址未对齐等。
    • 很多处理器还支持数据的完整性检查,例如处理器对L2Cache送来的数据进行奇偶校验或ECC校验,如果发现校验失败,也会产生异常;
  • 指令自身产生的异常;
    • 例如MIPS指令集中的SYSCALL和Trap两种指令,执行这些指令就会产生异常,其中:
      • SYSCALL 指令是无条件产生异常;
      • 而 Trap 指令则是有条件地产生异常
      • 普通的程序可以通过这种类型的指令来调用操作系统的某些任务,一个处理器要支持操作系统,这种类型的指令是必须有的。

异常处理流程

        对于一个特定的处理器来说,所有类型异常的处理过程是一样的,从处理器外部看起来,产生异常的指令之前的所有指令都已经完成了,而这条产生异常的指令及其之后的所有指令都不允许完成。

                        ​​​​​​​        ​​​​​​​        

  • 什么时候处理异常?
    • 遵循PO的顺序,需要再流水线最后一个阶段再对异常进行统一的处理;也就是,当ROB中,将要commit的指令,发现有excption时,才进行处理;
    • 发生异常的指令,及其以后的所有指令,都不能完成,因此,需要将异常之后的所有指令,都kill掉;
  • 处理器会跳转到对应的异常处理程序(exception handler)的入口地址,开始执行这个异常处理程序。
    • 保存PC值(或者下一条PC值,根据异常类型来决定),对于RISC处理器,放到EPC中来存储;
    • 将通用寄存器的值保存到堆栈(memory)中,因为异常处理过程,可能会修改这些寄存器的值;
      • 对于RISC处理器,访问memory只能用load/store指令;因此,存储通用寄存器的值,需要使用store指令;
      • 而堆栈的指针,则使用通用寄存器来模拟,MIPS中使用R29来作为堆栈指针;
      • 例如,将通用寄存器R20的内容,写到memory中:SW R20,0[R29], 实际上R29只是一个普通的寄存器,和其他寄存器没区别,只是一种约定俗称的做法,需要使用软件来管理堆栈指针的增减;
  • 当其执行完成后,会返回到刚才发生异常的地方,重新开始将这条指令取到流水线中,就好像这个异常没有发生过一样,这种方式也称做精确的异常(precise exception),因为总能够找到哪条指令发生了异常
  • 对于大部分类型的异常来说,从其对应的异常处理程序返回的时候,都需要重新执行这条产生异常的指令;有些类型的异常不能这样做,典型的例子就是 SYSCALL/Trap 指令产生的异常,如果重新执行,会死锁;
  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值