在ARM文档中,可以找到如下两句话:
When the processor moves from a higher to a lower Exception level, the Execution state can stay the same, or it can switch from AArch64 to AArch32.
When moving from a lower to a higher Exception level, the Execution state can stay the same or switch from AArch32 to AArch64
翻译之后就是:如果从高的异常级别切换到低的异常级别,执行状态可以保持不变,也可以从aarch64切换到aarch32;
例如从linux kernel切换到app,如果linux kernel是aarch64,那么app可以是aarch64或aarch32,如果linux kernel是aarch32,那么app只能是aarch32;如果从低的异常级别切换到高的异常级别,执行状态可以保持不变,也可以从aarch32切换到aarch64;
例如从app切换到linux kernel,如果app是aarch64,那么linux kernel可以是aarch64或aarch32,如果app是aarch32,那么linux kernel可以是aarch64或aarch32;
其实也可以这样总结:高的异常级别的执行状态,一定要大于等于低的异常级别的执行状态; 即EL1的执行状态要大于等于EL0的执行状态…
那么ARM为什么会有这种设计或约束呢?
我们以linux kernel和app(EL1 <—> EL0)为例来看:
如果linux kernel是aarch64的,那么在linux kernel启动和运行时修改的ARM系统寄存器(如SCTLR\TTBLRx等),都是以aarch64修改的,这些寄存器的修改当然也会map到aarch32上。
在系统切换app之后,linux kernel中修改的这些寄存器的属性对aarch32/aarch64依然都生效。 故如果EL1是aarch64,那么EL0可以是aarch64或aarch32;
如果linux kernel是aarch32的,那么在linux kernel启动和运行时修改的ARM系统寄存器(如SCTLR\TTBLRx等),都是以aarch32修改的,这些寄存器的修改不会map到aarch64上。
在系统切换app之后,linux kernel中修改的这些寄存器的属性仅对aarch32生效。 故如果EL1是aarch32,那么EL0只能是aarch32;