自我控制之(4)"/>
CPU的自我控制之(4)
——————————————————————异常第一步(xx纸尿裤) SPSR—————————————————————
好了,题外背景总算是磕磕绊绊的描述完了,终于可以说点本文主题相关的事儿。
当进入一次异常,首先是PSTATE,
进入异常将要用的PSTATE,即PE状态会被放在异常等级对应的SPSR_ELx(估计会被复制到PSTATE里),
x是EL等级,当然也就是会有多个SPSR_ELx寄存器,
准确的说是3个,可怜的EL0连个SPSR都混不上,不过。。。好像混上也没啥用,EL0就是傻傻的执行,没有异常,也不会处理。
很明显,估计没有人想让我在这里列出SPSR_ELx各个bit的定义,但是不说由不足以满足我的装逼属性,
那就拣两样(这个词是在仿照红楼梦语气,就是小丫鬟问主人吃啥点心的时候,"拣两样好吃的上吧~",~ 表示慵懒语气)
可能有人关心的说吧。
挑出算术计算相关的N Z C V等状态标志不说。
挑出aarch32相关的 Q IT J不说。
挑出PAN。。。等等,PAN得说了。。。
PAN全名叫Privileged Access Never,置1后,效用是EL0通过虚拟内存地址能访问的特权数据(原本是EL1/EL2特权数据),
都会在1阶段地址转换产生权限失败,或者说产生1阶段地址转换失败。
我很想简要的说明PAN的设计目的,可惜知识量并不足以使我简洁精确地指出,于是就照书念了。
UAO也得说,UAO全名叫User Access Override,
就是在EL1或EL2(HCR_EL2.{E2H=1,TGE=1})下执行unprivileged Load/Store 指令(LDTR/STTR...)时,
这些无特权的Load/Store指令能访问EL1/2特权等级下的内存空间了,
不然的话,它们是在EL0的吧;不过我并不是说进入异常后就会置位UAO,相反,它会被置0。
SS 是debuger相关的,不说。
IL比较牛逼,IL全名叫Illegal Execution state,
这个bit内容很丰富呀。。。好想跳过,可是这个位太特么没有跳过的理由了。。。
于是。。就一点一点说吧(为啥是一点一点说,因为,要说的东西分为两点!哈哈哈哈)。。。
首先要说的是,IL置1后,执行任何指令命令都会引起Illegal Execution state异常,
我认为这在本质上是一个保护,主要是硬件自动动作过程中置的位(也可以人工置位)。
其清除是自动的。
然后我们就可以说一下,它是如何被置位、清零的。
有两种情况IL位会被置位,一种是非法返回,一种是合法返回(这话。。简直了):
对于非法返回产生IL位置位的情况包含三种,
一种是执行了ERET指令,
另外两种是DEBUG相关的(跳过)。
ERET产生非法返回的情况有6中(。。我数了一下),
大概包含异常返回时,返到更高级异常去了;
返回某异常等级时,这个异常等级没开;
EL3下往EL2返;
还有32位64位间出的一些错。(相信不会有人要我把细节一条一条列出来的,毕竟大多数人英语还是比我好的)
对于合法返回产生IL位置位的情况,就是返回时复制到PSTATE的(恢复现场?)。
清零就比较简单了,一执行异常IL就被清零了。
nRW 指示当前执行状态aarch32或64
EL 指示当前异常等级,需要两个bit
SP。。。
SP有点熟呀,SP不是栈指针寄存器么,
这里搞了一个bit。。。
乍一看这个位我还是有点懵逼的,
直到看见了SP_EL0、SP_EL1、SP_EL2、SP_EL3。。。 于是我就可以很自然的说这是个栈指针寄存器选择位了,
需要注意的是,对于aarch32它是有不同的定义的,但是我并不十分关心,就不说了。
对于Aarch64,栈指针寄存器有四个,很明显EL0/1/2/3都能匀上一个,
但要是那么简单的话我肯定不会在这儿絮叨了,
毕竟,要看到SP位就1bit,而EL等级有四个的重特大问题,
SP肯定不是编码了四个寄存器的选择,
其实它只指示了使用SP_EL0还是SP_ELx,
可怜的小EL0终于感受到了一点优待。
那EL1/2/3三个栈指针是怎么选择的?
当然。。。是异常来选的(惊喜不惊喜~意外不意外~哈哈哈哈)。
当异常发生,
栈指针叮的一下,就选到了对应的异常等级的栈指针SP_ELx(x>0,从EL的那两bit中确定),
一般异常等级里执行程序时,都会再将SP位清零,也就是继续用SP_EL0,
可怜的小EL0的栈指针寄存器就这样被占用了。
于是为什么不直接用SP_ELx呢?
这么败家好像寄存器是免费的一样,
很明显ARM的大神儿们不会像我一样傻。。。
想象这样一种情况,
当ELx的异常发生了,
然后用上了栈指针寄存器SP_ELx,
然后就开始执行处理的指令流,
然后正在处理过程中,
又发生了一个同级的异常。。。
栈指针叮的一下,就选到了对应的异常等级的栈指针,
哎呦我去,这不就正用的这哥们儿呢么,懵逼了,当真此刻是:懵逼树上懵逼果,懵逼树下你和我。
新发生的这个异常就如同树叶一样轻轻飘过。。。
对,这就是为啥小EL0的SP栈指针寄存器单独用了一个标志位来表示。
其实有人可能会想,当SP_ELx正用着,还没转换过来的时候,来一下同级异常,叮一下。。。
(是不是想让我写点啥,哈哈哈哈,我正在懵逼树下修炼,练成再来告诉你)
我们继续走,让那个傻子在懵逼树下继续修炼去吧。
最后还有个A I F位,分别为SError、IRQ、FIQ屏蔽位,置位后对应中断不能发生。
终于完了,
虽然废话连篇,
但是从我读别人的东西的体验来看,凡是非常正式正规精确地语言描述的原理,我看起来都非常费劲,
并且这并不是在写手册或论文,所以我希望可以写的不那么无聊,
当然如果要形而上学到我写文档不行的话。。。咳咳,是的,我是写文档不行,我承认。
更多推荐
CPU的自我控制之(4)
发布评论