3. ARMv8 中斷及異常處理(包括系統呼叫,系統呼叫即同步異常)
ARMv8 64bits相對於之前的 32bits 有較大變動,所有中斷及異常的處理總入口都在entry.S 原始檔中。
1.1. 異常介紹(中斷即稱為 非同步異常)
分為同步和非同步 兩種型別異常,中斷劃入非同步異常型別:
Synchronous(同步異常) |
|
異常型別 |
描述 |
Undefined Instruction |
未定義指令異常 |
Illegal Execution State |
非常執行狀態異常 |
System Call |
系統呼叫指令異常(SVC/HVC/SMC) |
Misaligned PC/SP |
PC/SP未對齊異常 |
Instruction Abort |
指令終止異常 |
Data Abort |
資料終止異常 |
Debug exception |
軟體斷點指令/斷點/觀察點/向量捕獲/軟體單步 等Debug異常 |
Asynchronous(非同步異常) |
|
型別 |
描述 |
SError or vSError |
系統錯誤型別,包括外部資料終止 |
IRQ or vIRQ |
外部中斷 or 虛擬外部中斷 |
FIQ or vFIQ |
快速中斷 or 虛擬快速中斷 |
1.2. 異常處理邏輯
跳轉到哪個EL使用哪個向量偏移地址又路由關係決定。路由關係看的比較暈,需要對體系架構有一定了解,
異常進入滿足以下條件 |
向量地址偏移表 |
|||
Synchronous (同步異常) |
IRQ || vIRQ |
FIQ || vFIQ |
SError || vSError |
|
SP => SP_EL0 &&從Current EL來 |
0x000 |
0x080 |
0x100 |
0x180 |
SP => SP_ELx &&從Current EL來 |
0x200 |
0x280 |
0x300 |
0x380 |
64bit => 64bit &&從Low level EL來 |
0x400 |
0x480 |
0x500 |
0x580 |
32bit => 64bit &&從Low level EL |
0x600 |
0x680 |
0x700 |
0x780 |
• SP=> SP_EL0,表示使用SP_EL0堆疊指標,由PSTATE.SP== 0決定,PSTATE.SP == 1 則SP_ELx;
• 32bit=> 64bit 是指發生異常時PE從AArch32切換到AArch64的情況;
exception level遷移情況 |
Synchronous exception的offset值 |
IRQ和vIRQ exception的offset值 |
FIQ和vFIQ exception的offset值 |
SError和vSError exception的offset值 |
同級exception level遷移,使用SP_EL0。例如EL1遷移到EL1 |
0x000 |
0x080 |
0x100 |
0x180 |
同級exception level遷移,使用SP_ELx。例如EL1遷移到EL1 |
0x200 |
0x280 |
0x300 |
0x380 |
ELx遷移到ELy,其中y>x並且ELx處於AArch64狀態 |
0x400 |
0x480 |
0x500 |
0x580 |
ELx遷移到ELy,其中y>x並且ELx處於AArch32狀態 |
0x600 |
0x680 |
0x700 |
0x780 |
1.3. 程式碼實現,參考entry.S
帶invalid字尾的向量都是linux做未做進一步處理的向量,預設都會進入bad_mode()流程,說明這類異常Linux核心無法處理,只能上報給使用者程序(使用者態,sigkill或sigbus訊號)或die(核心態)。
el0_sync:在使用者態發生同步異常處理
el0_irq:在使用者態發生irq中斷處理
el1_sync:在核心態發生同步異常處理
el1_irq:在核心態發生irq中斷處理
對於非同步異常sError,當前都是不會進一步做處理,直接進入inalid處理邏輯。
1.4. 參考資料