Exception Vector Table
當中斷發生時,CPU 會根據目前的 exception level 查找對應的中斷向量表 (VBAR_ELx)。知道向量表在哪後,就可以根據中斷發生的類型執行對應的操作。
中斷發生的時機,可以是在 EL0 主動執行 svc trap 到 EL1 (Synchronous),或是被 timer interrupt (IRQ) 打到,也會從 EL0 轉換到 EL1。
Exception Mechanism
當中斷發生時,會有以下流程:
- 將目前的 PSTAT 儲存在
SPSR_ELx - 將 returned address 儲存在
ELR_ELx - 關閉 interrupt (
PSTATE.{D,A,I,F}are set to 1) - 若 exception 是 Synchronous exception 或是 SError interrupt,將 exception syndrome 保存在
ESR_ELx - 轉換 EL 到目標的 EL,
pc指到對應的中斷向量表
當中斷處理結束,執行 eret 回到中斷發生前的狀態:
pc變回先前在ELR_ELx儲存的值PSTATE變回先前在SPSR_ELx儲存的值
More details: Stack Pointer
當處在不同的 exception level 時,sp 這個暫存器會被當作是該 level sp 的別稱 (SP_ELx 的別稱)。可以使用 SPSel 在不同的 exception level 共享 SP_EL0,但是通常不建議這樣做。
- 對於 EL0,僅能使用
SP_EL0(簡稱為 EL0t) - 對於 EL1,可以選擇使用
SP_EL0(簡稱為 EL1t),或者使用SP_EL1(簡稱為 EL1h) - 對於 EL2,可以選擇使用
SP_EL0(簡稱為 EL2t),或者使用SP_EL2(簡稱為 EL2h) - 對於 EL3,可以選擇使用
SP_EL0(簡稱為 EL3t),或者使用SP_EL3(簡稱為 EL3h)
t: thread, h: handler
ELxt 與 ELxh 的區別在於是不是使用該 exception level 的 sp,t 代表使用 SP_EL0,h 代表使用該 exception level 自己的 sp
在 Exception Level Switch 設定 SPSR_EL1 與 SPSR_EL2 時,也會設定該 exception level 的 stack pointer (M[3:0] 欄位):
Interrupts vs Exceptions
In ARM.v8 architecture, interrupts are part of a more general term: exceptions. There are 4 types of exceptions:
- Synchronous exception
- caused by the currently executed instruction
- IRQ (Interrupt Request)
- always asynchronous, which means that they have nothing to do with the currently executed instruction
- they are always not generated by the processor itself, but by external hardware
- FIQ (Fast Interrupt Request)
- for the purpose of prioritizing exceptions
- SError (System Error)
- asynchronous and are generated by external hardware
- always indicates some error condition
中斷向量表
定義 Vector Table,總共會有 16 個 Exception Handler 需要實作:4 種類型,每種類型都有 4 種不同的 exception handler (Sync, IRQ, FIQ, SError),以 EL1 的 Vector Table 為例:
- EL0_32
VBAR_EL1+ 0x600
- EL0_64
VBAR_EL1+ 0x400
- EL1h (SPSel = 1)
VBAR_EL1+ 0x200
- EL1t (SPSel = 0)
VBAR_EL1+ 0x0

注意每個 exception handler 需要對齊 0x80
exception_table.h
先定義一下 invalid 的編號,當有還沒有實作的 exception handler 被呼叫到時,會將編號當作參數傳入某個 function 進行錯誤輸出
| |
exception_table.S
在進到 Exception Handler 時需要進行 context saving (kernel_entry 及 kernel_exit 這兩個 macro),避免 Exception Handler 覆寫先前的 Register 狀態。
| |
目前只實作了 EL1h 與 EL0_64 的 Synchronous Interrupt (for system call) 及 IRQ Interrupt (for timer interrupt) 的 exception handler,當觸發時會跳到用 C 的 code。
| |
start.S
在初始化到 EL1 時,將向量表的記憶體位址載入到 VBAR_EL1
| |
panic.c
| |
當發生 Exception 時怎麼知道會跳到哪個 level?
The Exception level that execution changes to, or remains in, on taking an exception, is called the target Exception level of the exception and:
- Every exception type has a target Exception level that is either:
- Implicit in the nature of the exception.
- Defined by configuration bits in the System registers.
- An exception cannot target the EL0 Exception level.
Synchronous exception 通常都有訂好 target exception level (e.g. svc: EL0 -> EL1, hvc: EL1 -> EL2)。
IRQ 可以通過設置不同 Register 來進行調整 (e.g. 設定 HCR_EL2.TGE 可以將 EL1 發生的 exception route 到 EL2),在實驗中我們都假設是由 EL1 來進行處理。