ARMv8 寄存器

本文主要介紹 Armv8/v9 指令集架構中常用部分,詳細的還是要看 Arm architecture reference manual.

ARMv8 架構

ARMv8 架構支持3種指令集: T32, A32, A64

ARMv8 架構有兩種執行狀態: AArch32, AArch64

image

一個App 可以混合使用 T32 和 A32, 但是不能混合使用 A32 和 A64.

image

Registers in AArch64

The general purpose registers

image

該架構提供了 31 個通用寄存器。每個寄存器都可以用作 64 位 X 寄存器 (X0…X30),或用作 32 位 W 寄存器 (W0…W30)。這是查看同一寄存器的兩種不同方式。比如這張寄存器圖,W0是X0的低32位,W1是X1的低32位:

image

對於數據處理指令,選擇X或W決定操作的大小。使用X寄存器將導致 64 位計算,使用 W 寄存器將導致 32 位計算。
此示例執行 32 位整數加法:ADD W0, W1, W2
此示例執行 64 位整數加法:ADD X0, X1, X2

寫入寄存器時W,如上例所示,64 位寄存器的前 32 位被清零。
image

特殊寄存器

image

Zero register

零寄存器XZR和WZR始終讀爲 0 並忽略寫入。

這個寄存器在編程中非常有用,因爲它可以簡化某些操作,例如:

  • 當需要將一個寄存器清零時,可以將 zero register 直接作爲源操作數,這樣就能夠避免使用額外的立即數或操作來實現清零。
  • 在某些算術或邏輯操作中作爲一個操作數使用,可以便捷地實現特定的功能。例如,如果仿效清零操作,可以通過將某個寄存器和 XZR/WZR 進行 OR 操作實現。

stack pointer

  1. ARMv8體系結構爲每個異常等級都實現了一個棧指針SP_ELn,以異常等級爲後綴
  2. 當PE在某個異常等級處理異常時,可配置使用如下2個棧指針之一(通過PSTATE.SP配置),
    ① 所處理異常的target exception level對應的SP_ELn(默認情況)
    ② SP_EL0(注意,EL0是不會作爲target exception level的,所以這不是默認情況,而是需要特殊配置的)
    說明1:配置使用SP_EL0是在PE已經切換到targe exception level上進行的
    說明2:即使異常處理沒有發生異常等級切換,也需要處理上述棧指針的配置
    例如PE當前在EL1運行,並且使用SP_EL0。此時如果發生異常,並且target exception level也是EL1,雖然異常等級不會切換,但是棧指針也會自動切換爲SP_EL1。此時如果想繼續使用SP_EL0,則仍需要設置PSTATE.SP

image

t後綴表示thread,此時使用SP_EL0作爲棧指針;h後綴表示handler,此時使用當前異常等級對應的棧指針。

3:在Linux內核中,當從EL0陷入EL1時,使用SP_EL1作爲當前棧指針。此時SP_EL0可以作爲一個臨時寄存器使用,Linux內核會使用該寄存器存放進程的task_struct結構指針

在 ARMv8 架構中,實際上有兩個堆棧指針,它們是:

  • SP_EL0:用於應用程序的用戶模式堆棧指針。
  • SP_ELx:x 可以是 1, 2, 或 3,代表不同的異常級別。不同的異常級別對應不同的操作模式,比如操作系統的內核模式或中斷處理模式,每個異常級別都有自己的堆棧。

當發生函數調用時,處理器通常會將當前的 PC (程序計數器) 寄存器值(即返回地址)和其他必要的寄存器保存在棧上,然後將 SP 寄存器減少一定量來爲新的函數調用預留空間。相反,在函數返回時,處理器會使用 SP 寄存器的內容來恢復之前保存的寄存器值並跳回到調用點。
SP 寄存器的使用遵循調用約定和堆棧平衡的規則,這些規則確保了函數間參數傳遞、局部變量存儲和控制流的正確性。

Saved Program Status Registers (SPSRs)(備份程序寄存器)

用於保存發生異常時的處理器狀態

  1. ARMv8體系結構爲每個可作爲target exception level的異常等級都實現了一個SPSR_ELn,以異常等級爲後綴
  2. 當異常發生時,處理器的狀態將被保存在target exception level的SPSR寄存器;當異常返回時,將使用的SPSR寄存器中的值恢復PSTATE
  3. 保存異常發生時PSTATE狀態的另一個作用,就是可以在異常處理時通過SPSR寄存器判斷髮生異常時的PE狀態,例如發生異常時PE的異常等級和執行狀態

image

SPSR寄存器保存的很多狀態位與PSTATE中是相同的。這裏特別說明一下M[4]和M[3:0]的含義
① M[4]:記錄異常發生時的執行狀態,即PSTATE.nRW位。0表示AArch64執行狀態,1表示AArch32執行狀態
② M[3:0]:記錄異常發生時的異常等級及其使用的棧指針

image

  • M[3:2]標識發生異常時的異常等級
  • M[1]爲保留位,需要置爲0
  • M[0]標識棧指針SP的選擇,0表示使用SP_EL0,1表示使用與異常等級對應對應的SP_ELn

說明2:不像棧指針SP的使用可配置,異常發生時只能使用與targe exception level相應的SPSR_ELn
說明2:異常返回時,使用SPSR_ ELx的內容來恢復PSTATE

  1. ARMv8體系結構爲每個可作爲target exception level的異常等級都實現了一個ELR_ELn,以異常等級爲後綴
  2. 當異常發生時,異常返回地址將被保存在target exception level的ELR寄存器;當異常返回時,將使用的ELR寄存器中的值恢復到PC寄存器
    說明:和SPSR寄存器一樣,異常發生時也只能使用與targe exception level相應的ELR_EL

其中,對於保存什麼異常返回地址,對於不同的異常規則不同。
首選的異常返回地址取決於異常的性質,如下所示:
l 對於異步異常,它是發生中斷的指令邊界之後的指令的地址。因此,它是由於中斷而沒有執行或沒有完成執行的第一條指令的地址。
l 對於系統調用以外的同步異常,它是生成異常的指令的地址。
l 對於系統調用,它是系統調用指令後面的指令的地址。
n 注意:如果由於異常級別沒有足夠的權限執行指令而導致系統調用指令被捕獲、禁用或未定義,則首選的異常返回地址爲系統調用指令的地址。
n 系統調用是通過執行SVC、HVC或SMC指令生成的

Process state, PSTATE

在ARMv7體系結構中,使用CPSR寄存器來表示當前處理器的狀態。在ARMv8中,將PE的狀態抽象爲PSTATE。在實現上,則是一組標誌位的集合
image

image

image

ARMv8體系結構提供了一組特殊寄存器,用於訪問PSTATE狀態位

CurrentEL寄存器 表示PSTATE寄存器中的EL字段
DAIF寄存器 表示PSTATE寄存器中的{D,A,I,F}字段
SPSel寄存器 表示PSTATE寄存器中的SP字段
PAN寄存器 PSTATE寄存器中的PAN
UAO寄存器 UAO爲1表示在EL1和EL2執行這非特權指令(例如LDTR、STTR)的效果與特權指令(例如LDR、STR)是一樣的。
NZCV寄存器

說明:當內核態擁有訪問用戶態內存或者執行用戶態程序的能力時,攻擊者就可以利用漏洞輕鬆地執行用戶的惡意程序。爲了修復這個漏洞,在ARMv8.1中新增了PAN特性,防止內核態惡意訪問用戶態內存。如果內核態需要訪問用戶態內存,那麼需要主動調用內核提供的接口,例如copy_from_user()或者copy_from_user()函數。(將內核態與用戶態隔離的思想,在很多方面都提現了出來,比如內存管理中的內存隔離,內存映射等)
PAN寄存器的值如下。

0:表示在內核態可以訪問用戶態內存。
1:表示在內核態訪問用戶態內存會觸發一個訪問權限異常。
對於這些特殊寄存器的訪問,只能通過MRS(讀)/MSR(寫)指令完成。
舉例:僅設置C標誌位爲1
MRS R0,NZCV ;讀NZCV到R0
ORR R0,R0,#0x200000000 ;設置R0的第29位
MSR NZCV,R0 ;寫NZCV

Counter( PC)

Program Counter( PC)在A64中不是通用寄存器,不能和數據處理指令一起使用。可以使用以下方式讀取 PC:ADR Xd, .
點 ( .) 表示“這裏”,因此顯示的指令返回其自身的地址。這相當於閱讀PC.

系統寄存器

數據處理或加載/存儲指令不能直接使用系統寄存器。相反,需要將系統寄存器的內容讀入寄存器X,對其進行操作,然後寫回系統寄存器。有兩個用於訪問系統寄存器的專用指令:
MRS Xd, 將系統寄存器讀入Xd.
MSR , Xn 寫入Xn系統寄存器。
系統寄存器由名稱指定,例如SCTLR_EL1:MRS X0, SCTLR_EL1 讀SCTLR_EL1入X0.
系統寄存器名稱以_ELx. 指定_ELx訪問寄存器所需的最低權限。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章