本文主要講解了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