CPU的自我控制之(4)-异常的SPSR

——————————————————————异常第一步(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屏蔽位,置位后对应中断不能发生。

 

终于完了,

虽然废话连篇,

但是从我读别人的东西的体验来看,凡是非常正式正规精确地语言描述的原理,我看起来都非常费劲,

并且这并不是在写手册或论文,所以我希望可以写的不那么无聊,

当然如果要形而上学到我写文档不行的话。。。咳咳,是的,我是写文档不行,我承认。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值