一個PCI中斷異步的問題

最近發現由於PCI數據傳輸錯誤導致IO request得到的數據不正確,這種現象讓我們思考,爲什麼系統都已經發現了PCI錯誤,IO request還能正確結束呢?按照慣例思考,PCI傳輸出錯,IO request就應該fail掉,但是,事實不是這樣。難道這個問題和PCI的中斷異步有關係?因此,這裏詳細討論一下PCI的中斷異步問題及PCI解決辦法。
 
PCI擁有多種數據傳輸模式,post、non-post、Delayed以及split方式,爲了提高傳輸效率,充分利用總線帶寬資源,PCI在memory write的時候通常採用post方式。即PCI設備通過DMA控制器在向memory寫數據的時候,先將數據提交給bridge的FIFO中,然後馬上釋放本級總線資源,完成memory寫操作。但實際上此時數據還沒有抵達memory,這是一種典型的異步寫操作行爲。
 

650) this.width=650;" onsubmit onchange onunload onselect onreset> 

如上圖所示,設備2通過DMA控制器向內存寫數據,當DMA將數據post到橋2之後,隨即釋放bus1,完成DMA操作,並且向處理器提交DMA完成中斷請求。位於處理器端的驅動程序在接收到中斷請求之後調用中斷服務程序,但是,此時設備2寫入的數據可能還沒有抵達內存,這就是PCI總線的“中斷異步”問題。
 
計算機系統是如何解決這個中斷異步問題的呢?其關鍵就在於PCI協議規範中定義的“執行序”。對於傳統PCI總線而言,需要嚴格遵守PCI請求的執行順序。在上述問題中,進入驅動程序之後,需要獲取對應設備的中斷狀態寄存器內容,這是一個讀操作,這個讀操作會將post在橋2、主橋中的數據最終寫入內存。這就是PCI總線規範遵守的數據一致性原則。
 

650) this.width=650;" onsubmit onchange onunload onselect onreset> 

如上圖所示,進入位於處理器的驅動程序之後,設備驅動會向設備2發送中斷狀態寄存器讀request。在PCI中,讀操作不能採用post的方式,只能採用non-post、Delayed或者split方式。讀request到達主橋或者橋2時,如果存在post到設備2的數據,那麼主橋或者橋2會將這些post的數據最終刷新到設備2,這樣保證後繼讀請求數據的一致性。在數據返回時(藍線路徑),橋2和主橋同樣需要首先將post在那裏的數據寫入內存,然後再返回request請求的數據,這樣才能保證數據的一致性。但是,分析到這裏,我們遇到了一個總線互鎖的問題:由於讀請求有可能採用non-post的方式,紅色路徑將無法獲取總線控制權,也就無法將數據寫入內存;而藍色路徑卻要等待紅色路徑完成之後才能繼續執行,這是典型的總線互鎖問題。PCI總線如何處理上述問題呢?
 
在PCI協議規範中,Post寫總線事務可以穿越non-post的總線事務。例如,主橋在等待non-post總線事務,此時橋2仍然可以將數據post寫入到主橋。這種處理方法就可以避免上述總線互鎖問題。
 
通過分析,我們可以知道通過中斷服務程序的讀操作將post到bridge中的數據刷新到了內存方向,等驅動程序訪問DMA內存時,數據一定已經抵達內存了。PCI總線執行序保證了數據的一致性。
 
在這裏我們假設橋2或者主橋在將post的數據寫入內存時,PCI傳輸出現了問題,而產生的這種錯誤會以中斷的形式發送給處理器。如果系統不對這個中斷進行處理,那麼,從DMA內存中獲取的數據將會存在data corruption問題,並且上層軟件無法知曉。
 
 

本文出自 “存儲之道” 博客,請務必保留此出處http://alanwu.blog.51cto.com/3652632/1073404

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章