中斷引腳:
在 ARM 體系結構裡,中斷是屬於非同步異常的一種,其處理過程與異常處理很類似。
ARM64 處理器有兩個與中斷相關的引腳——nIRQ 和 nFIQ(如下圖所示)。這兩個引腳直接連線到 ARM64 處理器核心上。ARM 處理器把中斷請求分成普通 IRQ(Interrupt Request)和FIQ(Fast Interrupt Request)兩種。
PSTATE 暫存器裡面有兩位與中斷相關,它們相當於 CPU 核心的中斷總開關。
I:用來遮蔽和開啟 IRQ。
F:用來遮蔽和開啟 FIQ。
中斷控制器:
隨著 SoC 越來越複雜,需要支援的中斷源越來越多,需要支援的中斷型別也越來越多,通常 ARM64 處理器內建了中斷控制器,如下圖 所示。例如,GIC400
中斷處理過程:
下圖中,假設有一個正在執行的程式,這個程式可能執行在核心態,也可能執行在使用者態:
中斷處理過程如下:
(1)CPU 面對中斷會自動做一些事情,例如,把當前的 PC 值儲存到 ELR 中,把 PSTATE暫存器的值儲存到 SPSR 中,然後跳轉到異常向量表裡面。
(2)在異常向量表裡,CPU 會跳轉到對應的彙編處理函式。對於 IRQ,若中斷髮生在核心態,則跳轉到 el1_irq 彙編函式;若中斷髮生在使用者態,則跳轉到 el0_irq 彙編函式。
(3)在上述彙編函式里儲存中斷現場。
(4)跳轉到中斷處理函式。例如,在 GIC 驅動裡讀取中斷號,根據中斷號跳轉到裝置中斷處理程式。
(5)在裝置中斷處理程式裡,處理這個中斷。
(6)返回 el1_irq 或者 el0_irq 彙編函式,恢復中斷上下文。
(7)呼叫 ERET 指令來完成中斷返回。CPU 會把 ELR 的值恢復到 PC 暫存器,把 SPSR 的值恢復到 PSTATE 暫存器。
(8)CPU 繼續執行中斷現場的下一條指令。
中斷處理過程是處理器在執行程式時,突然被一個外部事件(如裝置輸入/輸出完成、定時器到期等)打斷而轉而執行另一段程式碼的過程。下面是中斷處理過程的一般步驟:
- 中斷請求(Interrupt Request):外部裝置或其他系統元件向處理器傳送中斷請求,請求處理器停止當前正在執行的任務,並執行與該中斷相關的處理程式。
- 中斷響應(Interrupt Acknowledge):處理器接收到中斷請求後,會暫停當前執行的任務,並執行中斷響應過程。在中斷響應過程中,處理器會確定觸發中斷的裝置或事件,並獲取相關的中斷向量或中斷號。
- 儲存上下文(Context Saving):在執行中斷處理程式之前,處理器會儲存當前任務的上下文(例如程式計數器、暫存器狀態等)到堆疊或其他儲存區域中,以便在中斷處理結束後能夠恢復到中斷之前的狀態。
- 中斷處理(Interrupt Handling):處理器根據中斷向量或中斷號,跳轉到相應的中斷處理程式。中斷處理程式是事先定義好的,用於處理特定型別的中斷。它可能包括一系列的操作,如處理裝置資料、更新資料結構、通知其他任務等。
- 恢復上下文(Context Restoring):在中斷處理程式執行完成後,處理器會從堆疊或其他儲存區域中恢復之前儲存的上下文。這包括恢復程式計數器、暫存器狀態等資訊。
- 中斷返回(Interrupt Return):處理器根據恢復的上下文資訊,返回到中斷髮生時的執行點,繼續執行之前被中斷的任務。
- 清除中斷標誌(Clear Interrupt Flag):在中斷處理結束後,處理器可能需要清除中斷標誌位,以便允許其他中斷繼續被響應。
GIC-V2:
GIC發展史:
中斷狀態、中斷觸發方式和硬體中斷號:
每一箇中斷支援的狀態有以下 4 種。
不活躍(inactive)狀態:中斷處於無效狀態。
等待(pending)狀態:中斷處於有效狀態,但是等待 CPU 響應該中斷。
活躍(active)狀態:CPU 已經響應中斷。
活躍並等待(active and pending)狀態:CPU 正在響應中斷,但是該中斷源又傳送中斷過來。
外設中斷支援兩種中斷觸發方式。
邊沿觸發(edge-triggered):當中斷源產生一個上升沿或者下降沿時,觸發一箇中斷。
電平觸發(level-triggered):當中斷訊號線產生一個高電平或者低電平時,觸發一箇中斷。
對於 GIC 來說,為每一個硬體中斷源分配的中斷號就是硬體中斷號。GIC 會為支援的中斷型別分配中斷號範圍,如
不同型別中斷的作用:
SGI:SGI 通常用於多核之間的通訊。GIC-V2 最多支援 16 個 SGI,硬體中斷號範圍為 0~15。SGI通常在Linux核心中被用作處理器之間的中斷(Inter-Processor Interrupt,IPI),並會送達系統指定的 CPU 上。
PPI :每個處理器核心私有的中斷。GIC-V2 最多支援 16 個 PPI,硬體中斷號範圍為 16~31。PPI 通常會送達指定的 CPU 上,應用場景有 CPU 本地定時器(local timer)。
SPI :公用的外設中斷。GIC-V2 最多可以支援 988 個外設中斷,硬體中斷號範圍為 32~1019。
SGI 和 PPI 是每個 CPU 私有的中斷,而 SPI 是所有 CPU 核心共享的。
GIC-V2內部結構:
GIC-V2 是由兩個硬體單元組成的,一個是分發器,另一個是 CPU 介面(CPU interface),如下圖所示。分發器主要用來做仲裁和分發,CPU 介面是與 CPU 核心連線的模組。分發器只
有一個,是共用的,但是每個 CPU 核心有一個 CPU 介面,它們透過 nIRQ 與 nFIQ 這兩個引腳和 CPU 核心連線在一起。
中斷流程:
GIC 檢測中斷的流程如下。
(1)當 GIC 檢測到一箇中斷髮生時,會將該中斷標記為等待狀態。
(2)對於處於等待狀態的中斷,分發器會確定目標 CPU,將中斷請求傳送到這個 CPU。
(3)對於每個 CPU,分發器會從眾多處於等待狀態的中斷中選擇一個優先順序最高的中斷,傳送到目標 CPU 的 CPU 介面。
(4)CPU 介面會決定這個中斷是否可以傳送給 CPU。如果該中斷的優先順序滿足要求,GIC會傳送一箇中斷請求訊號給該 CPU。
(5)CPU 進入中斷異常,讀取 GICC_IAR 來響應該中斷(一般由 Linux 核心的中斷處理程式來讀暫存器)。暫存器會返回硬體中斷號(hardware interrupt ID)。對於 SGI 來說,返回源 CPU
的 ID(source processor ID)。當 GIC 感知到軟體讀取了該暫存器後,根據如下情況處理。
如果該中斷處於等待狀態,那麼狀態將變成活躍。
如果該中斷又重新產生,那麼等待狀態將變成活躍並等待狀態。
如果該中斷處於活躍狀態,將變成活躍並等待狀態。
(6)處理器完成中斷服務,傳送一個完成訊號結束中斷(End Of Interrupt,EOI)給 GIC。
GIC 支援中斷優先順序搶佔功能。一個高優先順序中斷可以搶佔一個處於活躍狀態的低優先順序中斷,即 GIC 的分發器會找出並記錄當前優先順序最高的且處於等待狀態的中斷,然後搶佔當前中斷,並且傳送這個最高優先順序的中斷請求給 CPU,CPU 應答了高優先順序中斷,暫停低優先順序中斷服務,轉而處理高優先順序中斷。總之,GIC 的分發器總會把等待狀態中優先順序最高的中斷請求傳送給 CPU。
GIC-V2暫存器:
GIC-V2 暫存器也分成兩部分:一部分是分發器的暫存器;另一部分是 CPU 介面的暫存器。分發器暫存器(以 GICD_為開頭)包含了中斷設定和配置,如下表 所示。CPU 介面的暫存器(以 GICC_為開頭)包含 CPU 相關的特殊設定,如下表所示:
分發器的暫存器:
CPU介面的暫存器:
中斷路由:
GIC-V2 可以配置 SPI 外設中斷的路由,如下圖:
GICD_ITARGETSRn 暫存器用來配置分發器,把某個中斷分發到哪個 CPU 上。
GICD_ITARGETSRn 暫存器使用 8 位來表示一箇中斷源,每位代表一個 CPU 編號,因為 GIC-V2 控制器最多支援 8 個 CPU。
某個中斷源的位被設定,說明該中斷源可以路由到這些位對應的 CPU 上。
前 32 箇中斷源的路由配置是硬體配置好的,它們是為 SGI 和 PPI 中斷準備的,軟體不能配置路由。
第 33~1019 號中斷可以由軟體來配置其路由。