以下文章來源于AdriftCoreFPGA芯研社,作者CNL中子
前言
PCIe 中斷機制主要分為兩類:一類是繼承自傳統 PCI 的 物理中斷線(INTx)中斷,通過硬件引腳觸發;另一類是 MSI(Message Signaled Interrupt)中斷,通過向指定內存地址寫入數據來通知系統。
很多人可能會好奇:為什么現代系統逐漸淘汰了傳統中斷?MSI 相比之下究竟有哪些優勢?本文將帶你逐一揭開這些問題的答案。
傳統PCI中斷
虛擬邊帶信號
在老式的 PCI 插槽上,主板是真的有四根物理信號線連著設備的,分別叫 INTA,INTB,INTC,INTD。

image
但是 PCIe 變成了串行的高速差分線,早就沒有這四根物理引腳了。那老驅動怎么用呢?
報文模擬
PCIe 規范發明了消息報文 (Message TLP)來驅動 INTx 中斷線產生中斷。

image
電平模擬
物理線的電平有拉高和拉低。所以在 TLP 報文里,必須成對發送。
當你的設備想發中斷時,硬件邏輯組裝一個Assert_INTA (消息碼 20h) 的報文發出去,告訴主機我把線拉低了。
當主機處理完中斷后,你的硬件邏輯必須再發一個Deassert_INTA (消息碼 24h) 的報文,告訴主機我把線松開了。如果忘了發 Deassert,系統就會一直被中斷卡死。

image
配置空間
在 PCIe Header 的配置空間里有兩個寄存器,Interrupt Pin (中斷引腳) 和Interrupt Line (中斷線) ,這兩個配置空間里的寄存器僅僅是為傳統中斷 (Legacy INTx) 服務的。
Interrupt Pin (中斷引腳)
這是硬件管的。
它是由 Device 這一側在初始化 IP 的時候配置好的。比如寫 1 代表用 INTA,寫 2 代表 INTB。
如果是 Xilinx 7 系列的 PCIe IP,并且是 Single Function(單功能設備),那么它只支持 INTA。所以你在配置 IP 時這個值通常寫死為 1。
Interrupt Line (中斷線)
這是軟件的草稿紙。
它是一個 8bit (0~255) 的寄存器,里面存的是系統的 irq 編號。
這個編號是上位機軟件(OS)根據系統中斷路由分配后,通過 RC 下發配置包寫進來的。
對于底層硬件設備來說,這個值完全沒有用,它只是給上層軟件驅動層留的一個存儲位置,方便驅動程序自己去讀,甚至發出去的 TLP 包里也根本不需要帶這個值。
INTX的困境
INTx 實在太慢、太難用了。它不僅需要來回發 Assert/Deassert 兩次報文,而且 4 根線常常需要和主板上的其他設備共享,導致 CPU 每次收到中斷還得挨個去查到底是哪個設備觸發的。
如果是做網卡這種需要處理海量網絡高并發數據的芯片,如果用 INTx,系統性能直接就崩潰了。現代的網卡設計,起步就是MSI,或者是支持成千上萬個中斷向量的MSI-X。
現代PCIe中斷
用寫內存代替拉信號線
在 MSI 機制下,你的芯片不再需要去拉扯虛擬的信號線(像 INTx 發送 Assert/Deassert 報文那樣)。
當設備需要觸發 CPU 中斷時,它直接往一條特定的總線地址發送一個Memory Write TLP (內存寫報文)。
就像送快遞。INTx 是你在樓下按門鈴大喊有快遞,CPU 得自己下樓看是誰的;而 MSI 則是你直接把寫著你名字的包裹塞進 CPU 指定的專屬信箱里。
MSI Capability 結構
既然是往特定地址寫特定數據,那這個地址和數據怎么來呢?這就要靠配置空間里的MSI Capability Register了。
在系統啟動枚舉 PCIe 設備時,操作系統和你的硬件會這樣配合

image
Message Address (消息地址)
軟件(驅動)在系統的內存空間(通常是 CPU 的 APIC 中斷控制器映射的一段空間)里申請好一個專屬地址,然后把這個地址寫入你配置空間里的Message Address寄存器。如果系統是 64 位的,就會用到帶Message Upper Address的 64-bit 結構。
Message Data (消息數據)
這是一串特定格式的數據包。不同的 CPU 架構對這個數據格式有不同的定義,內核可以通過 API 獲取,填入這個寄存器,為了讓 CPU 能區分到底是哪個具體的向量觸發了中斷,PCIe 硬件在發送報文時,會動態地把向量的編號(0~31)作為偏移量,加到這個基準 Message Data 的低位上。
當你網卡的某個業務模塊(比如收到一個網絡包)產生中斷請求時,你的 PCIe MAC/應用層邏輯,就會去讀取這兩個寄存器里的 Address 和 Data,把它們拼成一個 Memory Write TLP,直接發給 Host。
Mask & Pending

image
既然 MSI 支持了多達 32 個 Vector,那自然就需要一個 32 bit 的Mask Bits來讓軟件挨個控制這 32 個中斷源誰該靜音,以及一個 32 bit 的Pending Bits讓硬件挨個記錄誰在靜音期間舉手了。為了不讓 CPU 被海量的中斷請求淹沒,PCIe 規范定義了這套 Mask(屏蔽)和 Pending(掛起)的機制。
我們可以從控制權和工作流的角度,把這兩個寄存器的作用拆解得清清楚楚:
Mask Bits (屏蔽位)
他是軟件的靜音鍵
誰來控制: 由上層軟件 (OS / 設備驅動) 負責讀寫。
有什么用: MSI 模式最多支持 32 個中斷向量 (Vector),這里的 Mask Bits 恰好是 32 bit,每一位對應一個向量的掩碼。當軟件把某一位寫為1時,就表示屏蔽 (Mask) 對應的中斷向量。
實際場景: 比如 CPU 現在正在處理一段非常關鍵的代碼,或者正在批量處理網卡剛剛收上來的網絡包,不想被打擾。驅動程序就會把對應的 Mask Bit 置為 1。這時候,你的網卡硬件就算有天大的事,也不能往主機發那個中斷 TLP。
Pending Bits (掛起/未決位)
他是硬件的未接來電記錄
誰來控制: 由你的硬件 (DPU 的 RTL 邏輯) 負責置位 (Set) 和清零 (Clear)。軟件只能讀,不能寫。
有什么用: 它是用于掛起中斷的標志。如果在 Mask Bit 被置 1 (靜音) 的這段時間里,你的 DPU 內部剛好產生了一個中斷請求,因為被靜音了發不出去,你的硬件邏輯就會把對應的 Pending Bit 拉高。
實際場景: 這相當于給 CPU 留了一個“未接來電”。它保證了在軟件屏蔽中斷的期間,硬件產生的新中斷不會丟失。
系統設計的聯動過程
在系統設計中,處理這兩個寄存器的聯動邏輯通常是這樣的:
正常情況 (Mask = 0): 硬件產生中斷請求 -> 檢查對應的 Mask Bit 為 0 -> 直接組裝一個 Memory Write TLP (即 MSI 報文) 發給主機 -> Pending Bit 保持 0。
屏蔽情況 (Mask = 1): 硬件產生中斷請求 -> 檢查對應的 Mask Bit 為 1 -> 阻斷 TLP 的發送 -> 將對應的 Pending Bit 置為 1。
解除屏蔽 (Mask 1 -> 0): 軟件忙完了,決定放開中斷,通過讀取Peding寄存器知道設置掩碼時掛起了一個中斷請求。軟件在合理時機清除 Mask Bits,你的硬件邏輯檢測到 Mask Bit 從 1 變 0,且對應的 Pending Bit 為 1,就會立刻發送積壓的 MSI 報文,并同時把 Pending Bit 清零。
MSI的最大優勢
MSI 有個巨大的優點:它支持多達32 個配置的 vector (向量)。
INTx 因為只有 4 根線,經常幾個設備共用一根,CPU 收到中斷后還得一個個問 是你叫我嗎?。
32 個 vector 意味著你的網卡可以分配 32 個完全獨立的中斷源。
比如:你可以讓 Vector 0 專管網口 0 的接收,Vector 1 管網口 0 的發送,Vector 2 管錯誤報警
硬件發 MSI TLP 時,會根據具體的業務,把對應的 Vector 編號(0~31)動態疊加到前面軟件配好的Message Data的低位里。CPU 收到報文,瞬間就能精準定位是網卡的哪個隊列觸發了中斷。
MSI-X
剛才聊了 MSI 最多只能支持 32 個 Vector。對于一塊普通的網卡可能夠了,但對于動輒幾百上千個網絡隊列(Queue)并發的智能網卡來說,32 個中斷源簡直是杯水車薪。
MSI-X 作為升級版,每個 Function 支持的 Vector 數量直接飆升到了2048 個。這意味著你的網卡邏輯可以為每一個獨立的業務隊列分配一個專屬的中斷通道,徹底告別中斷擁擠。
MSI 只支持一個 MSI address。回憶一下剛才 MSI 的配置空間,系統只分配了一個基地址(Message Address)。如果設備要發不同的中斷,只能去修改數據包(Message Data)的低位來區分 Vector。
這導致所有的中斷報文最終都擠向了同一個內存地址(通常對應 CPU 的同一個處理節點)。
MSI-X 可以支持多個 address。在 MSI-X 的架構中,不再把地址寫在配置空間里了,而是直接在你的芯片內部(通常是 BAR 空間)開辟一塊專門的內存區域,叫做MSI-X Table。在這張表里,你可以為這 2048 個 Vector 中的每一個,都單獨配置獨立的 Address 和 Data。
MSI-X 最大的實戰價值是對于多核CPU可以均衡地分配資源。
在服務器環境里,CPU 都是幾十上百核的。 如果用 MSI(單地址),網卡幾百個隊列產生的中斷全都會砸到同一個 CPU 核心上,導致這個核心忙死(100% 負載),而其他核心閑死,網絡吞吐量直接卡住。 用了 MSI-X(多地址),系統軟件就可以在 MSI-X Table 里,把 Vector 0 的地址配給 CPU 核 1,把 Vector 1 的地址配給 CPU 核 2……以此類推。這樣網卡的硬件并發就能完美映射到 CPU 的多核并發上,真正實現性能的起飛。
寫在最后
PCIe 中斷機制的發展,本質上是一條非常典型的工程演進路徑——從兼容歷史 到 追求性能 再到 面向并行擴展
INTx 誕生在一個設備數量少、并發需求低的時代,它解決的是能不能通知 CPU這個最基礎的問題。而當系統進入高速網絡、NVMe 存儲、多隊列 DMA 的時代,中斷不再只是通知機制,而是系統性能鏈路中的關鍵一環。
這時,MSI 用一次內存寫入替代信號線拉扯,讓中斷從共享廣播變成精準投遞;再往后,MSI-X 進一步把中斷從可區分升級為可擴展,讓硬件并行度能夠真正映射到多核 CPU 架構上。
而這,正是 PCIe 體系最核心的設計哲學之一:讓數據更快地流動,讓事件更精準地到達,讓并行真正發揮價值。
-
中斷
+關注
關注
5文章
918瀏覽量
43777 -
PCIe
+關注
關注
16文章
1462瀏覽量
88474 -
引腳
+關注
關注
16文章
2112瀏覽量
55717
原文標題:一文看懂PCIe中斷
文章出處:【微信號:HXSLH1010101010,微信公眾號:FPGA技術江湖】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
PCIE MSI中斷的配置
PCIe掃盲—PCIe錯誤檢測機制的詳細資料概述
PCIe中斷機制介紹(MSI)
一文看懂PCIe中斷機制
評論