p7-知识点整理


mips 微系统

CP0协处理器

CPU 控制寄存器

寄存器助记符 寄存器编号 描述
SR 12 State Register
Cause 13 记录异常中断的原因
EPC 14 Exception program counter发生异常和中断后从哪里重新开始执行

SR

image-20231206164953902

这里我们实际使用到的或者说有意义的只有

IM——SR[15:10]

其实这里应该指的是SR[15:8]的这8位,其中IP1-0也就是SR[9:8]是由CPU内部产生的

  • 中断屏蔽:一个8位的域定义哪些允许中断源活动时产生异常。其中6个中断源由CPU核外部的信号产生。其余两个是Cause寄存器中软件可写的中断位

EXL——SR[1]

  • 异常级:任何异常发生时置位,这会强行进入核心态并禁止中断:目的是吧EXL位维持足够长的时间以便软件决定新的CPU特权级和中断屏蔽该设成什么

IE——SR[0]

  • 全局的中断使能位:注意不管这位是什么值,EXL和ERL总是禁止所有的中断

Cause

image-20231206170514085

BD——Cause[31]

  • 分支延迟:EPC保存的是异常处理完之后的返回地址,正常情况下,这也指向异常受害指令。

  • 但是如果发生异常的指令是在一条转移指令的延时槽里,EPC得指向那条转移指令:重新执行转移指令没有- 什么害处,但是如果返回到延迟槽指令本身,转移就不会发生,从而这个异常将破坏被中断的程序。

  • 只要异常发生在延迟槽的指令,Cause(BD)就会置为,EPC就会指向分支指令。如果想要分析异常受害指令,只要看看Cause(BD)(如果Cause(BD)==1,那么该指令位于EPC+4)就知道了。

IP——Cause[15:10]

这里其实也是IM一个道理

待决的中断:这里表示待发生的中断。IP照抄CPU硬件的输入信号,IP1-0(软件中断位)可读可写包含你最近写入的值。

  • 当相应的SR(IM)位(还要受到其它禁止中断的条件约束)允许时,这八位中的任意以为活动都会导致一个中断

BD——Cause[6:2]

这是一个5位的编码,告诉你发生了哪种异常。

ExcCode 助记符 指令与指令类型 描述
0 Int 所有指令 中断
4 AdEL 所有指令
load型指令(或特指其中某型)
(取数,取指或者存数时)地址错误:
PC地址未字对齐
PC地址超过0x3000-0x6ffc

(取数,取指或者存数时)地址错误:
lw:取数地址未与4字节对齐
lh:取数地址未与2字节对齐
lh,lb:取Timer
5 AdES store型指令 (取数,取指或者存数时)地址错误:
sw:存数地址未4字节对齐
sh:存数地址未2字节对齐
sh,sb:存Timer寄存器的值
store型指令:
计算地址加法溢出
向计时器的Count寄存器存值
存数地址超过DM,Timer0,Timer1,中断发生器的范围
8 Syscall syscall 系统调用,执行了一条syscall指令
10 RI 出现未知的指令码
12 Ov add,addi,sub 算数溢出

EPC

异常返回地址寄存器。这是一个博爱村异常返回点的寄存器。导致(或者遭受)异常的指令地址存入EPC,除非Cause寄存器中的BD位置位了,这种情况下EPC指向前一条(分支)指令

CPU控制指令

指令 格式 描述
mtc0 s,<n> 把数据传送到CP0
把CPU通用寄存器s中的内容传送到CP0的寄存器n
数据为32位
mfc0 d,<n> 从协处理器中取出数据
通用寄存器d中装入CPU控制寄存器n的值
这是查看控制寄存器的值的唯一方式

关于mfc0

想要更新控制寄存器中的单个域——比如说——状态寄存器SR

mfc0 t0, SR
and  t0, <要清零的为的反码>
or   t0, <要置1的位>
mtc0 SR, t0

这里有一个比较抽象的话后续再来理解一下

即返回到用户态和改变特权级的操作必须是同步的,不可分的(原文只讲了不可分的,我的理解就是同步的进行操作)

用软件触发的异常——异常调用——作为用户代码请求(运行在高特权级上的)操作系统内核服务的唯一机制。

什么时候需要用到哪些寄存器

这里是针对CP0中的控制寄存器而言的

上电后:

设置SR来使CPU进入一个可工作的状态

处理任意异常:

  • 早期:调用一个固定入口地址的公共的“通用异常处理程序”

  • 自那以后:对不同目的使用分开的异常处理程序

在异常入口处:不保存任何程序寄存器,只有返回地址被存在EPC中。

从异常返回:

  1. 控制最终必须返回到异常入口处保存到EPC中的地址。
  2. 不管是什么异常,返回时都需要报SR寄存器调整回原来的值,恢复用户态特权、允许中断以及消除异常的一般影响
  3. 异常返回指令eret合并完成了返回用户空间和复位SR(EXL)的功能

中断:

SR用来调整中断掩码(掩码就是一串二进制码,掩码的作用是用来存储和操作“状态”)

纯粹为了引发异常的指令:

比如breaksyscall

异常、中断及初始化

  • 外部事件:在CPU核之外的时间——即来自于真实的“连线”上的输入信号,这就是中断。
  • 存储器地址转换异常
  • 程序或硬件检测到的错误:这些包括不存在的指令、在用户权限下非法的指令、在相应SR位被禁止是执行的协处理器指令、整数溢出、地址对齐出错、用户态中访问kuseg以外的地址
  • 系统调用和自陷

精确异常

也就是我们的宏观pc的来由,如果某个pc是异常受害指令,那么我们希望在这个指令之前的指令已经全部处理完成,在这个指令之后的还没有开始处理。

全部内容如下:

  • 明确的罪证:在任何异常之后,CPU的控制寄存器EPC都指向一个正确的地方,异常处理之后从该处开始重新执行。在大多数情形中,EPC指向异常受害指令,但是如果异常受害指令处于分支延迟槽内,则EPC指向前面的分支指令:返回到分支指令去重新执行受害指令,但是返回到受害指令将导致分支被忽略。
    • 当受害指令处于分支延迟槽内时,原因寄存器的Cause(BD)位置位
  • 异常出现在指令序列中:由于是流水线,而且在不同的流水级都有可能会出现问题,但是我们为了实现精确异常,不应该是出现异常就处理,也就是出现第二条指令的异常事件先发生时需要先处理第一条指令
    • 为了避免这一个问题,早期发现的异常并不立即采取措施:该事件只是被记录并沿着流水线传递。在大多数CPU设计中,指定一个特定的流水线阶段作为检测异常的地方。如果当我们的异常记录正沿着流水线向下传递,更老的指令的后期检测到的事件到达了这个终点线,此时异常记录就直接丢弃。
  • 后续指令无效:因为流水线的原因,处于EPC中的受害指令之后的指令就已经开始了。

非精确异常

这里实际上指的是历史上的MPIS CPU的乘法器,也就是我们P6的内容,采取直接发送一个busy信号的处理方法,这里我们不在进行讨论

异常发生的时机

因为异常是精确的,那么异常发生的时间应当也是没有歧义的:

  • 异常之前执行的最后一条指令就是异常受害指令的前一条。
  • 如果该异常不是中断:受害指令即是引发异常的指令

下面是MIPS CPU决定处理一个异常是所要做的

  1. 设置EPC指向重新开始的地址
  2. 设置SR(EXL)位,强制CPU进入内核态(高特权态)并且禁止中断
  3. 设置Cause寄存器这样软件可以看到发生异常的原因。在地址异常时,BadVAddr也要设置但是我们课程好像没有这个要求
  4. 然后CPU开始从异常入口点取值,此后一切交给软件处理。其实也就是继续进行handler处理程序的执行部分

文章作者: hugo
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hugo !
  目录