1. 程式人生 > 其它 >004 PCI Express體系結構(四)

004 PCI Express體系結構(四)

一、PCI匯流排的中斷機制

PCI匯流排使用INTA#、INTB#、INTC#和INTD#訊號向處理器發出中斷請求。這些中斷請求訊號為低電平有效,並與處理器的中斷控制器連線。在PCI體系結構中,這些中斷訊號屬於邊帶訊號(Sideband Signals),PCI匯流排規範並沒有明確規定在一個處理器系統中如何使用這些訊號,因為這些訊號對於PCI匯流排是可選訊號。PCI裝置還可以使用MSI機制向處理器提交中斷請求,而不使用這組中斷訊號。有關MSI機制的詳細說明見第8章。

1、中斷訊號與中斷控制器的連線關係

不同的處理器使用的中斷控制器不同,如x86處理器使用APIC(Advanced Programmable Interrupt Controller)中斷控制器,而PowerPC處理器使用MPIC(Multiprocessor Interrupt Controller)中斷控制器。這些中斷控制器都提供了一些外部中斷請求引腳IRQ_PINx#。外部裝置,包括PCI裝置可以使用這些引腳向處理器提交中斷請求。

但是PCI匯流排規範沒有規定PCI裝置的INTx訊號如何與中斷控制器的IRQ_PINx#訊號相連,這為系統軟體的設計帶來了一定的困難,為此係統軟體使用中斷路由表存放PCI裝置的INTx訊號與中斷控制器的連線關係。在x86處理器系統中,BIOS可以提供這個中斷路由表,而在PowerPC處理器中Firmware也可以提供這個中斷路由表。

在一些簡單的嵌入式處理器系統中,Firmware並沒有提供中斷路由表,此時系統軟體開發者需要事先了解PCI裝置的INTx訊號與中斷控制器的連線關係。此時外部裝置與中斷控制器的連線關係由硬體設計人員指定。

我們假設在一個處理器系統中,共有3個PCI插槽(分別為PCI插槽A、B和C),這些PCI插槽與中斷控制器的IRQ_PINx引腳(分別為IRQW#、IRQX#、IRQY#和IRQZ#)可以按照圖1‑5所示的拓撲結構進行連線。

採用圖1‑5所示的拓撲結構時,PCI插槽A、B、C的INTA#、INTB#和INTC#訊號將分散連線到中斷控制器的IRQW#、IRQX#和IRQY#訊號,而所有INTD#訊號將共享一個IRQZ#訊號。採用這種連線方式時,整個處理器系統使用的中斷請求訊號,其負載較為均衡。而且這種連線方式保證了每一個插槽的INTA#訊號都與一根獨立的IRQx#訊號對應,從而提高了PCI插槽中斷請求的效率。

在一個處理器系統中,多數PCI裝置僅使用INTA#訊號,很少使用INTB#和INTC#訊號,而INTD#訊號更是極少使用。在PCI匯流排中,PCI裝置配置空間的Interrupt Pin暫存器記錄該裝置究竟使用哪個INTx訊號,該暫存器的詳細介紹見第2.3.2節。

2、 中斷訊號與PCI匯流排的連線關係

在PCI匯流排中,INTx訊號屬於邊帶訊號。所謂邊帶訊號是指這些訊號在PCI匯流排中是可選訊號,而且只能在一個處理器系統的內部使用,並不能離開這個處理器環境。PCI橋也不會處理這些邊帶訊號。這給PCI裝置將中斷請求發向處理器帶來了一些困難,特別是給掛接在PCI橋之下的PCI裝置進行中斷請求帶來了一些麻煩。

在一些嵌入式處理器系統中,這個問題較易解決。因為嵌入式處理器系統很清楚在當前系統中存在多少個PCI裝置,這些PCI裝置使用了哪些中斷資源。在多數嵌入式處理器系統中,PCI裝置的數量小於中斷控制器提供的外部中斷請求引腳數,而且在嵌入式系統中,多數PCI裝置僅使用INTA#訊號提交中斷請求。

在這類處理器系統中,可能並不含有PCI橋,因而PCI裝置的中斷請求訊號與中斷控制器的連線關係較易確定。而在這類處理器系統中,即便存在PCI橋,來自PCI橋之下的PCI裝置的中斷請求也較易處理。

在多數情況下,嵌入式處理器系統使用的PCI裝置僅使用INTA#訊號進行中斷請求,所以只要將這些INTA#訊號掛接到中斷控制器的獨立IRQ_PIN#引腳上即可。這樣每一個PCI裝置都可以獨佔一個單獨的中斷引腳。

而在x86處理器系統中,這個問題需要BIOS參與來解決。在x86處理器系統中,有許多PCI插槽,處理器系統並不知道在這些插槽上將要掛接哪些PCI裝置,而且也並不知道這些PCI裝置到底需不需要使用所有的INTx#訊號線。因此x86處理器系統必須要對各種情況進行處理。

x86處理器系統還經常使用PCI橋進行PCI匯流排擴充套件,擴展出來的PCI匯流排還可能掛接一些PCI插槽,這些插槽上INTx#訊號仍然需要處理。PCI橋規範並沒有要求橋片傳遞其下PCI裝置的中斷請求。事實上多數PCI橋也沒有為下游PCI匯流排提供中斷引腳INTx#,管理其下游匯流排的PCI裝置。但是PCI橋規範推薦使用表1‑3建立下游PCI裝置的INTx訊號與上游PCI匯流排INTx訊號之間的對映關係。

表1‑3 PCI裝置INTx#訊號與PCI匯流排INTx#訊號的對映關係

裝置號

PCI裝置的INTx#訊號

PCI匯流排的INTx#訊號

0, 4, 8, 12, 16, 20, 24, 28

INTA#

INTA#

INTB#

INTB#

INTC#

INTC#

INTD#

INTD#

1, 5, 9, 13, 17, 21, 25, 29

INTA#

INTB#

INTB#

INTC#

INTC#

INTD#

INTD#

INTA#

2, 6, 10, 14, 18, 22, 26, 30

INTA#

INTC#

INTB#

INTD#

INTC#

INTA#

INTD#

INTB#

3, 7, 11, 15, 19, 23, 27, 31

INTA#

INTD#

INTB#

INTA#

INTC#

INTB#

INTD#

INTC#

我們舉例說明該表的含義。在PCI橋下游總線上的PCI裝置,如果其裝置號為0,那麼這個裝置的INTA#引腳將和PCI匯流排的INTA#引腳相連;如果其裝置號為1,其INTA#引腳將和PCI匯流排的INTB#引腳相連;如果其裝置號為2,其INTA#引腳將和PCI匯流排的INTC#引腳相連;如果其裝置號為3,其INTA#引腳將和PCI匯流排的INTD#引腳相連。

在x86處理器系統中,由BIOS或者APCI表記錄PCI匯流排的INTA~D#訊號與中斷控制器之間的對映關係,儲存這個對映關係的資料結構也被稱為中斷路由表。大多數BIOS使用表1‑3中的對映關係,這也是絕大多數BIOS支援的方式。如果在一個x86處理器系統中,PCI橋下游匯流排的PCI裝置使用的中斷對映關係與此不同,那麼系統軟體程式設計師需要改動BIOS中的中斷路由表。

BIOS初始化程式碼根據中斷路由表中的資訊,可以將PCI裝置使用的中斷向量號寫入到該PCI裝置配置空間的Interrupt Line register暫存器中,該暫存器將在第2.3.2節中介紹。

3、中斷請求的同步

在PCI匯流排中,INTx訊號是一個非同步訊號。所謂非同步是指INTx訊號的傳遞並不與PCI匯流排的資料傳送同步,即INTx訊號的傳遞與PCI裝置使用的CLK#訊號無關。這個“非同步”訊號給系統軟體的設計帶來了一定的麻煩。

系統軟體程式設計師需要注意“非同步”這種事件,因為幾乎所有“非同步”事件都會帶來系統的“同步”問題。以圖1‑1為例,當PCI裝置11使用DMA寫方式,將一組資料寫入儲存器時,該裝置在最後一個數據離開PCI裝置11的傳送FIFO時,會認為DMA寫操作已經完成。此時這個裝置將通過INTx訊號,通知處理器DMA寫操作完成。

此時處理器(驅動程式的中斷服務例程)需要注意,因為INTx訊號是一個非同步訊號,當處理器收到INTx訊號時,並不意味著PCI裝置11已經將資料寫入儲存器中,因為PCI裝置11的資料傳遞需要通過PCI橋1和HOST主橋,最終才能到達儲存器控制器。

而INTx訊號是“非同步”傳送給處理器的,PCI匯流排並不知道這個“非同步”事件何時被處理。很有可能處理器已經接收到INTx訊號,開始執行中斷處理程式時,該PCI裝置還沒有完全將資料寫入儲存器。

因為“PCI裝置向處理器提交中斷請求”與“將資料寫入儲存器”分別使用了兩個不同的路徑,處理器系統無法保證哪個資訊率先到達。從而在處理器系統中存在“中斷同步”的問題,PCI匯流排提供了以下兩種方法解決這個同步問題。

(1) PCI裝置保證在資料到達目的地之後,再提交中斷請求。

顯然這種方法不僅加大了硬體的開銷,而且也不容易實現。如果PCI裝置採用Posted寫匯流排事務,PCI裝置無法單純通過硬體邏輯判斷資料什麼時候寫入到儲存器。此時為了保證資料到達目的地後,PCI裝置才能提交中斷請求,PCI裝置需要使用“讀重新整理”的方法保證資料可以到達目的地,其方法如下。

PCI裝置在提交中斷請求之前,向DMA寫的資料區域發出一個讀請求,這個讀請求匯流排事務將被PCI裝置轉換為讀完成匯流排事務,當PCI裝置收到這個讀完成匯流排事務後,再向處理器提交中斷請求。PCI匯流排的“序”機制保證這個儲存器讀請求,會將DMA資料最終寫入儲存器,有關PCI序的詳細說明見第9.3節。

PCI匯流排規範要求HOST主橋和PCI橋必須保證這種讀操作可以重新整理寫操作。但問題是,沒有多少晶片設計者願意提供這種機制,因為這將極大地增加他們的設計難度。除此之外,使用這種方法也將增加中斷請求的延時。

(2) 中斷服務例程使用“讀重新整理”方法。

中斷服務例程在使用“PCI裝置寫入儲存器”的這些資料之前,需要對這個PCI裝置進行讀操作。這個讀操作也可以強制將資料最終寫入儲存器,實際上是將資料寫到儲存器控制器中。這種方法利用了PCI匯流排的傳送序規則,這種方法與第1種方法基本相同,只是使用這種方法使用軟體方式,而第1種方式使用硬體方式。第9.3節將詳細介紹這個讀操作如何將資料重新整理到儲存器中。

第2種方法也是絕大多數處理器系統採用的方法。程式設計師在書寫中斷服務例程時,往往都是先讀取PCI裝置的中斷狀態暫存器,判斷中斷產生原因之後,才對PCI裝置寫入的資料進行操作。這個讀取中斷狀態暫存器的過程,一方面可以獲得裝置的中斷狀態,另一方面是保證DMA寫的資料最終到達儲存器。如果驅動程式不這樣做,就可能產生資料完整性問題。產生這種資料完整性問題的原因是INTx這個非同步訊號。

這裡也再次提醒系統程式設計師注意PCI匯流排的“非同步”中斷所帶來的資料完整性問題。在一個作業系統中,即便中斷處理程式沒有首先讀取PCI裝置的暫存器,也多半不會出現問題,因為在作業系統中,一個PCI裝置從提交中斷到處理器開始執行裝置的中斷服務例程,所需要的時間較長,處理器系統基本上可以保證此時資料已經寫入儲存器。

但是如果系統程式設計師不這樣做,這個驅動程式依然有Bug存在,儘管這個Bug因為各種機緣巧合,始終不能夠暴露出來,而一旦這些Bug被暴露出來將難以定位。為此係統程式設計師務必要重視設計中出現的每一個實現細節,當然僅憑謹慎小心是遠遠不夠的,因為重視細節的前提是充分理解這些細節。

PCI匯流排V2.2規範還定義了一種新的中斷機制,即MSI中斷機制。MSI中斷機制採用儲存器寫匯流排事務向處理器系統提交中斷請求,其實現機制是向HOST處理器指定的一個儲存器地址寫指定的資料。這個儲存器地址一般是中斷控制器規定的某段儲存器地址範圍,而且資料也是事先安排好的資料,通常含有中斷向量號。

HOST主橋會將MSI這個特殊的儲存器寫匯流排事務進一步翻譯為中斷請求,提交給處理器。目前PCIe和PCI-X裝置必須支援MSI中斷機制,但是PCI裝置並不一定都支援MSI中斷機制。

目前MSI中斷機制雖然在PCIe總線上已經成為主流,但是在PCI裝置中並不常用。即便是支援MSI中斷機制的PCI裝置,在裝置驅動程式的實現中也很少使用這種機制。首先PCI裝置具有INTx#訊號可以傳遞中斷,而且這種中斷傳送方式在PCI匯流排中根深蒂固。其次PCI匯流排是一個共享匯流排,傳遞MSI中斷需要佔用PCI匯流排的頻寬,需要進行匯流排仲裁等一系列過程,遠沒有使用INTx#訊號線直接。

但是使用MSI中斷機制可以取消PCI匯流排這個INTx#邊帶訊號,可以解決使用INTx中斷機制所帶來的資料完整性問題。而更為重要的是,PCI裝置使用MSI中斷機制,向處理器系統提交中斷請求的同時,還可以通知處理器系統產生該中斷的原因,即通過不同中斷向量號表示中斷請求的來源。當處理器系統執行中斷服務例程時,不需要讀取PCI裝置的中斷狀態暫存器,獲得中斷請求的來源,從而在一定程度上提高了中斷處理的效率。本書將在第8章詳細介紹MSI中斷機制。