x86架構中的外部中斷結構-Part 1:中斷控制器的演化
本文主要講解了x86體系架構從外部設備接受中斷的過程,本文是系列文章的第一部分,試圖回答以下問題:
- 什麼是PIC以及它的用途是什麼?
- 什麼是APIC以及它的用途是什麼?LAPIC和I/O APIC的目的是什麼?
- APIC,xAPIC以及x2APIC之間的區別在哪兒?
- 什麼是MSI? MSI以及MSI-X之間的存在哪些區別?
- $PIR, MPtable, 和 ACPI tables的用途是什麼?
如果你想知道上述問題的答案,或者僅僅想簡單了解一下中斷控制器的發展過程,耐心看完本文,你一定會有收穫。
原文地址:
本文是翻譯的國外大佬的文章,根據自己的理解稍加修改了語序,由於自己也在學習階段,翻譯難免有紕漏,如果感覺有些地方讀不懂,建議可以去看看原文,並向我提出翻譯修改的建議,謝謝。
《External Interrupts in the x86 system. Part 1. Interrupt controller evolution》
Introduction
對於那些不了解中斷(interrupt)是啥的同學,這裡引用Wikipedia的內容進行簡單的介紹:
在系統編程中,中斷是由硬體或軟體向CPU(處理器)發出的一種訊號,提示CPU需要立即處理一些高優先順序任務。 中斷提醒CPU注意高優先順序任務,同時停止CPU當前正在執行的程式碼。 隨後CPU暫停當前運行的程式碼、保存程式狀態、轉而去執行一個中斷處理程式(或中斷服務程式,ISR)來響應中斷事件。 中斷是暫時的,在中斷處理程式完成後,處理器恢復到之前運行的程式碼。
中斷一般分為兩類:硬體中斷和軟體中斷。
- 硬體中斷:外設一般使用硬體中斷向作業系統傳遞自身需要運行的訊號,在電腦內部,外部設備通過向處理器發送電子警報訊號實現硬體中斷,例如磁碟控制器,或者外部設備,當按下鍵盤上的鍵或移動滑鼠時會觸發硬體中斷,從而使處理器讀取按鍵值或滑鼠位置。啟動硬體中斷的行為被稱為中斷請求(IRQ)。
- 軟體中斷:軟體中斷是由處理器本身的異常,或者是指令集中特殊指令在執行時引起的中斷。 前者通常稱為陷阱(trap)或異常(exception),用於處理程式執行期間發生的錯誤或事件,這些錯誤或事件無法在程式內處理。 例如,數字除以零,會引發除零異常,由此產生軟體中斷。
本文主要講解的是硬體中斷IRQ。
中斷的目的是什麼? 舉個例子,在網卡傳輸數據包的過程中,我們希望數據包到達後立即對來自網卡的傳入數據包執行操作,而不是cpu連續詢問網卡«我的數據包到達了嗎?»,輪詢方式會浪費cpu處理的時間,在這個案例之下可以使用外部硬體中斷 IRQ,網卡的中斷線應該連接到 CPU 的 INTR 線,網卡每收到一個數據包,就通過中斷線發出訊號,通知cpu數據包已經收到,然後cpu停下手頭的工作,去讀取這個數據包。
但是如果有很多外部設備我們該怎麼辦?不可能將每個設備的中斷線直接連接到CPU上,雖然通訊效率高,但 在 CPU 上製作大量的 INTR 引腳是不現實的。

為了解決多個外設的中斷線連接CPU的問題,一個特殊的晶片被設計出來,這就是中斷控制器(an interrupt controller)。
PIC(可編程中斷控制器 Programm Interrupt Controller)
第一個中斷控制器晶片是 Intel 8259 PIC。 它有 8 條輸入線(IRQ0-7)和 1 條輸出線(連接中斷控制器和 CPU 的 INTR 線)。 當其輸入線上的任意一個設備發生中斷時,8259 將通過 INTR 線發出中斷訊號。 於是CPU 知道某個設備請求了中斷,處理器將詢問 PIC的 8 條輸入線(IRQx),並判斷哪條是此中斷的來源。 這個輪詢有一些開銷,但現在我們有 8 條中斷線而不是 1 條。

很快 8 條輸入線就不夠用了。 為了增加中斷線的總數,兩個 8259 控制器(主控制器master和從控制器slave)以級聯方式進行連接(Dual PIC)。
從 0 到 7 的 IRQ 由第一個 Intel 8259 PIC(主)處理,從 8 到 15 的 IRQ 由第二個 Intel 8259 PIC(從)處理。 只有主設備直接連接到 CPU 並可以發出中斷訊號。 如果第 8-15 行有中斷,第二個 PIC(從機)將通過 IRQ2 線向主機發送中斷訊號,然後主機向 CPU 發送中斷訊號。 這種級聯中斷佔用了 16 條線路中的 1 條,但對所有外部設備總共產生了 15 條中斷線(8+7)。

上述中斷控制器級聯方案很快被開發社區採用,現在當有人談論PIC(可編程中斷控制器)時,通常是指Dual PIC system即雙PIC級聯繫統。過了一段時間,8259改進為8259A。有了這個控制器,晶片組中就包含了雙PIC系統。當外部設備連接的主匯流排是ISA時,這個系統就足夠了。不同的設備需要連接到不同的IRQ線路,因為ISA匯流排的中斷是不可共享的。 設備中斷幾乎都按照如下標準進行映射:
Example (from here):
IRQ 0 — system timer
IRQ 1 — keyboard controller
IRQ 2 — cascade (interrupt from slave controller)
IRQ 3 — serial port COM2
IRQ 4 — serial port COM1
IRQ 5 — parallel port 2 and 3 or sound card
IRQ 6 — floppy controller
IRQ 7 — parallel port 1
IRQ 8 — RTC timer
IRQ 9 — ACPI
IRQ 10 — open/SCSI/NIC
IRQ 11 — open/SCSI/NIC
IRQ 12 — mouse controller
IRQ 13 — math co-processor
IRQ 14 — ATA channel 1
IRQ 15 — ATA chanel2
Intel 8259晶片的配置和工作通過I如下I/O埠進行:
|
Chip |
Register |
I/O port |
|
Master PIC |
Command |
0x0020 |
|
Master PIC |
Data |
0x0021 |
|
Slave PIC |
Command |
0x00A0 |
|
Slave PIC |
Data |
0x00A1 |
8259A更加完整的說明文檔在此鏈接here。
後來,外設數量超過了15台,PCI匯流排也逐漸替代了ISA匯流排,相比於靜態的ISA匯流排,PCI匯流排上的設備可以動態的加入到系統中,同時匯流排上的中斷可以共享,這樣可以實現利用一條中斷線IRQ連接多個設備。最後,為了解決中斷線不足的問題,設計者決定將所有PCI設備的中斷分配到PIRQ線(Programmable Interrupt Request 可編程中斷請求)。
例如,假設我們在PIC控制器和20個PCI設備上有4條空閑的中斷線。我們可以將來自5台設備的中斷合併成一條PIRQx線,並將這些PIRQx線連接到PIC控制器。在這種情況下,如果一條PIRQx線路上出現中斷,處理器必須詢問與該線路相連的所有設備的中斷情況,確定對哪個設備響應。由此將PCI中斷線與PIRQx線連接的設備稱為PIR路由器。使用這種方法必須要確保PIRQx線路沒有連接到ISA匯流排中斷上(這會產生衝突),同時要確保PIRQx線路分布是均衡的(我們連接到一條線路的設備越多,CPU在響應哪個設備的中斷時需要輪詢的次數就越多)。

Note:上圖展示了PCI設備->PIR的連接過程,在實際電路中,它們之間的連接更加複雜。實際上,每個PCI設備有4條中斷線(INTA、INTB、INTC、INTD)和多達8個中斷函數,其中每個函數只能有一個INTx中斷。每個中斷函數將使用哪條INTx線取決於晶片組配置。
從本質上講,中斷函數彼此間是獨立的。例如,一個PCI設備可以具有Smbus控制器函數、SATA控制器函數和LPC橋接函數。從作業系統(OS)的角度來看,每個函數就像一個單獨的設備,有自己的配置空間(PCI配置)。 PIC控制器的中斷路由資訊由BIOS發送給作業系統,BIOS主要通過$PIR 、3Ch暫存器、3Dh暫存器來對PCI 進行配置。
$PIR 表規範可以在微軟提供的網站查詢,或者從 PCI BIOS Specification獲取相關資訊。
APIC
最後一種方法主要用於多處理器系統。本質上,PIC只能向一個CPU發送中斷,在多處理器系統中,需要均衡的向CPU通知中斷。這個問題的解決方案是添加一種新的PIC介面----APIC(Advanced PIC)。
每一個處理器都添加一個特殊的控制器LAPIC(local APIC),以及提供外部設備中斷路由的I/O APIC控制器。這些所有的控制器都連接在APIC 匯流排上,設備連接示意圖如下。

當一個外部中斷訊號輸入到 APIC的I/O口上,這個控制器會將該中斷訊號傳送到系統中任意一個CPU上的LAPIC上,在上述傳輸方式中,APIC控制器可以均衡的將中斷訊號傳入不同的處理器上。第一款APIC晶片是82489DX,它是一個單獨的晶片,內部含有LAPIC和APIC,對於上圖中的雙處理器系統,需要三個這樣的晶片:兩個用於LAPIC,一個用於I/O APIC。後來,LAPIC功能直接包含在處理器中,APIC部分與82093AA晶片分離。
APIC 82093AA晶片有24個輸入,APIC體系架構最多可支援16個CPU。中斷0-15用於舊的ISA中斷,以便與舊的系統兼容,中斷16-23用於所有PCI設備。通過這種劃分,ISA和PCI中斷之間的所有衝突都可以輕鬆避免。隨著空閑中斷線數量的增加,也可以用來增加PIRQx線的數量。APIC和LAPIC編程可以通過MMIO完成。LAPIC暫存器通常放在地址0xFEE00000上,APIC暫存器放在地址0xFEС00000上,因此可以需要重新配置它們。與PIC的情況一樣,最初獨立的晶片後來會成為晶片組(處理器)的一部分。
APIC 體系結構的下一代是xAPIC (x -extended),可以完全向後兼容,並且系統支援的CPU個數增加到了256。xAPIC的下一代體系架構是x2APIC.該系統可以支援的CPUs數量增加到了 2^32。可以在xAPIC模式下運行,也可以在新的x2APIC模式下運行。在這種新模式下,控制器編程不是通過MMIO完成的,而是通過MSR暫存器(速度快得多)。根據該鏈接(this link,),IOMMU來支援該模式的編程。
值得一提的是,系統中可能有多個APIC控制器。例如,南橋中的APIC負責24次中斷,北橋中的另一個APIC負責32次中斷。在APIC系統中,中斷通常被稱為GSI(全局系統中斷)。因此,上述南北橋系統整體的GSIs為0-55。我們如何確定CPU內部是否含有LAPIC,以及它支援哪種APIC體系結構?我們可以通過檢查CPUID中的標誌位來確定。
為了幫助OS 發現 LAPIC 和 APIC硬體的存在,以及使用它們。BIOS可以通過MPtable(舊方法)或ACPI表(在本例中是MADT表)來提供有關它們的資訊,並載入到OS中。除了上述資訊,MPtable和ACPI都應該包含具體的中斷路由資訊。這包含著哪個設備具體使用哪個中斷線的資訊(類似於$PIR表),以及相互映射關係。
我們可以通過查看官方文檔(official specification)來了解MPtable,早些時候,該規範出現在英特爾網站上,但目前只能在存檔版本中找到。ACPI規範可在UEFI網站上找到(當前版本為6.2)。
MSI
隨著APIC的發展,所有設備的中斷線導致系統變得異常複雜並且增加了錯誤概率。同時PCI express匯流排也取代了PCI匯流排,PCIe匯流排簡化了中斷系統,該匯流排中沒有中斷線,但是為了向下兼容,中斷訊號(INTx#)用一種單獨的消息進行模擬。PCI匯流排中,中斷的連接是通過物理布線實現的。而PCIe匯流排中的中斷是邏輯連接的,並通過PCIe 橋接器進行傳輸。PCI express引入了一種全新的中斷傳遞方法——MSI(消息訊號中斷)。在這種方式中,設備只需將數據寫入CPU LAPIC的MMIO區域中的一個特殊位置,即可發出有關中斷的訊號。訊號傳輸示意圖如下:

早些時候,單個PCI設備只包含4個中斷,但是現在可以提供多達32個中斷。在MSI的情況下,沒有共享的中斷線:每個中斷自然地對應於它的設備。 MSI中斷還解決了另一個問題。例如,一個設備進行一個記憶體寫入事務,並希望通過中斷髮出其完成的訊號。但是,寫入事務在傳輸過程中可能會在匯流排上延遲(設備無法知道)。在這種情況下,中斷訊號可能提前到達CPU,因此處理器將讀取尚未生效的數據。如果使用MSI,MSI資訊將以與數據消息相同的方式傳輸,因此不能提前發送,從而不會出現衝突的情況。
需要注意的是,沒有LAPIC,MSI中斷將無法工作,但是MSI可以取代APIC(正如上圖所示,進一步簡化了電路的設計)。隨和一段時間的發展,MSI擴展到了MSI-X,現在每個設備最多可以處理2048個中斷,並且可以指定哪一個CPU去處理哪一個中斷,這對網卡等高負載設備都非常的有用。MSI不需要單獨的BIOS表來支援,但外設需要指明它自身與哪一個MSI訊號相對應,這些資訊都需要包含在外設的驅動程式中。
Сonclusion
在本文中,我們學習了有關中斷控制器演變的相關知識,並大致了解了x86中斷外設的一些基本知識。
在Part2部分中,我們將進行練習,了解如何在Linux中使用前面提到的每個中斷控制器。
在Part3部分,我們將研究coreboot程式碼,並查看晶片組中需要哪些設置才能實現正確的中斷路由資訊。
Links:
- Interrupt Controllers (Stuff in the Middle)
- What do the different interrupts in PCIe do?
- Reducing Interrupt Latency Through the Use of Message Signaled Interrupts
Acknowledgments
Special thanks to Jacob Garber from the coreboot community for helping me with this article translation.
Special thanks to Alex's suggestion for Computer architecture review

