在AArch64狀態下,SP對應的物理寄存器有如下四個(某一時刻只能對應下面其中一個):
- SP_EL0和SP_EL1
- SP_EL2
- SP_EL3
如何使用呢?
1、如果程序運行在EL0,那么使用的是SP_EL0
2、如果程序運行在其他Exception level下,可以使用SP_EL0和當前Exception level所對應的SP_ELx
3、默認情況下,進入異常后,使用的是當前Exception level對應的SP_ELx。即:發生的進入EL1的異常,那么在跳轉到EL1的異常處理入口后,會自動切到SP_EL1,此時SP對應的就是SP_EL1. 當然,可以在異常通過操作PSTATE.SP將SP強制切到SP_EL0
4、即便不是在異常處理程序中,也可以通過操作PSTATE.SP將SP強制切到SP_EL0或者SP_ELx
5、比如程序正運行在EL1,此時使用的SP是SP_EL0,突然發生了一個進入EL1的異常,在跳轉到異常處理入口后,SP會自動切到SP_EL1,在異常返回后,SP又會自動切回到原先的SP_EL0
6、后綴t和h:
t 表示使用的是SP_EL0
h 表示使用的是SP_ELx

驗證
下面使用DS5仿真的實驗,驗證一下上面的說法。

系統復位后,默認是在EL3,並且是secure模式。
第73行,將SP切到SP_EL0,然后設置SP的值為0x77,此時的寄存器狀態如下:

第77行,將SP切到SP_EL3,然后將SP設置為0x88,此時的寄存器狀態如下:

第81行,將SP重新切回SP_EL0,此時的寄存器狀態如下:

第83行,訪問ICC_SRE_EL2會觸發sync異常,因為在secure模式下不存在EL2,觸發異常后,會進入EL3的“Current EL with SP0”分支,因為發生異常時使用的是SP_EL0,下面是進入異常處理程序后的寄存器信息:

可以看到,此時SPSel的值是1,Mode的值為EL3h,說明此時SP用的是SP_ELx。此時SPSR_EL3的值是0x3CC,SPSR的含義如下:

M[3:0]的值是0xC,含義如下,表示發生異常前系統的模式和狀態:AArch64、EL3、SP_EL0

下面是異常處理函數:
1 // 2 // Current EL with SP0 3 // 4 el3_vectors: 5 c0sync3: 6 mrs x0, elr_el3 7 add x0, x0, #4 8 msr elr_el3, x0 9 10 mov x0, #0x1 11 msr spsel, x0 12 eret
第6到8行的作用是異常返回時跳轉到觸發異常的指令的下一條指令執行,當第12執行完畢,ELR_EL3的值會設置給PC,SPSR_EL3的值會設置給PSTATE,所以SP會重新切回到SP_EL0:

第85行的作用是將SP切換到SP_EL3,此時的寄存器內容如下:

緊接着第86行,再次觸發異常:

此時會跳轉到EL3的“Current EL with SPx”分支執行:
1 // 2 // Current EL with SPx 3 // 4 .balign 0x80 5 cxsync3: 6 mrs x0, elr_el3 7 add x0, x0, #4 8 msr elr_el3, x0 9 10 mov x0, #0x0 11 msr spsel, x0 12 eret
第12行,異常返回后,寄存器內容如下:

完。
